|
MongoDB
1.8.5
|
00001 // assert_util.h 00002 00003 /* Copyright 2009 10gen Inc. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 00019 #pragma once 00020 00021 #include "../db/lasterror.h" 00022 00023 namespace mongo { 00024 00025 enum CommonErrorCodes { 00026 DatabaseDifferCaseCode = 13297 , 00027 StaleConfigInContextCode = 13388 00028 }; 00029 00030 class AssertionCount { 00031 public: 00032 AssertionCount(); 00033 void rollover(); 00034 void condrollover( int newValue ); 00035 00036 int regular; 00037 int warning; 00038 int msg; 00039 int user; 00040 int rollovers; 00041 }; 00042 00043 extern AssertionCount assertionCount; 00044 00045 struct ExceptionInfo { 00046 ExceptionInfo() : msg(""),code(-1) {} 00047 ExceptionInfo( const char * m , int c ) 00048 : msg( m ) , code( c ) { 00049 } 00050 ExceptionInfo( const string& m , int c ) 00051 : msg( m ) , code( c ) { 00052 } 00053 void append( BSONObjBuilder& b , const char * m = "$err" , const char * c = "code" ) const ; 00054 string toString() const { stringstream ss; ss << "exception: " << code << " " << msg; return ss.str(); } 00055 bool empty() const { return msg.empty(); } 00056 00057 string msg; 00058 int code; 00059 }; 00060 00061 class DBException : public std::exception { 00062 public: 00063 DBException( const ExceptionInfo& ei ) : _ei(ei) {} 00064 DBException( const char * msg , int code ) : _ei(msg,code) {} 00065 DBException( const string& msg , int code ) : _ei(msg,code) {} 00066 virtual ~DBException() throw() { } 00067 00068 virtual const char* what() const throw() { return _ei.msg.c_str(); } 00069 virtual int getCode() const { return _ei.code; } 00070 00071 virtual void appendPrefix( stringstream& ss ) const { } 00072 00073 virtual string toString() const { 00074 stringstream ss; ss << getCode() << " " << what(); return ss.str(); 00075 return ss.str(); 00076 } 00077 00078 const ExceptionInfo& getInfo() const { return _ei; } 00079 00080 protected: 00081 ExceptionInfo _ei; 00082 }; 00083 00084 class AssertionException : public DBException { 00085 public: 00086 00087 AssertionException( const ExceptionInfo& ei ) : DBException(ei) {} 00088 AssertionException( const char * msg , int code ) : DBException(msg,code) {} 00089 AssertionException( const string& msg , int code ) : DBException(msg,code) {} 00090 00091 virtual ~AssertionException() throw() { } 00092 00093 virtual bool severe() { return true; } 00094 virtual bool isUserAssertion() { return false; } 00095 00096 /* true if an interrupted exception - see KillCurrentOp */ 00097 bool interrupted() { 00098 return _ei.code == 11600 || _ei.code == 11601; 00099 } 00100 }; 00101 00102 /* UserExceptions are valid errors that a user can cause, like out of disk space or duplicate key */ 00103 class UserException : public AssertionException { 00104 public: 00105 UserException(int c , const string& m) : AssertionException( m , c ) {} 00106 00107 virtual bool severe() { return false; } 00108 virtual bool isUserAssertion() { return true; } 00109 virtual void appendPrefix( stringstream& ss ) const { ss << "userassert:"; } 00110 }; 00111 00112 class MsgAssertionException : public AssertionException { 00113 public: 00114 MsgAssertionException( const ExceptionInfo& ei ) : AssertionException( ei ) {} 00115 MsgAssertionException(int c, const string& m) : AssertionException( m , c ) {} 00116 virtual bool severe() { return false; } 00117 virtual void appendPrefix( stringstream& ss ) const { ss << "massert:"; } 00118 }; 00119 00120 00121 void asserted(const char *msg, const char *file, unsigned line); 00122 void wasserted(const char *msg, const char *file, unsigned line); 00123 00127 void uasserted(int msgid, const char *msg); 00128 inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_str()); } 00129 00131 void uassert_nothrow(const char *msg); 00132 00136 void msgassertedNoTrace(int msgid, const char *msg); 00137 inline void msgassertedNoTrace(int msgid, const string& msg) { msgassertedNoTrace( msgid , msg.c_str() ); } 00138 void msgasserted(int msgid, const char *msg); 00139 inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg.c_str()); } 00140 00141 #ifdef assert 00142 #undef assert 00143 #endif 00144 00145 #define MONGO_assert(_Expression) (void)( (!!(_Expression)) || (mongo::asserted(#_Expression, __FILE__, __LINE__), 0) ) 00146 #define assert MONGO_assert 00147 00148 /* "user assert". if asserts, user did something wrong, not our code */ 00149 #define MONGO_uassert(msgid, msg, expr) (void)( (!!(expr)) || (mongo::uasserted(msgid, msg), 0) ) 00150 #define uassert MONGO_uassert 00151 00152 /* warning only - keeps going */ 00153 #define MONGO_wassert(_Expression) (void)( (!!(_Expression)) || (mongo::wasserted(#_Expression, __FILE__, __LINE__), 0) ) 00154 #define wassert MONGO_wassert 00155 00156 /* display a message, no context, and throw assertionexception 00157 00158 easy way to throw an exception and log something without our stack trace 00159 display happening. 00160 */ 00161 #define MONGO_massert(msgid, msg, expr) (void)( (!!(expr)) || (mongo::msgasserted(msgid, msg), 0) ) 00162 #define massert MONGO_massert 00163 00164 /* dassert is 'debug assert' -- might want to turn off for production as these 00165 could be slow. 00166 */ 00167 #if defined(_DEBUG) 00168 # define MONGO_dassert assert 00169 #else 00170 # define MONGO_dassert(x) 00171 #endif 00172 #define dassert MONGO_dassert 00173 00174 // some special ids that we want to duplicate 00175 00176 // > 10000 asserts 00177 // < 10000 UserException 00178 00179 enum { ASSERT_ID_DUPKEY = 11000 }; 00180 00181 /* throws a uassertion with an appropriate msg */ 00182 void streamNotGood( int code , string msg , std::ios& myios ); 00183 00184 inline void assertStreamGood(unsigned msgid, string msg, std::ios& myios) { 00185 if( !myios.good() ) streamNotGood(msgid, msg, myios); 00186 } 00187 00188 string demangleName( const type_info& typeinfo ); 00189 00190 } // namespace mongo 00191 00192 #define BOOST_CHECK_EXCEPTION MONGO_BOOST_CHECK_EXCEPTION 00193 #define MONGO_BOOST_CHECK_EXCEPTION( expression ) \ 00194 try { \ 00195 expression; \ 00196 } catch ( const std::exception &e ) { \ 00197 stringstream ss; \ 00198 ss << "caught boost exception: " << e.what(); \ 00199 msgasserted( 13294 , ss.str() ); \ 00200 } catch ( ... ) { \ 00201 massert( 10437 , "unknown boost failed" , false ); \ 00202 } 00203 00204 #define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD 00205 #define MONGO_DESTRUCTOR_GUARD( expression ) \ 00206 try { \ 00207 expression; \ 00208 } catch ( const std::exception &e ) { \ 00209 problem() << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ << ")" << endl; \ 00210 } catch ( ... ) { \ 00211 problem() << "caught unknown exception in destructor (" << __FUNCTION__ << ")" << endl; \ 00212 }
1.7.5.1