Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / assert.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2008-2011 New Dream Network
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "common/debug.h"
16
17 namespace ceph {
18   static CephContext *g_assert_context = NULL;
19
20   /* If you register an assert context, assert() will try to lock the dout
21    * stream of that context before starting an assert. This is nice because the
22    * output looks better. Your assert will not be interleaved with other dout
23    * statements.
24    *
25    * However, this is strictly optional and library code currently does not
26    * register an assert context. The extra complexity of supporting this
27    * wouldn't really be worth it.
28    */
29   void register_assert_context(CephContext *cct)
30   {
31     assert(!g_assert_context);
32     g_assert_context = cct;
33   }
34
35   void __ceph_assert_fail(const char *assertion, const char *file, int line,
36                           const char *func)
37   {
38     ostringstream tss;
39     tss << ceph_clock_now();
40
41     char buf[8096];
42     snprintf(buf, sizeof(buf),
43              "%s: In function '%s' thread %llx time %s\n"
44              "%s: %d: FAILED assert(%s)\n",
45              file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
46              file, line, assertion);
47     dout_emergency(buf);
48
49     // TODO: get rid of this memory allocation.
50     ostringstream oss;
51     oss << BackTrace(1);
52     dout_emergency(oss.str());
53
54     dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
55                    "is needed to interpret this.\n");
56
57     if (g_assert_context) {
58       lderr(g_assert_context) << buf << std::endl;
59       *_dout << oss.str();
60       *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
61              << "is needed to interpret this.\n" << dendl;
62
63       g_assert_context->_log->dump_recent();
64     }
65
66     abort();
67   }
68
69   void __ceph_assertf_fail(const char *assertion, const char *file, int line,
70                            const char *func, const char* msg, ...)
71   {
72     ostringstream tss;
73     tss << ceph_clock_now();
74
75     class BufAppender {
76     public:
77       BufAppender(char* buf, int size) : bufptr(buf), remaining(size) {
78       }
79
80       void printf(const char * format, ...) {
81         va_list args;
82         va_start(args, format);
83         this->vprintf(format, args);
84         va_end(args);
85       }
86
87       void vprintf(const char * format, va_list args) {
88         int n = vsnprintf(bufptr, remaining, format, args);
89         if (n >= 0) {
90           if (n < remaining) {
91             remaining -= n;
92             bufptr += n;
93           } else {
94             remaining = 0;
95           }
96         }
97       }
98
99     private:
100       char* bufptr;
101       int remaining;
102     };
103
104     char buf[8096];
105     BufAppender ba(buf, sizeof(buf));
106     BackTrace *bt = new BackTrace(1);
107     ba.printf("%s: In function '%s' thread %llx time %s\n"
108              "%s: %d: FAILED assert(%s)\n",
109              file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
110              file, line, assertion);
111     ba.printf("Assertion details: ");
112     va_list args;
113     va_start(args, msg);
114     ba.vprintf(msg, args);
115     va_end(args);
116     ba.printf("\n");
117     dout_emergency(buf);
118
119     // TODO: get rid of this memory allocation.
120     ostringstream oss;
121     oss << *bt;
122     dout_emergency(oss.str());
123
124     dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
125                    "is needed to interpret this.\n");
126
127     if (g_assert_context) {
128       lderr(g_assert_context) << buf << std::endl;
129       *_dout << oss.str();
130       *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
131              << "is needed to interpret this.\n" << dendl;
132
133       g_assert_context->_log->dump_recent();
134     }
135
136     abort();
137   }
138
139   void __ceph_assert_warn(const char *assertion, const char *file,
140                           int line, const char *func)
141   {
142     char buf[8096];
143     snprintf(buf, sizeof(buf),
144              "WARNING: assert(%s) at: %s: %d: %s()\n",
145              assertion, file, line, func);
146     dout_emergency(buf);
147   }
148 }