diff -r 000000000000 -r ba25891c3a9e ncdengine/inc/catalogsdebug.h --- /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 +#include +#include + +#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 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 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 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 iMsgQueue; + + TUint iFastCounterFrequency; + }; + +#endif // CATALOGSDEBUG_H