throw FailedAssertion(bt);
}
+ void __ceph_assertf_fail(const char *assertion, const char *file, int line, const char *func, const char* msg, ...)
+ {
+ ostringstream tss;
+ tss << ceph_clock_now(g_assert_context);
+
+ class BufAppender {
+ public:
+ BufAppender(char* buf, int size) : bufptr(buf), remaining(size) {
+ }
+
+ void printf(const char * format, ...) {
+ va_list args;
+ va_start(args, format);
+ this->vprintf(format, args);
+ va_end(args);
+ }
+
+ void vprintf(const char * format, va_list args) {
+ int n = vsnprintf(bufptr, remaining, format, args);
+ if (n >= 0) {
+ if (n < remaining) {
+ remaining -= n;
+ bufptr += n;
+ } else {
+ remaining = 0;
+ }
+ }
+ }
+
+ private:
+ char* bufptr;
+ int remaining;
+ };
+
+ char buf[8096];
+ BufAppender ba(buf, sizeof(buf));
+ BackTrace *bt = new BackTrace(1);
+ ba.printf("%s: In function '%s' thread %llx time %s\n"
+ "%s: %d: FAILED assert(%s)\n",
+ file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
+ file, line, assertion);
+ ba.printf("Assertion details: ");
+ va_list args;
+ va_start(args, msg);
+ ba.vprintf(msg, args);
+ va_end(args);
+ ba.printf("\n");
+ dout_emergency(buf);
+
+ // TODO: get rid of this memory allocation.
+ ostringstream oss;
+ bt->print(oss);
+ dout_emergency(oss.str());
+
+ dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
+ "is needed to interpret this.\n");
+
+ if (g_assert_context) {
+ lderr(g_assert_context) << buf << std::endl;
+ bt->print(*_dout);
+ *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
+ << "is needed to interpret this.\n" << dendl;
+
+ g_assert_context->_log->dump_recent();
+ }
+
+ throw FailedAssertion(bt);
+ }
+
void __ceph_assert_warn(const char *assertion, const char *file,
int line, const char *func)
{
extern void register_assert_context(CephContext *cct);
extern void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *function)
__attribute__ ((__noreturn__));
+extern void __ceph_assertf_fail(const char *assertion, const char *file, int line, const char *function, const char* msg, ...)
+ __attribute__ ((__noreturn__));
extern void __ceph_assert_warn(const char *assertion, const char *file, int line, const char *function);
#define ceph_assert(expr) \
? __CEPH_ASSERT_VOID_CAST (0) \
: __ceph_assert_fail (__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION))
+// Named by analogy with printf. Along with an expression, takes a format
+// string and parameters which are printed if the assertion fails.
+#define assertf(expr, ...) \
+ ((expr) \
+ ? __CEPH_ASSERT_VOID_CAST (0) \
+ : __ceph_assertf_fail (__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION, __VA_ARGS__))