exception.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: exception.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:19:05  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: exception.cpp,v 1000.2 2004/06/01 19:19:05 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE                          
  13.  *               National Center for Biotechnology Information
  14.  *                                                                          
  15.  *  This software/database is a "United States Government Work" under the   
  16.  *  terms of the United States Copyright Act.  It was written as part of    
  17.  *  the author's official duties as a United States Government employee and 
  18.  *  thus cannot be copyrighted.  This software/database is freely available 
  19.  *  to the public for use. The National Library of Medicine and the U.S.    
  20.  *  Government have not placed any restriction on its use or reproduction.  
  21.  *                                                                          
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy  
  23.  *  and reliability of the software and data, the NLM and the U.S.          
  24.  *  Government do not and cannot warrant the performance or results that    
  25.  *  may be obtained by using this software or data. The NLM and the U.S.    
  26.  *  Government disclaim all warranties, express or implied, including       
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.                                                                
  29.  *                                                                          
  30.  *  Please cite the author in any work or product based on this material.   
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov, Vladimir Soussov
  35.  *   
  36.  * File Description:  Exceptions
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/exception.hpp>
  41. BEGIN_NCBI_SCOPE
  42. /////////////////////////////////////////////////////////////////////////////
  43. //  CDB_Exception::
  44. //
  45. CDB_Exception::CDB_Exception(EType type, EDB_Severity severity, int err_code,
  46.                              const string& originated_from, const string& msg)
  47. {
  48.     m_Type           = type;
  49.     m_Severity       = severity;
  50.     m_ErrCode        = err_code;
  51.     m_OriginatedFrom = originated_from;
  52.     m_Message        = msg;
  53. }
  54. CDB_Exception::~CDB_Exception() throw()
  55. {
  56.     return;
  57. }
  58. const char* CDB_Exception::what() const throw()
  59. {
  60.     if ( m_What.empty() ) {
  61.         try {
  62.             x_ComposeWhat();
  63.         } catch (exception& ex) {
  64.             static char s_StartOfWhat[] =
  65.                 "CDB_Exception::what(): x_ComposeWhat() threw an exception: ";
  66.             static char s_What[sizeof(s_StartOfWhat) + 128];
  67.             strcpy(s_What, s_StartOfWhat);
  68.             const char* ex_what = ex.what() ? ex.what() : "NULL";
  69.             size_t len = strlen(s_StartOfWhat);
  70.             strncpy(s_What + len, ex_what,
  71.                     sizeof(s_What) - strlen(s_StartOfWhat) - 1);
  72.             s_What[sizeof(s_What) - 1] = '';
  73.             return s_What;
  74.         }
  75.     }
  76.     return m_What.c_str();
  77. }
  78. const char* CDB_Exception::SeverityString(EDB_Severity sev)
  79. {
  80.     switch ( sev ) {
  81.     case eDB_Info:     return "Info";
  82.     case eDB_Warning:  return "Warning";
  83.     case eDB_Error:    return "Error";
  84.     case eDB_Fatal:    return "Fatal";
  85.     default:           return "Unclear";
  86.     }
  87. }
  88. void CDB_Exception::x_ComposeWhat(void) const
  89. {
  90.     x_StartOfWhat(&m_What);
  91.     x_EndOfWhat(&m_What);
  92. }
  93. string& CDB_Exception::x_StartOfWhat(string* str) const
  94. {
  95.     *str += "[";
  96.     *str += SeverityString();
  97.     *str += " #";
  98.     *str += NStr::IntToString(ErrCode());
  99.     *str += ", ";
  100.     *str += TypeString();
  101.     *str += " in ";
  102.     *str += OriginatedFrom();
  103.     *str += "]  ";
  104.     return *str;
  105. }
  106. string& CDB_Exception::x_EndOfWhat(string* str) const
  107. {
  108.     *str += "<<<";
  109.     *str += Message();
  110.     *str += ">>>";
  111.     return *str;
  112. }
  113. /////////////////////////////////////////////////////////////////////////////
  114. //  CDB_DSEx::
  115. //
  116. const char* CDB_DSEx::TypeString() const
  117. {
  118.     return "Data_Source";
  119. }
  120. CDB_Exception* CDB_DSEx::Clone() const
  121. {
  122.     return new CDB_DSEx
  123.         (m_Severity, m_ErrCode, m_OriginatedFrom, m_Message);
  124. }
  125. /////////////////////////////////////////////////////////////////////////////
  126. //  CDB_RPCEx::
  127. //
  128. CDB_RPCEx::CDB_RPCEx(EDB_Severity severity, int err_code,
  129.                      const string& originated_from, const string& msg,
  130.                      const string& proc_name, int proc_line)
  131.     : CDB_Exception(eRPC, severity, err_code, originated_from, msg)
  132. {
  133.     static const string s_UnknownProcName = "Unknown";
  134.     m_ProcName = proc_name.empty() ? s_UnknownProcName : proc_name;
  135.     m_ProcLine = proc_line;
  136. }
  137. CDB_RPCEx::~CDB_RPCEx() throw()
  138. {
  139.     return;
  140. }
  141. const char* CDB_RPCEx::TypeString() const
  142. {
  143.     return "Remote_Procedure_Call";
  144. }
  145. CDB_Exception* CDB_RPCEx::Clone() const
  146. {
  147.     return new CDB_RPCEx
  148.         (m_Severity, m_ErrCode, m_OriginatedFrom, m_Message,
  149.          m_ProcName, m_ProcLine);
  150. }
  151. void CDB_RPCEx::x_ComposeWhat(void) const
  152. {
  153.     x_StartOfWhat(&m_What);
  154.     m_What += "Procedure '";
  155.     m_What += ProcName();
  156.     m_What += "', Line ";
  157.     m_What += NStr::IntToString(ProcLine());
  158.     x_EndOfWhat(&m_What);
  159. }
  160. /////////////////////////////////////////////////////////////////////////////
  161. //  CDB_SQLEx::
  162. //
  163. CDB_SQLEx::CDB_SQLEx(EDB_Severity severity, int err_code,
  164.                      const string& originated_from, const string& msg,
  165.                      const string& sql_state, int batch_line)
  166.     : CDB_Exception(eSQL, severity, err_code, originated_from, msg)
  167. {
  168.     static const string s_UnknownSqlState = "Unknown";
  169.     m_SqlState  = sql_state.empty() ? s_UnknownSqlState : sql_state;
  170.     m_BatchLine = batch_line;
  171. }
  172. CDB_SQLEx::~CDB_SQLEx() throw()
  173. {
  174.     return;
  175. }
  176. const char* CDB_SQLEx::TypeString() const
  177. {
  178.     return "SQL";
  179. }
  180. CDB_Exception* CDB_SQLEx::Clone() const
  181. {
  182.     return new CDB_SQLEx
  183.         (m_Severity, m_ErrCode, m_OriginatedFrom, m_Message,
  184.          m_SqlState, m_BatchLine);
  185. }
  186. void CDB_SQLEx::x_ComposeWhat(void) const
  187. {
  188.     x_StartOfWhat(&m_What);
  189.     m_What += "Procedure '";
  190.     m_What += SqlState();
  191.     m_What += "', Line ";
  192.     m_What += NStr::IntToString(BatchLine());
  193.     x_EndOfWhat(&m_What);
  194. }
  195. /////////////////////////////////////////////////////////////////////////////
  196. //  CDB_DeadlockEx::
  197. //
  198. const char* CDB_DeadlockEx::TypeString() const
  199. {
  200.     return "Deadlock";
  201. }
  202. CDB_Exception* CDB_DeadlockEx::Clone() const
  203. {
  204.     return new CDB_DeadlockEx
  205.         (m_OriginatedFrom, m_Message);
  206. }
  207. /////////////////////////////////////////////////////////////////////////////
  208. //  CDB_TimeoutEx::
  209. //
  210. const char* CDB_TimeoutEx::TypeString() const
  211. {
  212.     return "Timeout";
  213. }
  214. CDB_Exception* CDB_TimeoutEx::Clone() const
  215. {
  216.     return new CDB_TimeoutEx
  217.         (m_ErrCode, m_OriginatedFrom, m_Message);
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. //  CDB_ClientEx::
  221. //
  222. const char* CDB_ClientEx::TypeString() const
  223. {
  224.     return "Client";
  225. }
  226. CDB_Exception* CDB_ClientEx::Clone() const
  227. {
  228.     return
  229.         new CDB_ClientEx
  230.         (m_Severity, m_ErrCode, m_OriginatedFrom, m_Message);
  231. }
  232. /////////////////////////////////////////////////////////////////////////////
  233. //  CDB_MultiEx::
  234. //
  235. CDB_MultiEx::CDB_MultiEx(const string& originated_from, unsigned int capacity)
  236.     : CDB_Exception(eMulti, eDB_Unknown, 0, originated_from, kEmptyStr)
  237. {
  238.     m_Bag = new CDB_MultiExStorage(capacity);
  239. }
  240. CDB_MultiEx::CDB_MultiEx(const CDB_MultiEx& mex) :
  241.     CDB_Exception(eMulti, eDB_Unknown, 0, mex.m_OriginatedFrom, mex.m_Message)
  242. {
  243.     m_Bag = mex.m_Bag;
  244.     m_Bag->AddRef();
  245. }
  246. CDB_MultiEx::~CDB_MultiEx() throw()
  247. {
  248.     m_Bag->DelRef();
  249. }
  250. const char* CDB_MultiEx::TypeString() const
  251. {
  252.     return "MultiException";
  253. }
  254. CDB_Exception* CDB_MultiEx::Clone() const
  255. {
  256.     return new CDB_MultiEx(*this);
  257. }
  258. string CDB_MultiEx::WhatThis(void) const
  259. {
  260.     string str;
  261.     str += "---  [Multi-Exception in ";
  262.     str += OriginatedFrom();
  263.     str += "]   Contains a backtrace of ";
  264.     str += NStr::UIntToString( NofExceptions() );
  265.     str += " exceptions  ---";
  266.     return str;
  267. }
  268. void CDB_MultiEx::x_ComposeWhat(void) const
  269. {
  270.     m_What  = WhatThis();
  271.     m_What += Endl();
  272.     m_What += m_Bag->What();
  273.     m_What += Endl();
  274.     m_What += "---  [Multi-Exception]  End of backtrace  ---";
  275. }
  276. /////////////////////////////////////////////////////////////////////////////
  277. //  CDB_MultiEx::CDB_MultiExStorage::
  278. //
  279. CDB_MultiEx::CDB_MultiExStorage::CDB_MultiExStorage(unsigned int capacity)
  280. {
  281.     m_NofRooms = capacity;
  282.     m_NofExs   = 0;
  283.     m_RefCnt   = 0;
  284.     m_Ex       = new CDB_Exception* [m_NofRooms];
  285. }
  286. string CDB_MultiEx::CDB_MultiExStorage::What()
  287. {
  288.     string str;
  289.     if (m_NofExs == 0)
  290.         return str;
  291.     if (m_NofExs > m_NofRooms) {
  292.         str += " *** Too many exceptions -- the last ";
  293.         str += NStr::UIntToString(m_NofExs - m_NofRooms);
  294.         str += " exceptions are not shown ***";
  295.     }
  296.     
  297.     for (size_t i = 0;  i < min(m_NofExs, m_NofRooms);  i++) {
  298.         str += Endl();
  299.         str += "  ";
  300.         str += m_Ex[i]->what();
  301.     }
  302.     return str;
  303. }
  304. bool CDB_MultiEx::CDB_MultiExStorage::Push(const CDB_Exception* ex)
  305. {
  306.     if (ex->Type() == eMulti) { // this is a multi exception
  307.         CDB_MultiEx& mex =
  308.             const_cast<CDB_MultiEx&> (dynamic_cast<const CDB_MultiEx&> (*ex));
  309.         for (CDB_Exception* pex = mex.Pop();  pex;  pex = mex.Pop()) {
  310.             if (m_NofExs < m_NofRooms) {
  311.                 m_Ex[m_NofExs] = pex;
  312.             }
  313.             else {
  314.                 delete pex;
  315.             }
  316.             ++m_NofExs;
  317.         }
  318.     }
  319.     else { // this is an ordinary exception
  320.         if (m_NofExs < m_NofRooms) {
  321.             m_Ex[m_NofExs] = ex->Clone();
  322.         }
  323.         ++m_NofExs;
  324.     }
  325.     return (m_NofExs <= m_NofRooms);
  326. }
  327. CDB_Exception* CDB_MultiEx::CDB_MultiExStorage::Pop(void)
  328. {
  329.     if (m_NofExs == 0)
  330.         return 0;
  331.     if (m_NofExs > m_NofRooms) {
  332.         CDB_ClientEx* pex = new CDB_ClientEx
  333.             (eDB_Warning, m_NofExs,
  334.              "CDB_MultiEx::CDB_MultiExStorage",
  335.              "Too many exceptions. The error code shows the count.");
  336.         m_NofExs = m_NofRooms;
  337.         return pex;
  338.     }
  339.     return m_Ex[--m_NofExs];
  340. }
  341. CDB_MultiEx::CDB_MultiExStorage::~CDB_MultiExStorage()
  342. {
  343.     if (m_NofExs > m_NofRooms) {
  344.         m_NofExs = m_NofRooms;
  345.     }
  346.     while (m_NofExs != 0) {
  347.         delete m_Ex[--m_NofExs];
  348.     }
  349.     delete [] m_Ex;
  350. }
  351. /////////////////////////////////////////////////////////////////////////////
  352. //  CDB_UserHandler_Wrapper::  wrapper for the actual current handler
  353. //
  354. //    NOTE:  it is a singleton
  355. //
  356. class CDB_UserHandler_Wrapper : public CDB_UserHandler
  357. {
  358. public:
  359.     CDB_UserHandler* Set(CDB_UserHandler* h);
  360.     virtual bool HandleIt(CDB_Exception* ex);
  361.     virtual ~CDB_UserHandler_Wrapper();
  362. private:
  363.     CDB_UserHandler* m_Handler; 
  364. };
  365. static CDB_UserHandler_Wrapper s_CDB_DefUserHandler;  // (singleton)
  366. static bool                    s_CDB_DefUserHandler_IsSet = false;
  367. CDB_UserHandler* CDB_UserHandler_Wrapper::Set(CDB_UserHandler* h)
  368. {
  369.     if (h == this) {
  370.         throw runtime_error("CDB_UserHandler_Wrapper::Reset() -- attempt "
  371.                             "to set handle wrapper as a handler");
  372.     }
  373.     CDB_UserHandler* prev_h = m_Handler;
  374.     m_Handler = h;
  375.     return prev_h;
  376. }
  377. CDB_UserHandler_Wrapper::~CDB_UserHandler_Wrapper()
  378. {
  379.     delete m_Handler;
  380.     m_Handler = 0;
  381.     s_CDB_DefUserHandler_IsSet = false;
  382. }
  383. bool CDB_UserHandler_Wrapper::HandleIt(CDB_Exception* ex)
  384. {
  385.     return m_Handler ? m_Handler->HandleIt(ex) : true;
  386. }
  387. /////////////////////////////////////////////////////////////////////////////
  388. //  CDB_UserHandler::
  389. //
  390. CDB_UserHandler::~CDB_UserHandler()
  391. {
  392.     return;
  393. }
  394. //
  395. // ATTENTION:  Should you change the following static methods, please make sure
  396. //             to rebuild all DLLs which have this code statically linked in!
  397. //
  398. CDB_UserHandler& CDB_UserHandler::GetDefault(void)
  399. {
  400.     if ( !s_CDB_DefUserHandler_IsSet ) {
  401.         s_CDB_DefUserHandler_IsSet = true;
  402.         s_CDB_DefUserHandler.Set(new CDB_UserHandler_Default);
  403.     }
  404.     return s_CDB_DefUserHandler;
  405. }
  406. CDB_UserHandler* CDB_UserHandler::SetDefault(CDB_UserHandler* h)
  407. {
  408.     s_CDB_DefUserHandler_IsSet = true;
  409.     return s_CDB_DefUserHandler.Set(h);
  410. }
  411. /////////////////////////////////////////////////////////////////////////////
  412. //  CDB_UserHandler_Diag::
  413. //
  414. CDB_UserHandler_Diag::CDB_UserHandler_Diag(const string& prefix)
  415.     : m_Prefix(prefix)
  416. {
  417.     return;
  418. }
  419. CDB_UserHandler_Diag::~CDB_UserHandler_Diag()
  420. {
  421.     m_Prefix.erase();
  422. }
  423. bool CDB_UserHandler_Diag::HandleIt(CDB_Exception* ex)
  424. {
  425.     if ( !ex )
  426.         return true;
  427.         
  428.     if ( m_Prefix.empty() ) {
  429.         LOG_POST( ex->what() );
  430.     } else {
  431.         LOG_POST(m_Prefix << ' ' << ex->what());
  432.     } 
  433.     return true;
  434. }
  435. /////////////////////////////////////////////////////////////////////////////
  436. //  CDB_UserHandler_Stream::
  437. //
  438. CDB_UserHandler_Stream::CDB_UserHandler_Stream(ostream*      os,
  439.                                                const string& prefix,
  440.                                                bool          own_os)
  441.     : m_Output(os ? os : &cerr),
  442.       m_Prefix(prefix),
  443.       m_OwnOutput(own_os)
  444. {
  445.     if (m_OwnOutput  &&  (m_Output == &cerr  ||  m_Output == &cout)) {
  446.         m_OwnOutput = false;
  447.     }
  448. }
  449. CDB_UserHandler_Stream::~CDB_UserHandler_Stream()
  450. {
  451.     if ( m_OwnOutput ) {
  452.         delete m_Output;
  453.         m_OwnOutput = false;
  454.         m_Output = 0;
  455.     }
  456.     m_Prefix.erase();
  457. }
  458. bool CDB_UserHandler_Stream::HandleIt(CDB_Exception* ex)
  459. {
  460.     if ( !ex )
  461.         return true;
  462.     if ( !m_Output )
  463.         return false;
  464.     if ( !m_Prefix.empty() ) {
  465.         *m_Output << m_Prefix << ' ';
  466.     }
  467.     *m_Output << ex->what();
  468.     *m_Output << endl;
  469.     return m_Output->good();
  470. }
  471. END_NCBI_SCOPE
  472. /*
  473.  * ===========================================================================
  474.  * $Log: exception.cpp,v $
  475.  * Revision 1000.2  2004/06/01 19:19:05  gouriano
  476.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  477.  *
  478.  * Revision 1.12  2004/05/17 21:11:38  gorelenk
  479.  * Added include of PCH ncbi_pch.hpp
  480.  *
  481.  * Revision 1.11  2003/11/04 22:22:01  vakatov
  482.  * Factorize the code (especially the reporting one) through better inheritance.
  483.  * +CDB_Exception::TypeString()
  484.  * CDB_MultiEx to become more CDB_Exception-like.
  485.  * Improve the user-defined handlers' API, add CDB_UserHandler_Diag.
  486.  *
  487.  * Revision 1.8  2002/09/04 21:46:12  vakatov
  488.  * Added missing 'const' to CDB_Exception::SeverityString()
  489.  *
  490.  * Revision 1.7  2001/11/06 17:59:53  lavr
  491.  * Formatted uniformly as the rest of the library
  492.  *
  493.  * Revision 1.6  2001/10/04 20:26:45  vakatov
  494.  * Added missing virtual destructors to CDB_RPCEx and CDB_SQLEx
  495.  *
  496.  * Revision 1.5  2001/10/01 20:09:29  vakatov
  497.  * Introduced a generic default user error handler and the means to
  498.  * alternate it. Added an auxiliary error handler class
  499.  * "CDB_UserHandler_Stream".
  500.  * Moved "{Push/Pop}{Cntx/Conn}MsgHandler()" to the generic code
  501.  * (in I_DriverContext).
  502.  *
  503.  * Revision 1.4  2001/09/28 16:37:34  vakatov
  504.  * Added missing "throw()" to exception classes derived from "std::exception"
  505.  *
  506.  * Revision 1.3  2001/09/27 20:08:32  vakatov
  507.  * Added "DB_" (or "I_") prefix where it was missing
  508.  *
  509.  * Revision 1.2  2001/09/24 19:18:38  vakatov
  510.  * Fixed a couple of typos
  511.  *
  512.  * Revision 1.1  2001/09/21 23:39:59  vakatov
  513.  * -----  Initial (draft) revision.  -----
  514.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  515.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  516.  * The revamp involved massive code shuffling and grooming, numerous local
  517.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  518.  *
  519.  * ===========================================================================
  520.  */