MongoDB C++ Driver legacy-1.1.2
Loading...
Searching...
No Matches
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
30namespace mongo {
31
32enum 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
43class BSONObjBuilder;
44
45struct MONGO_CLIENT_API ExceptionInfo {
46 ExceptionInfo() : msg(""), code(-1) {}
47 ExceptionInfo(const char* m, int c) : msg(m), code(c) {}
48 ExceptionInfo(const std::string& m, int c) : msg(m), code(c) {}
49 void append(BSONObjBuilder& b, const char* m = "$err", const char* c = "code") const;
50 std::string toString() const;
51 bool empty() const {
52 return msg.empty();
53 }
54 void reset() {
55 msg = "";
56 code = -1;
57 }
58 std::string msg;
59 int code;
60};
61
70class MONGO_CLIENT_API ErrorMsg {
71public:
72 ErrorMsg(const char* msg, char ch);
73 ErrorMsg(const char* msg, unsigned val);
74 operator std::string() const {
75 return buf;
76 }
77
78private:
79 char buf[256];
80};
81
82class DBException;
83MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const DBException& e);
84MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const std::string& e);
85
87class MONGO_CLIENT_API DBException : public std::exception {
88public:
89 DBException(const ExceptionInfo& ei) : _ei(ei) {}
90 DBException(const char* msg, int code) : _ei(msg, code) {}
91 DBException(const std::string& msg, int code) : _ei(msg, code) {}
92 virtual ~DBException() throw() {}
93
94 virtual const char* what() const throw() {
95 return _ei.msg.c_str();
96 }
97 virtual int getCode() const {
98 return _ei.code;
99 }
100 virtual void appendPrefix(std::stringstream& ss) const {}
101 virtual void addContext(const std::string& str) {
102 _ei.msg = str + causedBy(_ei.msg);
103 }
104
105 // Utilities for the migration to Status objects
106 static ErrorCodes::Error MONGO_CLIENT_FUNC convertExceptionCode(int exCode);
107
108 Status toStatus(const std::string& context) const {
109 return Status(convertExceptionCode(getCode()), context + causedBy(*this));
110 }
111 Status toStatus() const {
112 return Status(convertExceptionCode(getCode()), this->what());
113 }
114
115 // context when applicable. otherwise ""
116 std::string _shard;
117
118 virtual std::string toString() const;
119
120 const ExceptionInfo& getInfo() const {
121 return _ei;
122 }
123
124protected:
125 ExceptionInfo _ei;
126};
127
128class MONGO_CLIENT_API AssertionException : public DBException {
129public:
131 AssertionException(const char* msg, int code) : DBException(msg, code) {}
132 AssertionException(const std::string& msg, int code) : DBException(msg, code) {}
133
134 virtual ~AssertionException() throw() {}
135
136 virtual bool severe() const {
137 return true;
138 }
139 virtual bool isUserAssertion() const {
140 return false;
141 }
142};
143
144/* UserExceptions are valid errors that a user can cause, like out of disk space or duplicate key */
145class MONGO_CLIENT_API UserException : public AssertionException {
146public:
147 UserException(int c, const std::string& m) : AssertionException(m, c) {}
148 virtual bool severe() const {
149 return false;
150 }
151 virtual bool isUserAssertion() const {
152 return true;
153 }
154 virtual void appendPrefix(std::stringstream& ss) const;
155};
156
157class MONGO_CLIENT_API MsgAssertionException : public AssertionException {
158public:
160 MsgAssertionException(int c, const std::string& m) : AssertionException(m, c) {}
161 virtual bool severe() const {
162 return false;
163 }
164 virtual void appendPrefix(std::stringstream& ss) const;
165};
166
167MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
168verifyFailed(const char* expr, const char* file, unsigned line);
169MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
170invariantFailed(const char* expr, const char* file, unsigned line);
171MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
172invariantOKFailed(const char* expr, const Status& status, const char* file, unsigned line);
173MONGO_CLIENT_API void MONGO_CLIENT_FUNC
174wasserted(const char* expr, const char* file, unsigned line);
175MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC fassertFailed(int msgid);
176MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
177fassertFailedWithStatus(int msgid, const Status& status);
178MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
179fassertFailedWithStatusNoTrace(int msgid, const Status& status);
180
184MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
185uasserted(int msgid, const char* msg);
186MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
187uasserted(int msgid, const std::string& msg);
188
192MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
193msgassertedNoTrace(int msgid, const char* msg);
194MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
195msgassertedNoTrace(int msgid, const std::string& msg);
196MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
197msgasserted(int msgid, const char* msg);
198MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC
199msgasserted(int msgid, const std::string& msg);
200
201/* convert various types of exceptions to strings */
202MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const char* e);
203MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const DBException& e);
204MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const std::exception& e);
205MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const std::string& e);
206MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const std::string* e);
207MONGO_CLIENT_API std::string MONGO_CLIENT_FUNC causedBy(const Status& e);
208
210MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC fassert(int msgid, bool testOK) {
211 if (MONGO_unlikely(!testOK))
212 fassertFailed(msgid);
213}
214
215MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC fassert(int msgid, const Status& status) {
216 if (MONGO_unlikely(!status.isOK())) {
217 fassertFailedWithStatus(msgid, status);
218 }
219}
220
221MONGO_CLIENT_API inline void fassertNoTrace(int msgid, const Status& status) {
222 if (MONGO_unlikely(!status.isOK())) {
223 fassertFailedWithStatusNoTrace(msgid, status);
224 }
225}
226
227
228/* "user assert". if asserts, user did something wrong, not our code */
229#define MONGO_uassert(msgid, msg, expr) \
230 do { \
231 if (MONGO_unlikely(!(expr))) { \
232 ::mongo::uasserted(msgid, msg); \
233 } \
234 } while (false)
235
236MONGO_CLIENT_API inline void MONGO_CLIENT_FUNC uassertStatusOK(const Status& status) {
237 if (MONGO_unlikely(!status.isOK())) {
238 uasserted((status.location() != 0 ? status.location() : status.code()), status.reason());
239 }
240}
241
242/* warning only - keeps going */
243#define MONGO_wassert(_Expression) \
244 do { \
245 if (MONGO_unlikely(!(_Expression))) { \
246 ::mongo::wasserted(#_Expression, __FILE__, __LINE__); \
247 } \
248 } while (false)
249
250/* display a message, no context, and throw assertionexception
251
252 easy way to throw an exception and log something without our stack trace
253 display happening.
254*/
255#define MONGO_massert(msgid, msg, expr) \
256 do { \
257 if (MONGO_unlikely(!(expr))) { \
258 ::mongo::msgasserted(msgid, msg); \
259 } \
260 } while (false)
261
262MONGO_CLIENT_API inline void massertStatusOK(const Status& status) {
263 if (MONGO_unlikely(!status.isOK())) {
264 msgasserted((status.location() != 0 ? status.location() : status.code()), status.reason());
265 }
266}
267
268MONGO_CLIENT_API inline void massertNoTraceStatusOK(const Status& status) {
269 if (MONGO_unlikely(!status.isOK())) {
270 msgassertedNoTrace((status.location() != 0 ? status.location() : status.code()),
271 status.reason());
272 }
273}
274
275/* same as massert except no msgid */
276#define MONGO_verify(_Expression) \
277 do { \
278 if (MONGO_unlikely(!(_Expression))) { \
279 ::mongo::verifyFailed(#_Expression, __FILE__, __LINE__); \
280 } \
281 } while (false)
282
283#define MONGO_invariant(_Expression) \
284 do { \
285 if (MONGO_unlikely(!(_Expression))) { \
286 ::mongo::invariantFailed(#_Expression, __FILE__, __LINE__); \
287 } \
288 } while (false)
289
290#define MONGO_invariantOK(expression) \
291 do { \
292 const ::mongo::Status _invariantOK_status = expression; \
293 if (MONGO_unlikely(!_invariantOK_status.isOK())) { \
294 ::mongo::invariantOKFailed(#expression, _invariantOK_status, __FILE__, __LINE__); \
295 } \
296 } while (false)
297
298#ifdef MONGO_EXPOSE_MACROS
299#define verify(expression) MONGO_verify(expression)
300#define invariant MONGO_invariant
301#define invariantOK MONGO_invariantOK
302#define uassert MONGO_uassert
303#define wassert MONGO_wassert
304#define massert MONGO_massert
305#endif
306
307// some special ids that we want to duplicate
308
309// > 10000 asserts
310// < 10000 UserException
311
312enum { ASSERT_ID_DUPKEY = 11000 };
313
314std::string demangleName(const std::type_info& typeinfo);
315
316} // namespace mongo
317
318#define MONGO_ASSERT_ON_EXCEPTION(expression) \
319 try { \
320 expression; \
321 } catch (const std::exception& e) { \
322 std::stringstream ss; \
323 ss << "caught exception: " << e.what() << ' ' << __FILE__ << ' ' << __LINE__; \
324 msgasserted(13294, ss.str()); \
325 } catch (...) { \
326 massert(10437, "unknown exception", false); \
327 }
328
329#define MONGO_ASSERT_ON_EXCEPTION_WITH_MSG(expression, msg) \
330 try { \
331 expression; \
332 } catch (const std::exception& e) { \
333 std::stringstream ss; \
334 ss << msg << " caught exception exception: " << e.what(); \
335 msgasserted(14043, ss.str()); \
336 } catch (...) { \
337 msgasserted(14044, std::string("unknown exception") + msg); \
338 }
339
340#define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD
341#define MONGO_DESTRUCTOR_GUARD(expression) \
342 try { \
343 expression; \
344 } catch (const std::exception& e) { \
345 ::mongo::logger::LogstreamBuilder(::mongo::logger::globalLogDomain(), \
346 std::string(), \
347 ::mongo::logger::LogSeverity::Log()) \
348 << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ << ")" \
349 << std::endl; \
350 } catch (...) { \
351 ::mongo::logger::LogstreamBuilder(::mongo::logger::globalLogDomain(), \
352 std::string(), \
353 ::mongo::logger::LogSeverity::Log()) \
354 << "caught unknown exception in destructor (" << __FUNCTION__ << ")" << std::endl; \
355 }
356
369#define MONGO_UNREACHABLE ::mongo::invariantFailed("Hit a MONGO_UNREACHABLE!", __FILE__, __LINE__);
Definition assert_util.h:128
Utility for creating a BSONObj.
Definition bsonobjbuilder.h:53
Most mongo exceptions inherit from this; this is commonly caught in most threads.
Definition assert_util.h:87
helper class that builds error strings.
Definition assert_util.h:70
Definition assert_util.h:157
Status represents an error state or the absence thereof.
Definition status.h:50
Definition assert_util.h:145
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:20
MONGO_CLIENT_API MONGO_COMPILER_NORETURN void MONGO_CLIENT_FUNC uasserted(int msgid, const char *msg)
a "user assertion".
MONGO_CLIENT_API void MONGO_CLIENT_FUNC fassert(int msgid, bool testOK)
aborts on condition failure
Definition assert_util.h:210
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:45