MongoDB C++ Driver  legacy-1.0.5
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
assert_util.h
1 // assert_util.h
2 
3 /* Copyright 2009 10gen Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <typeinfo>
21 #include <string>
22 
23 #include "mongo/base/status.h" // NOTE: This is safe as utils depend on base
24 #include "mongo/client/export_macros.h"
25 #include "mongo/platform/compiler.h"
26 #include "mongo/logger/log_severity.h"
27 #include "mongo/logger/logger.h"
28 #include "mongo/logger/logstream_builder.h"
29 
30 namespace mongo {
31 
32  enum CommonErrorCodes {
33  OkCode = 0,
34  DatabaseDifferCaseCode = 13297 , // uassert( 13297 )
35  SendStaleConfigCode = 13388 , // uassert( 13388 )
36  RecvStaleConfigCode = 9996, // uassert( 9996 )
37  PrepareConfigsFailedCode = 13104, // uassert( 13104 )
38  NotMasterOrSecondaryCode = 13436, // uassert( 13436 )
39  NotMasterNoSlaveOkCode = 13435, // uassert( 13435 )
40  NotMaster = 10107, // uassert( 10107 )
41  };
42 
43  class BSONObjBuilder;
44 
45  struct MONGO_CLIENT_API ExceptionInfo {
46  ExceptionInfo() : msg(""),code(-1) {}
47  ExceptionInfo( const char * m , int c )
48  : msg( m ) , code( c ) {
49  }
50  ExceptionInfo( const std::string& m , int c )
51  : msg( m ) , code( c ) {
52  }
53  void append( BSONObjBuilder& b , const char * m = "$err" , const char * c = "code" ) const ;
54  std::string toString() const;
55  bool empty() const { return msg.empty(); }
56  void reset(){ msg = ""; code=-1; }
57  std::string msg;
58  int code;
59  };
60 
67  class MONGO_CLIENT_API ErrorMsg {
68  public:
69  ErrorMsg(const char *msg, char ch);
70  ErrorMsg(const char *msg, unsigned val);
71  operator std::string() const { return buf; }
72  private:
73  char buf[256];
74  };
75 
76  class DBException;
77  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const DBException& e );
78  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const std::string& e );
79 
81  class MONGO_CLIENT_API DBException : public std::exception {
82  public:
83  DBException( const ExceptionInfo& ei ) : _ei(ei) {}
84  DBException( const char * msg , int code ) : _ei(msg,code) {}
85  DBException( const std::string& msg , int code ) : _ei(msg,code) {}
86  virtual ~DBException() throw() { }
87 
88  virtual const char* what() const throw() { return _ei.msg.c_str(); }
89  virtual int getCode() const { return _ei.code; }
90  virtual void appendPrefix( std::stringstream& ss ) const { }
91  virtual void addContext( const std::string& str ) {
92  _ei.msg = str + causedBy( _ei.msg );
93  }
94 
95  // Utilities for the migration to Status objects
96  static ErrorCodes::Error MONGO_CLIENT_FUNC convertExceptionCode(int exCode);
97 
98  Status toStatus(const std::string& context) const {
99  return Status(convertExceptionCode(getCode()), context + causedBy(*this));
100  }
101  Status toStatus() const {
102  return Status(convertExceptionCode(getCode()), this->what());
103  }
104 
105  // context when applicable. otherwise ""
106  std::string _shard;
107 
108  virtual std::string toString() const;
109 
110  const ExceptionInfo& getInfo() const { return _ei; }
111 
112  protected:
113  ExceptionInfo _ei;
114  };
115 
116  class MONGO_CLIENT_API AssertionException : public DBException {
117  public:
118 
119  AssertionException( const ExceptionInfo& ei ) : DBException(ei) {}
120  AssertionException( const char * msg , int code ) : DBException(msg,code) {}
121  AssertionException( const std::string& msg , int code ) : DBException(msg,code) {}
122 
123  virtual ~AssertionException() throw() { }
124 
125  virtual bool severe() const { return true; }
126  virtual bool isUserAssertion() const { return false; }
127  };
128 
129  /* UserExceptions are valid errors that a user can cause, like out of disk space or duplicate key */
130  class MONGO_CLIENT_API UserException : public AssertionException {
131  public:
132  UserException(int c , const std::string& m) : AssertionException( m , c ) {}
133  virtual bool severe() const { return false; }
134  virtual bool isUserAssertion() const { return true; }
135  virtual void appendPrefix( std::stringstream& ss ) const;
136  };
137 
138  class MONGO_CLIENT_API MsgAssertionException : public AssertionException {
139  public:
141  MsgAssertionException(int c, const std::string& m) : AssertionException( m , c ) {}
142  virtual bool severe() const { return false; }
143  virtual void appendPrefix( std::stringstream& ss ) const;
144  };
145 
146  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC verifyFailed(const char *expr, const char *file, unsigned line);
147  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC invariantFailed(const char *expr, const char *file, unsigned line);
148  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC invariantOKFailed(const char *expr, const Status& status, const char *file, unsigned line);
149  MONGO_CLIENT_API void MONGO_CLIENT_FUNC wasserted(const char *expr, const char *file, unsigned line);
150  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC fassertFailed( int msgid );
151  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC fassertFailedWithStatus(
152  int msgid, const Status& status);
153  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC fassertFailedWithStatusNoTrace(
154  int msgid, const Status& status);
155 
159  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC uasserted(int msgid, const char *msg);
160  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC uasserted(int msgid , const std::string &msg);
161 
165  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC msgassertedNoTrace(int msgid, const char *msg);
166  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC msgassertedNoTrace(int msgid, const std::string &msg);
167  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC msgasserted(int msgid, const char *msg);
168  MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC msgasserted(int msgid, const std::string &msg);
169 
170  /* convert various types of exceptions to strings */
171  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const char* e );
172  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const DBException& e );
173  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const std::exception& e );
174  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const std::string& e );
175  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const std::string* e );
176  MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy( const Status& e );
177 
179  MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC fassert(int msgid, bool testOK) {
180  if (MONGO_unlikely(!testOK)) fassertFailed(msgid);
181  }
182 
183  MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC fassert(int msgid, const Status& status) {
184  if (MONGO_unlikely(!status.isOK())) {
185  fassertFailedWithStatus(msgid, status);
186  }
187  }
188 
189  MONGO_CLIENT_API inline void fassertNoTrace(int msgid, const Status& status) {
190  if (MONGO_unlikely(!status.isOK())) {
191  fassertFailedWithStatusNoTrace(msgid, status);
192  }
193  }
194 
195 
196  /* "user assert". if asserts, user did something wrong, not our code */
197 #define MONGO_uassert(msgid, msg, expr) do { \
198  if (MONGO_unlikely(!(expr))) { \
199  ::mongo::uasserted(msgid, msg); \
200  } \
201  } while (false)
202 
203  MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC uassertStatusOK(const Status& status) {
204  if (MONGO_unlikely(!status.isOK())) {
205  uasserted((status.location() != 0 ? status.location() : status.code()),
206  status.reason());
207  }
208  }
209 
210  /* warning only - keeps going */
211 #define MONGO_wassert(_Expression) do { \
212  if (MONGO_unlikely(!(_Expression))) { \
213  ::mongo::wasserted(#_Expression, __FILE__, __LINE__); \
214  } \
215  } while (false)
216 
217  /* display a message, no context, and throw assertionexception
218 
219  easy way to throw an exception and log something without our stack trace
220  display happening.
221  */
222 #define MONGO_massert(msgid, msg, expr) do { \
223  if (MONGO_unlikely(!(expr))) { \
224  ::mongo::msgasserted(msgid, msg); \
225  } \
226  } while (false)
227 
228  MONGO_CLIENT_API inline void massertStatusOK(const Status& status) {
229  if (MONGO_unlikely(!status.isOK())) {
230  msgasserted((status.location() != 0 ? status.location() : status.code()),
231  status.reason());
232  }
233  }
234 
235  MONGO_CLIENT_API inline void massertNoTraceStatusOK(const Status& status) {
236  if (MONGO_unlikely(!status.isOK())) {
237  msgassertedNoTrace((status.location() != 0 ? status.location() : status.code()),
238  status.reason());
239  }
240  }
241 
242  /* same as massert except no msgid */
243 #define MONGO_verify(_Expression) do { \
244  if (MONGO_unlikely(!(_Expression))) { \
245  ::mongo::verifyFailed(#_Expression, __FILE__, __LINE__); \
246  } \
247  } while (false)
248 
249 #define MONGO_invariant(_Expression) do { \
250  if (MONGO_unlikely(!(_Expression))) { \
251  ::mongo::invariantFailed(#_Expression, __FILE__, __LINE__); \
252  } \
253  } while (false)
254 
255 #define MONGO_invariantOK(expression) do { \
256  const ::mongo::Status _invariantOK_status = expression; \
257  if (MONGO_unlikely(!_invariantOK_status.isOK())) { \
258  ::mongo::invariantOKFailed(#expression, _invariantOK_status, __FILE__, __LINE__); \
259  } \
260  } while (false)
261 
262 #ifdef MONGO_EXPOSE_MACROS
263 # define verify(expression) MONGO_verify(expression)
264 # define invariant MONGO_invariant
265 # define invariantOK MONGO_invariantOK
266 # define uassert MONGO_uassert
267 # define wassert MONGO_wassert
268 # define massert MONGO_massert
269 #endif
270 
271  // some special ids that we want to duplicate
272 
273  // > 10000 asserts
274  // < 10000 UserException
275 
276  enum { ASSERT_ID_DUPKEY = 11000 };
277 
278  std::string demangleName( const std::type_info& typeinfo );
279 
280 } // namespace mongo
281 
282 #define MONGO_ASSERT_ON_EXCEPTION( expression ) \
283  try { \
284  expression; \
285  } catch ( const std::exception &e ) { \
286  std::stringstream ss; \
287  ss << "caught exception: " << e.what() << ' ' << __FILE__ << ' ' << __LINE__; \
288  msgasserted( 13294 , ss.str() ); \
289  } catch ( ... ) { \
290  massert( 10437 , "unknown exception" , false ); \
291  }
292 
293 #define MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( expression, msg ) \
294  try { \
295  expression; \
296  } catch ( const std::exception &e ) { \
297  std::stringstream ss; \
298  ss << msg << " caught exception exception: " << e.what(); \
299  msgasserted( 14043 , ss.str() ); \
300  } catch ( ... ) { \
301  msgasserted( 14044 , std::string("unknown exception") + msg ); \
302  }
303 
304 #define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD
305 #define MONGO_DESTRUCTOR_GUARD( expression ) \
306  try { \
307  expression; \
308  } catch ( const std::exception &e ) { \
309  ::mongo::logger::LogstreamBuilder(::mongo::logger::globalLogDomain(), \
310  std::string(), \
311  ::mongo::logger::LogSeverity::Log()) \
312  << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ \
313  << ")" << std::endl; \
314  } catch ( ... ) { \
315  ::mongo::logger::LogstreamBuilder(::mongo::logger::globalLogDomain(), \
316  std::string(), \
317  ::mongo::logger::LogSeverity::Log()) \
318  << "caught unknown exception in destructor (" << __FUNCTION__ << ")" \
319  << std::endl; \
320  }
321 
the main MongoDB namespace
Definition: bulk_operation_builder.h:24
Definition: assert_util.h:45
helper class that builds error strings.
Definition: assert_util.h:67
MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC uasserted(int msgid, const char *msg)
a "user assertion".
Utility for creating a BSONObj.
Definition: bsonobjbuilder.h:53
MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC msgassertedNoTrace(int msgid, const char *msg)
msgassert and massert are for errors that are internal but have a well defined error text std::string...
Definition: assert_util.h:116
MONGO_CLIENT_API void MONGO_CLIENT_FUNC fassert(int msgid, bool testOK)
aborts on condition failure
Definition: assert_util.h:179
Definition: assert_util.h:130
Most mongo exceptions inherit from this; this is commonly caught in most threads. ...
Definition: assert_util.h:81
MONGO_CLIENT_API Status(MONGO_CLIENT_FUNC *saslClientAuthenticate)(DBClientWithCommands *client
Attempts to authenticate "client" using the SASL protocol.
Definition: assert_util.h:138