`

一个通用的错误处理器

 
阅读更多
书上的一个例子:比较好

set serveroutput on size 200000
set linesize 250

-- These 3 procedures illustrate the use of FORMAT_CALL_STACK.
CREATE OR REPLACE PROCEDURE C AS
  v_CallStack VARCHAR2(2000);
BEGIN
  v_CallStack := DBMS_UTILITY.FORMAT_CALL_STACK;
  DBMS_OUTPUT.PUT_LINE(v_CallStack);
END C;
/

CREATE OR REPLACE PROCEDURE B AS
BEGIN
  C;
END B;
/

CREATE OR REPLACE PROCEDURE A AS
BEGIN
  B;
END A;
/

exec A;

DROP TABLE errors;
CREATE TABLE errors (
  module       VARCHAR2(50),
  seq_number   NUMBER,
  error_number NUMBER,
  error_mesg   VARCHAR2(100),
  error_stack  VARCHAR2(2000),
  call_stack   VARCHAR2(2000),
  timestamp    DATE,
  PRIMARY KEY (module, seq_number));

DROP TABLE call_stacks;
CREATE TABLE call_stacks (
  module        VARCHAR2(50),
  seq_number    NUMBER,
  call_order    NUMBER,
  object_handle VARCHAR2(10),
  line_num      NUMBER,
  object_name   VARCHAR2(80),
  PRIMARY KEY (module, seq_number, call_order),
  FOREIGN KEY (module, seq_number) REFERENCES errors ON DELETE CASCADE);

DROP TABLE error_stacks;
CREATE TABLE error_stacks (
  module        VARCHAR2(50),
  seq_number    NUMBER,
  error_order   NUMBER,
  facility      CHAR(3),
  error_number  NUMBER(5),
  error_mesg    VARCHAR2(100),
  PRIMARY KEY (module, seq_number, error_order),
  FOREIGN KEY (module, seq_number) REFERENCES errors ON DELETE CASCADE);

DROP SEQUENCE error_seq;
CREATE SEQUENCE error_seq
  START WITH 1
  INCREMENT BY 1;

/* Generic error-handling package, using
 DBMS_UTILITY.FORMAT_ERROR_STACK and DBMS_UTILITY.FORMAT_CALL_STACK. 
 This package will store general error information in the errors
 table, with detailed call stack and error stack information in the
 call_stacks and error_stacks tables, respectively. */
CREATE OR REPLACE PACKAGE ErrorPkg AS

  -- Entry point for handling errors.  HandleAll should be called
  -- from all exception handlers where you want the error to be
  -- logged.  p_Top should be TRUE only at the topmost level of
  -- procedure nesting.  It should be FALSE at other levels.
  PROCEDURE HandleAll(p_Top BOOLEAN);

  -- Prints the error and call stacks (using DBMS_OUTPUT) for the
  -- given module and sequence number.
  PROCEDURE PrintStacks(p_Module IN errors.module%TYPE,
                        p_SeqNum IN errors.seq_number%TYPE);

  -- Unwinds the call and error stacks, and stores them in the errors
  -- and call_stacks tables.  Returns the sequence number under which
  -- the error is stored.
  -- If p_CommitFlag is TRUE, then the inserts are committed.
  -- In order to use StoreStacks, an error must have been handled. 
  -- Thus HandleAll should have been called with p_Top = TRUE.
  PROCEDURE StoreStacks(p_Module IN errors.module%TYPE,
                        p_SeqNum OUT errors.seq_number%TYPE,
                        p_CommitFlag BOOLEAN DEFAULT FALSE);
END ErrorPkg;
/
show errors

CREATE OR REPLACE PACKAGE BODY ErrorPkg AS

  v_NewLine     CONSTANT CHAR(1) := CHR(10);

  v_Handled     BOOLEAN := FALSE;
  v_ErrorStack  VARCHAR2(2000);
  v_CallStack   VARCHAR2(2000);

  PROCEDURE HandleAll(p_Top BOOLEAN) IS
  BEGIN
    IF p_Top THEN
      v_Handled := FALSE;
    ELSIF NOT v_Handled THEN
      v_Handled := TRUE;
      v_ErrorStack := DBMS_UTILITY.FORMAT_ERROR_STACK;
      v_CallStack := DBMS_UTILITY.FORMAT_CALL_STACK;
    END IF;      
  END HandleAll;

  PROCEDURE PrintStacks(p_Module IN errors.module%TYPE,
                        p_SeqNum IN errors.seq_number%TYPE) IS
    v_TimeStamp errors.timestamp%TYPE;
    v_ErrorMsg  errors.error_mesg%TYPE;

    CURSOR c_CallCur IS
      SELECT object_handle, line_num, object_name
        FROM call_stacks
        WHERE module = p_Module
        AND seq_number = p_SeqNum
        ORDER BY call_order;

    CURSOR c_ErrorCur IS
      SELECT facility, error_number, error_mesg
        FROM error_stacks
        WHERE module = p_Module
        AND seq_number = p_SeqNum
        ORDER BY error_order;
  BEGIN
    SELECT timestamp, error_mesg
      INTO v_TimeStamp, v_ErrorMsg
      FROM errors
      WHERE module = p_Module
      AND seq_number = p_SeqNum;

    -- Output general error information.
    DBMS_OUTPUT.PUT(TO_CHAR(v_TimeStamp, 'DD-MON-YY HH24:MI:SS'));
    DBMS_OUTPUT.PUT('  Module: ' || p_Module);
    DBMS_OUTPUT.PUT('  Error #' || p_SeqNum || ':  ');
    DBMS_OUTPUT.PUT_LINE(v_ErrorMsg);

    -- Output the call stack.
    DBMS_OUTPUT.PUT_LINE('Complete Call Stack:');
    DBMS_OUTPUT.PUT_LINE('  Object Handle  Line Number  Object Name');
    DBMS_OUTPUT.PUT_LINE('  -------------  -----------  -----------');
    FOR v_CallRec in c_CallCur LOOP
      DBMS_OUTPUT.PUT(RPAD('  ' || v_CallRec.object_handle, 15));
      DBMS_OUTPUT.PUT(RPAD('  ' || TO_CHAR(v_CallRec.line_num), 13));
      DBMS_OUTPUT.PUT_LINE('  ' || v_CallRec.object_name);
    END LOOP;

    -- Output the error stack.
    DBMS_OUTPUT.PUT_LINE('Complete Error Stack:');
    FOR v_ErrorRec in c_ErrorCur LOOP
      DBMS_OUTPUT.PUT('  ' || v_ErrorRec.facility || '-');
      DBMS_OUTPUT.PUT(TO_CHAR(v_ErrorRec.error_number) || ': ');
      DBMS_OUTPUT.PUT_LINE(v_ErrorRec.error_mesg);
    END LOOP;
    
  END PrintStacks;

  PROCEDURE StoreStacks(p_Module IN errors.module%TYPE,
                        p_SeqNum OUT errors.seq_number%TYPE,
                        p_CommitFlag BOOLEAN DEFAULT FALSE) IS
    v_SeqNum     NUMBER;

    v_Index      NUMBER;
    v_Length     NUMBER;
    v_End        NUMBER;

    v_Call       VARCHAR2(100);
    v_CallOrder  NUMBER := 1;
    v_Handle     call_stacks.object_handle%TYPE;
    v_LineNum    call_stacks.line_num%TYPE;
    v_ObjectName call_stacks.object_name%TYPE;

    v_Error      VARCHAR2(120);
    v_ErrorOrder NUMBER := 1;
    v_Facility   error_stacks.facility%TYPE;
    v_ErrNum     error_stacks.error_number%TYPE;
    v_ErrMsg     error_stacks.error_mesg%TYPE;

    v_FirstErrNum errors.error_number%TYPE;
    v_FirstErrMsg errors.error_mesg%TYPE;
  BEGIN
    -- First get the error sequence number.
    SELECT error_seq.nextval
      INTO v_SeqNum
      FROM dual;

    p_SeqNum := v_SeqNum;

    -- Insert the first part of the header information into the
    -- errors table.
    INSERT INTO errors
      (module, seq_number, error_stack, call_stack, timestamp)
    VALUES
      (p_Module, v_SeqNum, v_ErrorStack, v_CallStack, SYSDATE);

    -- Unwind the error stack to get each error out.  We do this by
    -- scanning the error stack string.  Start with the index at the
    -- beginning of the string.
    v_Index := 1;
 
    -- Loop through the string, finding each newline.  A newline ends
    -- each error on the stack.
    WHILE v_Index <  LENGTH(v_ErrorStack) LOOP
      -- v_End is the position of the newline.
      v_End := INSTR(v_ErrorStack, v_NewLine, v_Index);

      -- Thus, the error is between the current index and the
      -- newline.
      v_Error := SUBSTR(v_ErrorStack, v_Index, v_End - v_Index);

      -- Skip over the current error, for the next iteration.
      v_Index := v_Index + LENGTH(v_Error) + 1;

      -- An error looks like 'facility-number: mesg'.  We need to get
      -- each piece out for insertion.

      -- First, the facility is the first 3 characters of the error.
      v_Facility := SUBSTR(v_Error, 1, 3); 

      -- Remove the facility and the dash (always 4 characters).
      v_Error := SUBSTR(v_Error, 5);

      -- Now we can get the error number.
      v_ErrNum :=
        TO_NUMBER(SUBSTR(v_Error, 1, INSTR(v_Error, ':') - 1));

      -- Remove the error number, colon and space (always 7
      -- characters).
      v_Error := SUBSTR(v_Error, 8);

      -- What's left is the error message.
      v_ErrMsg := v_Error;

      -- Insert the errors, and grab the first error number and
      -- message while we're at it.
      INSERT INTO error_stacks
        (module, seq_number, error_order, facility, error_number,
         error_mesg)
      VALUES
        (p_Module, p_SeqNum, v_ErrorOrder, v_Facility, v_ErrNum, v_ErrMsg);

      IF v_ErrorOrder = 1 THEN
        v_FirstErrNum := v_ErrNum;
        v_FirstErrMsg := v_Facility || '-' || TO_NUMBER(v_ErrNum) ||
                         ': ' || v_ErrMsg;
      END IF;

      v_ErrorOrder := v_ErrorOrder + 1;
    END LOOP;
 
    -- Update the errors table with the message and code.
    UPDATE errors
      SET error_number = v_FirstErrNum,
          error_mesg = v_FirstErrMsg
      WHERE module = p_Module
      AND seq_number = v_SeqNum;

    -- Now we need to unwind the call stack, to get each call out.
    -- We do this by scanning the call stack string.  Start with the
    -- index after the first call on the stack.  This will be after
    -- the first occurrence of 'name' and the newline.
    v_Index := INSTR(v_CallStack, 'name') + 5;

    -- Loop through the string, finding each newline.  A newline ends
    -- each call on the stack.
    WHILE v_Index <  LENGTH(v_CallStack) LOOP
      -- v_End is the position of the newline.
      v_End := INSTR(v_CallStack, v_NewLine, v_Index);

      -- Thus, the call is between the current index and the newline.
      v_Call := SUBSTR(v_CallStack, v_Index, v_End - v_Index);

      -- Skip over the current call, for the next iteration.
      v_Index := v_Index + LENGTH(v_Call) + 1;

      -- Within a call, we have the object handle, then the line
      -- number, then the object name, separated by spaces.  We need
      -- to separate them out for insertion.

      -- Trim white space from the call first.
      v_Call := LTRIM(v_Call);

      -- First get the object handle.
      v_Handle := SUBSTR(v_Call, 1, INSTR(v_Call, ' '));

      -- Now, remove the object handle, then the white space from
      -- the call.
      v_Call := SUBSTR(v_Call, LENGTH(v_Handle) + 1);
      v_Call := LTRIM(v_Call);

      -- Now we can get the line number.
      v_LineNum := TO_NUMBER(SUBSTR(v_Call, 1, INSTR(v_Call, ' ')));

      -- Remove the line number, and white space.
      v_Call := SUBSTR(v_Call, LENGTH(v_LineNum) + 1);
      v_Call := LTRIM(v_Call);

      -- What is left is the object name.
      v_ObjectName := v_Call;

      -- Insert all calls except the call for ErrorPkg.
      IF v_CallOrder > 1 THEN
        INSERT INTO call_stacks
          (module, seq_number, call_order, object_handle, line_num, 
           object_name)
        VALUES
          (p_Module, v_SeqNum, v_CallOrder, v_Handle, v_LineNum, 
           v_ObjectName);
      END IF;

      v_Callorder := v_CallOrder + 1;

    END LOOP;

    IF p_CommitFlag THEN 
      COMMIT;
    END IF;
  END StoreStacks;

END ErrorPkg;
/
show errors


CREATE OR REPLACE TRIGGER temp_insert
  BEFORE INSERT ON temp_table
BEGIN
  RAISE ZERO_DIVIDE;
END ttt_insert;
/

CREATE OR REPLACE PROCEDURE C AS
BEGIN
  INSERT INTO temp_table (num_col) VALUES (7);
EXCEPTION
  WHEN OTHERS THEN
    ErrorPkg.HandleAll(FALSE);
    RAISE;
END C;
/

CREATE OR REPLACE PROCEDURE B AS
BEGIN
  C;
EXCEPTION
  WHEN OTHERS THEN
    ErrorPkg.HandleAll(FALSE);
    RAISE;
END B;
/

CREATE OR REPLACE PROCEDURE A AS
  v_ErrorSeq NUMBER;
BEGIN
  B;
EXCEPTION
  WHEN OTHERS THEN
    ErrorPkg.HandleAll(TRUE);
    ErrorPkg.StoreStacks('Error Test', v_ErrorSeq, TRUE);
    ErrorPkg.PrintStacks('Error Test', v_ErrorSeq);
END A;
/


SET SERVEROUTPUT ON SIZE 1000000 FORMAT TRUNCATED
exec A;
分享到:
评论

相关推荐

    ug三轴通用后处理器

    标题中的"ug三轴通用后处理器"指的是一个适用于三轴数控机床的UG后处理器。三轴指的是X、Y、Z三个线性轴的运动,这种机床广泛应用于各种机械加工领域,如模具制造、零件生产等。通用后处理器意味着它能适应多种三轴...

    一种嵌入式通用多处理器通信管理单元设计.pdf

    【嵌入式通用多处理器通信管理单元设计】 嵌入式通用多处理器通信管理单元(CMU)设计是针对数据链网络系统...通过精心设计,可以创建一个高效、可定制且可靠的通信管理解决方案,以适应不断发展的电子信息技术需求。

    基于指令模板的通用处理器约束随机指令生成方法.pdf

    基于指令模板的通用处理器约束随机指令生成方法是一个用于验证通用处理器的功能的方法。该方法通过从指令集中提取指令模板,然后使用指令模板生成合法的ARMv8指令。通过调整约束支持各种功能场景的验证。 知识点: ...

    通用处理器和图像处理器新型融合架构分析.pdf

    随着计算机应用的日益复杂,对计算能力的需求不断提升,传统的单核心或双核心处理器已无法满足需求,因此,融合CPU和GPU的优势成为了一个重要的研究方向。 CPU和GPU各自具有独特的技术特点。CPU擅长执行复杂的控制...

    基于PowerPC架构的通用处理器系统虚拟验证.pdf

    通过构建软硬件协同工作的虚拟验证环境,可以模拟实际处理器系统的行为,提供了一个在系统级验证功能和性能的有效途径。这种平台通常包括验证模型的开发和测试程序的编写,以便全面测试处理器的各种功能和性能特性。...

    基于POWER PC通用处理器的CPU模块设计.pdf

    POWER PC通用处理器是一种高效能的超标量处理器,以其低功耗和高性能的特点广泛应用于多种计算平台。本文主要探讨了基于这种处理器的CPU模块设计,特别是以Motorola的POWER PC603e芯片为例进行详细说明。 1. CPU...

    需求不断提升:后摩尔时代下通用多核处理器的机遇和挑战.pdf

    多线程处理器则在单个核心内支持多个硬件线程,以利用细粒度的线程切换来提高资源利用率,减少因分支预测错误或延迟访问内存造成的效率损失。 在多核处理器领域,Intel、IBM、ARM等国际巨头凭借深厚的技术积累,...

    从头开始的可解释代理通信(附带一个通用的可视处理器)_Interpretable agent communication fro

    "从头开始的可解释代理通信(附带一个通用的可视处理器)"这篇论文聚焦于如何通过无监督的自动生成通信来训练两个深度网络进行大规模的参照识别任务。这种通信方式部分可解释,能帮助网络成功地交流它们在训练时未曾...

    自适应补偿的无线通用处理器共享模型调度算法.pdf

    新算法的核心是定义了一个根据终端有效吞吐量动态调整的时变共享份额。在传统的GPS模型中,公平份额是固定的,而在这种自适应补偿算法中,公平份额会随着终端的实际性能变化而变化,从而更好地反映出信道状况对各...

    基于现代通用处理器的数据库优化综述.pdf

    【基于现代通用处理器的数据库优化】是计算机科学领域的一个重要课题,主要关注如何利用现代处理器的特性提升数据库系统的性能。随着处理器技术的飞速发展,虽然计算机性能得到了显著提升,但同时也带来了新的挑战,...

    基于通用处理器的TD-LTE资源映射的设计与实现.pdf

    【TD-LTE资源映射】 TD-LTE(Time Division Long Term Evolution)是3GPP制定的4G移动通信标准之一,它利用时分双工(TDD)...本文的研究基于通用处理器,提供了实现资源映射的一种方法,为实际系统设计提供了参考。

    ARM处理器的编程模型和arm处理器结构详解

    选择ARM处理器主要考虑以下几个方面: 1. **性能需求**:根据应用的需求选择合适的处理器内核,如ARM7TDMI、Cortex-A、Cortex-M或Cortex-R系列。 2. **功耗和成本**:嵌入式系统往往对功耗敏感,ARM处理器因低功耗而...

    ARM处理器异常处理步骤

    ARM处理器有37个寄存器,其中31个是通用寄存器,包括程序计数器(PC),以及6个32位的状态寄存器。异常处理的第一步是保存当前处理器的状态,称为CPSR(当前程序状态寄存器),以便异常处理完成后能恢复到异常发生前...

    号码处理器

    "号码处理器"是一个可能涉及到数据处理、电话号码管理或通信技术的应用程序。在这个场景中,我们主要探讨与号码处理相关的IT知识点。 1. **数据处理**:号码处理器的核心功能可能是对数字序列进行操作,比如清洗、...

    操作系统通用处理器调度演示程序课程设计报告总结报告.doc

    在这个课程设计中,学生需要实现一个模拟环境,能够演示五种不同的处理器调度算法,包括时间片轮转、先来先服务(FCFS)、短作业优先(SJF)、静态优先权优先调度以及高响应比优先调度。 课程设计的目标是让学生...

    ARM处理器架构(经典手册)

    12. **ARM Cortex系列**: ARM Cortex是ARM公司的一个产品系列,包括A、R和M三大类,分别针对应用处理器、实时系统和微控制器市场。 通过深入学习这本“ARM处理器架构(经典手册)”,读者可以理解ARM处理器的工作...

    基于UG NX7.5专用后处理器的开发与应用.pdf

    总结起来,UG NX 7.5的专用后处理器开发是一个关键的技术环节,对于实现高效、准确的数控编程至关重要。通过PostBuilder提供的工具,工程师能够根据实际需求定制后处理器,以适应各种类型的数控系统,提升制造业的...

    高速专用GFP处理器的FPGA实现

    论文中提及的0x7E是HDLC中用于帧定界的一个特殊字节。 通过以上知识点,可以清晰地了解本篇论文所涉及的技术范围和研究深度,展示了如何通过FPGA技术来优化GFP处理器的设计,以提高SDH网络中数据处理的效率和速度。...

    一种新的嵌入式处理器在线调试方法.pdf

    该方法主要通过引入一个通用的调试模块,使得即使是没有调试接口的处理器也能实现在线调试。这一创新方法的核心在于利用专用的调试中断和对应的调试服务程序,创建了一种处理器响应断点的机制。调试中断允许处理器在...

    Go-pkgreflect-一个Go预处理器用于包范围反射

    `pkgreflect` 是一个针对Go语言的预处理器,它的目标是简化包范围内的反射操作,使得开发者可以更方便地在不违反Go语言的静态类型约束下,动态地获取和操作类型信息。 在Go语言的标准库中,`reflect` 包提供了反射...

Global site tag (gtag.js) - Google Analytics