2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Copyright (C) 1994 Cazamar Systems, Inc. */
12 #include <afs/param.h>
22 #include <WINNT\afsreg.h>
25 #define AFS_DAEMON_EVENT_NAME "TransarcAFSDaemon"
27 /* the size; overrideable */
28 long osi_logSize
= OSI_LOG_DEFAULTSIZE
;
30 static osi_once_t osi_logOnce
;
32 osi_log_t
*osi_allLogsp
; /* all logs known; for use during panic */
34 unsigned long osi_logFreq
; /* 0, or frequency of high perf counter */
35 unsigned long osi_logTixToMicros
; /* mult. correction factor */
37 #define TRACE_OPTION_EVENT 2
38 #define TRACE_OPTION_DEBUGLOG 4
40 #define ISCLIENTTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
41 #define ISCLIENTDEBUGLOG(v) (((v) & TRACE_OPTION_DEBUGLOG)==TRACE_OPTION_DEBUGLOG)
43 DWORD osi_TraceOption
=0;
45 osi_fdOps_t osi_logFDOps
= {
51 /* create a new log, taking a name and a size in entries (not words) */
52 osi_log_t
*osi_LogCreate(char *namep
, size_t size
)
57 LARGE_INTEGER bigFreq
;
58 LARGE_INTEGER bigTemp
;
59 LARGE_INTEGER bigJunk
;
61 if (osi_Once(&osi_logOnce
)) {
62 QueryPerformanceFrequency(&bigFreq
);
63 if (bigFreq
.LowPart
== 0 && bigFreq
.HighPart
== 0)
66 /* turn frequency into ticks per 10 micros */
67 bigTemp
.LowPart
= 100000;
69 osi_logTixToMicros
= 10;
70 bigFreq
= LargeIntegerDivide(bigFreq
, bigTemp
, &bigJunk
);
72 /* check if resolution is too fine or to gross for this to work */
73 if (bigFreq
.HighPart
> 0 || bigFreq
.LowPart
< 8)
74 osi_logFreq
= 0; /* too big to represent as long */
76 osi_logFreq
= bigFreq
.LowPart
;
80 osi_EndOnce(&osi_logOnce
);
83 logp
= malloc(sizeof(osi_log_t
));
84 memset(logp
, 0, sizeof(osi_log_t
));
86 size_t namelen
= strlen(namep
) + 1;
88 logp
->namep
= malloc(namelen
* sizeof(char));
89 StringCchCopyA(logp
->namep
, namelen
, namep
);
91 osi_QAdd((osi_queue_t
**) &osi_allLogsp
, &logp
->q
);
93 /* compute size we'll use */
94 if (size
== 0) size
= osi_logSize
;
96 /* handle init for this size */
98 logp
->datap
= malloc(size
* sizeof(osi_logEntry_t
));
100 /* init strings array */
101 logp
->maxstringindex
= size
/3;
102 logp
->stringindex
= 0;
103 logp
->stringsp
= malloc(logp
->maxstringindex
* OSI_LOG_STRINGSIZE
);
106 thrd_InitCrit(&logp
->cs
);
108 StringCbCopyA(tbuffer
, sizeof(tbuffer
), "log:");
109 StringCbCatA(tbuffer
, sizeof(tbuffer
), namep
);
110 typep
= osi_RegisterFDType(tbuffer
, &osi_logFDOps
, logp
);
112 /* add formatting info */
113 osi_AddFDFormatInfo(typep
, OSI_DBRPC_REGIONINT
, 0,
114 "Thread ID", OSI_DBRPC_HEX
);
115 osi_AddFDFormatInfo(typep
, OSI_DBRPC_REGIONSTRING
, 1,
122 /* we just panic'd. Log the error to all enabled log files.
123 * Be careful not to wait for a lock.
125 void osi_LogPanic(char *msgp
, char *filep
, size_t lineNumber
)
129 for(tlp
= osi_allLogsp
; tlp
; tlp
= (osi_log_t
*) osi_QNext(&tlp
->q
)) {
130 if (!tlp
->enabled
) continue;
132 /* otherwise, proceed */
134 osi_LogAdd(tlp
, "**PANIC** \"%s\" (file %s:%d)", (size_t)msgp
, (size_t) filep
, lineNumber
, 0, 0);
136 osi_LogAdd(tlp
, "**PANIC** \"%s\"", (size_t)msgp
, 0, 0, 0, 0);
138 /* should grab lock for this, but we're in panic, and better safe than
145 /* reset the contents of a log */
146 void osi_LogReset(osi_log_t
*logp
)
149 thrd_EnterCrit(&logp
->cs
);
151 thrd_LeaveCrit(&logp
->cs
);
156 void osi_LogFree(osi_log_t
*logp
)
160 osi_QRemove((osi_queue_t
**) &osi_allLogsp
, &logp
->q
);
164 thrd_DeleteCrit(&logp
->cs
);
168 /* add an element to a log */
170 osi_IntLogAdd(osi_log_t
*logp
, int debug
, char *formatp
, size_t p0
, size_t p1
, size_t p2
, size_t p3
, size_t p4
)
174 LARGE_INTEGER bigTime
;
176 /* handle init races */
180 /* do this w/o locking for speed; it is obviously harmless if we're off
185 thrd_EnterCrit(&logp
->cs
);
186 if (logp
->nused
< logp
->alloc
)
190 if (logp
->first
>= logp
->alloc
)
191 logp
->first
-= logp
->alloc
;
193 ix
= logp
->first
+ logp
->nused
- 1;
194 if (ix
>= logp
->alloc
)
197 lep
= logp
->datap
+ ix
; /* ptr arith */
198 lep
->tid
= thrd_Current();
200 /* get the time, using the high res timer if available */
202 QueryPerformanceCounter(&bigTime
);
203 lep
->micros
= (bigTime
.LowPart
/ osi_logFreq
) * osi_logTixToMicros
;
205 else lep
->micros
= GetCurrentTime() * 1000;
207 lep
->formatp
= formatp
;
214 printf( "%9ld:", lep
->micros
);
215 printf( formatp
, p0
, p1
, p2
, p3
, p4
);
218 thrd_LeaveCrit(&logp
->cs
);
221 if (debug
|| (logp
->enabled
&& ISCLIENTDEBUGLOG(osi_TraceOption
))) {
222 char wholemsg
[1024], msg
[1000];
224 StringCbPrintfA(msg
, sizeof(msg
), formatp
,
226 StringCbPrintfA(wholemsg
, sizeof(wholemsg
),
228 thrd_Current(), msg
);
229 OutputDebugStringA(wholemsg
);
233 void osi_LogAdd(osi_log_t
*logp
, char *formatp
, size_t p0
, size_t p1
, size_t p2
, size_t p3
, size_t p4
)
235 osi_IntLogAdd(logp
, FALSE
, formatp
, p0
, p1
, p2
, p3
, p4
);
238 void osi_DebugAdd(osi_log_t
*logp
, char *formatp
, size_t p0
, size_t p1
, size_t p2
, size_t p3
, size_t p4
)
240 osi_IntLogAdd(logp
, TRUE
, formatp
, p0
, p1
, p2
, p3
, p4
);
243 void osi_LogPrint(osi_log_t
*logp
, FILE_HANDLE handle
)
245 char wholemsg
[1024], msg
[1000];
249 if (!logp
->enabled
) return;
251 thrd_EnterCrit(&logp
->cs
);
253 for (ix
= logp
->first
, i
= 0;
255 i
++, ix
++, (ix
>= logp
->alloc
? ix
-= logp
->alloc
: 0)) {
256 lep
= logp
->datap
+ ix
; /* pointer arithmetic */
257 StringCbPrintfA(msg
, sizeof(msg
), lep
->formatp
,
258 lep
->parms
[0], lep
->parms
[1],
259 lep
->parms
[2], lep
->parms
[3],
261 StringCbPrintfA(wholemsg
, sizeof(wholemsg
),
262 "time %d.%06d, tid %d %s\r\n",
263 lep
->micros
/ 1000000,
264 lep
->micros
% 1000000,
266 if (!WriteFile(handle
, wholemsg
, strlen(wholemsg
),
271 thrd_LeaveCrit(&logp
->cs
);
274 char *osi_LogSaveString(osi_log_t
*logp
, char *s
)
280 if (!logp
->enabled
) return s
;
282 if (s
== NULL
) return NULL
;
284 thrd_EnterCrit(&logp
->cs
);
286 saveplace
= logp
->stringsp
[logp
->stringindex
];
288 if (strlen(s
) >= OSI_LOG_STRINGSIZE
)
289 StringCbPrintfA(saveplace
, OSI_LOG_STRINGSIZE
,
291 s
+ strlen(s
) - (OSI_LOG_STRINGSIZE
- 4));
293 StringCbCopyA(saveplace
, OSI_LOG_STRINGSIZE
, s
);
297 if (logp
->stringindex
>= logp
->maxstringindex
)
298 logp
->stringindex
= 0;
300 thrd_LeaveCrit(&logp
->cs
);
305 wchar_t *osi_LogSaveStringW(osi_log_t
*logp
, wchar_t *s
)
311 if (!logp
->enabled
) return s
;
313 if (s
== NULL
) return NULL
;
315 thrd_EnterCrit(&logp
->cs
);
317 saveplace
= (wchar_t *) (logp
->stringsp
[logp
->stringindex
]);
319 if (wcslen(s
)*sizeof(wchar_t) >= OSI_LOG_STRINGSIZE
)
320 StringCbPrintfW(saveplace
, OSI_LOG_STRINGSIZE
, L
"...%s",
321 (s
+ wcslen(s
) - (OSI_LOG_STRINGSIZE
/sizeof(wchar_t) - 4)));
323 StringCbCopyW(saveplace
, OSI_LOG_STRINGSIZE
, s
);
327 if (logp
->stringindex
>= logp
->maxstringindex
)
328 logp
->stringindex
= 0;
330 thrd_LeaveCrit(&logp
->cs
);
335 long osi_LogFDCreate(osi_fdType_t
*typep
, osi_fd_t
**outpp
)
340 lfdp
= malloc(sizeof(*lfdp
));
341 logp
= lfdp
->logp
= typep
->rockp
; /* the log we were created for */
342 thrd_EnterCrit(&logp
->cs
);
343 lfdp
->nused
= logp
->nused
;
344 lfdp
->first
= logp
->first
;
346 thrd_LeaveCrit(&logp
->cs
);
352 long osi_LogFDGetInfo(osi_fd_t
*ifd
, osi_remGetInfoParms_t
*outp
)
360 lfdp
= (osi_logFD_t
*) ifd
;
363 /* see if we're done */
364 if (lfdp
->current
>= lfdp
->nused
) return OSI_DBRPC_EOF
;
367 thrd_EnterCrit(&logp
->cs
);
369 /* compute which one we want */
370 ix
= lfdp
->first
+ lfdp
->current
;
371 if (ix
>= logp
->alloc
) ix
-= logp
->alloc
;
373 lep
= logp
->datap
+ ix
; /* ptr arith to current index */
375 StringCbPrintfA(tbuffer
, sizeof(tbuffer
), lep
->formatp
, lep
->parms
[0], lep
->parms
[1],
376 lep
->parms
[2], lep
->parms
[3], lep
->parms
[4]);
378 /* now copy out info */
379 StringCbCopyA(outp
->sdata
[0], sizeof(outp
->sdata
[0]), tbuffer
);
380 StringCbPrintfA(tbuffer
, sizeof(tbuffer
), "%5.6f", ((double)lep
->micros
)/1000000.0);
381 StringCbCopyA(outp
->sdata
[1], sizeof(outp
->sdata
[0]), tbuffer
);
382 outp
->idata
[0] = lep
->tid
;
386 thrd_LeaveCrit(&logp
->cs
);
390 long osi_LogFDClose(osi_fd_t
*ifdp
)
396 void osi_LogEnable(osi_log_t
*logp
)
402 void osi_LogDisable(osi_log_t
*logp
)
408 void osi_InitTraceOption()
410 DWORD LSPtype
, LSPsize
;
412 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE
, AFSREG_CLT_SVC_PARAM_SUBKEY
,
413 0, KEY_QUERY_VALUE
, &NPKey
);
414 LSPsize
=sizeof(osi_TraceOption
);
415 RegQueryValueEx(NPKey
, "TraceOption", NULL
,
416 &LSPtype
, (LPBYTE
)&osi_TraceOption
, &LSPsize
);
421 void osi_LogEvent0(char *a
,char *b
)
425 if (!ISCLIENTTRACE(osi_TraceOption
))
427 h
= RegisterEventSource(NULL
, AFS_DAEMON_EVENT_NAME
);
429 ReportEvent(h
, EVENTLOG_INFORMATION_TYPE
, 0, 0, NULL
, 1, 0, (const char **)ptbuf
, NULL
);
430 DeregisterEventSource(h
);
434 void osi_LogEvent(char *a
,char *b
,char *c
,...)
436 HANDLE h
; char *ptbuf
[1],buf
[MAXBUF_
+1];
438 if (!ISCLIENTTRACE(osi_TraceOption
))
440 h
= RegisterEventSource(NULL
, AFS_DAEMON_EVENT_NAME
);
442 StringCbVPrintfA(buf
,MAXBUF_
,c
,marker
);
444 ReportEvent(h
, EVENTLOG_INFORMATION_TYPE
, 0, 0, NULL
, 1, 0, (const char **)ptbuf
, NULL
);\
445 DeregisterEventSource(h
);
449 char *osi_HexifyString(char *s
) {
451 char *hex
= "0123456789abcdef";
452 char *buf
, *counter
, *bufp
;
456 bufp
= buf
= malloc( len
* 3 ); /* [xx.xx.xx.xx\0] */
458 if(!buf
) return NULL
;
460 for(counter
= s
; *counter
; counter
++) {
461 if(counter
!= s
) *bufp
++ = '.';
463 *bufp
++ = hex
[(c
>>4) & 0xf];
464 *bufp
++ = hex
[c
& 0xf];