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>
27 #define AFS_DAEMON_EVENT_NAME "TransarcAFSDaemon"
29 /* the size; overrideable */
30 long osi_logSize = OSI_LOG_DEFAULTSIZE;
32 static osi_once_t osi_logOnce;
34 osi_log_t *osi_allLogsp; /* all logs known; for use during panic */
36 unsigned long osi_logFreq; /* 0, or frequency of high perf counter */
37 unsigned long osi_logTixToMicros; /* mult. correction factor */
39 osi_fdOps_t osi_logFDOps = {
47 /* create a new log, taking a name and a size in entries (not words) */
48 osi_log_t *osi_LogCreate(char *namep, long size)
53 LARGE_INTEGER bigFreq;
54 LARGE_INTEGER bigTemp;
55 LARGE_INTEGER bigJunk;
58 if (osi_Once(&osi_logOnce)) {
59 QueryPerformanceFrequency(&bigFreq);
60 if (bigFreq.LowPart == 0 && bigFreq.HighPart == 0)
63 /* turn frequency into ticks per 10 micros */
64 bigTemp.LowPart = 100000;
66 osi_logTixToMicros = 10;
67 bigFreq = LargeIntegerDivide(bigFreq, bigTemp, &bigJunk);
69 /* check if resolution is too fine or to gross for this to work */
70 if (bigFreq.HighPart > 0 || bigFreq.LowPart < 8)
71 osi_logFreq = 0; /* too big to represent as long */
73 osi_logFreq = bigFreq.LowPart;
77 osi_EndOnce(&osi_logOnce);
81 logp = malloc(sizeof(osi_log_t));
82 memset(logp, 0, sizeof(osi_log_t));
83 logp->namep = malloc(strlen(namep)+1);
84 strcpy(logp->namep, namep);
86 osi_QAdd((osi_queue_t **) &osi_allLogsp, &logp->q);
88 /* compute size we'll use */
89 if (size == 0) size = osi_logSize;
91 /* handle init for this size */
93 logp->datap = malloc(size * sizeof(osi_logEntry_t));
95 /* init strings array */
96 logp->maxstringindex = size/10;
97 logp->stringindex = 0;
98 logp->stringsp = malloc((size/10) * OSI_LOG_STRINGSIZE);
101 thrd_InitCrit(&logp->cs);
103 strcpy(tbuffer, "log:");
104 strcat(tbuffer, namep);
105 typep = osi_RegisterFDType(tbuffer, &osi_logFDOps, logp);
108 /* add formatting info */
109 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
110 "Thread ID", OSI_DBRPC_HEX);
111 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 1,
119 /* we just panic'd. Turn off all logging adding special log record
120 * to all enabled logs. Be careful not to wait for a lock.
122 void osi_LogPanic(char *filep, long lineNumber)
126 for(tlp = osi_allLogsp; tlp; tlp = (osi_log_t *) osi_QNext(&tlp->q)) {
127 if (!tlp->enabled) continue;
129 /* otherwise, proceed */
131 osi_LogAdd(tlp, "**PANIC** (file %s:%d)", (long) filep, lineNumber, 0, 0);
133 osi_LogAdd(tlp, "**PANIC**", 0, 0, 0, 0);
135 /* should grab lock for this, but we're in panic, and better safe than
142 /* reset the contents of a log */
143 void osi_LogReset(osi_log_t *logp)
146 thrd_EnterCrit(&logp->cs);
148 thrd_LeaveCrit(&logp->cs);
153 void osi_LogFree(osi_log_t *logp)
157 osi_QRemove((osi_queue_t **) &osi_allLogsp, &logp->q);
161 thrd_DeleteCrit(&logp->cs);
165 /* add an element to a log */
166 void osi_LogAdd(osi_log_t *logp, char *formatp, long p0, long p1, long p2, long p3)
170 LARGE_INTEGER bigTime;
172 /* handle init races */
175 /* do this w/o locking for speed; it is obviously harmless if we're off
178 if (!logp->enabled) return;
180 thrd_EnterCrit(&logp->cs);
181 if (logp->nused < logp->alloc) logp->nused++;
184 if (logp->first >= logp->alloc) logp->first -= logp->alloc;
186 ix = logp->first + logp->nused - 1;
187 if (ix >= logp->alloc) ix -= logp->alloc;
189 lep = logp->datap + ix; /* ptr arith */
190 lep->tid = thrd_Current();
192 /* get the time, using the high res timer if available */
195 QueryPerformanceCounter(&bigTime);
196 lep->micros = (bigTime.LowPart / osi_logFreq) * osi_logTixToMicros;
198 else lep->micros = GetCurrentTime() * 1000;
200 lep->micros = gettime_us();
203 lep->formatp = formatp;
210 printf( "%9ld:", lep->micros );
211 printf( formatp, p0, p1, p2, p3);
215 thrd_LeaveCrit(&logp->cs);
218 void osi_LogPrint(osi_log_t *logp, FILE_HANDLE handle)
220 char wholemsg[1000], msg[1000];
224 if (!logp->enabled) return;
226 thrd_EnterCrit(&logp->cs);
228 for (ix = logp->first, i = 0;
230 i++, ix++, (ix >= logp->alloc ? ix -= logp->alloc : 0)) {
231 lep = logp->datap + ix; /* pointer arithmetic */
232 sprintf(msg, lep->formatp,
233 lep->parms[0], lep->parms[1],
234 lep->parms[2], lep->parms[3]);
235 sprintf(wholemsg, "time %d.%06d, pid %d %s\n",
236 lep->micros / 1000000,
237 lep->micros % 1000000,
240 if (!WriteFile(handle, wholemsg, strlen(wholemsg),
243 if ((ioCount = fwrite(wholemsg, 1, strlen(wholemsg), handle)) == 0)
248 thrd_LeaveCrit(&logp->cs);
251 char *osi_LogSaveString(osi_log_t *logp, char *s)
253 char *saveplace = logp->stringsp[logp->stringindex];
255 if (s == NULL) return NULL;
257 if (strlen(s) >= OSI_LOG_STRINGSIZE)
258 sprintf(saveplace, "...%s",
259 s + strlen(s) - (OSI_LOG_STRINGSIZE - 4));
261 strcpy(saveplace, s);
263 if (logp->stringindex >= logp->maxstringindex)
264 logp->stringindex = 0;
269 long osi_LogFDCreate(osi_fdType_t *typep, osi_fd_t **outpp)
274 lfdp = malloc(sizeof(*lfdp));
275 logp = lfdp->logp = typep->rockp; /* the log we were created for */
276 thrd_EnterCrit(&logp->cs);
277 lfdp->nused = logp->nused;
278 lfdp->first = logp->first;
280 thrd_LeaveCrit(&logp->cs);
287 long osi_LogFDGetInfo(osi_fd_t *ifd, osi_remGetInfoParms_t *outp)
295 lfdp = (osi_logFD_t *) ifd;
298 /* see if we're done */
299 if (lfdp->current >= lfdp->nused) return OSI_DBRPC_EOF;
302 thrd_EnterCrit(&logp->cs);
304 /* compute which one we want */
305 ix = lfdp->first + lfdp->current;
306 if (ix >= logp->alloc) ix -= logp->alloc;
308 lep = logp->datap + ix; /* ptr arith to current index */
310 sprintf(tbuffer, lep->formatp, lep->parms[0], lep->parms[1],
311 lep->parms[2], lep->parms[3]);
313 /* now copy out info */
314 strcpy(outp->sdata[0], tbuffer);
315 sprintf(tbuffer, "%5.6f", ((double)lep->micros)/1000000.0);
316 strcpy(outp->sdata[1], tbuffer);
317 outp->idata[0] = lep->tid;
321 thrd_LeaveCrit(&logp->cs);
326 long osi_LogFDClose(osi_fd_t *ifdp)
332 void osi_LogEnable(osi_log_t *logp)
338 void osi_LogDisable(osi_log_t *logp)
344 #define REG_CLIENT_PARMS_KEY "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
345 #define TRACE_OPTION_EVENT 1
346 #define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
348 DWORD osi_TraceOption=0;
350 void osi_InitTraceOption()
352 DWORD LSPtype, LSPsize;
354 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
355 0, KEY_QUERY_VALUE, &NPKey);
356 LSPsize=sizeof(osi_TraceOption);
357 RegQueryValueEx(NPKey, "TraceOption", NULL,
358 &LSPtype, (LPBYTE)&osi_TraceOption, &LSPsize);
363 void osi_LogEvent0(char *a,char *b)
367 if (!ISLOGONTRACE(osi_TraceOption))
369 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
371 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
372 DeregisterEventSource(h);
376 void osi_LogEvent(char *a,char *b,char *c,...)
378 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
380 if (!ISLOGONTRACE(osi_TraceOption))
382 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
384 _vsnprintf(buf,MAXBUF_,c,marker);
386 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
387 DeregisterEventSource(h);
391 char *osi_HexifyString(char *s) {
393 char *hex = "0123456789abcdef";
394 char *buf, *counter, *bufp;
398 bufp = buf = malloc( len * 3 ); /* [xx.xx.xx.xx\0] */
400 if(!buf) return NULL;
402 for(counter = s; *counter; counter ++) {
403 if(counter != s) *bufp++ = '.';
405 *bufp++ = hex[(c>>4) & 0xf];
406 *bufp++ = hex[c & 0xf];