ncdengine/inc/catalogsdebug.h
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/inc/catalogsdebug.h	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,461 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   Debug logging utility
+*
+*/
+
+
+/**
+* INSTRUCTIONS
+*
+* To enable logging, add MACROs in the mmp for individual options:
+* This enables debug logging and the undertaker watchdog.
+* MACRO CATALOGS_BUILD_CONFIG_DEBUG
+*
+* Define this to direct debug output to external logger app (must be started before starting Catalogs).
+* Only has effect if CATALOGS_BUILD_CONFIG_DEBUG is defined.
+* MACRO CATALOGS_BUILD_CONFIG_DEBUG_EXT_LOGGER
+*
+* Define this to write debug output to a file using file logger (slow)
+* Only has effect if CATALOGS_BUILD_CONFIG_DEBUG is defined.
+* MACRO CATALOGS_BUILD_CONFIG_DEBUG_FILE_LOGGER
+*
+* Define this to send Catalogs debug print output to system debug log (RDebug)
+* Only has effect if CATALOGS_BUILD_CONFIG_DEBUG is defined.
+* MACRO CATALOGS_BUILD_CONFIG_DEBUG_RDEBUG
+*
+* This enables the heap checker utility, needs CATALOGS_BUILD_CONFIG_DEBUG.
+* Note that on ARMV5 build the heap checker is never enabled.
+* MACRO CATALOGS_BUILD_CONFIG_HEAP_CHECKER
+*
+* Enable method in/out logging
+* MACRO CATALOGS_LOG_TRACE
+*
+* Enable general logging (dltrace etc matcros)
+* MACRO CATALOGS_LOG_DEBUG
+*
+* Enable DASSERT macro
+* MACRO CATALOGS_DEBUG_ASSERTS
+*
+* This first version will create normal a normal file log.
+* Create dir "c:\Logs\Catalogs". Log file "debug.log" will be created there, if the 
+* directory exists.
+*
+* For each cpp file, include "catalogsdebug.h". 
+* For each MMP, include "ncddebug_20019119.lib".
+* For each executable, place DLINIT macro in entry code before using any debug prints, and
+* DLUNINIT macro in exit code after last debug prints have been made.
+* 
+* NOTE: DO NOT USE CATALOGS_FILEID. Causes trouble in branch management.
+* To log Perforce file and version information, do this for each cpp file:
+* #undef CATALOGS_FILEID
+* #define CATALOGS_FILEID "$Id$"
+* P4 will replace this with "//depot/path/file.txt#3" during the next submit.
+* If this define is not done, only file name is logged.
+* NOTE! $Id$ is only replaced if the corresponding file has keyword expansion enabled,
+* this can be changed by right clicking a file in the changelist and selecting 
+* "Change file type...".
+*
+* Logging is done using macros. Each macro automatically log the following information:
+* - source file name and revision (from P4), or filename if not available
+* - function name
+* - line number
+*
+* Note the double parentheses in the macros.
+*
+* Use DLTRACEIN macro to log function entry, and DLTRACEOUT to log function exit. 
+* DLTRACE can be used to log entries to some important parts of the code.
+* Example:
+* DLTRACEIN((_L("Input parameter aParam=%d"),aParam));
+* DLTRACE((_L("Branch taken")));
+* DLTRACEOUT((_L("Output=%d"),result));
+*
+* DLINFO can be used to log generic info:
+* DLINFO((_L("Parsing created an element with name %S"),&elementName));
+*
+* DLERROR can be used to log errors:
+* DLERROR((_L("Error while processing data error=%d, message=%S"),errorCode,&errorMessage));
+*
+* DLWARNING is used to log warnings.
+*
+* The macros support both 16-bit and 8-bit descriptors.
+* 8-bit format:
+* DLERROR(("this is a 8-bit string: %S",&K8BitString));
+*
+* NOTE! It's important to choose the right variant depending
+* on the %S parameter type you want to print.
+*
+* DLERRORDUMP and DLINFODUMP can be used to output hex data to the log file.
+*
+* DASSERT should be used for asserts.
+*/
+
+
+#ifndef CATALOGSDEBUG_H
+#define CATALOGSDEBUG_H
+
+#include <e32std.h>
+#include <flogger.h>
+#include <e32msgqueue.h>
+
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG
+// This could be overridden by each source file:
+//#undef CATALOGS_FILEID
+#define CATALOGS_FILEID __FILE__
+#define CATALOGS_FUNCNAME __PRETTY_FUNCTION__
+
+// panic with <filename>, <lineno>
+// Filename is formatted so that extension (.cpp) is dropped, and 16
+// rightmost characters are used. This maximises information about where problem occured.
+// (the code is inside if statements is in one line because otherwise doesn't compile on codewarrior)
+#define DEBUG_PANIC { \
+    const TInt KPanicSize = 16; \
+    TPtrC8 fname((const TUint8 *)CATALOGS_FILEID); \
+    TBuf<KPanicSize> panic; \
+    TInt dotPos = fname.LocateReverse('.'); \
+    if ( dotPos == KErrNotFound ) { panic.Copy(fname.Right(KPanicSize)); } \
+    else \
+        { \
+        TInt start = dotPos - KPanicSize; \
+        /* we have to clip from start, panicsize=4 -> "c:\something\test.cpp" -> "test" */ \
+        if ( start >= 0 ) { panic.Copy( fname.Mid( start, KPanicSize ) ); } \
+        else \
+            { /* no clipping from the start needed */ \
+            panic.Copy( fname.Left( KPanicSize ) ); \
+            } \
+        }  \
+    User::Panic( panic, __LINE__ ); }
+
+#define DLINIT { \
+    TRAPD( err, RCatalogsDebugHeap::InstallL() ); \
+    if( err != KErrNone ) DEBUG_PANIC; }
+#define DLUNINIT RCatalogsDebugHeap::Uninstall();
+#else
+#define DLINIT
+#define DLUNINIT
+#endif  // CATALOGS_BUILD_CONFIG_DEBUG
+
+// For now, enable all debug utilities disabled by default
+//#define CATALOGS_LOG_TRACE
+//#define CATALOGS_LOG_DEBUG
+//#define CATALOGS_DEBUG_ASSERTS
+
+#ifdef CATALOGS_BUILD_CONFIG_HEAP_CHECKER
+#define CATALOGS_DEBUG_CHECKS
+#endif  // CATALOGS_BUILD_CONFIG_HEAP_CHECKER
+
+// Define to enable debug logger GUI
+//#define CATALOGS_EXT_LOGGER
+
+
+
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG) && defined (CATALOGS_LOG_TRACE)
+#   define DLTRACE( x )     { TCatalogsDebug debug( TCatalogsDebug::ETrace,    CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print x; }
+#   define DLTRACEIN( x )   TCatalogsLocalExitTrace __traceIn( CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); { TCatalogsDebug debug( TCatalogsDebug::ETraceIn, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print x; }
+#   define DLTRACEOUT( x )  { TCatalogsDebug debug( TCatalogsDebug::ETraceOut, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID, User::FastCounter()-__traceIn.iEntryTime ); debug.Print x; __traceIn.Disable(); }
+#   undef TRAP_INSTRUMENTATION_LEAVE
+#   define TRAP_INSTRUMENTATION_LEAVE( x ) { TCatalogsDebug debug( TCatalogsDebug::ETrace, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print(_L("Leave code=%d"), x); }
+#else
+#   define DLTRACE( x )
+#   define DLTRACEIN( x )
+#   define DLTRACEOUT( x )
+#endif  // CATALOGS_BUILD_CONFIG_DEBUG && CATALOGS_LOG_TRACE
+
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG) && defined (CATALOGS_LOG_DEBUG)
+#   define DLERROR( x )     { TCatalogsDebug debug( TCatalogsDebug::EError, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print x; }
+#   define DLWARNING( x )   { (void)__traceIn; TCatalogsDebug debug( TCatalogsDebug::EWarning, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print x; }
+#   define DLINFO( x )      { (void)__traceIn; TCatalogsDebug debug( TCatalogsDebug::EInfo,  CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print x; }
+#   define DLERRORDUMP( ptr, size, clip ) { (void)__traceIn; TCatalogsDebug debug( TCatalogsDebug::EError, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.DumpData( ptr, size, clip ); }
+#   define DLINFODUMP( ptr, size, clip )  { (void)__traceIn; TCatalogsDebug debug( TCatalogsDebug::EInfo,  CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.DumpData( ptr, size, clip ); }
+#else
+#   define DLERROR( x )
+#   define DLWARNING( x )
+#   define DLINFO( x )
+#   define DLERRORDUMP( ptr, size, clip )
+#   define DLINFODUMP( ptr, size, clip )
+#endif  // CATALOGS_BUILD_CONFIG_DEBUG && CATALOGS_LOG_DEBUG
+
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG) && defined (CATALOGS_DEBUG_ASSERTS)
+#   define DASSERT( x ) if(!(x)) { DLERROR(("ASSERTION FAILED")); DEBUG_PANIC; }
+#else
+#   define DASSERT( x )
+#endif
+
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG) && defined (CATALOGS_DEBUG_CHECKS)
+  #define DCHECK_CSTACK TCatalogsLocalCleanupStackWatcher __cleanupStackWatcher;
+  #define DCHECK_HEAP TCatalogsLocalDebugHeapActivator __debugHeapActivator;
+  #define DCHECK \
+    TCatalogsLocalCleanupStackWatcher __cleanupStackWatcher; \
+    TCatalogsLocalDebugHeapActivator __debugHeapActivator;
+#else
+  #define DCHECK_CSTACK
+  #define DCHECK_HEAP
+  #define DCHECK
+#endif // CATALOGS_BUILD_CONFIG_DEBUG && CATALOGS_DEBUG_CHECKS
+
+
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG) && defined (CATALOGS_PROFILING)
+#   if defined(COMPONENT_CATALOGSSERVEREXE)
+#       define DPROFILING_BEGIN( x ) TTime x; x.HomeTime(); static TInt64 total = 0
+#       define DPROFILING_END( x ) { TTime now2; \
+                    now2.HomeTime(); \
+                    TInt64 time1 = now2.MicroSecondsFrom( x ).Int64();\
+                    total = total + time1; \
+                    TCatalogsDebug debug( TCatalogsDebug::ETrace, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print( "%Ld ms, total: %Ld ms", (time1 / 1000 ), (total / 1000) ); }
+#   else // Non-server code
+#       define DPROFILING_BEGIN( x ) TTime x; x.HomeTime()
+#       define DPROFILING_END( x ) { TTime now2; \
+                    now2.HomeTime(); \
+                    TInt64 time1 = now2.MicroSecondsFrom( x ).Int64();\
+                    TCatalogsDebug debug( TCatalogsDebug::ETrace, CATALOGS_FUNCNAME, __LINE__, CATALOGS_FILEID ); debug.Print( "%Ld ms", (time1 / 1000 ) ); }
+#   endif
+#else
+#   define DPROFILING_BEGIN( x )
+#   define DPROFILING_END( x )
+#endif
+
+
+// Helpers for reference count checking
+#if defined (CATALOGS_BUILD_CONFIG_DEBUG)
+
+    #define DREFCOUNT_IS( objectPtr, value ) { if ( objectPtr ) { (objectPtr)->AddRef(); TInt count = (objectPtr)->Release(); DASSERT( count == value ); } }
+    
+    #define DREFCOUNT_EVAL( objectPtr, expression ) { if ( objectPtr ) { (objectPtr)->AddRef(); TInt count = (objectPtr)->Release(); DASSERT( count expression ); } }            
+
+#else
+
+    #define DREFCOUNT_IS( objectPtr, value )
+    #define DREFCOUNT_EVAL( objectPtr, expression )
+
+#endif
+
+
+/**
+ * Function-local exit tracer. When instantiated as a local variable at start of a scope (e.g. function)
+ * makes a debug print when the scope is left (either normally or through a leave)
+ *
+ * @note Cannot be used in scopes that leave item(s) on cleanup stack, such as an LC function.
+ * @note Can be used in nested scopes.
+ */
+class TCatalogsLocalExitTrace
+    {
+public:
+    IMPORT_C TCatalogsLocalExitTrace( const char* aFunctionName, TInt aLine, const char* aFileId );
+    IMPORT_C ~TCatalogsLocalExitTrace();
+    IMPORT_C void Disable();
+
+    const char* iFunctionName;
+    TInt iLine;
+    const char* iFileId;   
+    TBool iDisabled;
+    TUint32 iEntryTime;
+    };
+
+/**
+ * Function-local cleanup stack watcher. When instantiated as a local variable at start of a scope (e.g. function),
+ * tracks cleanupstack balance; will cause E32USER-CBase 90 panic if cleanupstack in the beginning and end of the scope
+ * doesn't match (one or more items have been left on cleanup stack or popped out).
+ *
+ * @note Cannot be used in scopes that are supposed to leave item(s) on cleanup stack, such as an LC function.
+ * @note Can be used in nested scopes.
+ */
+class TCatalogsLocalCleanupStackWatcher
+    {
+public:
+    IMPORT_C TCatalogsLocalCleanupStackWatcher();
+    IMPORT_C ~TCatalogsLocalCleanupStackWatcher();
+    TBool iPopped;
+    };
+
+/**
+ * Function-local debug heap activator. When instantiated as a local variable at start of a scope (e.g. function)
+ * makes sure debug heap is active only within the scope.
+ *
+ * @note Cannot be used in scopes that leave item(s) on cleanup stack, such as an LC function.
+ * @note Can be used in nested scopes.
+ */
+class TCatalogsLocalDebugHeapActivator
+    {
+public:
+    IMPORT_C TCatalogsLocalDebugHeapActivator();
+    IMPORT_C ~TCatalogsLocalDebugHeapActivator();
+    TBool iPopped;
+    TBool iActive;
+    };
+
+
+// Big enough formatting buffer. If the format parameters exceeds this, a panic occurs!
+const TInt KCatalogsDebugBufferSize = 1024*80;
+
+/**
+* Debug utility class. 
+*/
+class TCatalogsDebug
+    {
+public:
+    /**
+    * Debug log event types
+    */
+    enum TType
+        {
+        ETrace,
+        ETraceIn,
+        ETraceOut,
+        EError,
+        EWarning,
+        EInfo,
+        ETraceLeave
+        };
+    
+    enum
+        {
+        EOutputRDebug = 1,
+        EOutputFileLogger = 2,
+        EOutputExtLogger = 4
+        };
+        
+    enum
+        {
+        EBuildOutput = 0
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG_RDEBUG
+        | EOutputRDebug
+#endif
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG_FILE_LOGGER
+        | EOutputFileLogger
+#endif
+#ifdef CATALOGS_BUILD_CONFIG_DEBUG_EXT_LOGGER
+        | EOutputExtLogger
+#endif
+        };
+        
+    /**
+    * Constructor, sets generic information for the print.
+    * @param aType
+    * @param aFunction Function name
+    * @param aLine Source code line
+    * @param aFileId File identification
+    */
+    IMPORT_C TCatalogsDebug( 
+        TType aType, 
+        const char* aFunction, 
+        TInt aLine, 
+        const char* aFileId,
+        TUint aDeltaTime = 0,
+        TInt aOutput = EBuildOutput
+        );
+    
+    /**
+    * Print formatted data to the log, 16-bit descriptors.
+    * @param aFmt Format string
+    */
+    IMPORT_C void Print( TRefByValue<const TDesC16> aFmt, ... );
+
+    /**
+    * Print formatted data to the log, 8-bit descriptors.
+    * @param aFmt Format string
+    */
+    IMPORT_C void Print( const char* aFmt, ... );
+
+    /**
+    * Print hex data to the log.
+    * @param aData Data pointer
+    * @param aSize 
+    * @param aClipToSize 
+    */
+    IMPORT_C void DumpData( const TAny* aData, TInt aSize, TInt aClipToSize );
+
+private:
+    void PrintGeneral( TPtr8 aPrintBuf );
+    void FileWrite( const TDesC8& aPrintBuf );
+
+private:
+
+    TType       iType;
+    const char* iFunction;
+    TInt        iLine;
+    const char* iFileId;
+    TUint       iDeltaTime;
+    TInt        iOutput;
+    };
+
+/**
+ * Debug heap implementation. Holds "global" data for debug printing, and has
+ * utilities for finding memory leaks.
+ */
+class RCatalogsDebugHeap : public RHeap
+    {
+public:
+
+    IMPORT_C static void InstallL( TBool aEnabled = 
+#ifdef CATALOGS_BUILD_CONFIG_HEAP_CHECKER
+        ETrue );
+#else
+        EFalse );
+#endif    
+    IMPORT_C static void Uninstall();
+    IMPORT_C static TBool Activate( TBool aActive );
+
+    void ChunkOutput( const TDesC8& aBuffer, TUint aDeltaTime );
+    TBool IsEnabled( TCatalogsDebug::TType aPrintType );
+
+public: // from RHeap
+
+    TAny* Alloc( TInt aSize );
+    void Free( TAny* aPtr );
+    TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
+    TInt AllocLen(const TAny* aCell) const;
+    TInt Compress();
+    void Reset();
+    TInt AllocSize(TInt& aTotalAllocSize) const;
+    TInt Available(TInt& aBiggestBlock) const;
+    TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL);
+
+    TAny* operator new( TUint aSize );
+    void operator delete( TAny* aPtr );
+
+protected: // from RHeap
+    TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
+
+    RCatalogsDebugHeap( RHeap& aBaseHeap, TBool aEnabled );
+    ~RCatalogsDebugHeap();
+
+private:
+
+    RHeap&  iBaseHeap;
+    TInt    iAllocCounter; // running counter for allocs
+    
+    struct TAllocInfo
+        {
+        TAny*   iAllocPtr;
+        TInt    iAllocSize;
+        TInt    iAllocNum;
+        };
+
+    RArray< TAllocInfo > iAllocInfo;
+    TBool               iEnabled;
+    TBool               iActive;
+
+    // Debug chunk logging
+    void InitExtLogger();
+
+    TInt    iChunkIndex;    // current chunk index
+    RChunk  iChunk[2];
+    RSemaphore iChunkWriteSemaphore;
+    RMutex  iMutex;
+    RMsgQueue<TInt> iMsgQueue;
+    
+    TUint   iFastCounterFrequency;
+    };
+
+#endif // CATALOGSDEBUG_H