LCOV - code coverage report
Current view: top level - nsprpub/pr/src/misc - prtrace.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 313 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : 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           0 :     logSegments = DEFAULT_BUFFER_SEGMENTS;
     125           0 :     logEntries = size / sizeof(PRTraceEntry);
     126           0 :     logEntriesPerSegment = logEntries / logSegments;
     127           0 :     logEntries = logSegments * logEntriesPerSegment;
     128           0 :     bufSize = logEntries * sizeof(PRTraceEntry);
     129           0 :     logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);
     130           0 :     PR_ASSERT( bufSize != 0);
     131           0 :     PR_LOG( lm, PR_LOG_ERROR,
     132             :         ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",
     133             :             logSegments, logEntries, logEntriesPerSegment, logSegSize ));
     134             : 
     135             : 
     136           0 :     tBuf = PR_Malloc( bufSize );
     137           0 :     if ( tBuf == NULL )
     138             :     {
     139           0 :         PR_LOG( lm, PR_LOG_ERROR,
     140             :             ("PRTrace: Failed to get trace buffer"));
     141           0 :         PR_ASSERT( 0 );
     142             :     } 
     143             :     else
     144             :     {
     145           0 :         PR_LOG( lm, PR_LOG_NOTICE,
     146             :             ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));
     147             :     }
     148             : 
     149           0 :     next = 0;
     150           0 :     last = logEntries -1;
     151           0 :     logCount = 0;
     152           0 :     logLostData = PR_TRUE; /* not really on first call */
     153           0 :     logOrder = LogReset;
     154             : 
     155           0 : } /* end NewTraceBuffer() */
     156             : 
     157             : /*
     158             : ** _PR_InitializeTrace() -- Initialize the trace facility
     159             : */
     160           0 : static void _PR_InitializeTrace( void )
     161             : {
     162             :     /* The lock pointer better be null on this call */
     163           0 :     PR_ASSERT( traceLock == NULL );
     164             : 
     165           0 :     traceLock = PR_NewLock();
     166           0 :     PR_ASSERT( traceLock != NULL );
     167             : 
     168           0 :     PR_Lock( traceLock );
     169             :     
     170           0 :     PR_INIT_CLIST( &qNameList );
     171             : 
     172           0 :     lm = PR_NewLogModule("trace");
     173             : 
     174           0 :     bufSize = DEFAULT_TRACE_BUFSIZE;
     175           0 :     NewTraceBuffer( bufSize );
     176             : 
     177             :     /* Initialize logging controls */
     178           0 :     logLock = PR_NewLock();
     179           0 :     logCVar = PR_NewCondVar( logLock );
     180             : 
     181           0 :     PR_Unlock( traceLock );
     182           0 :     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           0 :     PRBool  matchQname = PR_FALSE;
     198             : 
     199             :     /* Self initialize, if necessary */
     200           0 :     if ( traceLock == NULL )
     201           0 :         _PR_InitializeTrace();
     202             : 
     203             :     /* Validate input arguments */
     204           0 :     PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );
     205           0 :     PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );
     206           0 :     PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );
     207             : 
     208           0 :     PR_LOG( lm, PR_LOG_DEBUG,
     209             :             ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));
     210             : 
     211             :     /* Lock the Facility */
     212           0 :     PR_Lock( traceLock );
     213             : 
     214             :     /* Do we already have a matching QName? */
     215           0 :     if (!PR_CLIST_IS_EMPTY( &qNameList ))
     216             :     {
     217           0 :         qnp = (QName *) PR_LIST_HEAD( &qNameList );
     218             :         do {
     219           0 :             if ( strcmp(qnp->name, qName) == 0)
     220             :             {
     221           0 :                 matchQname = PR_TRUE;
     222           0 :                 break;
     223             :             }
     224           0 :             qnp = (QName *)PR_NEXT_LINK( &qnp->link );
     225           0 :         } 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           0 :     if ( matchQname != PR_TRUE )
     234             :     {
     235           0 :         qnp = PR_NEWZAP( QName );
     236           0 :         PR_ASSERT( qnp != NULL );
     237           0 :         PR_INIT_CLIST( &qnp->link ); 
     238           0 :         PR_INIT_CLIST( &qnp->rNameList ); 
     239           0 :         strcpy( qnp->name, qName );
     240           0 :         PR_APPEND_LINK( &qnp->link, &qNameList ); 
     241             :     }
     242             : 
     243             :     /* Do we already have a matching RName? */
     244           0 :     if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
     245             :     {
     246           0 :         rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
     247             :         do {
     248             :             /*
     249             :             ** No duplicate RNames are allowed within a QName
     250             :             **
     251             :             */
     252           0 :             PR_ASSERT( strcmp(rnp->name, rName));
     253           0 :             rnp = (RName *)PR_NEXT_LINK( &rnp->link );
     254           0 :         } while( rnp != (RName *)&qnp->rNameList );
     255             :     }
     256             : 
     257             :     /* Get a new RName structure; initialize its members */
     258           0 :     rnp = PR_NEWZAP( RName );
     259           0 :     PR_ASSERT( rnp != NULL );
     260           0 :     PR_INIT_CLIST( &rnp->link );
     261           0 :     strcpy( rnp->name, rName );
     262           0 :     strcpy( rnp->desc, description );
     263           0 :     rnp->lock = PR_NewLock();
     264           0 :     rnp->state = Running;
     265           0 :     if ( rnp->lock == NULL )
     266             :     {
     267           0 :         PR_ASSERT(0);
     268             :     }
     269             : 
     270           0 :     PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */    
     271           0 :     rnp->qName = qnp;                       /* point the RName to the QName */
     272             : 
     273             :     /* Unlock the Facility */
     274           0 :     PR_Unlock( traceLock );
     275           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",
     276             :         qName, qnp, rName, rnp ));
     277             : 
     278           0 :     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           0 :     RName   *rnp = (RName *)handle;
     290           0 :     QName   *qnp = rnp->qName;
     291             : 
     292           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s", 
     293             :         qnp->name, rnp->name));
     294             : 
     295             :     /* Lock the Facility */
     296           0 :     PR_Lock( traceLock );
     297             : 
     298             :     /*
     299             :     ** Remove RName from the list of RNames in QName
     300             :     ** and free RName
     301             :     */
     302           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p", 
     303             :         rnp->name, rnp));
     304           0 :     PR_REMOVE_LINK( &rnp->link );
     305           0 :     PR_Free( rnp->lock );
     306           0 :     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           0 :     if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
     313             :     {
     314           0 :         PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p", 
     315             :             qnp->name, qnp));
     316           0 :         PR_REMOVE_LINK( &qnp->link );
     317           0 :         PR_DELETE( qnp );
     318             :     } 
     319             : 
     320             :     /* Unlock the Facility */
     321           0 :     PR_Unlock( traceLock );
     322           0 :     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           0 :     if ( (traceState == Suspended ) 
     345           0 :         || ( ((RName *)handle)->state == Suspended )) 
     346           0 :         return;
     347             : 
     348             :     /*
     349             :     ** Get the next trace entry slot w/ minimum delay
     350             :     */
     351           0 :     PR_Lock( traceLock );
     352             : 
     353           0 :     tep = &tBuf[next++]; 
     354           0 :     if ( next > last )
     355           0 :         next = 0;
     356           0 :     if ( fetchLostData == PR_FALSE && next == fetchLastSeen )
     357           0 :         fetchLostData = PR_TRUE;
     358             :     
     359           0 :     mark = next;
     360             :         
     361           0 :     PR_Unlock( traceLock );
     362             : 
     363             :     /*
     364             :     ** We have a trace entry. Fill it in.
     365             :     */
     366           0 :     tep->thread = PR_GetCurrentThread();
     367           0 :     tep->handle = handle;
     368           0 :     tep->time   = PR_Now();
     369           0 :     tep->userData[0] = userData0;
     370           0 :     tep->userData[1] = userData1;
     371           0 :     tep->userData[2] = userData2;
     372           0 :     tep->userData[3] = userData3;
     373           0 :     tep->userData[4] = userData4;
     374           0 :     tep->userData[5] = userData5;
     375           0 :     tep->userData[6] = userData6;
     376           0 :     tep->userData[7] = userData7;
     377             : 
     378             :     /* When buffer segment is full, signal trace log thread to run */
     379           0 :     if (( mark % logEntriesPerSegment) == 0 )
     380             :     {
     381           0 :         PR_Lock( logLock );
     382           0 :         logCount++;
     383           0 :         PR_NotifyCondVar( logCVar );
     384           0 :         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           0 :     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           0 :     switch ( command )
     412             :     {
     413             :         case PRTraceBufSize :
     414           0 :             PR_Lock( traceLock );
     415           0 :             PR_Free( tBuf );
     416           0 :             bufSize = *(PRInt32 *)value;
     417           0 :             NewTraceBuffer( bufSize );
     418           0 :             PR_Unlock( traceLock );
     419           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     420             :                 ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));
     421           0 :             break;
     422             :         
     423             :         case PRTraceEnable :
     424           0 :             rnp = *(RName **)value;
     425           0 :             rnp->state = Running;
     426           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     427             :                 ("PRSetTraceOption: PRTraceEnable: %p", rnp));
     428           0 :             break;
     429             :         
     430             :         case PRTraceDisable :
     431           0 :             rnp = *(RName **)value;
     432           0 :             rnp->state = Suspended;
     433           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     434             :                 ("PRSetTraceOption: PRTraceDisable: %p", rnp));
     435           0 :             break;
     436             :         
     437             :         case PRTraceSuspend :
     438           0 :             traceState = Suspended;
     439           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     440             :                 ("PRSetTraceOption: PRTraceSuspend"));
     441           0 :             break;
     442             :         
     443             :         case PRTraceResume :
     444           0 :             traceState = Running;
     445           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     446             :                 ("PRSetTraceOption: PRTraceResume"));
     447           0 :             break;
     448             :         
     449             :         case PRTraceSuspendRecording :
     450           0 :             PR_Lock( logLock );
     451           0 :             logOrder = LogSuspend;
     452           0 :             PR_NotifyCondVar( logCVar );
     453           0 :             PR_Unlock( logLock );
     454           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     455             :                 ("PRSetTraceOption: PRTraceSuspendRecording"));
     456           0 :             break;
     457             :         
     458             :         case PRTraceResumeRecording :
     459           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     460             :                 ("PRSetTraceOption: PRTraceResumeRecording"));
     461           0 :             if ( logState != LogSuspend )
     462           0 :                 break;
     463           0 :             PR_Lock( logLock );
     464           0 :             logOrder = LogResume;
     465           0 :             PR_NotifyCondVar( logCVar );
     466           0 :             PR_Unlock( logLock );
     467           0 :             break;
     468             :         
     469             :         case PRTraceStopRecording :
     470           0 :             PR_Lock( logLock );
     471           0 :             logOrder = LogStop;
     472           0 :             PR_NotifyCondVar( logCVar );
     473           0 :             PR_Unlock( logLock );
     474           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     475             :                 ("PRSetTraceOption: PRTraceStopRecording"));
     476           0 :             break;
     477             : 
     478             :         case PRTraceLockHandles :
     479           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     480             :                 ("PRSetTraceOption: PRTraceLockTraceHandles"));
     481           0 :             PR_Lock( traceLock );
     482           0 :             break;
     483             :         
     484             :         case PRTraceUnLockHandles :
     485           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     486             :                 ("PRSetTraceOption: PRTraceUnLockHandles"));
     487           0 :             PR_Unlock( traceLock );
     488           0 :             break;
     489             : 
     490             :         default:
     491           0 :             PR_LOG( lm, PR_LOG_ERROR,
     492             :                 ("PRSetTraceOption: Invalid command %ld", command ));
     493           0 :             PR_ASSERT( 0 );
     494           0 :             break;
     495             :     } /* end switch() */
     496           0 :     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           0 :     switch ( command )
     509             :     {
     510             :         case PRTraceBufSize :
     511           0 :             *((PRInt32 *)value) = bufSize;
     512           0 :             PR_LOG( lm, PR_LOG_DEBUG,
     513             :                 ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize ));
     514           0 :             break;
     515             :         
     516             :         default:
     517           0 :             PR_LOG( lm, PR_LOG_ERROR,
     518             :                 ("PRGetTraceOption: Invalid command %ld", command ));
     519           0 :             PR_ASSERT( 0 );
     520           0 :             break;
     521             :     } /* end switch() */
     522           0 :     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           0 :     PRTraceHandle     qh, rh = NULL;
     536           0 :     RName   *rnp = NULL;
     537             : 
     538           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t"
     539             :         "QName: %s, RName: %s", qName, rName ));
     540             : 
     541           0 :     qh = PR_FindNextTraceQname( NULL );
     542           0 :     while (qh != NULL)
     543             :     {
     544           0 :         rh = PR_FindNextTraceRname( NULL, qh );
     545           0 :         while ( rh != NULL )
     546             :         {
     547           0 :             PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc );
     548           0 :             if ( (strcmp( qName, qn ) == 0)
     549           0 :                 && (strcmp( rName, rn ) == 0 ))
     550             :             {
     551           0 :                 rnp = (RName *)rh;
     552           0 :                 goto foundIt;
     553             :             }
     554           0 :             rh = PR_FindNextTraceRname( rh, qh );
     555             :         }
     556           0 :         qh = PR_FindNextTraceQname( NULL );
     557             :     }
     558             : 
     559             : foundIt:
     560           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
     561           0 :     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           0 :     RName   *rnp = (RName *)handle;
     576           0 :     QName   *qnp = rnp->qName;
     577             : 
     578           0 :     *qName = qnp->name;
     579           0 :     *rName = rnp->name;
     580           0 :     *description = rnp->desc;
     581             : 
     582           0 :     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           0 :     return;
     587             : } /* end PR_GetTraceNameFromHandle() */
     588             : 
     589             : /*
     590             : **
     591             : */
     592             : PR_IMPLEMENT(PRTraceHandle) 
     593             :         PR_FindNextTraceQname( 
     594             :         PRTraceHandle handle
     595             : )
     596             : {
     597           0 :     QName *qnp = (QName *)handle;
     598             : 
     599           0 :     if ( PR_CLIST_IS_EMPTY( &qNameList ))
     600           0 :             qnp = NULL;
     601           0 :     else if ( qnp == NULL )
     602           0 :         qnp = (QName *)PR_LIST_HEAD( &qNameList );
     603           0 :     else if ( PR_NEXT_LINK( &qnp->link ) ==  &qNameList )
     604           0 :         qnp = NULL;
     605             :     else  
     606           0 :         qnp = (QName *)PR_NEXT_LINK( &qnp->link );
     607             : 
     608           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p", 
     609             :         handle, qnp ));
     610             : 
     611           0 :     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           0 :     RName *rnp = (RName *)rhandle;
     624           0 :     QName *qnp = (QName *)qhandle;
     625             : 
     626             : 
     627           0 :     if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
     628           0 :         rnp = NULL;
     629           0 :     else if ( rnp == NULL )
     630           0 :         rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
     631           0 :     else if ( PR_NEXT_LINK( &rnp->link ) ==  &qnp->rNameList )
     632           0 :         rnp = NULL;
     633             :     else
     634           0 :         rnp = (RName *)PR_NEXT_LINK( &rnp->link );
     635             : 
     636           0 :     PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", 
     637             :         rhandle, qhandle, rnp ));
     638             : 
     639           0 :     return((PRTraceHandle)rnp);
     640             : } /* end PR_FindNextTraceRname() */
     641             :     
     642             : /*
     643             : **
     644             : */
     645           0 : static PRFileDesc * InitializeRecording( void )
     646             : {
     647             :     char    *logFileName;
     648             :     PRFileDesc  *logFile;
     649             : 
     650             :     /* Self initialize, if necessary */
     651           0 :     if ( traceLock == NULL )
     652           0 :         _PR_InitializeTrace();
     653             : 
     654           0 :     PR_LOG( lm, PR_LOG_DEBUG,
     655             :         ("PR_RecordTraceEntries: begins"));
     656             : 
     657           0 :     logLostData = 0; /* reset at entry */
     658           0 :     logState = LogReset;
     659             : 
     660             :     /* Get the filename for the logfile from the environment */
     661           0 :     logFileName = PR_GetEnvSecure( "NSPR_TRACE_LOG" );
     662           0 :     if ( logFileName == NULL )
     663             :     {
     664           0 :         PR_LOG( lm, PR_LOG_ERROR,
     665             :             ("RecordTraceEntries: Environment variable not defined. Exiting"));
     666           0 :         return NULL;
     667             :     }
     668             :     
     669             :     /* Open the logfile */
     670           0 :     logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 );
     671           0 :     if ( logFile == NULL )
     672             :     {
     673           0 :         PR_LOG( lm, PR_LOG_ERROR,
     674             :             ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld", 
     675             :                 logFileName, PR_GetOSError()));
     676           0 :         return NULL;
     677             :     }
     678           0 :     return logFile;
     679             : } /* end InitializeRecording() */
     680             : 
     681             : /*
     682             : **
     683             : */
     684           0 : static void ProcessOrders( void )
     685             : {
     686           0 :     switch ( logOrder )
     687             :     {
     688             :     case LogReset :
     689           0 :         logOrder = logState = localState;
     690           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     691             :             ("RecordTraceEntries: LogReset"));
     692           0 :         break;
     693             : 
     694             :     case LogSuspend :
     695           0 :         localState = logOrder = logState = LogSuspend;
     696           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     697             :             ("RecordTraceEntries: LogSuspend"));
     698           0 :         break;
     699             : 
     700             :     case LogResume :
     701           0 :         localState = logOrder = logState = LogActive;
     702           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     703             :             ("RecordTraceEntries: LogResume"));
     704           0 :         break;
     705             : 
     706             :     case LogStop :
     707           0 :         logOrder = logState = LogStop;
     708           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     709             :             ("RecordTraceEntries: LogStop"));
     710           0 :         break;
     711             : 
     712             :     default :
     713           0 :         PR_LOG( lm, PR_LOG_ERROR,
     714             :             ("RecordTraceEntries: Invalid logOrder: %ld", logOrder ));
     715           0 :         PR_ASSERT( 0 );
     716           0 :         break;
     717             :     } /* end switch() */
     718           0 :     return ;
     719             : } /* end ProcessOrders() */
     720             : 
     721             : /*
     722             : **
     723             : */
     724           0 : static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount )
     725             : {
     726             :     PRInt32 rc;
     727             : 
     728             : 
     729           0 :     PR_LOG( lm, PR_LOG_ERROR,
     730             :         ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount));
     731           0 :     rc = PR_Write( logFile, buf , amount );
     732           0 :     if ( rc == -1 )
     733           0 :         PR_LOG( lm, PR_LOG_ERROR,
     734             :             ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() ));
     735           0 :     else if ( rc != amount )
     736           0 :         PR_LOG( lm, PR_LOG_ERROR,
     737             :             ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc));
     738             :     else 
     739           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     740             :             ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount));
     741             : 
     742           0 :     return;
     743             : } /* end WriteTraceSegment() */
     744             : 
     745             : /*
     746             : **
     747             : */
     748             : PR_IMPLEMENT(void)
     749             :         PR_RecordTraceEntries(
     750             :         void 
     751             : )
     752             : {
     753             :     PRFileDesc  *logFile;
     754             :     PRInt32     lostSegments;
     755           0 :     PRInt32     currentSegment = 0;
     756             :     void        *buf;
     757             :     PRBool      doWrite;
     758             : 
     759           0 :     logFile = InitializeRecording();
     760           0 :     if ( logFile == NULL )
     761             :     {
     762           0 :         PR_LOG( lm, PR_LOG_DEBUG,
     763             :             ("PR_RecordTraceEntries: Failed to initialize"));
     764           0 :         return;
     765             :     }
     766             : 
     767             :     /* Do this until told to stop */
     768           0 :     while ( logState != LogStop )
     769             :     {
     770             : 
     771           0 :         PR_Lock( logLock );
     772             : 
     773           0 :         while ( (logCount == 0) && ( logOrder == logState ) )
     774           0 :             PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT );
     775             : 
     776             :         /* Handle state transitions */
     777           0 :         if ( logOrder != logState )
     778           0 :             ProcessOrders();
     779             : 
     780             :         /* recalculate local controls */
     781           0 :         if ( logCount )
     782             :         {
     783           0 :             lostSegments = logCount - logSegments;
     784           0 :             if ( lostSegments > 0 )
     785             :             {
     786           0 :                 logLostData += ( logCount - logSegments );
     787           0 :                 logCount = (logCount % logSegments);
     788           0 :                 currentSegment = logCount;
     789           0 :                 PR_LOG( lm, PR_LOG_DEBUG,
     790             :                     ("PR_RecordTraceEntries: LostData segments: %ld", logLostData));
     791             :             }
     792             :             else
     793             :             {
     794           0 :                 logCount--;
     795             :             }
     796             : 
     797           0 :             buf = tBuf + ( logEntriesPerSegment * currentSegment );
     798           0 :             if (++currentSegment >= logSegments )
     799           0 :                 currentSegment = 0;
     800           0 :             doWrite = PR_TRUE;
     801             :         }
     802             :         else
     803           0 :             doWrite = PR_FALSE;
     804             : 
     805           0 :         PR_Unlock( logLock );
     806             : 
     807           0 :         if ( doWrite == PR_TRUE )
     808             :         {
     809           0 :             if ( localState != LogSuspend )
     810           0 :                 WriteTraceSegment( logFile, buf, logSegSize );
     811             :             else
     812           0 :                 PR_LOG( lm, PR_LOG_DEBUG,
     813             :                     ("RecordTraceEntries: PR_Write(): is suspended" ));
     814             :         }
     815             : 
     816             :     } /* end while(logState...) */
     817             : 
     818           0 :     PR_Close( logFile );
     819           0 :     PR_LOG( lm, PR_LOG_DEBUG,
     820             :         ("RecordTraceEntries: exiting"));
     821           0 :     return;
     822             : } /* end  PR_RecordTraceEntries() */
     823             : 
     824             : /*
     825             : **
     826             : */
     827             : PR_IMPLEMENT(PRIntn)
     828             :     PR_GetTraceEntries(
     829             :         PRTraceEntry    *buffer,    /* where to write output */
     830             :         PRInt32         count,      /* number to get */
     831             :         PRInt32         *found      /* number you got */
     832             : )
     833             : {
     834             :     PRInt32 rc; 
     835           0 :     PRInt32 copied = 0;
     836             :     
     837           0 :     PR_Lock( traceLock );
     838             :     
     839             :     /*
     840             :     ** Depending on where the LastSeen and Next indices are,
     841             :     ** copy the trace buffer in one or two pieces. 
     842             :     */
     843           0 :     PR_LOG( lm, PR_LOG_ERROR,
     844             :         ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen));
     845             : 
     846           0 :     if ( fetchLastSeen <= next )
     847             :     {
     848           0 :         while (( count-- > 0 ) && (fetchLastSeen < next ))
     849             :         {
     850           0 :             *(buffer + copied++) = *(tBuf + fetchLastSeen++);
     851             :         }
     852           0 :         PR_LOG( lm, PR_LOG_ERROR,
     853             :             ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
     854             :     }
     855             :     else /* copy in 2 parts */
     856             :     {
     857           0 :         while ( count-- > 0  && fetchLastSeen <= last )
     858             :         {
     859           0 :             *(buffer + copied++) = *(tBuf + fetchLastSeen++);
     860             :         }
     861           0 :         fetchLastSeen = 0;
     862             : 
     863           0 :         PR_LOG( lm, PR_LOG_ERROR,
     864             :             ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
     865             : 
     866           0 :         while ( count-- > 0  && fetchLastSeen < next )
     867             :         {
     868           0 :             *(buffer + copied++) = *(tBuf + fetchLastSeen++);
     869             :         }
     870           0 :         PR_LOG( lm, PR_LOG_ERROR,
     871             :             ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
     872             :     }
     873             : 
     874           0 :     *found = copied;
     875           0 :     rc = ( fetchLostData == PR_TRUE )? 1 : 0;
     876           0 :     fetchLostData = PR_FALSE;
     877             : 
     878           0 :     PR_Unlock( traceLock );
     879           0 :     return rc;
     880             : } /* end PR_GetTraceEntries() */
     881             : 
     882             : /* end prtrace.c */

Generated by: LCOV version 1.13