Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/misc/prtrace.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
5 | |
6 /* | |
7 ** prtrace.c -- NSPR Trace Instrumentation | |
8 ** | |
9 ** Implement the API defined in prtrace.h | |
10 ** | |
11 ** | |
12 ** | |
13 */ | |
14 | |
15 #include <string.h> | |
16 #include "primpl.h" | |
17 | |
18 | |
19 #define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 ) | |
20 #define DEFAULT_BUFFER_SEGMENTS 2 | |
21 | |
22 /* | |
23 ** Enumerate states in a RName structure | |
24 */ | |
25 typedef enum TraceState | |
26 { | |
27 Running = 1, | |
28 Suspended = 2 | |
29 } TraceState; | |
30 | |
31 /* | |
32 ** Define QName structure | |
33 */ | |
34 typedef struct QName | |
35 { | |
36 PRCList link; | |
37 PRCList rNameList; | |
38 char name[PRTRACE_NAME_MAX+1]; | |
39 } QName; | |
40 | |
41 /* | |
42 ** Define RName structure | |
43 */ | |
44 typedef struct RName | |
45 { | |
46 PRCList link; | |
47 PRLock *lock; | |
48 QName *qName; | |
49 TraceState state; | |
50 char name[PRTRACE_NAME_MAX+1]; | |
51 char desc[PRTRACE_DESC_MAX+1]; | |
52 } RName; | |
53 | |
54 | |
55 /* | |
56 ** The Trace Facility database | |
57 ** | |
58 */ | |
59 static PRLogModuleInfo *lm; | |
60 | |
61 static PRLock *traceLock; /* Facility Lock */ | |
62 static PRCList qNameList; /* anchor to all QName structures */ | |
63 static TraceState traceState = Running; | |
64 | |
65 /* | |
66 ** in-memory trace buffer controls | |
67 */ | |
68 static PRTraceEntry *tBuf; /* pointer to buffer */ | |
69 static PRInt32 bufSize; /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */ | |
70 static volatile PRInt32 next; /* index to next PRTraceEntry */ | |
71 static PRInt32 last; /* index of highest numbered trace entry */ | |
72 | |
73 /* | |
74 ** Real-time buffer capture controls | |
75 */ | |
76 static PRInt32 fetchLastSeen = 0; | |
77 static PRBool fetchLostData = PR_FALSE; | |
78 | |
79 /* | |
80 ** Buffer write-to-file controls | |
81 */ | |
82 static PRLock *logLock; /* Sync lock */ | |
83 static PRCondVar *logCVar; /* Sync Condidtion Variable */ | |
84 /* | |
85 ** Inter-thread state communication. | |
86 ** Controling thread writes to logOrder under protection of logCVar | |
87 ** the logging thread reads logOrder and sets logState on Notify. | |
88 ** | |
89 ** logSegments, logCount, logLostData must be read and written under | |
90 ** protection of logLock, logCVar. | |
91 ** | |
92 */ | |
93 static enum LogState | |
94 { | |
95 LogNotRunning, /* Initial state */ | |
96 LogReset, /* Causes logger to re-calc controls */ | |
97 LogActive, /* Logging in progress, set only by log thread */ | |
98 LogSuspend, /* Suspend Logging */ | |
99 LogResume, /* Resume Logging => LogActive */ | |
100 LogStop /* Stop the log thread */ | |
101 } logOrder, logState, localState; /* controlling state variables */ | |
102 static PRInt32 logSegments; /* Number of buffer segments */ | |
103 static PRInt32 logEntries; /* number of Trace Entries in the buffer */ | |
104 static PRInt32 logEntriesPerSegment; /* number of PRTraceEntries per buffer segment */ | |
105 static PRInt32 logSegSize; /* size of buffer segment */ | |
106 static PRInt32 logCount; /* number of segments pending output */ | |
107 static PRInt32 logLostData; /* number of lost log buffer segments */ | |
108 | |
109 /* | |
110 ** end Trace Database | |
111 ** | |
112 */ | |
113 | |
114 /* | |
115 ** _PR_InitializeTrace() -- Initialize the trace facility | |
116 */ | |
117 static void NewTraceBuffer( PRInt32 size ) | |
118 { | |
119 /* | |
120 ** calculate the size of the buffer | |
121 ** round down so that each segment has the same number of | |
122 ** trace entries | |
123 */ | |
124 logSegments = DEFAULT_BUFFER_SEGMENTS; | |
125 logEntries = size / sizeof(PRTraceEntry); | |
126 logEntriesPerSegment = logEntries / logSegments; | |
127 logEntries = logSegments * logEntriesPerSegment; | |
128 bufSize = logEntries * sizeof(PRTraceEntry); | |
129 logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry); | |
130 PR_ASSERT( bufSize != 0); | |
131 PR_LOG( lm, PR_LOG_ERROR, | |
132 ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld", | |
133 logSegments, logEntries, logEntriesPerSegment, logSegSize )); | |
134 | |
135 | |
136 tBuf = PR_Malloc( bufSize ); | |
137 if ( tBuf == NULL ) | |
138 { | |
139 PR_LOG( lm, PR_LOG_ERROR, | |
140 ("PRTrace: Failed to get trace buffer")); | |
141 PR_ASSERT( 0 ); | |
142 } | |
143 else | |
144 { | |
145 PR_LOG( lm, PR_LOG_NOTICE, | |
146 ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf)); | |
147 } | |
148 | |
149 next = 0; | |
150 last = logEntries -1; | |
151 logCount = 0; | |
152 logLostData = PR_TRUE; /* not really on first call */ | |
153 logOrder = LogReset; | |
154 | |
155 } /* end NewTraceBuffer() */ | |
156 | |
157 /* | |
158 ** _PR_InitializeTrace() -- Initialize the trace facility | |
159 */ | |
160 static void _PR_InitializeTrace( void ) | |
161 { | |
162 /* The lock pointer better be null on this call */ | |
163 PR_ASSERT( traceLock == NULL ); | |
164 | |
165 traceLock = PR_NewLock(); | |
166 PR_ASSERT( traceLock != NULL ); | |
167 | |
168 PR_Lock( traceLock ); | |
169 | |
170 PR_INIT_CLIST( &qNameList ); | |
171 | |
172 lm = PR_NewLogModule("trace"); | |
173 | |
174 bufSize = DEFAULT_TRACE_BUFSIZE; | |
175 NewTraceBuffer( bufSize ); | |
176 | |
177 /* Initialize logging controls */ | |
178 logLock = PR_NewLock(); | |
179 logCVar = PR_NewCondVar( logLock ); | |
180 | |
181 PR_Unlock( traceLock ); | |
182 return; | |
183 } /* end _PR_InitializeTrace() */ | |
184 | |
185 /* | |
186 ** Create a Trace Handle | |
187 */ | |
188 PR_IMPLEMENT(PRTraceHandle) | |
189 PR_CreateTrace( | |
190 const char *qName, /* QName for this trace handle */ | |
191 const char *rName, /* RName for this trace handle */ | |
192 const char *description /* description for this trace handle */ | |
193 ) | |
194 { | |
195 QName *qnp; | |
196 RName *rnp; | |
197 PRBool matchQname = PR_FALSE; | |
198 | |
199 /* Self initialize, if necessary */ | |
200 if ( traceLock == NULL ) | |
201 _PR_InitializeTrace(); | |
202 | |
203 /* Validate input arguments */ | |
204 PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX ); | |
205 PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX ); | |
206 PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX ); | |
207 | |
208 PR_LOG( lm, PR_LOG_DEBUG, | |
209 ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName)); | |
210 | |
211 /* Lock the Facility */ | |
212 PR_Lock( traceLock ); | |
213 | |
214 /* Do we already have a matching QName? */ | |
215 if (!PR_CLIST_IS_EMPTY( &qNameList )) | |
216 { | |
217 qnp = (QName *) PR_LIST_HEAD( &qNameList ); | |
218 do { | |
219 if ( strcmp(qnp->name, qName) == 0) | |
220 { | |
221 matchQname = PR_TRUE; | |
222 break; | |
223 } | |
224 qnp = (QName *)PR_NEXT_LINK( &qnp->link ); | |
225 } while( qnp != (QName *)&qNameList ); | |
226 } | |
227 /* | |
228 ** If we did not find a matching QName, | |
229 ** allocate one and initialize it. | |
230 ** link it onto the qNameList. | |
231 ** | |
232 */ | |
233 if ( matchQname != PR_TRUE ) | |
234 { | |
235 qnp = PR_NEWZAP( QName ); | |
236 PR_ASSERT( qnp != NULL ); | |
237 PR_INIT_CLIST( &qnp->link ); | |
238 PR_INIT_CLIST( &qnp->rNameList ); | |
239 strcpy( qnp->name, qName ); | |
240 PR_APPEND_LINK( &qnp->link, &qNameList ); | |
241 } | |
242 | |
243 /* Do we already have a matching RName? */ | |
244 if (!PR_CLIST_IS_EMPTY( &qnp->rNameList )) | |
245 { | |
246 rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList ); | |
247 do { | |
248 /* | |
249 ** No duplicate RNames are allowed within a QName | |
250 ** | |
251 */ | |
252 PR_ASSERT( strcmp(rnp->name, rName)); | |
253 rnp = (RName *)PR_NEXT_LINK( &rnp->link ); | |
254 } while( rnp != (RName *)&qnp->rNameList ); | |
255 } | |
256 | |
257 /* Get a new RName structure; initialize its members */ | |
258 rnp = PR_NEWZAP( RName ); | |
259 PR_ASSERT( rnp != NULL ); | |
260 PR_INIT_CLIST( &rnp->link ); | |
261 strcpy( rnp->name, rName ); | |
262 strcpy( rnp->desc, description ); | |
263 rnp->lock = PR_NewLock(); | |
264 rnp->state = Running; | |
265 if ( rnp->lock == NULL ) | |
266 { | |
267 PR_ASSERT(0); | |
268 } | |
269 | |
270 PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */ | |
271 rnp->qName = qnp; /* point the RName to the QName */ | |
272 | |
273 /* Unlock the Facility */ | |
274 PR_Unlock( traceLock ); | |
275 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t", | |
276 qName, qnp, rName, rnp )); | |
277 | |
278 return((PRTraceHandle)rnp); | |
279 } /* end PR_CreateTrace() */ | |
280 | |
281 /* | |
282 ** | |
283 */ | |
284 PR_IMPLEMENT(void) | |
285 PR_DestroyTrace( | |
286 PRTraceHandle handle /* Handle to be destroyed */ | |
287 ) | |
288 { | |
289 RName *rnp = (RName *)handle; | |
290 QName *qnp = rnp->qName; | |
291 | |
292 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s", | |
293 qnp->name, rnp->name)); | |
294 | |
295 /* Lock the Facility */ | |
296 PR_Lock( traceLock ); | |
297 | |
298 /* | |
299 ** Remove RName from the list of RNames in QName | |
300 ** and free RName | |
301 */ | |
302 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p", | |
303 rnp->name, rnp)); | |
304 PR_REMOVE_LINK( &rnp->link ); | |
305 PR_Free( rnp->lock ); | |
306 PR_DELETE( rnp ); | |
307 | |
308 /* | |
309 ** If this is the last RName within QName | |
310 ** remove QName from the qNameList and free it | |
311 */ | |
312 if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) ) | |
313 { | |
314 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p", | |
315 qnp->name, qnp)); | |
316 PR_REMOVE_LINK( &qnp->link ); | |
317 PR_DELETE( qnp ); | |
318 } | |
319 | |
320 /* Unlock the Facility */ | |
321 PR_Unlock( traceLock ); | |
322 return; | |
323 } /* end PR_DestroyTrace() */ | |
324 | |
325 /* | |
326 ** Create a TraceEntry in the trace buffer | |
327 */ | |
328 PR_IMPLEMENT(void) | |
329 PR_Trace( | |
330 PRTraceHandle handle, /* use this trace handle */ | |
331 PRUint32 userData0, /* User supplied data word 0 */ | |
332 PRUint32 userData1, /* User supplied data word 1 */ | |
333 PRUint32 userData2, /* User supplied data word 2 */ | |
334 PRUint32 userData3, /* User supplied data word 3 */ | |
335 PRUint32 userData4, /* User supplied data word 4 */ | |
336 PRUint32 userData5, /* User supplied data word 5 */ | |
337 PRUint32 userData6, /* User supplied data word 6 */ | |
338 PRUint32 userData7 /* User supplied data word 7 */ | |
339 ) | |
340 { | |
341 PRTraceEntry *tep; | |
342 PRInt32 mark; | |
343 | |
344 if ( (traceState == Suspended ) | |
345 || ( ((RName *)handle)->state == Suspended )) | |
346 return; | |
347 | |
348 /* | |
349 ** Get the next trace entry slot w/ minimum delay | |
350 */ | |
351 PR_Lock( traceLock ); | |
352 | |
353 tep = &tBuf[next++]; | |
354 if ( next > last ) | |
355 next = 0; | |
356 if ( fetchLostData == PR_FALSE && next == fetchLastSeen ) | |
357 fetchLostData = PR_TRUE; | |
358 | |
359 mark = next; | |
360 | |
361 PR_Unlock( traceLock ); | |
362 | |
363 /* | |
364 ** We have a trace entry. Fill it in. | |
365 */ | |
366 tep->thread = PR_GetCurrentThread(); | |
367 tep->handle = handle; | |
368 tep->time = PR_Now(); | |
369 tep->userData[0] = userData0; | |
370 tep->userData[1] = userData1; | |
371 tep->userData[2] = userData2; | |
372 tep->userData[3] = userData3; | |
373 tep->userData[4] = userData4; | |
374 tep->userData[5] = userData5; | |
375 tep->userData[6] = userData6; | |
376 tep->userData[7] = userData7; | |
377 | |
378 /* When buffer segment is full, signal trace log thread to run */ | |
379 if (( mark % logEntriesPerSegment) == 0 ) | |
380 { | |
381 PR_Lock( logLock ); | |
382 logCount++; | |
383 PR_NotifyCondVar( logCVar ); | |
384 PR_Unlock( logLock ); | |
385 /* | |
386 ** Gh0D! This is awful! | |
387 ** Anyway, to minimize lost trace data segments, | |
388 ** I inserted the PR_Sleep(0) to cause a context switch | |
389 ** so that the log thread could run. | |
390 ** I know, it perturbs the universe and may cause | |
391 ** funny things to happen in the optimized builds. | |
392 ** Take it out, lose data; leave it in risk Heisenberg. | |
393 */ | |
394 /* PR_Sleep(0); */ | |
395 } | |
396 | |
397 return; | |
398 } /* end PR_Trace() */ | |
399 | |
400 /* | |
401 ** | |
402 */ | |
403 PR_IMPLEMENT(void) | |
404 PR_SetTraceOption( | |
405 PRTraceOption command, /* One of the enumerated values */ | |
406 void *value /* command value or NULL */ | |
407 ) | |
408 { | |
409 RName * rnp; | |
410 | |
411 switch ( command ) | |
412 { | |
413 case PRTraceBufSize : | |
414 PR_Lock( traceLock ); | |
415 PR_Free( tBuf ); | |
416 bufSize = *(PRInt32 *)value; | |
417 NewTraceBuffer( bufSize ); | |
418 PR_Unlock( traceLock ); | |
419 PR_LOG( lm, PR_LOG_DEBUG, | |
420 ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize)); | |
421 break; | |
422 | |
423 case PRTraceEnable : | |
424 rnp = *(RName **)value; | |
425 rnp->state = Running; | |
426 PR_LOG( lm, PR_LOG_DEBUG, | |
427 ("PRSetTraceOption: PRTraceEnable: %p", rnp)); | |
428 break; | |
429 | |
430 case PRTraceDisable : | |
431 rnp = *(RName **)value; | |
432 rnp->state = Suspended; | |
433 PR_LOG( lm, PR_LOG_DEBUG, | |
434 ("PRSetTraceOption: PRTraceDisable: %p", rnp)); | |
435 break; | |
436 | |
437 case PRTraceSuspend : | |
438 traceState = Suspended; | |
439 PR_LOG( lm, PR_LOG_DEBUG, | |
440 ("PRSetTraceOption: PRTraceSuspend")); | |
441 break; | |
442 | |
443 case PRTraceResume : | |
444 traceState = Running; | |
445 PR_LOG( lm, PR_LOG_DEBUG, | |
446 ("PRSetTraceOption: PRTraceResume")); | |
447 break; | |
448 | |
449 case PRTraceSuspendRecording : | |
450 PR_Lock( logLock ); | |
451 logOrder = LogSuspend; | |
452 PR_NotifyCondVar( logCVar ); | |
453 PR_Unlock( logLock ); | |
454 PR_LOG( lm, PR_LOG_DEBUG, | |
455 ("PRSetTraceOption: PRTraceSuspendRecording")); | |
456 break; | |
457 | |
458 case PRTraceResumeRecording : | |
459 PR_LOG( lm, PR_LOG_DEBUG, | |
460 ("PRSetTraceOption: PRTraceResumeRecording")); | |
461 if ( logState != LogSuspend ) | |
462 break; | |
463 PR_Lock( logLock ); | |
464 logOrder = LogResume; | |
465 PR_NotifyCondVar( logCVar ); | |
466 PR_Unlock( logLock ); | |
467 break; | |
468 | |
469 case PRTraceStopRecording : | |
470 PR_Lock( logLock ); | |
471 logOrder = LogStop; | |
472 PR_NotifyCondVar( logCVar ); | |
473 PR_Unlock( logLock ); | |
474 PR_LOG( lm, PR_LOG_DEBUG, | |
475 ("PRSetTraceOption: PRTraceStopRecording")); | |
476 break; | |
477 | |
478 case PRTraceLockHandles : | |
479 PR_LOG( lm, PR_LOG_DEBUG, | |
480 ("PRSetTraceOption: PRTraceLockTraceHandles")); | |
481 PR_Lock( traceLock ); | |
482 break; | |
483 | |
484 case PRTraceUnLockHandles : | |
485 PR_LOG( lm, PR_LOG_DEBUG, | |
486 ("PRSetTraceOption: PRTraceUnLockHandles")); | |
487 PR_Unlock( traceLock ); | |
488 break; | |
489 | |
490 default: | |
491 PR_LOG( lm, PR_LOG_ERROR, | |
492 ("PRSetTraceOption: Invalid command %ld", command )); | |
493 PR_ASSERT( 0 ); | |
494 break; | |
495 } /* end switch() */ | |
496 return; | |
497 } /* end PR_SetTraceOption() */ | |
498 | |
499 /* | |
500 ** | |
501 */ | |
502 PR_IMPLEMENT(void) | |
503 PR_GetTraceOption( | |
504 PRTraceOption command, /* One of the enumerated values */ | |
505 void *value /* command value or NULL */ | |
506 ) | |
507 { | |
508 switch ( command ) | |
509 { | |
510 case PRTraceBufSize : | |
511 *((PRInt32 *)value) = bufSize; | |
512 PR_LOG( lm, PR_LOG_DEBUG, | |
513 ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize )); | |
514 break; | |
515 | |
516 default: | |
517 PR_LOG( lm, PR_LOG_ERROR, | |
518 ("PRGetTraceOption: Invalid command %ld", command )); | |
519 PR_ASSERT( 0 ); | |
520 break; | |
521 } /* end switch() */ | |
522 return; | |
523 } /* end PR_GetTraceOption() */ | |
524 | |
525 /* | |
526 ** | |
527 */ | |
528 PR_IMPLEMENT(PRTraceHandle) | |
529 PR_GetTraceHandleFromName( | |
530 const char *qName, /* QName search argument */ | |
531 const char *rName /* RName search argument */ | |
532 ) | |
533 { | |
534 const char *qn, *rn, *desc; | |
535 PRTraceHandle qh, rh = NULL; | |
536 RName *rnp = NULL; | |
537 | |
538 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t" | |
539 "QName: %s, RName: %s", qName, rName )); | |
540 | |
541 qh = PR_FindNextTraceQname( NULL ); | |
542 while (qh != NULL) | |
543 { | |
544 rh = PR_FindNextTraceRname( NULL, qh ); | |
545 while ( rh != NULL ) | |
546 { | |
547 PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc ); | |
548 if ( (strcmp( qName, qn ) == 0) | |
549 && (strcmp( rName, rn ) == 0 )) | |
550 { | |
551 rnp = (RName *)rh; | |
552 goto foundIt; | |
553 } | |
554 rh = PR_FindNextTraceRname( rh, qh ); | |
555 } | |
556 qh = PR_FindNextTraceQname( NULL ); | |
557 } | |
558 | |
559 foundIt: | |
560 PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp )); | |
561 return(rh); | |
562 } /* end PR_GetTraceHandleFromName() */ | |
563 | |
564 /* | |
565 ** | |
566 */ | |
567 PR_IMPLEMENT(void) | |
568 PR_GetTraceNameFromHandle( | |
569 PRTraceHandle handle, /* handle as search argument */ | |
570 const char **qName, /* pointer to associated QName */ | |
571 const char **rName, /* pointer to associated RName */ | |
572 const char **description /* pointer to associated description */ | |
573 ) | |
574 { | |
575 RName *rnp = (RName *)handle; | |
576 QName *qnp = rnp->qName; | |
577 | |
578 *qName = qnp->name; | |
579 *rName = rnp->name; | |
580 *description = rnp->desc; | |
581 | |
582 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: " | |
583 "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", | |
584 qnp, rnp, qnp->name, rnp->name, rnp->desc )); | |
585 | |
586 return; | |
587 } /* end PR_GetTraceNameFromHandle() */ | |
588 | |
589 /* | |
590 ** | |
591 */ | |
592 PR_IMPLEMENT(PRTraceHandle) | |
593 PR_FindNextTraceQname( | |
594 PRTraceHandle handle | |
595 ) | |
596 { | |
597 QName *qnp = (QName *)handle; | |
598 | |
599 if ( PR_CLIST_IS_EMPTY( &qNameList )) | |
600 qnp = NULL; | |
601 else if ( qnp == NULL ) | |
602 qnp = (QName *)PR_LIST_HEAD( &qNameList ); | |
603 else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList ) | |
604 qnp = NULL; | |
605 else | |
606 qnp = (QName *)PR_NEXT_LINK( &qnp->link ); | |
607 | |
608 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p", | |
609 handle, qnp )); | |
610 | |
611 return((PRTraceHandle)qnp); | |
612 } /* end PR_FindNextTraceQname() */ | |
613 | |
614 /* | |
615 ** | |
616 */ | |
617 PR_IMPLEMENT(PRTraceHandle) | |
618 PR_FindNextTraceRname( | |
619 PRTraceHandle rhandle, | |
620 PRTraceHandle qhandle | |
621 ) | |
622 { | |
623 RName *rnp = (RName *)rhandle; | |
624 QName *qnp = (QName *)qhandle; | |
625 | |
626 | |
627 if ( PR_CLIST_IS_EMPTY( &qnp->rNameList )) | |
628 rnp = NULL; | |
629 else if ( rnp == NULL ) | |
630 rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList ); | |
631 else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList ) | |
632 rnp = NULL; | |
633 else | |
634 rnp = (RName *)PR_NEXT_LINK( &rnp->link ); | |
635 | |
636 PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", | |
637 rhandle, qhandle, rnp )); | |
638 | |
639 return((PRTraceHandle)rnp); | |
640 } /* end PR_FindNextTraceRname() */ | |
641 | |
642 /* | |
643 ** | |
644 */ | |
645 static PRFileDesc * InitializeRecording( void ) | |
646 { | |
647 char *logFileName; | |
648 PRFileDesc *logFile; | |
649 | |
650 /* Self initialize, if necessary */ | |
651 if ( traceLock == NULL ) | |
652 _PR_InitializeTrace(); | |
653 | |
654 PR_LOG( lm, PR_LOG_DEBUG, | |
655 ("PR_RecordTraceEntries: begins")); | |
656 | |
657 logLostData = 0; /* reset at entry */ | |
658 logState = LogReset; | |
659 | |
660 #ifdef XP_UNIX | |
661 if ((getuid() != geteuid()) || (getgid() != getegid())) { | |
662 return NULL; | |
663 } | |
664 #endif /* XP_UNIX */ | |
665 | |
666 /* Get the filename for the logfile from the environment */ | |
667 logFileName = PR_GetEnv( "NSPR_TRACE_LOG" ); | |
668 if ( logFileName == NULL ) | |
669 { | |
670 PR_LOG( lm, PR_LOG_ERROR, | |
671 ("RecordTraceEntries: Environment variable not defined. Exiting")); | |
672 return NULL; | |
673 } | |
674 | |
675 /* Open the logfile */ | |
676 logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 ); | |
677 if ( logFile == NULL ) | |
678 { | |
679 PR_LOG( lm, PR_LOG_ERROR, | |
680 ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld", | |
681 logFileName, PR_GetOSError())); | |
682 return NULL; | |
683 } | |
684 return logFile; | |
685 } /* end InitializeRecording() */ | |
686 | |
687 /* | |
688 ** | |
689 */ | |
690 static void ProcessOrders( void ) | |
691 { | |
692 switch ( logOrder ) | |
693 { | |
694 case LogReset : | |
695 logOrder = logState = localState; | |
696 PR_LOG( lm, PR_LOG_DEBUG, | |
697 ("RecordTraceEntries: LogReset")); | |
698 break; | |
699 | |
700 case LogSuspend : | |
701 localState = logOrder = logState = LogSuspend; | |
702 PR_LOG( lm, PR_LOG_DEBUG, | |
703 ("RecordTraceEntries: LogSuspend")); | |
704 break; | |
705 | |
706 case LogResume : | |
707 localState = logOrder = logState = LogActive; | |
708 PR_LOG( lm, PR_LOG_DEBUG, | |
709 ("RecordTraceEntries: LogResume")); | |
710 break; | |
711 | |
712 case LogStop : | |
713 logOrder = logState = LogStop; | |
714 PR_LOG( lm, PR_LOG_DEBUG, | |
715 ("RecordTraceEntries: LogStop")); | |
716 break; | |
717 | |
718 default : | |
719 PR_LOG( lm, PR_LOG_ERROR, | |
720 ("RecordTraceEntries: Invalid logOrder: %ld", logOrder )); | |
721 PR_ASSERT( 0 ); | |
722 break; | |
723 } /* end switch() */ | |
724 return ; | |
725 } /* end ProcessOrders() */ | |
726 | |
727 /* | |
728 ** | |
729 */ | |
730 static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount ) | |
731 { | |
732 PRInt32 rc; | |
733 | |
734 | |
735 PR_LOG( lm, PR_LOG_ERROR, | |
736 ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount)); | |
737 rc = PR_Write( logFile, buf , amount ); | |
738 if ( rc == -1 ) | |
739 PR_LOG( lm, PR_LOG_ERROR, | |
740 ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() )); | |
741 else if ( rc != amount ) | |
742 PR_LOG( lm, PR_LOG_ERROR, | |
743 ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc)); | |
744 else | |
745 PR_LOG( lm, PR_LOG_DEBUG, | |
746 ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount)); | |
747 | |
748 return; | |
749 } /* end WriteTraceSegment() */ | |
750 | |
751 /* | |
752 ** | |
753 */ | |
754 PR_IMPLEMENT(void) | |
755 PR_RecordTraceEntries( | |
756 void | |
757 ) | |
758 { | |
759 PRFileDesc *logFile; | |
760 PRInt32 lostSegments; | |
761 PRInt32 currentSegment = 0; | |
762 void *buf; | |
763 PRBool doWrite; | |
764 | |
765 logFile = InitializeRecording(); | |
766 if ( logFile == NULL ) | |
767 { | |
768 PR_LOG( lm, PR_LOG_DEBUG, | |
769 ("PR_RecordTraceEntries: Failed to initialize")); | |
770 return; | |
771 } | |
772 | |
773 /* Do this until told to stop */ | |
774 while ( logState != LogStop ) | |
775 { | |
776 | |
777 PR_Lock( logLock ); | |
778 | |
779 while ( (logCount == 0) && ( logOrder == logState ) ) | |
780 PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT ); | |
781 | |
782 /* Handle state transitions */ | |
783 if ( logOrder != logState ) | |
784 ProcessOrders(); | |
785 | |
786 /* recalculate local controls */ | |
787 if ( logCount ) | |
788 { | |
789 lostSegments = logCount - logSegments; | |
790 if ( lostSegments > 0 ) | |
791 { | |
792 logLostData += ( logCount - logSegments ); | |
793 logCount = (logCount % logSegments); | |
794 currentSegment = logCount; | |
795 PR_LOG( lm, PR_LOG_DEBUG, | |
796 ("PR_RecordTraceEntries: LostData segments: %ld", logLostData)); | |
797 } | |
798 else | |
799 { | |
800 logCount--; | |
801 } | |
802 | |
803 buf = tBuf + ( logEntriesPerSegment * currentSegment ); | |
804 if (++currentSegment >= logSegments ) | |
805 currentSegment = 0; | |
806 doWrite = PR_TRUE; | |
807 } | |
808 else | |
809 doWrite = PR_FALSE; | |
810 | |
811 PR_Unlock( logLock ); | |
812 | |
813 if ( doWrite == PR_TRUE ) | |
814 { | |
815 if ( localState != LogSuspend ) | |
816 WriteTraceSegment( logFile, buf, logSegSize ); | |
817 else | |
818 PR_LOG( lm, PR_LOG_DEBUG, | |
819 ("RecordTraceEntries: PR_Write(): is suspended" )); | |
820 } | |
821 | |
822 } /* end while(logState...) */ | |
823 | |
824 PR_Close( logFile ); | |
825 PR_LOG( lm, PR_LOG_DEBUG, | |
826 ("RecordTraceEntries: exiting")); | |
827 return; | |
828 } /* end PR_RecordTraceEntries() */ | |
829 | |
830 /* | |
831 ** | |
832 */ | |
833 PR_IMPLEMENT(PRIntn) | |
834 PR_GetTraceEntries( | |
835 PRTraceEntry *buffer, /* where to write output */ | |
836 PRInt32 count, /* number to get */ | |
837 PRInt32 *found /* number you got */ | |
838 ) | |
839 { | |
840 PRInt32 rc; | |
841 PRInt32 copied = 0; | |
842 | |
843 PR_Lock( traceLock ); | |
844 | |
845 /* | |
846 ** Depending on where the LastSeen and Next indices are, | |
847 ** copy the trace buffer in one or two pieces. | |
848 */ | |
849 PR_LOG( lm, PR_LOG_ERROR, | |
850 ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen)); | |
851 | |
852 if ( fetchLastSeen <= next ) | |
853 { | |
854 while (( count-- > 0 ) && (fetchLastSeen < next )) | |
855 { | |
856 *(buffer + copied++) = *(tBuf + fetchLastSeen++); | |
857 } | |
858 PR_LOG( lm, PR_LOG_ERROR, | |
859 ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); | |
860 } | |
861 else /* copy in 2 parts */ | |
862 { | |
863 while ( count-- > 0 && fetchLastSeen <= last ) | |
864 { | |
865 *(buffer + copied++) = *(tBuf + fetchLastSeen++); | |
866 } | |
867 fetchLastSeen = 0; | |
868 | |
869 PR_LOG( lm, PR_LOG_ERROR, | |
870 ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); | |
871 | |
872 while ( count-- > 0 && fetchLastSeen < next ) | |
873 { | |
874 *(buffer + copied++) = *(tBuf + fetchLastSeen++); | |
875 } | |
876 PR_LOG( lm, PR_LOG_ERROR, | |
877 ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); | |
878 } | |
879 | |
880 *found = copied; | |
881 rc = ( fetchLostData == PR_TRUE )? 1 : 0; | |
882 fetchLostData = PR_FALSE; | |
883 | |
884 PR_Unlock( traceLock ); | |
885 return rc; | |
886 } /* end PR_GetTraceEntries() */ | |
887 | |
888 /* end prtrace.c */ |