DNBLog.cpp revision 0e8147bd867e4cdaae9400f56d02c7aacd40a9b3
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
93bool
94DNBLogEnabledForAny (uint32_t mask)
95{
96    if (g_log_callback)
97        return (g_log_bits & mask) != 0;
98    return false;
99}
100static inline void
101_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
102{
103    static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
104    PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
105
106    if (g_log_callback)
107      g_log_callback(g_log_baton, flags, format, args);
108}
109
110void
111_DNBLog(uint32_t flags, const char *format, ...)
112{
113    va_list args;
114    va_start (args, format);
115    _DNBLogVAPrintf(flags, format, args);
116    va_end (args);
117}
118
119//----------------------------------------------------------------------
120// Print debug strings if and only if the global g_debug is set to
121// a non-zero value.
122//----------------------------------------------------------------------
123void
124_DNBLogDebug (const char *format, ...)
125{
126    if (DNBLogEnabled () && g_debug)
127    {
128        va_list args;
129        va_start (args, format);
130        _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
131        va_end (args);
132    }
133}
134
135
136//----------------------------------------------------------------------
137// Print debug strings if and only if the global g_debug is set to
138// a non-zero value.
139//----------------------------------------------------------------------
140void
141_DNBLogDebugVerbose (const char *format, ...)
142{
143    if (DNBLogEnabled () && g_debug && g_verbose)
144    {
145        va_list args;
146        va_start (args, format);
147        _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
148        va_end (args);
149    }
150}
151
152
153static uint32_t g_message_id = 0;
154
155//----------------------------------------------------------------------
156// Prefix the formatted log string with process and thread IDs and
157// suffix it with a newline.
158//----------------------------------------------------------------------
159void
160_DNBLogThreaded (const char *format, ...)
161{
162    if (DNBLogEnabled ())
163    {
164        //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
165
166        char *arg_msg = NULL;
167        va_list args;
168        va_start (args, format);
169        ::vasprintf (&arg_msg, format, args);
170        va_end (args);
171
172        if (arg_msg != NULL)
173        {
174            static struct timeval g_timeval = { 0 , 0 };
175            static struct timeval tv;
176            static struct timeval delta;
177            gettimeofday(&tv, NULL);
178            if (g_timeval.tv_sec == 0)
179            {
180                delta.tv_sec = 0;
181                delta.tv_usec = 0;
182            }
183            else
184            {
185                timersub (&tv, &g_timeval, &delta);
186            }
187            g_timeval = tv;
188            _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
189                     ++g_message_id,
190                     delta.tv_sec,
191                     delta.tv_usec,
192                     getpid(),
193                     mach_thread_self(),
194                     arg_msg);
195            free (arg_msg);
196        }
197    }
198}
199
200//----------------------------------------------------------------------
201// Prefix the formatted log string with process and thread IDs and
202// suffix it with a newline.
203//----------------------------------------------------------------------
204void
205_DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
206{
207    if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
208    {
209        //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
210
211        char *arg_msg = NULL;
212        va_list args;
213        va_start (args, format);
214        ::vasprintf (&arg_msg, format, args);
215        va_end (args);
216
217        if (arg_msg != NULL)
218        {
219            static struct timeval g_timeval = { 0 , 0 };
220            static struct timeval tv;
221            static struct timeval delta;
222            gettimeofday(&tv, NULL);
223            if (g_timeval.tv_sec == 0)
224            {
225                delta.tv_sec = 0;
226                delta.tv_usec = 0;
227            }
228            else
229            {
230                timersub (&tv, &g_timeval, &delta);
231            }
232            g_timeval = tv;
233            _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s",
234                     ++g_message_id,
235                     delta.tv_sec,
236                     delta.tv_usec,
237                     getpid(),
238                     mach_thread_self(),
239                     arg_msg);
240            free (arg_msg);
241        }
242    }
243}
244
245
246
247//----------------------------------------------------------------------
248// Printing of errors that are not fatal.
249//----------------------------------------------------------------------
250void
251_DNBLogError (const char *format, ...)
252{
253    if (DNBLogEnabled ())
254    {
255        char *arg_msg = NULL;
256        va_list args;
257        va_start (args, format);
258        ::vasprintf (&arg_msg, format, args);
259        va_end (args);
260
261        if (arg_msg != NULL)
262        {
263            _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
264            free (arg_msg);
265        }
266    }
267}
268
269//----------------------------------------------------------------------
270// Printing of errors that ARE fatal. Exit with ERR exit code
271// immediately.
272//----------------------------------------------------------------------
273void
274_DNBLogFatalError (int err, const char *format, ...)
275{
276    if (DNBLogEnabled ())
277    {
278        char *arg_msg = NULL;
279        va_list args;
280        va_start (args, format);
281        ::vasprintf (&arg_msg, format, args);
282        va_end (args);
283
284        if (arg_msg != NULL)
285        {
286            _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
287            free (arg_msg);
288        }
289        ::exit (err);
290    }
291}
292
293
294//----------------------------------------------------------------------
295// Printing of warnings that are not fatal only if verbose mode is
296// enabled.
297//----------------------------------------------------------------------
298void
299_DNBLogVerbose (const char *format, ...)
300{
301    if (DNBLogEnabled () && g_verbose)
302    {
303        va_list args;
304        va_start (args, format);
305        _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
306        va_end (args);
307    }
308}
309
310//----------------------------------------------------------------------
311// Printing of warnings that are not fatal only if verbose mode is
312// enabled.
313//----------------------------------------------------------------------
314void
315_DNBLogWarningVerbose (const char *format, ...)
316{
317    if (DNBLogEnabled () && g_verbose)
318    {
319        char *arg_msg = NULL;
320        va_list args;
321        va_start (args, format);
322        ::vasprintf (&arg_msg, format, args);
323        va_end (args);
324
325        if (arg_msg != NULL)
326        {
327            _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
328            free (arg_msg);
329        }
330    }
331}
332//----------------------------------------------------------------------
333// Printing of warnings that are not fatal.
334//----------------------------------------------------------------------
335void
336_DNBLogWarning (const char *format, ...)
337{
338    if (DNBLogEnabled ())
339    {
340        char *arg_msg = NULL;
341        va_list args;
342        va_start (args, format);
343        ::vasprintf (&arg_msg, format, args);
344        va_end (args);
345
346        if (arg_msg != NULL)
347        {
348            _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
349            free (arg_msg);
350        }
351    }
352}
353
354#endif
355