DNBLog.cpp revision b749a265a2b97f9cef71c362dfd6dae26c8f2973
1//===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  Created by Greg Clayton on 6/18/07.
11//
12//===----------------------------------------------------------------------===//
13
14#include "DNBLog.h"
15
16static int g_debug = 0;
17static int g_verbose = 0;
18
19#if defined (DNBLOG_ENABLED)
20
21#include <stdio.h>
22#include <stdarg.h>
23#include <stdlib.h>
24#include <sys/time.h>
25#include <unistd.h>
26#include <mach/mach.h>
27#include <pthread.h>
28#include "PThreadMutex.h"
29
30uint32_t g_log_bits = 0;
31static DNBCallbackLog g_log_callback = NULL;
32static void *g_log_baton = NULL;
33
34
35int
36DNBLogGetDebug ()
37{
38    return g_debug;
39}
40
41
42void
43DNBLogSetDebug (int g)
44{
45    g_debug = g;
46}
47
48int
49DNBLogGetVerbose ()
50{
51    return g_verbose;
52}
53
54void
55DNBLogSetVerbose (int v)
56{
57    g_verbose = v;
58}
59
60bool
61DNBLogCheckLogBit (uint32_t bit)
62{
63    return (g_log_bits & bit) != 0;
64}
65
66uint32_t
67DNBLogSetLogMask (uint32_t mask)
68{
69    uint32_t old = g_log_bits;
70    g_log_bits = mask;
71    return old;
72}
73
74uint32_t
75DNBLogGetLogMask ()
76{
77    return g_log_bits;
78}
79
80void
81DNBLogSetLogCallback (DNBCallbackLog callback, void *baton)
82{
83    g_log_callback = callback;
84    g_log_baton = baton;
85}
86
87bool
88DNBLogEnabled ()
89{
90    return g_log_callback != NULL;
91}
92
93static inline void
94_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
95{
96    if (g_log_callback)
97      g_log_callback(g_log_baton, flags, format, args);
98}
99
100void
101_DNBLog(uint32_t flags, const char *format, ...)
102{
103    va_list args;
104    va_start (args, format);
105    _DNBLogVAPrintf(flags, format, args);
106    va_end (args);
107}
108
109//----------------------------------------------------------------------
110// Print debug strings if and only if the global g_debug is set to
111// a non-zero value.
112//----------------------------------------------------------------------
113void
114_DNBLogDebug (const char *format, ...)
115{
116    if (DNBLogEnabled () && g_debug)
117    {
118        va_list args;
119        va_start (args, format);
120        _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
121        va_end (args);
122    }
123}
124
125
126//----------------------------------------------------------------------
127// Print debug strings if and only if the global g_debug is set to
128// a non-zero value.
129//----------------------------------------------------------------------
130void
131_DNBLogDebugVerbose (const char *format, ...)
132{
133    if (DNBLogEnabled () && g_debug && g_verbose)
134    {
135        va_list args;
136        va_start (args, format);
137        _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
138        va_end (args);
139    }
140}
141
142
143static pthread_mutex_t *
144GetLogThreadedMutex()
145{
146    static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
147    return g_LogThreadedMutex.Mutex();
148}
149static uint32_t g_message_id = 0;
150
151//----------------------------------------------------------------------
152// Prefix the formatted log string with process and thread IDs and
153// suffix it with a newline.
154//----------------------------------------------------------------------
155void
156_DNBLogThreaded (const char *format, ...)
157{
158    if (DNBLogEnabled ())
159    {
160        PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
161
162        char *arg_msg = NULL;
163        va_list args;
164        va_start (args, format);
165        ::vasprintf (&arg_msg, format, args);
166        va_end (args);
167
168        if (arg_msg != NULL)
169        {
170            static struct timeval g_timeval = { 0 , 0 };
171            static struct timeval tv;
172            static struct timeval delta;
173            gettimeofday(&tv, NULL);
174            if (g_timeval.tv_sec == 0)
175            {
176                delta.tv_sec = 0;
177                delta.tv_usec = 0;
178            }
179            else
180            {
181                timersub (&tv, &g_timeval, &delta);
182            }
183            g_timeval = tv;
184            _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
185                     ++g_message_id,
186                     delta.tv_sec,
187                     delta.tv_usec,
188                     getpid(),
189                     mach_thread_self(),
190                     arg_msg);
191            free (arg_msg);
192        }
193    }
194}
195
196//----------------------------------------------------------------------
197// Prefix the formatted log string with process and thread IDs and
198// suffix it with a newline.
199//----------------------------------------------------------------------
200void
201_DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
202{
203    if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
204    {
205        PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
206
207        char *arg_msg = NULL;
208        va_list args;
209        va_start (args, format);
210        ::vasprintf (&arg_msg, format, args);
211        va_end (args);
212
213        if (arg_msg != NULL)
214        {
215            static struct timeval g_timeval = { 0 , 0 };
216            static struct timeval tv;
217            static struct timeval delta;
218            gettimeofday(&tv, NULL);
219            if (g_timeval.tv_sec == 0)
220            {
221                delta.tv_sec = 0;
222                delta.tv_usec = 0;
223            }
224            else
225            {
226                timersub (&tv, &g_timeval, &delta);
227            }
228            g_timeval = tv;
229            _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
230                     ++g_message_id,
231                     delta.tv_sec,
232                     delta.tv_usec,
233                     getpid(),
234                     mach_thread_self(),
235                     arg_msg);
236            free (arg_msg);
237        }
238    }
239}
240
241
242
243//----------------------------------------------------------------------
244// Printing of errors that are not fatal.
245//----------------------------------------------------------------------
246void
247_DNBLogError (const char *format, ...)
248{
249    if (DNBLogEnabled ())
250    {
251        char *arg_msg = NULL;
252        va_list args;
253        va_start (args, format);
254        ::vasprintf (&arg_msg, format, args);
255        va_end (args);
256
257        if (arg_msg != NULL)
258        {
259            _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
260            free (arg_msg);
261        }
262    }
263}
264
265//----------------------------------------------------------------------
266// Printing of errors that ARE fatal. Exit with ERR exit code
267// immediately.
268//----------------------------------------------------------------------
269void
270_DNBLogFatalError (int err, const char *format, ...)
271{
272    if (DNBLogEnabled ())
273    {
274        char *arg_msg = NULL;
275        va_list args;
276        va_start (args, format);
277        ::vasprintf (&arg_msg, format, args);
278        va_end (args);
279
280        if (arg_msg != NULL)
281        {
282            _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
283            free (arg_msg);
284        }
285        ::exit (err);
286    }
287}
288
289
290//----------------------------------------------------------------------
291// Printing of warnings that are not fatal only if verbose mode is
292// enabled.
293//----------------------------------------------------------------------
294void
295_DNBLogVerbose (const char *format, ...)
296{
297    if (DNBLogEnabled () && g_verbose)
298    {
299        va_list args;
300        va_start (args, format);
301        _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
302        va_end (args);
303    }
304}
305
306//----------------------------------------------------------------------
307// Printing of warnings that are not fatal only if verbose mode is
308// enabled.
309//----------------------------------------------------------------------
310void
311_DNBLogWarningVerbose (const char *format, ...)
312{
313    if (DNBLogEnabled () && g_verbose)
314    {
315        char *arg_msg = NULL;
316        va_list args;
317        va_start (args, format);
318        ::vasprintf (&arg_msg, format, args);
319        va_end (args);
320
321        if (arg_msg != NULL)
322        {
323            _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
324            free (arg_msg);
325        }
326    }
327}
328//----------------------------------------------------------------------
329// Printing of warnings that are not fatal.
330//----------------------------------------------------------------------
331void
332_DNBLogWarning (const char *format, ...)
333{
334    if (DNBLogEnabled ())
335    {
336        char *arg_msg = NULL;
337        va_list args;
338        va_start (args, format);
339        ::vasprintf (&arg_msg, format, args);
340        va_end (args);
341
342        if (arg_msg != NULL)
343        {
344            _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
345            free (arg_msg);
346        }
347    }
348}
349
350#endif
351