|
MongoDB
2.0.3
|
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 // MONGO_NORETURN undefed at end of file 00024 #ifdef __GNUC__ 00025 # define MONGO_NORETURN __attribute__((__noreturn__)) 00026 #else 00027 # define MONGO_NORETURN 00028 #endif 00029 00030 namespace mongo { 00031 00032 enum CommonErrorCodes { 00033 DatabaseDifferCaseCode = 13297 , 00034 StaleConfigInContextCode = 13388 00035 }; 00036 00037 class AssertionCount { 00038 public: 00039 AssertionCount(); 00040 void rollover(); 00041 void condrollover( int newValue ); 00042 00043 int regular; 00044 int warning; 00045 int msg; 00046 int user; 00047 int rollovers; 00048 }; 00049 00050 extern AssertionCount assertionCount; 00051 00052 struct ExceptionInfo { 00053 ExceptionInfo() : msg(""),code(-1) {} 00054 ExceptionInfo( const char * m , int c ) 00055 : msg( m ) , code( c ) { 00056 } 00057 ExceptionInfo( const string& m , int c ) 00058 : msg( m ) , code( c ) { 00059 } 00060 void append( BSONObjBuilder& b , const char * m = "$err" , const char * c = "code" ) const ; 00061 string toString() const { stringstream ss; ss << "exception: " << code << " " << msg; return ss.str(); } 00062 bool empty() const { return msg.empty(); } 00063 00064 void reset(){ msg = ""; code=-1; } 00065 00066 string msg; 00067 int code; 00068 }; 00069 00076 class ErrorMsg { 00077 public: 00078 ErrorMsg(const char *msg, char ch); 00079 ErrorMsg(const char *msg, unsigned val); 00080 operator string() const { return buf; } 00081 private: 00082 char buf[256]; 00083 }; 00084 00085 class DBException : public std::exception { 00086 public: 00087 DBException( const ExceptionInfo& ei ) : _ei(ei) {} 00088 DBException( const char * msg , int code ) : _ei(msg,code) {} 00089 DBException( const string& msg , int code ) : _ei(msg,code) {} 00090 virtual ~DBException() throw() { } 00091 00092 virtual const char* what() const throw() { return _ei.msg.c_str(); } 00093 virtual int getCode() const { return _ei.code; } 00094 00095 virtual void appendPrefix( stringstream& ss ) const { } 00096 00097 virtual string toString() const { 00098 stringstream ss; ss << getCode() << " " << what(); return ss.str(); 00099 return ss.str(); 00100 } 00101 00102 const ExceptionInfo& getInfo() const { return _ei; } 00103 00104 protected: 00105 ExceptionInfo _ei; 00106 }; 00107 00108 class AssertionException : public DBException { 00109 public: 00110 00111 AssertionException( const ExceptionInfo& ei ) : DBException(ei) {} 00112 AssertionException( const char * msg , int code ) : DBException(msg,code) {} 00113 AssertionException( const string& msg , int code ) : DBException(msg,code) {} 00114 00115 virtual ~AssertionException() throw() { } 00116 00117 virtual bool severe() { return true; } 00118 virtual bool isUserAssertion() { return false; } 00119 00120 /* true if an interrupted exception - see KillCurrentOp */ 00121 bool interrupted() { 00122 return _ei.code == 11600 || _ei.code == 11601; 00123 } 00124 }; 00125 00126 /* UserExceptions are valid errors that a user can cause, like out of disk space or duplicate key */ 00127 class UserException : public AssertionException { 00128 public: 00129 UserException(int c , const string& m) : AssertionException( m , c ) {} 00130 00131 virtual bool severe() { return false; } 00132 virtual bool isUserAssertion() { return true; } 00133 virtual void appendPrefix( stringstream& ss ) const { ss << "userassert:"; } 00134 }; 00135 00136 class MsgAssertionException : public AssertionException { 00137 public: 00138 MsgAssertionException( const ExceptionInfo& ei ) : AssertionException( ei ) {} 00139 MsgAssertionException(int c, const string& m) : AssertionException( m , c ) {} 00140 virtual bool severe() { return false; } 00141 virtual void appendPrefix( stringstream& ss ) const { ss << "massert:"; } 00142 }; 00143 00144 void asserted(const char *msg, const char *file, unsigned line) MONGO_NORETURN; 00145 void wasserted(const char *msg, const char *file, unsigned line); 00146 void verifyFailed( int msgid ); 00147 00151 void uasserted(int msgid, const char *msg) MONGO_NORETURN; 00152 inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_str()); } 00153 00155 void uassert_nothrow(const char *msg); 00156 00160 void msgassertedNoTrace(int msgid, const char *msg) MONGO_NORETURN; 00161 inline void msgassertedNoTrace(int msgid, const string& msg) { msgassertedNoTrace( msgid , msg.c_str() ); } 00162 void msgasserted(int msgid, const char *msg) MONGO_NORETURN; 00163 inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg.c_str()); } 00164 00165 /* convert various types of exceptions to strings */ 00166 inline string causedBy( const char* e ){ return (string)" :: caused by :: " + e; } 00167 inline string causedBy( const DBException& e ){ return causedBy( e.toString().c_str() ); } 00168 inline string causedBy( const std::exception& e ){ return causedBy( e.what() ); } 00169 inline string causedBy( const string& e ){ return causedBy( e.c_str() ); } 00170 00172 inline void verify( int msgid , bool testOK ) { if ( ! testOK ) verifyFailed( msgid ); } 00173 00174 #ifdef assert 00175 #undef assert 00176 #endif 00177 00178 #define MONGO_assert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::asserted(#_Expression, __FILE__, __LINE__), 0) ) 00179 #define assert MONGO_assert 00180 00181 /* "user assert". if asserts, user did something wrong, not our code */ 00182 #define MONGO_uassert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || (mongo::uasserted(msgid, msg), 0) ) 00183 #define uassert MONGO_uassert 00184 00185 /* warning only - keeps going */ 00186 #define MONGO_wassert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::wasserted(#_Expression, __FILE__, __LINE__), 0) ) 00187 #define wassert MONGO_wassert 00188 00189 /* display a message, no context, and throw assertionexception 00190 00191 easy way to throw an exception and log something without our stack trace 00192 display happening. 00193 */ 00194 #define MONGO_massert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || (mongo::msgasserted(msgid, msg), 0) ) 00195 #define massert MONGO_massert 00196 00197 /* dassert is 'debug assert' -- might want to turn off for production as these 00198 could be slow. 00199 */ 00200 #if defined(_DEBUG) 00201 # define MONGO_dassert assert 00202 #else 00203 # define MONGO_dassert(x) 00204 #endif 00205 #define dassert MONGO_dassert 00206 00207 // some special ids that we want to duplicate 00208 00209 // > 10000 asserts 00210 // < 10000 UserException 00211 00212 enum { ASSERT_ID_DUPKEY = 11000 }; 00213 00214 /* throws a uassertion with an appropriate msg */ 00215 void streamNotGood( int code , string msg , std::ios& myios ) MONGO_NORETURN; 00216 00217 inline void assertStreamGood(unsigned msgid, string msg, std::ios& myios) { 00218 if( !myios.good() ) streamNotGood(msgid, msg, myios); 00219 } 00220 00221 string demangleName( const type_info& typeinfo ); 00222 00223 } // namespace mongo 00224 00225 #define BOOST_CHECK_EXCEPTION MONGO_BOOST_CHECK_EXCEPTION 00226 #define MONGO_BOOST_CHECK_EXCEPTION( expression ) \ 00227 try { \ 00228 expression; \ 00229 } catch ( const std::exception &e ) { \ 00230 stringstream ss; \ 00231 ss << "caught boost exception: " << e.what() << ' ' << __FILE__ << ' ' << __LINE__; \ 00232 msgasserted( 13294 , ss.str() ); \ 00233 } catch ( ... ) { \ 00234 massert( 10437 , "unknown boost failed" , false ); \ 00235 } 00236 00237 #define MONGO_BOOST_CHECK_EXCEPTION_WITH_MSG( expression, msg ) \ 00238 try { \ 00239 expression; \ 00240 } catch ( const std::exception &e ) { \ 00241 stringstream ss; \ 00242 ss << msg << " caught boost exception: " << e.what(); \ 00243 msgasserted( 14043 , ss.str() ); \ 00244 } catch ( ... ) { \ 00245 msgasserted( 14044 , string("unknown boost failed ") + msg ); \ 00246 } 00247 00248 #define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD 00249 #define MONGO_DESTRUCTOR_GUARD( expression ) \ 00250 try { \ 00251 expression; \ 00252 } catch ( const std::exception &e ) { \ 00253 problem() << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ << ")" << endl; \ 00254 } catch ( ... ) { \ 00255 problem() << "caught unknown exception in destructor (" << __FUNCTION__ << ")" << endl; \ 00256 } 00257 00258 #undef MONGO_NORETURN
1.8.0