~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjlib/src/pj/log.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: log.c 4761 2014-02-24 09:02:44Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pj/types.h>
 
21
#include <pj/log.h>
 
22
#include <pj/string.h>
 
23
#include <pj/os.h>
 
24
#include <pj/compat/stdarg.h>
 
25
 
 
26
#if PJ_LOG_MAX_LEVEL >= 1
 
27
 
 
28
#if 0
 
29
PJ_DEF_DATA(int) pj_log_max_level = PJ_LOG_MAX_LEVEL;
 
30
#else
 
31
static int pj_log_max_level = PJ_LOG_MAX_LEVEL;
 
32
#endif
 
33
 
 
34
static void *g_last_thread;
 
35
 
 
36
#if PJ_HAS_THREADS
 
37
static long thread_suspended_tls_id = -1;
 
38
#  if PJ_LOG_ENABLE_INDENT
 
39
static long thread_indent_tls_id = -1;
 
40
#  endif
 
41
#endif
 
42
 
 
43
#if !PJ_LOG_ENABLE_INDENT || !PJ_HAS_THREADS
 
44
static int log_indent;
 
45
#endif
 
46
 
 
47
static pj_log_func *log_writer = &pj_log_write;
 
48
static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
 
49
                            PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
 
50
                            PJ_LOG_HAS_SPACE | PJ_LOG_HAS_THREAD_SWC |
 
51
                            PJ_LOG_HAS_INDENT
 
52
#if (defined(PJ_WIN32) && PJ_WIN32!=0) || \
 
53
    (defined(PJ_WIN64) && PJ_WIN64!=0)
 
54
                            | PJ_LOG_HAS_COLOR
 
55
#endif
 
56
                            ;
 
57
 
 
58
static pj_color_t PJ_LOG_COLOR_0 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
 
59
static pj_color_t PJ_LOG_COLOR_1 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
 
60
static pj_color_t PJ_LOG_COLOR_2 = PJ_TERM_COLOR_BRIGHT | 
 
61
                                   PJ_TERM_COLOR_R | 
 
62
                                   PJ_TERM_COLOR_G;
 
63
static pj_color_t PJ_LOG_COLOR_3 = PJ_TERM_COLOR_BRIGHT | 
 
64
                                   PJ_TERM_COLOR_R | 
 
65
                                   PJ_TERM_COLOR_G | 
 
66
                                   PJ_TERM_COLOR_B;
 
67
static pj_color_t PJ_LOG_COLOR_4 = PJ_TERM_COLOR_R | 
 
68
                                   PJ_TERM_COLOR_G | 
 
69
                                   PJ_TERM_COLOR_B;
 
70
static pj_color_t PJ_LOG_COLOR_5 = PJ_TERM_COLOR_R | 
 
71
                                   PJ_TERM_COLOR_G | 
 
72
                                   PJ_TERM_COLOR_B;
 
73
static pj_color_t PJ_LOG_COLOR_6 = PJ_TERM_COLOR_R | 
 
74
                                   PJ_TERM_COLOR_G | 
 
75
                                   PJ_TERM_COLOR_B;
 
76
/* Default terminal color */
 
77
static pj_color_t PJ_LOG_COLOR_77 = PJ_TERM_COLOR_R | 
 
78
                                    PJ_TERM_COLOR_G | 
 
79
                                    PJ_TERM_COLOR_B;
 
80
 
 
81
#if PJ_LOG_USE_STACK_BUFFER==0
 
82
static char log_buffer[PJ_LOG_MAX_SIZE];
 
83
#endif
 
84
 
 
85
#define LOG_MAX_INDENT          80
 
86
 
 
87
#if PJ_HAS_THREADS
 
88
static void logging_shutdown(void)
 
89
{
 
90
    if (thread_suspended_tls_id != -1) {
 
91
        pj_thread_local_free(thread_suspended_tls_id);
 
92
        thread_suspended_tls_id = -1;
 
93
    }
 
94
#  if PJ_LOG_ENABLE_INDENT
 
95
    if (thread_indent_tls_id != -1) {
 
96
        pj_thread_local_free(thread_indent_tls_id);
 
97
        thread_indent_tls_id = -1;
 
98
    }
 
99
#  endif
 
100
}
 
101
#endif  /* PJ_HAS_THREADS */
 
102
 
 
103
#if PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS
 
104
static void log_set_indent(int indent)
 
105
{
 
106
    if (indent < 0) indent = 0;
 
107
    pj_thread_local_set(thread_indent_tls_id, (void*)(pj_ssize_t)indent);
 
108
}
 
109
 
 
110
static int log_get_raw_indent(void)
 
111
{
 
112
    return (long)(pj_ssize_t)pj_thread_local_get(thread_indent_tls_id);
 
113
}
 
114
 
 
115
#else
 
116
static void log_set_indent(int indent)
 
117
{
 
118
    log_indent = indent;
 
119
    if (log_indent < 0) log_indent = 0;
 
120
}
 
121
 
 
122
static int log_get_raw_indent(void)
 
123
{
 
124
    return log_indent;
 
125
}
 
126
#endif  /* PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS */
 
127
 
 
128
static int log_get_indent(void)
 
129
{
 
130
    int indent = log_get_raw_indent();
 
131
    return indent > LOG_MAX_INDENT ? LOG_MAX_INDENT : indent;
 
132
}
 
133
 
 
134
PJ_DEF(void) pj_log_add_indent(int indent)
 
135
{
 
136
    log_set_indent(log_get_raw_indent() + indent);
 
137
}
 
138
 
 
139
PJ_DEF(void) pj_log_push_indent(void)
 
140
{
 
141
    pj_log_add_indent(PJ_LOG_INDENT_SIZE);
 
142
}
 
143
 
 
144
PJ_DEF(void) pj_log_pop_indent(void)
 
145
{
 
146
    pj_log_add_indent(-PJ_LOG_INDENT_SIZE);
 
147
}
 
148
 
 
149
pj_status_t pj_log_init(void)
 
150
{
 
151
#if PJ_HAS_THREADS
 
152
    if (thread_suspended_tls_id == -1) {
 
153
        pj_status_t status;
 
154
        status = pj_thread_local_alloc(&thread_suspended_tls_id);
 
155
        if (status != PJ_SUCCESS)
 
156
            return status;
 
157
 
 
158
#  if PJ_LOG_ENABLE_INDENT
 
159
        status = pj_thread_local_alloc(&thread_indent_tls_id);
 
160
        if (status != PJ_SUCCESS) {
 
161
            pj_thread_local_free(thread_suspended_tls_id);
 
162
            thread_suspended_tls_id = -1;
 
163
            return status;
 
164
        }
 
165
#  endif
 
166
        pj_atexit(&logging_shutdown);
 
167
    }
 
168
#endif
 
169
    g_last_thread = NULL;
 
170
    return PJ_SUCCESS;
 
171
}
 
172
 
 
173
PJ_DEF(void) pj_log_set_decor(unsigned decor)
 
174
{
 
175
    log_decor = decor;
 
176
}
 
177
 
 
178
PJ_DEF(unsigned) pj_log_get_decor(void)
 
179
{
 
180
    return log_decor;
 
181
}
 
182
 
 
183
PJ_DEF(void) pj_log_set_color(int level, pj_color_t color)
 
184
{
 
185
    switch (level) 
 
186
    {
 
187
        case 0: PJ_LOG_COLOR_0 = color; 
 
188
            break;
 
189
        case 1: PJ_LOG_COLOR_1 = color; 
 
190
            break;
 
191
        case 2: PJ_LOG_COLOR_2 = color; 
 
192
            break;
 
193
        case 3: PJ_LOG_COLOR_3 = color; 
 
194
            break;
 
195
        case 4: PJ_LOG_COLOR_4 = color; 
 
196
            break;
 
197
        case 5: PJ_LOG_COLOR_5 = color; 
 
198
            break;
 
199
        case 6: PJ_LOG_COLOR_6 = color; 
 
200
            break;
 
201
        /* Default terminal color */
 
202
        case 77: PJ_LOG_COLOR_77 = color; 
 
203
            break;
 
204
        default:
 
205
            /* Do nothing */
 
206
            break;
 
207
    }
 
208
}
 
209
 
 
210
PJ_DEF(pj_color_t) pj_log_get_color(int level)
 
211
{
 
212
    switch (level) {
 
213
        case 0:
 
214
            return PJ_LOG_COLOR_0;
 
215
        case 1:
 
216
            return PJ_LOG_COLOR_1;
 
217
        case 2:
 
218
            return PJ_LOG_COLOR_2;
 
219
        case 3:
 
220
            return PJ_LOG_COLOR_3;
 
221
        case 4:
 
222
            return PJ_LOG_COLOR_4;
 
223
        case 5:
 
224
            return PJ_LOG_COLOR_5;
 
225
        case 6:
 
226
            return PJ_LOG_COLOR_6;
 
227
        default:
 
228
            /* Return default terminal color */
 
229
            return PJ_LOG_COLOR_77;
 
230
    }
 
231
}
 
232
 
 
233
PJ_DEF(void) pj_log_set_level(int level)
 
234
{
 
235
    pj_log_max_level = level;
 
236
}
 
237
 
 
238
#if 1
 
239
PJ_DEF(int) pj_log_get_level(void)
 
240
{
 
241
    return pj_log_max_level;
 
242
}
 
243
#endif
 
244
 
 
245
PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
 
246
{
 
247
    log_writer = func;
 
248
}
 
249
 
 
250
PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
 
251
{
 
252
    return log_writer;
 
253
}
 
254
 
 
255
/* Temporarily suspend logging facility for this thread.
 
256
 * If thread local storage/variable is not used or not initialized, then
 
257
 * we can only suspend the logging globally across all threads. This may
 
258
 * happen e.g. when log function is called before PJLIB is fully initialized
 
259
 * or after PJLIB is shutdown.
 
260
 */
 
261
static void suspend_logging(int *saved_level)
 
262
{
 
263
        /* Save the level regardless, just in case PJLIB is shutdown
 
264
         * between suspend and resume.
 
265
         */
 
266
        *saved_level = pj_log_max_level;
 
267
 
 
268
#if PJ_HAS_THREADS
 
269
    if (thread_suspended_tls_id != -1) 
 
270
    {
 
271
        pj_thread_local_set(thread_suspended_tls_id, 
 
272
                            (void*)(pj_ssize_t)PJ_TRUE);
 
273
    } 
 
274
    else
 
275
#endif
 
276
    {
 
277
        pj_log_max_level = 0;
 
278
    }
 
279
}
 
280
 
 
281
/* Resume logging facility for this thread */
 
282
static void resume_logging(int *saved_level)
 
283
{
 
284
#if PJ_HAS_THREADS
 
285
    if (thread_suspended_tls_id != -1) 
 
286
    {
 
287
        pj_thread_local_set(thread_suspended_tls_id,
 
288
                            (void*)(pj_size_t)PJ_FALSE);
 
289
    }
 
290
    else
 
291
#endif
 
292
    {
 
293
        /* Only revert the level if application doesn't change the
 
294
         * logging level between suspend and resume.
 
295
         */
 
296
        if (pj_log_max_level==0 && *saved_level)
 
297
            pj_log_max_level = *saved_level;
 
298
    }
 
299
}
 
300
 
 
301
/* Is logging facility suspended for this thread? */
 
302
static pj_bool_t is_logging_suspended(void)
 
303
{
 
304
#if PJ_HAS_THREADS
 
305
    if (thread_suspended_tls_id != -1) 
 
306
    {
 
307
        return pj_thread_local_get(thread_suspended_tls_id) != NULL;
 
308
    }
 
309
    else
 
310
#endif
 
311
    {
 
312
        return pj_log_max_level == 0;
 
313
    }
 
314
}
 
315
 
 
316
PJ_DEF(void) pj_log( const char *sender, int level, 
 
317
                     const char *format, va_list marker)
 
318
{
 
319
    pj_time_val now;
 
320
    pj_parsed_time ptime;
 
321
    char *pre;
 
322
#if PJ_LOG_USE_STACK_BUFFER
 
323
    char log_buffer[PJ_LOG_MAX_SIZE];
 
324
#endif
 
325
    int saved_level, len, print_len, indent;
 
326
 
 
327
    PJ_CHECK_STACK();
 
328
 
 
329
    if (level > pj_log_max_level)
 
330
        return;
 
331
 
 
332
    if (is_logging_suspended())
 
333
        return;
 
334
 
 
335
    /* Temporarily disable logging for this thread. Some of PJLIB APIs that
 
336
     * this function calls below will recursively call the logging function 
 
337
     * back, hence it will cause infinite recursive calls if we allow that.
 
338
     */
 
339
    suspend_logging(&saved_level);
 
340
 
 
341
    /* Get current date/time. */
 
342
    pj_gettimeofday(&now);
 
343
    pj_time_decode(&now, &ptime);
 
344
 
 
345
    pre = log_buffer;
 
346
    if (log_decor & PJ_LOG_HAS_LEVEL_TEXT) {
 
347
        static const char *ltexts[] = { "FATAL:", "ERROR:", " WARN:", 
 
348
                              " INFO:", "DEBUG:", "TRACE:", "DETRC:"};
 
349
        pj_ansi_strcpy(pre, ltexts[level]);
 
350
        pre += 6;
 
351
    }
 
352
    if (log_decor & PJ_LOG_HAS_DAY_NAME) {
 
353
        static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
 
354
                                       "Thu", "Fri", "Sat"};
 
355
        pj_ansi_strcpy(pre, wdays[ptime.wday]);
 
356
        pre += 3;
 
357
    }
 
358
    if (log_decor & PJ_LOG_HAS_YEAR) {
 
359
        if (pre!=log_buffer) *pre++ = ' ';
 
360
        pre += pj_utoa(ptime.year, pre);
 
361
    }
 
362
    if (log_decor & PJ_LOG_HAS_MONTH) {
 
363
        *pre++ = '-';
 
364
        pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0');
 
365
    }
 
366
    if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
 
367
        *pre++ = '-';
 
368
        pre += pj_utoa_pad(ptime.day, pre, 2, '0');
 
369
    }
 
370
    if (log_decor & PJ_LOG_HAS_TIME) {
 
371
        if (pre!=log_buffer) *pre++ = ' ';
 
372
        pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
 
373
        *pre++ = ':';
 
374
        pre += pj_utoa_pad(ptime.min, pre, 2, '0');
 
375
        *pre++ = ':';
 
376
        pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
 
377
    }
 
378
    if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
 
379
        *pre++ = '.';
 
380
        pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
 
381
    }
 
382
    if (log_decor & PJ_LOG_HAS_SENDER) {
 
383
        enum { SENDER_WIDTH = 14 };
 
384
        pj_size_t sender_len = strlen(sender);
 
385
        if (pre!=log_buffer) *pre++ = ' ';
 
386
        if (sender_len <= SENDER_WIDTH) {
 
387
            while (sender_len < SENDER_WIDTH)
 
388
                *pre++ = ' ', ++sender_len;
 
389
            while (*sender)
 
390
                *pre++ = *sender++;
 
391
        } else {
 
392
            int i;
 
393
            for (i=0; i<SENDER_WIDTH; ++i)
 
394
                *pre++ = *sender++;
 
395
        }
 
396
    }
 
397
    if (log_decor & PJ_LOG_HAS_THREAD_ID) {
 
398
        enum { THREAD_WIDTH = 12 };
 
399
        const char *thread_name = pj_thread_get_name(pj_thread_this());
 
400
        pj_size_t thread_len = strlen(thread_name);
 
401
        *pre++ = ' ';
 
402
        if (thread_len <= THREAD_WIDTH) {
 
403
            while (thread_len < THREAD_WIDTH)
 
404
                *pre++ = ' ', ++thread_len;
 
405
            while (*thread_name)
 
406
                *pre++ = *thread_name++;
 
407
        } else {
 
408
            int i;
 
409
            for (i=0; i<THREAD_WIDTH; ++i)
 
410
                *pre++ = *thread_name++;
 
411
        }
 
412
    }
 
413
 
 
414
    if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
 
415
        *pre++ = ' ';
 
416
 
 
417
    if (log_decor & PJ_LOG_HAS_THREAD_SWC) {
 
418
        void *current_thread = (void*)pj_thread_this();
 
419
        if (current_thread != g_last_thread) {
 
420
            *pre++ = '!';
 
421
            g_last_thread = current_thread;
 
422
        } else {
 
423
            *pre++ = ' ';
 
424
        }
 
425
    } else if (log_decor & PJ_LOG_HAS_SPACE) {
 
426
        *pre++ = ' ';
 
427
    }
 
428
 
 
429
#if PJ_LOG_ENABLE_INDENT
 
430
    if (log_decor & PJ_LOG_HAS_INDENT) {
 
431
        indent = log_get_indent();
 
432
        if (indent > 0) {
 
433
            pj_memset(pre, PJ_LOG_INDENT_CHAR, indent);
 
434
            pre += indent;
 
435
        }
 
436
    }
 
437
#endif
 
438
 
 
439
    len = (int)(pre - log_buffer);
 
440
 
 
441
    /* Print the whole message to the string log_buffer. */
 
442
    print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format, 
 
443
                                  marker);
 
444
    if (print_len < 0) {
 
445
        level = 1;
 
446
        print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len, 
 
447
                                     "<logging error: msg too long>");
 
448
    }
 
449
    if (print_len < 1 || print_len >= (int)(sizeof(log_buffer)-len)) {
 
450
        print_len = sizeof(log_buffer) - len - 1;
 
451
    }
 
452
    len = len + print_len;
 
453
    if (len > 0 && len < (int)sizeof(log_buffer)-2) {
 
454
        if (log_decor & PJ_LOG_HAS_CR) {
 
455
            log_buffer[len++] = '\r';
 
456
        }
 
457
        if (log_decor & PJ_LOG_HAS_NEWLINE) {
 
458
            log_buffer[len++] = '\n';
 
459
        }
 
460
        log_buffer[len] = '\0';
 
461
    } else {
 
462
        len = sizeof(log_buffer)-1;
 
463
        if (log_decor & PJ_LOG_HAS_CR) {
 
464
            log_buffer[sizeof(log_buffer)-3] = '\r';
 
465
        }
 
466
        if (log_decor & PJ_LOG_HAS_NEWLINE) {
 
467
            log_buffer[sizeof(log_buffer)-2] = '\n';
 
468
        }
 
469
        log_buffer[sizeof(log_buffer)-1] = '\0';
 
470
    }
 
471
 
 
472
    /* It should be safe to resume logging at this point. Application can
 
473
     * recursively call the logging function inside the callback.
 
474
     */
 
475
    resume_logging(&saved_level);
 
476
 
 
477
    if (log_writer)
 
478
        (*log_writer)(level, log_buffer, len);
 
479
}
 
480
 
 
481
/*
 
482
PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
 
483
{
 
484
    va_list arg;
 
485
    va_start(arg, format);
 
486
    pj_log(obj, 0, format, arg);
 
487
    va_end(arg);
 
488
}
 
489
*/
 
490
 
 
491
PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
 
492
{
 
493
    va_list arg;
 
494
    va_start(arg, format);
 
495
    pj_log(obj, 1, format, arg);
 
496
    va_end(arg);
 
497
}
 
498
#endif  /* PJ_LOG_MAX_LEVEL >= 1 */
 
499
 
 
500
#if PJ_LOG_MAX_LEVEL >= 2
 
501
PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
 
502
{
 
503
    va_list arg;
 
504
    va_start(arg, format);
 
505
    pj_log(obj, 2, format, arg);
 
506
    va_end(arg);
 
507
}
 
508
#endif
 
509
 
 
510
#if PJ_LOG_MAX_LEVEL >= 3
 
511
PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
 
512
{
 
513
    va_list arg;
 
514
    va_start(arg, format);
 
515
    pj_log(obj, 3, format, arg);
 
516
    va_end(arg);
 
517
}
 
518
#endif
 
519
 
 
520
#if PJ_LOG_MAX_LEVEL >= 4
 
521
PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
 
522
{
 
523
    va_list arg;
 
524
    va_start(arg, format);
 
525
    pj_log(obj, 4, format, arg);
 
526
    va_end(arg);
 
527
}
 
528
#endif
 
529
 
 
530
#if PJ_LOG_MAX_LEVEL >= 5
 
531
PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
 
532
{
 
533
    va_list arg;
 
534
    va_start(arg, format);
 
535
    pj_log(obj, 5, format, arg);
 
536
    va_end(arg);
 
537
}
 
538
#endif
 
539
 
 
540
#if PJ_LOG_MAX_LEVEL >= 6
 
541
PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
 
542
{
 
543
    va_list arg;
 
544
    va_start(arg, format);
 
545
    pj_log(obj, 6, format, arg);
 
546
    va_end(arg);
 
547
}
 
548
#endif
 
549