00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef OM_HGUARD_OMDEBUG_H
00028 #define OM_HGUARD_OMDEBUG_H
00029
00030 #ifdef XAPIAN_DEBUG_VERBOSE
00031
00032 #include <xapian/visibility.h>
00033
00034 #include "omtime.h"
00035 #include "output.h"
00036 #include "stringutils.h"
00037
00038 #include <iomanip>
00039 #include <sstream>
00040 #include <vector>
00041
00042 #include "safeunistd.h"
00043
00044 inline std::ostream &
00045 operator<<(std::ostream & os, const OmTime & om_time) {
00046 return os << om_time.sec << '.' << std::setw(6) << std::setfill('0') << om_time.usec;
00047 }
00048
00052 enum om_debug_types {
00056 OM_DEBUG_UNKNOWN,
00057
00059 OM_DEBUG_DUMMY,
00060
00063 OM_DEBUG_DB,
00064
00067 OM_DEBUG_MATCH,
00068
00071 OM_DEBUG_EXPAND,
00072
00075 OM_DEBUG_WTCALC,
00076
00079 OM_DEBUG_API,
00080
00084 OM_DEBUG_APICALL,
00085
00088 OM_DEBUG_EXCEPTION,
00089
00092 OM_DEBUG_DBLOCK,
00093
00096 OM_DEBUG_INDEXER,
00097
00099 OM_DEBUG_DUMMY2,
00100
00102 OM_DEBUG_REMOTE,
00103
00105 OM_DEBUG_QUERYPARSER,
00106
00108 OM_DEBUG_SPELLING,
00109
00112 OM_DEBUG_NUMTYPES
00113 };
00114
00117 class XAPIAN_VISIBILITY_DEFAULT OmDebug {
00118 private:
00120 OmDebug(OmDebug &);
00121
00123 void operator=(OmDebug &);
00124
00126 bool initialised;
00127
00133 unsigned int wanted_types;
00134
00136 int fd;
00137
00138 public:
00140 void display_message(enum om_debug_types type, std::string msg);
00141
00143 bool want_type(enum om_debug_types type);
00144
00146 void initialise();
00147
00149 OmDebug();
00150
00152 ~OmDebug();
00153 };
00154
00155 XAPIAN_VISIBILITY_DEFAULT
00156 extern OmDebug om_debug;
00157
00159
00160 #define DEBUGMSG2(a,b) do { \
00161 if (om_debug.want_type(a)) { \
00162 std::ostringstream os; \
00163 os << b; \
00164 om_debug.display_message(a, os.str()); \
00165 } \
00166 } while (0)
00167
00168 #define DEBUGLINE2(a,b) DEBUGMSG2(a, "Xapian " << getpid() << ": " << b << '\n')
00169
00172 class OmDebugCall {
00173 private:
00175 std::string methodname;
00176
00178 std::string returnval;
00179
00181 enum om_debug_types type;
00182 public:
00184 OmDebugCall(enum om_debug_types type_,
00185 std::string methodname_,
00186 std::string params)
00187 : methodname(methodname_),
00188 type(type_)
00189 {
00190 DEBUGLINE2(type, methodname << "(" << params << ") called");
00191 }
00192
00194 void setreturnval(std::string returnval_) { returnval = returnval_; }
00195
00197 ~OmDebugCall() {
00198 DEBUGLINE2(type, methodname << "() returning " << returnval);
00199 }
00200 };
00201
00205 #define DEBUGCALL(t,r,a,b) \
00206 std::string omdebugapicall_str; \
00207 std::string omdebugapicall_method; \
00208 typedef r omdebugapicallreturn_t; \
00209 if (om_debug.want_type(OM_DEBUG_##t)) { \
00210 std::ostringstream os1; \
00211 os1 << "[" << static_cast<const void*>(this) << "] " << STRINGIZE(r) << " " << a; \
00212 omdebugapicall_method = os1.str(); \
00213 std::ostringstream os2; \
00214 os2 << b; \
00215 omdebugapicall_str = os2.str(); \
00216 } \
00217 OmDebugCall omdebugapicall(OM_DEBUG_##t, omdebugapicall_method, omdebugapicall_str);
00218
00221 #define DEBUGCALL_STATIC(t,r,a,b) \
00222 std::string omdebugapicall_str; \
00223 std::string omdebugapicall_method; \
00224 typedef r omdebugapicallreturn_t; \
00225 if (om_debug.want_type(OM_DEBUG_##t)) { \
00226 std::ostringstream os1; \
00227 os1 << "[static ] " << STRINGIZE(r) << " " << a; \
00228 omdebugapicall_method = os1.str(); \
00229 std::ostringstream os2; \
00230 os2 << b; \
00231 omdebugapicall_str = os2.str(); \
00232 } \
00233 OmDebugCall omdebugapicall(OM_DEBUG_##t, omdebugapicall_method, omdebugapicall_str);
00234
00235 #define RETURN(A) do { \
00236 omdebugapicallreturn_t omdebugapicallreturn = A; \
00237 std::ostringstream os; \
00238 os << omdebugapicallreturn; \
00239 omdebugapicall.setreturnval(os.str()); \
00240 return omdebugapicallreturn; \
00241 } while (0)
00242
00243 #define DEBUGMSG(a,b) DEBUGMSG2(OM_DEBUG_##a, b)
00244 #define DEBUGLINE(a,b) DEBUGLINE2(OM_DEBUG_##a, b)
00245
00246 using std::endl;
00247
00248 #elif defined(XAPIAN_DEBUG_PROFILE)
00249
00250 #define DEBUGMSG(a,b) (void)0
00251 #define DEBUGLINE(a,b) (void)0
00252 #define RETURN(A) return A
00253
00254 #include <cstdio>
00255 #include <cstdlib>
00256 #include <sys/time.h>
00257
00258 #include <list>
00259 #include <string>
00260
00261 namespace Xapian {
00262 namespace Internal {
00263
00264 class Timer {
00265 private:
00266 std::string call;
00267
00268
00269 struct timeval entry;
00270
00271
00272 struct timeval start;
00273
00274
00275 struct timeval dead;
00276
00277
00278 struct timeval kids;
00279
00280
00281 static struct timeval paused;
00282
00283
00284 static struct timeval * pstart;
00285
00286 static std::list<Timer *> stack;
00287
00288 static int depth;
00289
00290 public:
00291 Timer(const std::string &call_) : call(call_) {
00292 stack.push_back(this);
00293 depth++;
00294 entry = paused;
00295 pstart = &start;
00296 timerclear(&dead);
00297 timerclear(&kids);
00298 }
00299
00300 ~Timer() {
00301 gettimeofday(&paused, NULL);
00302 {
00303 if (stack.empty()) std::abort();
00304 stack.pop_back();
00305 depth--;
00306
00307
00308 int runu = paused.tv_usec - start.tv_usec - dead.tv_usec;
00309 int runs = paused.tv_sec - start.tv_sec - dead.tv_sec;
00310 runs += runu / 1000000;
00311 runu %= 1000000;
00312 if (runu < 0) {
00313 runu += 1000000;
00314 runs--;
00315 }
00316
00317 if (!stack.empty()) {
00318 struct timeval * k = &(stack.back()->kids);
00319 k->tv_sec += runs;
00320 k->tv_usec += runu;
00321 }
00322
00323
00324 int myu = runu - kids.tv_usec;
00325 int mys = runs - kids.tv_sec;
00326 mys += myu / 1000000;
00327 myu %= 1000000;
00328 if (myu < 0) {
00329 myu += 1000000;
00330 mys--;
00331 }
00332 std::fprintf(stderr, "% 5d.%06d % 5d.%06d %-*s%s\n",
00333 runs, runu, mys, myu, depth, "", call.c_str());
00334 }
00335
00336
00337 int usec = start.tv_usec - entry.tv_usec;
00338 int sec = start.tv_sec - entry.tv_sec;
00339 sec += usec / 1000000;
00340 usec %= 1000000;
00341 if (usec < 0) {
00342 usec += 1000000;
00343 sec--;
00344 }
00345
00346
00347 usec += dead.tv_usec;
00348 sec += dead.tv_sec;
00349
00350
00351 usec -= paused.tv_usec;
00352 sec -= paused.tv_sec;
00353
00354 pstart = NULL;
00355 struct timeval * d = NULL;
00356 if (!stack.empty()) {
00357 d = &(stack.back()->dead);
00358 d->tv_sec += sec;
00359 d->tv_usec += usec;
00360 }
00361 gettimeofday(&paused, NULL);
00362 if (d) {
00363 d->tv_sec += paused.tv_sec;
00364 d->tv_usec += paused.tv_usec;
00365 }
00366 }
00367
00368 static void pause() {
00369 gettimeofday(&paused, NULL);
00370 }
00371
00372 static void resume() {
00373 if (pstart == NULL) std::abort();
00374 gettimeofday(pstart, NULL);
00375 }
00376 };
00377
00378 }
00379 }
00380
00384 #define DEBUGCALL(t,r,a,b) \
00385 Xapian::Internal::Timer::pause(); \
00386 Xapian::Internal::Timer om_time_call(a); \
00387 Xapian::Internal::Timer::resume();
00388
00389 #define DEBUGCALL_STATIC(t,r,a,b) \
00390 Xapian::Internal::Timer::pause(); \
00391 Xapian::Internal::Timer om_time_call(a); \
00392 Xapian::Internal::Timer::resume();
00393
00394 #else
00395
00396 #define DEBUGMSG(a,b) (void)0
00397 #define DEBUGLINE(a,b) (void)0
00398 #define RETURN(A) return A
00399
00400 #define DEBUGCALL(r,t,a,b) (void)0
00401 #define DEBUGCALL_STATIC(r,t,a,b) (void)0
00402 #endif
00403
00404 #define DEBUGAPICALL(r,a,b) DEBUGCALL(APICALL,r,a,b)
00405 #define DEBUGAPICALL_STATIC(r,a,b) DEBUGCALL_STATIC(APICALL,r,a,b)
00406 #define DebugMsg(a) DEBUGMSG(UNKNOWN, a)
00407
00408 #endif