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 */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)