diff nspr/pr/src/misc/prtrace.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nspr/pr/src/misc/prtrace.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,888 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** prtrace.c -- NSPR Trace Instrumentation
+**
+** Implement the API defined in prtrace.h
+**
+**
+**
+*/
+
+#include <string.h>
+#include "primpl.h"
+
+
+#define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 )
+#define DEFAULT_BUFFER_SEGMENTS    2
+
+/*
+** Enumerate states in a RName structure
+*/
+typedef enum TraceState
+{
+    Running = 1,
+    Suspended = 2
+} TraceState;
+
+/*
+** Define QName structure
+*/
+typedef struct QName
+{
+    PRCList link;
+    PRCList rNameList;
+    char    name[PRTRACE_NAME_MAX+1];
+} QName;
+
+/*
+** Define RName structure
+*/
+typedef struct RName
+{
+    PRCList link;
+    PRLock  *lock;
+    QName   *qName;
+    TraceState state;
+    char    name[PRTRACE_NAME_MAX+1];
+    char    desc[PRTRACE_DESC_MAX+1];
+} RName;
+
+
+/*
+** The Trace Facility database
+**
+*/
+static PRLogModuleInfo *lm;
+
+static PRLock      *traceLock;      /* Facility Lock */
+static PRCList     qNameList;       /* anchor to all QName structures */
+static TraceState traceState = Running;
+
+/*
+** in-memory trace buffer controls
+*/
+static  PRTraceEntry    *tBuf;      /* pointer to buffer */
+static  PRInt32         bufSize;    /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */
+static  volatile PRInt32  next;     /* index to next PRTraceEntry */
+static  PRInt32         last;       /* index of highest numbered trace entry */
+
+/*
+** Real-time buffer capture controls
+*/
+static PRInt32 fetchLastSeen = 0;
+static PRBool  fetchLostData = PR_FALSE;
+
+/*
+** Buffer write-to-file controls
+*/
+static  PRLock      *logLock;               /* Sync lock */
+static  PRCondVar   *logCVar;               /* Sync Condidtion Variable */
+/*
+** Inter-thread state communication.
+** Controling thread writes to logOrder under protection of logCVar
+** the logging thread reads logOrder and sets logState on Notify.
+** 
+** logSegments, logCount, logLostData must be read and written under
+** protection of logLock, logCVar.
+** 
+*/
+static  enum LogState
+{
+    LogNotRunning,  /* Initial state */
+    LogReset,       /* Causes logger to re-calc controls */
+    LogActive,      /* Logging in progress, set only by log thread */
+    LogSuspend,     /* Suspend Logging */ 
+    LogResume,      /* Resume Logging => LogActive */ 
+    LogStop         /* Stop the log thread */
+}   logOrder, logState, localState;         /* controlling state variables */
+static  PRInt32     logSegments;            /* Number of buffer segments */
+static  PRInt32     logEntries;             /* number of Trace Entries in the buffer */
+static  PRInt32     logEntriesPerSegment;   /* number of PRTraceEntries per buffer segment */
+static  PRInt32     logSegSize;             /* size of buffer segment */
+static  PRInt32     logCount;               /* number of segments pending output */
+static  PRInt32     logLostData;            /* number of lost log buffer segments */
+
+/*
+** end Trace Database
+**
+*/
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void NewTraceBuffer( PRInt32 size )
+{
+    /*
+    ** calculate the size of the buffer
+    ** round down so that each segment has the same number of
+    ** trace entries
+    */
+    logSegments = DEFAULT_BUFFER_SEGMENTS;
+    logEntries = size / sizeof(PRTraceEntry);
+    logEntriesPerSegment = logEntries / logSegments;
+    logEntries = logSegments * logEntriesPerSegment;
+    bufSize = logEntries * sizeof(PRTraceEntry);
+    logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);
+    PR_ASSERT( bufSize != 0);
+    PR_LOG( lm, PR_LOG_ERROR,
+        ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",
+            logSegments, logEntries, logEntriesPerSegment, logSegSize ));
+
+
+    tBuf = PR_Malloc( bufSize );
+    if ( tBuf == NULL )
+    {
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("PRTrace: Failed to get trace buffer"));
+        PR_ASSERT( 0 );
+    } 
+    else
+    {
+        PR_LOG( lm, PR_LOG_NOTICE,
+            ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));
+    }
+
+    next = 0;
+    last = logEntries -1;
+    logCount = 0;
+    logLostData = PR_TRUE; /* not really on first call */
+    logOrder = LogReset;
+
+} /* end NewTraceBuffer() */
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void _PR_InitializeTrace( void )
+{
+    /* The lock pointer better be null on this call */
+    PR_ASSERT( traceLock == NULL );
+
+    traceLock = PR_NewLock();
+    PR_ASSERT( traceLock != NULL );
+
+    PR_Lock( traceLock );
+    
+    PR_INIT_CLIST( &qNameList );
+
+    lm = PR_NewLogModule("trace");
+
+    bufSize = DEFAULT_TRACE_BUFSIZE;
+    NewTraceBuffer( bufSize );
+
+    /* Initialize logging controls */
+    logLock = PR_NewLock();
+    logCVar = PR_NewCondVar( logLock );
+
+    PR_Unlock( traceLock );
+    return;    
+} /* end _PR_InitializeTrace() */
+
+/*
+** Create a Trace Handle
+*/
+PR_IMPLEMENT(PRTraceHandle)
+	PR_CreateTrace( 
+    	const char *qName,          /* QName for this trace handle */
+	    const char *rName,          /* RName for this trace handle */
+	    const char *description     /* description for this trace handle */
+)
+{
+    QName   *qnp;
+    RName   *rnp;
+    PRBool  matchQname = PR_FALSE;
+
+    /* Self initialize, if necessary */
+    if ( traceLock == NULL )
+        _PR_InitializeTrace();
+
+    /* Validate input arguments */
+    PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );
+    PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );
+    PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );
+
+    PR_LOG( lm, PR_LOG_DEBUG,
+            ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));
+
+    /* Lock the Facility */
+    PR_Lock( traceLock );
+
+    /* Do we already have a matching QName? */
+    if (!PR_CLIST_IS_EMPTY( &qNameList ))
+    {
+        qnp = (QName *) PR_LIST_HEAD( &qNameList );
+        do {
+            if ( strcmp(qnp->name, qName) == 0)
+            {
+                matchQname = PR_TRUE;
+                break;
+            }
+            qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+        } while( qnp != (QName *)&qNameList );
+    }
+    /*
+    ** If we did not find a matching QName,
+    **    allocate one and initialize it.
+    **    link it onto the qNameList.
+    **
+    */
+    if ( matchQname != PR_TRUE )
+    {
+        qnp = PR_NEWZAP( QName );
+        PR_ASSERT( qnp != NULL );
+        PR_INIT_CLIST( &qnp->link ); 
+        PR_INIT_CLIST( &qnp->rNameList ); 
+        strcpy( qnp->name, qName );
+        PR_APPEND_LINK( &qnp->link, &qNameList ); 
+    }
+
+    /* Do we already have a matching RName? */
+    if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+    {
+        rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
+        do {
+            /*
+            ** No duplicate RNames are allowed within a QName
+            **
+            */
+            PR_ASSERT( strcmp(rnp->name, rName));
+            rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+        } while( rnp != (RName *)&qnp->rNameList );
+    }
+
+    /* Get a new RName structure; initialize its members */
+    rnp = PR_NEWZAP( RName );
+    PR_ASSERT( rnp != NULL );
+    PR_INIT_CLIST( &rnp->link );
+    strcpy( rnp->name, rName );
+    strcpy( rnp->desc, description );
+    rnp->lock = PR_NewLock();
+    rnp->state = Running;
+    if ( rnp->lock == NULL )
+    {
+        PR_ASSERT(0);
+    }
+
+    PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */    
+    rnp->qName = qnp;                       /* point the RName to the QName */
+
+    /* Unlock the Facility */
+    PR_Unlock( traceLock );
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",
+        qName, qnp, rName, rnp ));
+
+    return((PRTraceHandle)rnp);
+} /* end  PR_CreateTrace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void) 
+	PR_DestroyTrace( 
+		PRTraceHandle handle    /* Handle to be destroyed */
+)
+{
+    RName   *rnp = (RName *)handle;
+    QName   *qnp = rnp->qName;
+
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s", 
+        qnp->name, rnp->name));
+
+    /* Lock the Facility */
+    PR_Lock( traceLock );
+
+    /*
+    ** Remove RName from the list of RNames in QName
+    ** and free RName
+    */
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p", 
+        rnp->name, rnp));
+    PR_REMOVE_LINK( &rnp->link );
+    PR_Free( rnp->lock );
+    PR_DELETE( rnp );
+
+    /*
+    ** If this is the last RName within QName
+    **   remove QName from the qNameList and free it
+    */
+    if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
+    {
+        PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p", 
+            qnp->name, qnp));
+        PR_REMOVE_LINK( &qnp->link );
+        PR_DELETE( qnp );
+    } 
+
+    /* Unlock the Facility */
+    PR_Unlock( traceLock );
+    return;
+} /* end PR_DestroyTrace()  */
+
+/*
+** Create a TraceEntry in the trace buffer
+*/
+PR_IMPLEMENT(void) 
+	PR_Trace( 
+    	PRTraceHandle handle,       /* use this trace handle */
+	    PRUint32    userData0,      /* User supplied data word 0 */
+	    PRUint32    userData1,      /* User supplied data word 1 */
+	    PRUint32    userData2,      /* User supplied data word 2 */
+	    PRUint32    userData3,      /* User supplied data word 3 */
+	    PRUint32    userData4,      /* User supplied data word 4 */
+	    PRUint32    userData5,      /* User supplied data word 5 */
+	    PRUint32    userData6,      /* User supplied data word 6 */
+	    PRUint32    userData7       /* User supplied data word 7 */
+)
+{
+    PRTraceEntry   *tep;
+    PRInt32         mark;
+
+    if ( (traceState == Suspended ) 
+        || ( ((RName *)handle)->state == Suspended )) 
+        return;
+
+    /*
+    ** Get the next trace entry slot w/ minimum delay
+    */
+    PR_Lock( traceLock );
+
+    tep = &tBuf[next++]; 
+    if ( next > last )
+        next = 0;
+    if ( fetchLostData == PR_FALSE && next == fetchLastSeen )
+        fetchLostData = PR_TRUE;
+    
+    mark = next;
+        
+    PR_Unlock( traceLock );
+
+    /*
+    ** We have a trace entry. Fill it in.
+    */
+    tep->thread = PR_GetCurrentThread();
+    tep->handle = handle;
+    tep->time   = PR_Now();
+    tep->userData[0] = userData0;
+    tep->userData[1] = userData1;
+    tep->userData[2] = userData2;
+    tep->userData[3] = userData3;
+    tep->userData[4] = userData4;
+    tep->userData[5] = userData5;
+    tep->userData[6] = userData6;
+    tep->userData[7] = userData7;
+
+    /* When buffer segment is full, signal trace log thread to run */
+    if (( mark % logEntriesPerSegment) == 0 )
+    {
+        PR_Lock( logLock );
+        logCount++;
+        PR_NotifyCondVar( logCVar );
+        PR_Unlock( logLock );
+        /*
+        ** Gh0D! This is awful!
+        ** Anyway, to minimize lost trace data segments,
+        ** I inserted the PR_Sleep(0) to cause a context switch
+        ** so that the log thread could run.
+        ** I know, it perturbs the universe and may cause
+        ** funny things to happen in the optimized builds.
+        ** Take it out, lose data; leave it in risk Heisenberg.
+        */
+        /* PR_Sleep(0); */
+    }
+
+    return;
+} /* end PR_Trace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void) 
+	PR_SetTraceOption( 
+	    PRTraceOption command,  /* One of the enumerated values */
+	    void *value             /* command value or NULL */
+)
+{
+    RName * rnp;
+
+    switch ( command )
+    {
+        case PRTraceBufSize :
+            PR_Lock( traceLock );
+            PR_Free( tBuf );
+            bufSize = *(PRInt32 *)value;
+            NewTraceBuffer( bufSize );
+            PR_Unlock( traceLock );
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));
+            break;
+        
+        case PRTraceEnable :
+            rnp = *(RName **)value;
+            rnp->state = Running;
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceEnable: %p", rnp));
+            break;
+        
+        case PRTraceDisable :
+            rnp = *(RName **)value;
+            rnp->state = Suspended;
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceDisable: %p", rnp));
+            break;
+        
+        case PRTraceSuspend :
+            traceState = Suspended;
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceSuspend"));
+            break;
+        
+        case PRTraceResume :
+            traceState = Running;
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceResume"));
+            break;
+        
+        case PRTraceSuspendRecording :
+            PR_Lock( logLock );
+            logOrder = LogSuspend;
+            PR_NotifyCondVar( logCVar );
+            PR_Unlock( logLock );
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceSuspendRecording"));
+            break;
+        
+        case PRTraceResumeRecording :
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceResumeRecording"));
+            if ( logState != LogSuspend )
+                break;
+            PR_Lock( logLock );
+            logOrder = LogResume;
+            PR_NotifyCondVar( logCVar );
+            PR_Unlock( logLock );
+            break;
+        
+        case PRTraceStopRecording :
+            PR_Lock( logLock );
+            logOrder = LogStop;
+            PR_NotifyCondVar( logCVar );
+            PR_Unlock( logLock );
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceStopRecording"));
+            break;
+
+        case PRTraceLockHandles :
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceLockTraceHandles"));
+            PR_Lock( traceLock );
+            break;
+        
+        case PRTraceUnLockHandles :
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRSetTraceOption: PRTraceUnLockHandles"));
+            PR_Unlock( traceLock );
+            break;
+
+        default:
+            PR_LOG( lm, PR_LOG_ERROR,
+                ("PRSetTraceOption: Invalid command %ld", command ));
+            PR_ASSERT( 0 );
+            break;
+    } /* end switch() */
+    return;
+} /* end  PR_SetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void) 
+	PR_GetTraceOption( 
+    	PRTraceOption command,  /* One of the enumerated values */
+	    void *value             /* command value or NULL */
+)
+{
+    switch ( command )
+    {
+        case PRTraceBufSize :
+            *((PRInt32 *)value) = bufSize;
+            PR_LOG( lm, PR_LOG_DEBUG,
+                ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize ));
+            break;
+        
+        default:
+            PR_LOG( lm, PR_LOG_ERROR,
+                ("PRGetTraceOption: Invalid command %ld", command ));
+            PR_ASSERT( 0 );
+            break;
+    } /* end switch() */
+    return;
+} /* end PR_GetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle) 
+	PR_GetTraceHandleFromName( 
+    	const char *qName,      /* QName search argument */
+        const char *rName       /* RName search argument */
+)
+{
+    const char    *qn, *rn, *desc;
+    PRTraceHandle     qh, rh = NULL;
+    RName   *rnp = NULL;
+
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t"
+        "QName: %s, RName: %s", qName, rName ));
+
+    qh = PR_FindNextTraceQname( NULL );
+    while (qh != NULL)
+    {
+        rh = PR_FindNextTraceRname( NULL, qh );
+        while ( rh != NULL )
+        {
+            PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc );
+            if ( (strcmp( qName, qn ) == 0)
+                && (strcmp( rName, rn ) == 0 ))
+            {
+                rnp = (RName *)rh;
+                goto foundIt;
+            }
+            rh = PR_FindNextTraceRname( rh, qh );
+        }
+        qh = PR_FindNextTraceQname( NULL );
+    }
+
+foundIt:
+    PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
+    return(rh);
+} /* end PR_GetTraceHandleFromName() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void) 
+	PR_GetTraceNameFromHandle( 
+    	PRTraceHandle handle,       /* handle as search argument */
+	    const char **qName,         /* pointer to associated QName */
+	    const char **rName,         /* pointer to associated RName */
+    	const char **description    /* pointer to associated description */
+)
+{
+    RName   *rnp = (RName *)handle;
+    QName   *qnp = rnp->qName;
+
+    *qName = qnp->name;
+    *rName = rnp->name;
+    *description = rnp->desc;
+
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: "
+        "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", 
+        qnp, rnp, qnp->name, rnp->name, rnp->desc ));
+
+    return;
+} /* end PR_GetTraceNameFromHandle() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle) 
+	PR_FindNextTraceQname( 
+        PRTraceHandle handle
+)
+{
+    QName *qnp = (QName *)handle;
+
+    if ( PR_CLIST_IS_EMPTY( &qNameList ))
+            qnp = NULL;
+    else if ( qnp == NULL )
+        qnp = (QName *)PR_LIST_HEAD( &qNameList );
+    else if ( PR_NEXT_LINK( &qnp->link ) ==  &qNameList )
+        qnp = NULL;
+    else  
+        qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p", 
+        handle, qnp ));
+
+    return((PRTraceHandle)qnp);
+} /* end PR_FindNextTraceQname() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle) 
+	PR_FindNextTraceRname( 
+        PRTraceHandle rhandle,
+        PRTraceHandle qhandle
+)
+{
+    RName *rnp = (RName *)rhandle;
+    QName *qnp = (QName *)qhandle;
+
+
+    if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+        rnp = NULL;
+    else if ( rnp == NULL )
+        rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
+    else if ( PR_NEXT_LINK( &rnp->link ) ==  &qnp->rNameList )
+        rnp = NULL;
+    else
+        rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+
+    PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", 
+        rhandle, qhandle, rnp ));
+
+    return((PRTraceHandle)rnp);
+} /* end PR_FindNextTraceRname() */
+    
+/*
+**
+*/
+static PRFileDesc * InitializeRecording( void )
+{
+    char    *logFileName;
+    PRFileDesc  *logFile;
+
+    /* Self initialize, if necessary */
+    if ( traceLock == NULL )
+        _PR_InitializeTrace();
+
+    PR_LOG( lm, PR_LOG_DEBUG,
+        ("PR_RecordTraceEntries: begins"));
+
+    logLostData = 0; /* reset at entry */
+    logState = LogReset;
+
+#ifdef XP_UNIX
+    if ((getuid() != geteuid()) || (getgid() != getegid())) {
+        return NULL;
+    }
+#endif /* XP_UNIX */
+
+    /* Get the filename for the logfile from the environment */
+    logFileName = PR_GetEnv( "NSPR_TRACE_LOG" );
+    if ( logFileName == NULL )
+    {
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("RecordTraceEntries: Environment variable not defined. Exiting"));
+        return NULL;
+    }
+    
+    /* Open the logfile */
+    logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 );
+    if ( logFile == NULL )
+    {
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld", 
+		logFileName, PR_GetOSError()));
+        return NULL;
+    }
+    return logFile;
+} /* end InitializeRecording() */
+
+/*
+**
+*/
+static void ProcessOrders( void )
+{
+    switch ( logOrder )
+    {
+    case LogReset :
+        logOrder = logState = localState;
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("RecordTraceEntries: LogReset"));
+        break;
+
+    case LogSuspend :
+        localState = logOrder = logState = LogSuspend;
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("RecordTraceEntries: LogSuspend"));
+        break;
+
+    case LogResume :
+        localState = logOrder = logState = LogActive;
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("RecordTraceEntries: LogResume"));
+        break;
+
+    case LogStop :
+        logOrder = logState = LogStop;
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("RecordTraceEntries: LogStop"));
+        break;
+
+    default :
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("RecordTraceEntries: Invalid logOrder: %ld", logOrder ));
+        PR_ASSERT( 0 );
+        break;
+    } /* end switch() */
+    return ;
+} /* end ProcessOrders() */
+
+/*
+**
+*/
+static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount )
+{
+    PRInt32 rc;
+
+
+    PR_LOG( lm, PR_LOG_ERROR,
+        ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount));
+    rc = PR_Write( logFile, buf , amount );
+    if ( rc == -1 )
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() ));
+    else if ( rc != amount )
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc));
+    else 
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount));
+
+    return;
+} /* end WriteTraceSegment() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+	PR_RecordTraceEntries(
+        void 
+)
+{
+    PRFileDesc  *logFile;
+    PRInt32     lostSegments;
+    PRInt32     currentSegment = 0;
+    void        *buf;
+    PRBool      doWrite;
+
+    logFile = InitializeRecording();
+    if ( logFile == NULL )
+    {
+        PR_LOG( lm, PR_LOG_DEBUG,
+            ("PR_RecordTraceEntries: Failed to initialize"));
+        return;
+    }
+
+    /* Do this until told to stop */
+    while ( logState != LogStop )
+    {
+
+        PR_Lock( logLock );
+
+        while ( (logCount == 0) && ( logOrder == logState ) )
+            PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT );
+
+        /* Handle state transitions */
+        if ( logOrder != logState )
+            ProcessOrders();
+
+        /* recalculate local controls */
+        if ( logCount )
+        {
+            lostSegments = logCount - logSegments;
+            if ( lostSegments > 0 )
+            {
+                logLostData += ( logCount - logSegments );
+                logCount = (logCount % logSegments);
+                currentSegment = logCount;
+                PR_LOG( lm, PR_LOG_DEBUG,
+                    ("PR_RecordTraceEntries: LostData segments: %ld", logLostData));
+            }
+            else
+            {
+                logCount--;
+            }
+
+            buf = tBuf + ( logEntriesPerSegment * currentSegment );
+            if (++currentSegment >= logSegments )
+                currentSegment = 0;
+            doWrite = PR_TRUE;
+        }
+        else
+            doWrite = PR_FALSE;
+
+        PR_Unlock( logLock );
+
+        if ( doWrite == PR_TRUE )
+        {
+            if ( localState != LogSuspend )
+                WriteTraceSegment( logFile, buf, logSegSize );
+            else
+                PR_LOG( lm, PR_LOG_DEBUG,
+                    ("RecordTraceEntries: PR_Write(): is suspended" ));
+        }
+
+    } /* end while(logState...) */
+
+    PR_Close( logFile );
+    PR_LOG( lm, PR_LOG_DEBUG,
+        ("RecordTraceEntries: exiting"));
+    return;
+} /* end  PR_RecordTraceEntries() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRIntn)
+    PR_GetTraceEntries(
+        PRTraceEntry    *buffer,    /* where to write output */
+        PRInt32         count,      /* number to get */
+        PRInt32         *found      /* number you got */
+)
+{
+    PRInt32 rc; 
+    PRInt32 copied = 0;
+    
+    PR_Lock( traceLock );
+    
+    /*
+    ** Depending on where the LastSeen and Next indices are,
+    ** copy the trace buffer in one or two pieces. 
+    */
+    PR_LOG( lm, PR_LOG_ERROR,
+        ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen));
+
+    if ( fetchLastSeen <= next )
+    {
+        while (( count-- > 0 ) && (fetchLastSeen < next ))
+        {
+            *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+        }
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+    }
+    else /* copy in 2 parts */
+    {
+        while ( count-- > 0  && fetchLastSeen <= last )
+        {
+            *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+        }
+        fetchLastSeen = 0;
+
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+
+        while ( count-- > 0  && fetchLastSeen < next )
+        {
+            *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+        }
+        PR_LOG( lm, PR_LOG_ERROR,
+            ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+    }
+
+    *found = copied;
+    rc = ( fetchLostData == PR_TRUE )? 1 : 0;
+    fetchLostData = PR_FALSE;
+
+    PR_Unlock( traceLock );
+    return rc;
+} /* end PR_GetTraceEntries() */
+
+/* end prtrace.c */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)