--- /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