1
/* Copyright (C) 2005 PrimeBase Technologies GmbH
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* 2005-02-07 Paul McCullagh
24
#include "xt_config.h"
33
#include "pthread_xt.h"
34
#include "thread_xt.h"
38
//#define RESET_AFTER_DUMP
39
//#define DUMP_TO_STDOUT
42
static xtBool trace_initialized = FALSE;
43
static xt_mutex_type trace_mutex;
44
static size_t trace_log_size;
45
static size_t trace_log_offset;
46
static size_t trace_log_end;
47
static char *trace_log_buffer;
48
static u_long trace_stat_count;
49
static FILE *trace_dump_file;
50
static xtBool trace_flush_dump = FALSE;
52
#define DEFAULT_TRACE_LOG_SIZE (40*1024*1204)
53
#define MAX_PRINT_LEN 2000
55
xtPublic xtBool xt_init_trace(void)
59
err = xt_p_mutex_init_with_autoname(&trace_mutex, NULL);
61
xt_log_errno(XT_NS_CONTEXT, err);
62
trace_initialized = FALSE;
65
trace_initialized = TRUE;
66
trace_log_buffer = (char *) malloc(DEFAULT_TRACE_LOG_SIZE+1);
67
if (!trace_log_buffer) {
68
xt_log_errno(XT_NS_CONTEXT, ENOMEM);
72
trace_log_size = DEFAULT_TRACE_LOG_SIZE;
77
#ifdef XT_TRACK_CONNECTIONS
78
for (int i=0; i<XT_TRACK_MAX_CONNS; i++)
79
xt_track_conn_info[i].cu_t_id = i;
85
xtPublic void xt_exit_trace(void)
87
if (trace_initialized) {
91
xt_free_mutex(&trace_mutex);
92
trace_initialized = FALSE;
94
free(trace_log_buffer);
95
trace_log_buffer = NULL;
101
if (trace_dump_file) {
102
fclose(trace_dump_file);
103
trace_dump_file = NULL;
107
xtPublic void xt_print_trace(void)
109
if (trace_log_offset) {
110
xt_lock_mutex_ns(&trace_mutex);
111
if (trace_log_end > trace_log_offset+1) {
112
trace_log_buffer[trace_log_end] = 0;
113
printf("%s", trace_log_buffer + trace_log_offset + 1);
115
trace_log_buffer[trace_log_offset] = 0;
116
printf("%s", trace_log_buffer);
117
trace_log_offset = 0;
119
xt_unlock_mutex_ns(&trace_mutex);
123
xtPublic void xt_dump_trace(void)
125
if (trace_log_offset) {
126
#ifdef DUMP_TO_STDOUT
127
if (trace_log_end > trace_log_offset+1) {
128
trace_log_buffer[trace_log_end] = 0;
129
printf("%s", trace_log_buffer + trace_log_offset + 1);
131
trace_log_buffer[trace_log_offset] = 0;
132
printf("%s", trace_log_buffer);
137
fp = fopen("pbxt.log", "w");
139
xt_lock_mutex_ns(&trace_mutex);
141
if (trace_log_end > trace_log_offset+1) {
142
trace_log_buffer[trace_log_end] = 0;
143
fprintf(fp, "%s", trace_log_buffer + trace_log_offset + 1);
145
trace_log_buffer[trace_log_offset] = 0;
146
fprintf(fp, "%s", trace_log_buffer);
151
#ifdef RESET_AFTER_DUMP
152
trace_log_offset = 0;
154
trace_stat_count = 0;
156
xt_unlock_mutex_ns(&trace_mutex);
159
if (trace_dump_file) {
160
xt_lock_mutex_ns(&trace_mutex);
161
if (trace_dump_file) {
162
fflush(trace_dump_file);
163
fclose(trace_dump_file);
164
trace_dump_file = NULL;
166
xt_unlock_mutex_ns(&trace_mutex);
170
xtPublic void xt_trace(const char *fmt, ...)
176
xt_lock_mutex_ns(&trace_mutex);
178
if (trace_log_offset + MAX_PRINT_LEN > trace_log_size) {
179
/* Start at the beginning of the buffer again: */
180
trace_log_end = trace_log_offset;
181
trace_log_offset = 0;
184
len = (size_t) vsnprintf(trace_log_buffer + trace_log_offset, trace_log_size - trace_log_offset, fmt, ap);
185
trace_log_offset += len;
187
xt_unlock_mutex_ns(&trace_mutex);
195
xtPublic void xt_ttracef(XTThreadPtr self, char *fmt, ...)
201
xt_lock_mutex_ns(&trace_mutex);
203
if (trace_log_offset + MAX_PRINT_LEN > trace_log_size) {
204
trace_log_end = trace_log_offset;
205
trace_log_offset = 0;
209
len = (size_t) sprintf(trace_log_buffer + trace_log_offset, "%lu %s: ", trace_stat_count, self->t_name);
210
trace_log_offset += len;
211
len = (size_t) vsnprintf(trace_log_buffer + trace_log_offset, trace_log_size - trace_log_offset, fmt, ap);
212
trace_log_offset += len;
214
xt_unlock_mutex_ns(&trace_mutex);
222
xtPublic void xt_ttraceq(XTThreadPtr self, char *query)
224
size_t qlen = strlen(query), tlen;
228
self = xt_get_self();
230
xt_lock_mutex_ns(&trace_mutex);
232
if (trace_log_offset + qlen + 100 >= trace_log_size) {
233
/* Start at the beginning of the buffer again: */
234
trace_log_end = trace_log_offset;
235
trace_log_offset = 0;
239
tlen = (size_t) sprintf(trace_log_buffer + trace_log_offset, "%lu %s: ", trace_stat_count, self->t_name);
240
trace_log_offset += tlen;
242
ptr = trace_log_buffer + trace_log_offset;
246
if (*qptr == '\n' || *qptr == '\r')
250
if (*qptr == '\n' || *qptr == '\r' || *qptr == ' ') {
252
while (*qptr == '\n' || *qptr == '\r' || *qptr == ' ')
261
trace_log_offset += qlen;
262
*(trace_log_buffer + trace_log_offset) = '\n';
263
*(trace_log_buffer + trace_log_offset + 1) = '\0';
266
xt_unlock_mutex_ns(&trace_mutex);
274
* Returns the time in microseconds.
275
* (1/1000000 of a second)
277
xtPublic xtWord8 xt_trace_clock(void)
279
static xtWord8 trace_start_clock = 0;
283
now = ((xtWord8) GetTickCount()) * (xtWord8) 1000;
287
gettimeofday(&tv, NULL);
288
now = (xtWord8) tv.tv_sec * (xtWord8) 1000000 + tv.tv_usec;
290
if (trace_start_clock)
291
return now - trace_start_clock;
292
trace_start_clock = now;
296
xtPublic char *xt_trace_clock_str(char *ptr)
298
static char buffer[50];
299
xtWord8 now = xt_trace_clock();
304
sprintf(ptr, "%d.%06d", (int) (now / (xtWord8) 1000000), (int) (now % (xtWord8) 1000000));
308
xtPublic char *xt_trace_clock_diff(char *ptr)
310
static xtWord8 trace_last_clock = 0;
311
static char buffer[50];
312
xtWord8 now = xt_trace_clock();
317
sprintf(ptr, "%d.%06d (%d)", (int) (now / (xtWord8) 1000000), (int) (now % (xtWord8) 1000000), (int) (now - trace_last_clock));
318
trace_last_clock = now;
322
xtPublic char *xt_trace_clock_diff(char *ptr, xtWord8 start_time)
324
xtWord8 now = xt_trace_clock();
326
sprintf(ptr, "%d.%06d (%d)", (int) (now / (xtWord8) 1000000), (int) (now % (xtWord8) 1000000), (int) (now - start_time));
331
xtPublic void xt_set_fflush(xtBool on)
333
trace_flush_dump = on;
336
xtPublic void xt_ftracef(char *fmt, ...)
341
xt_lock_mutex_ns(&trace_mutex);
343
if (!trace_dump_file) {
346
for (int i=1; ;i++) {
347
sprintf(buffer, "pbxt-dump-%d.log", i);
348
if (!xt_fs_exists(buffer)) {
349
trace_dump_file = fopen(buffer, "w");
355
vfprintf(trace_dump_file, fmt, ap);
356
if (trace_flush_dump)
357
fflush(trace_dump_file);
359
xt_unlock_mutex_ns(&trace_mutex);
364
* -----------------------------------------------------------------------
365
* CONNECTION TRACKING
368
#ifdef XT_TRACK_CONNECTIONS
369
XTConnInfoRec xt_track_conn_info[XT_TRACK_MAX_CONNS];
371
static int trace_comp_conn_info(const void *a, const void *b)
373
XTConnInfoPtr ci_a = (XTConnInfoPtr) a, ci_b = (XTConnInfoPtr) b;
375
if (ci_a->ci_curr_xact_id > ci_b->ci_curr_xact_id)
377
if (ci_a->ci_curr_xact_id < ci_b->ci_curr_xact_id)
382
xtPublic void xt_dump_conn_tracking(void)
384
XTConnInfoRec conn_info[XT_TRACK_MAX_CONNS];
387
memcpy(conn_info, xt_track_conn_info, sizeof(xt_track_conn_info));
388
qsort(conn_info, XT_TRACK_MAX_CONNS, sizeof(XTConnInfoRec), trace_comp_conn_info);
391
for (int i=0; i<XT_TRACK_MAX_CONNS; i++) {
392
if (ptr->ci_curr_xact_id || ptr->ci_prev_xact_id) {
393
printf("%3d curr=%d prev=%d prev-time=%ld\n", (int) ptr->cu_t_id, (int) ptr->ci_curr_xact_id, (int) ptr->ci_prev_xact_id, (long) ptr->ci_prev_xact_time);
394
if (i+1<XT_TRACK_MAX_CONNS) {
395
printf(" diff=%d\n", (int) (ptr+1)->ci_curr_xact_id - (int) ptr->ci_curr_xact_id);