LCOV - code coverage report
Current view: directory - nsprpub/pr/src/misc - prtrace.c (source / functions) Found Hit Coverage
Test: app.info Lines: 319 0 0.0 %
Date: 2012-06-02 Functions: 16 0 0.0 %

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

Generated by: LCOV version 1.7