windows-updates-including-dont-lose-tokens-20011110
[openafs.git] / src / WINNT / client_osi / osilog.c
1 /* 
2  * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
3  *
4  * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5  * LICENSED MATERIALS - PROPERTY OF IBM
6  *
7  */
8
9 /* Copyright (C) 1994 Cazamar Systems, Inc. */
10
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #ifndef DJGPP
15 #include <windows.h>
16 #include <rpc.h>
17 #endif /* !DJGPP */
18 #include <malloc.h>
19 #include "osi.h"
20 #ifndef DJGPP
21 #include "dbrpc.h"
22 #endif /* !DJGPP */
23 #include <stdio.h>
24 #include <assert.h>
25
26 /* the size; overrideable */
27 long osi_logSize = OSI_LOG_DEFAULTSIZE;
28
29 static osi_once_t osi_logOnce;
30
31 osi_log_t *osi_allLogsp;        /* all logs known; for use during panic */
32
33 unsigned long osi_logFreq;      /* 0, or frequency of high perf counter */
34 unsigned long osi_logTixToMicros;       /* mult. correction factor */
35
36 osi_fdOps_t osi_logFDOps = {
37         osi_LogFDCreate,
38 #ifndef DJGPP
39         osi_LogFDGetInfo,
40 #endif
41         osi_LogFDClose
42 };
43
44 /* create a new log, taking a name and a size in entries (not words) */
45 osi_log_t *osi_LogCreate(char *namep, long size)
46 {
47         osi_log_t *logp;
48         osi_fdType_t *typep;
49         char tbuffer[256];
50         LARGE_INTEGER bigFreq;
51         LARGE_INTEGER bigTemp;
52         LARGE_INTEGER bigJunk;
53         
54 #ifndef DJGPP
55         if (osi_Once(&osi_logOnce)) {
56                 QueryPerformanceFrequency(&bigFreq);
57                 if (bigFreq.LowPart == 0 && bigFreq.HighPart == 0)
58                         osi_logFreq = 0;
59                 else {
60                         /* turn frequency into ticks per 10 micros */
61                         bigTemp.LowPart = 100000;
62                         bigTemp.HighPart = 0;
63                         osi_logTixToMicros = 10;
64                         bigFreq = LargeIntegerDivide(bigFreq, bigTemp, &bigJunk);
65
66                         /* check if resolution is too fine or to gross for this to work */
67                         if (bigFreq.HighPart > 0 || bigFreq.LowPart < 8)
68                                 osi_logFreq = 0;        /* too big to represent as long */
69                         else
70                                 osi_logFreq = bigFreq.LowPart;
71                 }
72
73                 /* done with init */
74                 osi_EndOnce(&osi_logOnce);
75         }
76 #endif /* !DJGPP */
77
78         logp = malloc(sizeof(osi_log_t));
79         memset(logp, 0, sizeof(osi_log_t));
80         logp->namep = malloc(strlen(namep)+1);
81         strcpy(logp->namep, namep);
82         
83         osi_QAdd((osi_queue_t **) &osi_allLogsp, &logp->q);
84
85         /* compute size we'll use */
86         if (size == 0) size = osi_logSize;
87
88         /* handle init for this size */
89         logp->alloc = size;
90         logp->datap = malloc(size * sizeof(osi_logEntry_t));
91
92         /* init strings array */
93         logp->maxstringindex = size/10;
94         logp->stringindex = 0;
95         logp->stringsp = malloc((size/10) * OSI_LOG_STRINGSIZE);
96  
97         /* and sync */
98         thrd_InitCrit(&logp->cs);
99         
100         strcpy(tbuffer, "log:");
101         strcat(tbuffer, namep);
102         typep = osi_RegisterFDType(tbuffer, &osi_logFDOps, logp);
103 #ifndef DJGPP
104         if (typep) {
105                 /* add formatting info */
106                 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONINT, 0,
107                         "Thread ID", OSI_DBRPC_HEX);
108                 osi_AddFDFormatInfo(typep, OSI_DBRPC_REGIONSTRING, 1,
109                         "Time (mics)", 0);
110         }
111 #endif
112         
113         return logp;
114 }
115
116 /* we just panic'd.  Turn off all logging adding special log record
117  * to all enabled logs.  Be careful not to wait for a lock.
118  */
119 void osi_LogPanic(char *filep, long lineNumber)
120 {
121         osi_log_t *tlp;
122
123         for(tlp = osi_allLogsp; tlp; tlp = (osi_log_t *) osi_QNext(&tlp->q)) {
124                 if (!tlp->enabled) continue;
125
126                 /* otherwise, proceed */
127                 if (filep)
128                         osi_LogAdd(tlp, "**PANIC** (file %s:%d)", (long) filep, lineNumber, 0, 0);
129                 else
130                         osi_LogAdd(tlp, "**PANIC**", 0, 0, 0, 0);
131                 
132                 /* should grab lock for this, but we're in panic, and better safe than
133                  * sorry.
134                  */
135                 tlp->enabled = 0;
136         }
137 }
138
139 /* reset the contents of a log */
140 void osi_LogReset(osi_log_t *logp)
141 {
142         if (logp) {
143                 thrd_EnterCrit(&logp->cs);
144                 logp->nused = 0;
145                 thrd_LeaveCrit(&logp->cs);
146         }
147 }
148
149 /* free a log */
150 void osi_LogFree(osi_log_t *logp)
151 {
152         if (!logp) return;
153
154         osi_QRemove((osi_queue_t **) &osi_allLogsp, &logp->q);
155
156         free(logp->namep);
157         free(logp->datap);
158         thrd_DeleteCrit(&logp->cs);
159         free(logp);
160 }
161
162 /* add an element to a log */
163 void osi_LogAdd(osi_log_t *logp, char *formatp, long p0, long p1, long p2, long p3)
164 {
165         osi_logEntry_t *lep;
166         long ix;
167         LARGE_INTEGER bigTime;
168
169         /* handle init races */
170         if (!logp) return;
171
172         /* do this w/o locking for speed; it is obviously harmless if we're off
173          * by a bit.
174          */
175         if (!logp->enabled) return;
176         
177         thrd_EnterCrit(&logp->cs);
178         if (logp->nused < logp->alloc) logp->nused++;
179         else {
180                 logp->first++;
181                 if (logp->first >= logp->alloc) logp->first -= logp->alloc;
182         }
183         ix = logp->first + logp->nused - 1;
184         if (ix >= logp->alloc) ix -= logp->alloc;
185
186         lep = logp->datap + ix; /* ptr arith */
187         lep->tid = thrd_Current();
188
189         /* get the time, using the high res timer if available */
190 #ifndef DJGPP
191         if (osi_logFreq) {
192                 QueryPerformanceCounter(&bigTime);
193                 lep->micros = (bigTime.LowPart / osi_logFreq) * osi_logTixToMicros;
194         }
195         else lep->micros = GetCurrentTime() * 1000;
196 #else
197         lep->micros = gettime_us();
198 #endif /* !DJGPP */                
199
200         lep->formatp = formatp;
201         lep->parms[0] = p0;
202         lep->parms[1] = p1;
203         lep->parms[2] = p2;
204         lep->parms[3] = p3;
205         thrd_LeaveCrit(&logp->cs);
206 }
207
208 void osi_LogPrint(osi_log_t *logp, FILE_HANDLE handle)
209 {
210         char wholemsg[1000], msg[1000];
211         int i, ix, ioCount;
212         osi_logEntry_t *lep;
213
214         if (!logp->enabled) return;
215
216         thrd_EnterCrit(&logp->cs);
217
218         for (ix = logp->first, i = 0;
219              i < logp->nused;
220              i++, ix++, (ix >= logp->alloc ? ix -= logp->alloc : 0)) {
221                 lep = logp->datap + ix;         /* pointer arithmetic */
222                 sprintf(msg, lep->formatp,
223                         lep->parms[0], lep->parms[1],
224                         lep->parms[2], lep->parms[3]);
225                 sprintf(wholemsg, "time %d.%06d, pid %d %s\n",
226                         lep->micros / 1000000,
227                         lep->micros % 1000000,
228                         lep->tid, msg);
229 #ifndef DJGPP
230                 if (!WriteFile(handle, wholemsg, strlen(wholemsg),
231                                 &ioCount, NULL))
232 #else /* DJGPP */
233                 if ((ioCount = fwrite(wholemsg, 1, strlen(wholemsg), handle)) == 0)
234 #endif /* !DJGPP */
235                         break;
236         }
237
238         thrd_LeaveCrit(&logp->cs);
239 }
240
241 char *osi_LogSaveString(osi_log_t *logp, char *s)
242 {
243         char *saveplace = logp->stringsp[logp->stringindex];
244
245         if (s == NULL) return NULL;
246
247         if (strlen(s) >= OSI_LOG_STRINGSIZE)
248                 sprintf(saveplace, "...%s",
249                         s + strlen(s) - (OSI_LOG_STRINGSIZE - 4));
250         else
251                 strcpy(saveplace, s);
252         logp->stringindex++;
253         if (logp->stringindex >= logp->maxstringindex)
254             logp->stringindex = 0;
255
256         return saveplace;
257 }
258
259 long osi_LogFDCreate(osi_fdType_t *typep, osi_fd_t **outpp)
260 {
261         osi_logFD_t *lfdp;
262         osi_log_t *logp;
263         
264         lfdp = malloc(sizeof(*lfdp));
265         logp = lfdp->logp = typep->rockp;       /* the log we were created for */
266         thrd_EnterCrit(&logp->cs);
267         lfdp->nused = logp->nused;
268         lfdp->first = logp->first;
269         lfdp->current = 0;
270         thrd_LeaveCrit(&logp->cs);
271
272         *outpp = &lfdp->fd;
273         return 0;
274 }
275
276 #ifndef DJGPP
277 long osi_LogFDGetInfo(osi_fd_t *ifd, osi_remGetInfoParms_t *outp)
278 {
279         osi_logFD_t *lfdp;
280         osi_log_t *logp;
281         osi_logEntry_t *lep;
282         char tbuffer[256];
283         long ix;
284         
285         lfdp = (osi_logFD_t *) ifd;
286         logp = lfdp->logp;
287         
288         /* see if we're done */
289         if (lfdp->current >= lfdp->nused) return OSI_DBRPC_EOF;
290         
291         /* grab lock */
292         thrd_EnterCrit(&logp->cs);
293
294         /* compute which one we want */
295         ix = lfdp->first + lfdp->current;
296         if (ix >= logp->alloc) ix -= logp->alloc;
297         lfdp->current++;
298         lep = logp->datap + ix; /* ptr arith to current index */
299
300         sprintf(tbuffer, lep->formatp, lep->parms[0], lep->parms[1],
301                 lep->parms[2], lep->parms[3]);
302
303         /* now copy out info */
304         strcpy(outp->sdata[0], tbuffer);
305         sprintf(tbuffer, "%5.6f", ((double)lep->micros)/1000000.0);
306         strcpy(outp->sdata[1], tbuffer);
307         outp->idata[0] = lep->tid;
308         outp->scount = 2;
309         outp->icount = 1;
310
311         thrd_LeaveCrit(&logp->cs);
312         return 0;
313 }
314 #endif /* !DJGPP */
315
316 long osi_LogFDClose(osi_fd_t *ifdp)
317 {
318         free(ifdp);
319         return 0;
320 }
321
322 void osi_LogEnable(osi_log_t *logp)
323 {
324         if (logp)
325                 logp->enabled = 1;
326 }
327
328 void osi_LogDisable(osi_log_t *logp)
329 {
330         if (logp)
331                 logp->enabled = 0;
332 }
333
334 #define REG_CLIENT_PARMS_KEY  "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
335 #define TRACE_OPTION_EVENT 1
336 #define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
337
338 DWORD osi_TraceOption=0;
339
340 void osi_InitTraceOption()
341 {
342         DWORD LSPtype, LSPsize;
343         HKEY NPKey;
344         (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY,
345                     0, KEY_QUERY_VALUE, &NPKey);
346         LSPsize=sizeof(osi_TraceOption);
347         RegQueryValueEx(NPKey, "TraceOption", NULL,
348                                 &LSPtype, (LPBYTE)&osi_TraceOption, &LSPsize);\r
349 }
350
351
352 #define MAXBUF_ 131
353 void osi_LogEvent0(char *a,char *b) 
354 {
355         HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
356         if (!ISLOGONTRACE(osi_TraceOption))
357                 return;
358         h = RegisterEventSource(NULL, a);
359         ptbuf[0] = b;
360         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
361         DeregisterEventSource(h);
362 }
363
364
365 void osi_LogEvent(char *a,char *b,char *c,...) 
366 {
367         HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
368         va_list marker;
369         if (!ISLOGONTRACE(osi_TraceOption))
370                 return;
371         if (b)
372         {
373                 wsprintf(buf,a,b);
374                 h = RegisterEventSource(NULL, buf);
375         }
376         else
377                 h = RegisterEventSource(NULL, a);
378         va_start(marker,c);
379         _vsnprintf(buf,MAXBUF_,c,marker);
380         ptbuf[0] = buf;
381         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
382         DeregisterEventSource(h);
383         va_end(marker);
384 }