--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/debuglogger/src/catalogsloggermsgqueueobserver.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,343 @@
+/*
+* 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:
+*
+*/
+
+
+#include "catalogsloggermsgqueueobserver.h"
+#include "catalogsloggerappui.h"
+
+//#define _DDPRINT( x ) RDebug::Printf x
+#define _DDPRINT( x )
+
+CCatalogsLoggerMsgQueueObserver* CCatalogsLoggerMsgQueueObserver::NewL()
+ {
+ CCatalogsLoggerMsgQueueObserver* self =
+ CCatalogsLoggerMsgQueueObserver::NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CCatalogsLoggerMsgQueueObserver* CCatalogsLoggerMsgQueueObserver::NewLC()
+ {
+ CCatalogsLoggerMsgQueueObserver* self =
+ new( ELeave ) CCatalogsLoggerMsgQueueObserver();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+CCatalogsLoggerMsgQueueObserver::~CCatalogsLoggerMsgQueueObserver()
+ {
+ Flush();
+ Cancel();
+
+ delete iObexSender;
+ iLogFile.Close();
+ iFs.Close();
+ iChunk1.Close();
+ iChunk2.Close();
+ iChunkMutex.Close();
+ iChunkWriteSemaphore.Close();
+ iMsgQueue.Close();
+ }
+
+void CCatalogsLoggerMsgQueueObserver::StartLogging()
+ {
+ iIsLogging = ETrue;
+ SetEnableFlags( iEnableFlags );
+ }
+
+void CCatalogsLoggerMsgQueueObserver::StopLogging()
+ {
+ TInt flags = iEnableFlags;
+ SetEnableFlags( 0 );
+ iIsLogging = EFalse;
+ iEnableFlags = flags;
+ Flush();
+ }
+
+TUint CCatalogsLoggerMsgQueueObserver::CurrentChunkOffset()
+ {
+ // take the the other chunk than the one last full/written
+ RChunk& chunk = iLastChunk == 1 ? iChunk1 : iChunk2;
+
+ // read its header
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)chunk.Base();
+
+ return header->iOffset;
+ }
+
+TPtrC8 CCatalogsLoggerMsgQueueObserver::LastData( TUint aMaxSize )
+ {
+ // take the the other chunk than the one last full/written
+ RChunk& chunk = iLastChunk == 1 ? iChunk1 : iChunk2;
+
+ // read its header
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)chunk.Base();
+
+ // calculate start offset to data
+ TInt start = Max( (TInt)0, (TInt)header->iOffset - (TInt)aMaxSize );
+
+ // return descriptor pointing to the data.
+ return TPtrC8( (TUint8*)(header+1) + start, header->iOffset - start );
+ }
+
+void CCatalogsLoggerMsgQueueObserver::Flush()
+ {
+ // Prevent log writes.
+ iChunkMutex.Wait();
+
+ // take the the other chunk than the one last full/written
+ RChunk& chunk1 = iLastChunk == 1 ? iChunk1 : iChunk2;
+
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)chunk1.Base();
+ if( !(header->iFlags & ECatalogsDebugFlagFlushChunk) && (header->iOffset > 0) )
+ {
+ _DDPRINT(( "DLOG: Debug chunk %d has data, flushing", iLastChunk ^ 1 ));
+
+ // Make a descriptor to hold the data in chunk.
+ TPtrC8 data( (TUint8*)(header+1), header->iOffset );
+
+ // Write it to the log file in one big chunk.
+ _DDPRINT(( "DLOG: Debug chunk %d data writing to disk", iLastChunk ^ 1 ));
+ iLogFile.Write( data );
+ _DDPRINT(( "DLOG: Debug chunk %d data written to disk", iLastChunk ^ 1 ));
+
+ header->iOffset = 0;
+ header->iFlags &= ~ECatalogsDebugFlagFlushChunk;
+ }
+
+ // check if the other one has already been written to as well
+ RChunk& chunk2 = iLastChunk == 0 ? iChunk1 : iChunk2;
+
+ header = (TCatalogsDebugChunkHeader*)chunk2.Base();
+ if( !(header->iFlags & ECatalogsDebugFlagFlushChunk) )
+ {
+ _DDPRINT(( "DLOG: Debug chunk %d has data, flushing", iLastChunk ));
+
+ // has been written to
+ // Make a descriptor to hold the data in chunk.
+ TPtrC8 data( (TUint8*)(header+1), header->iOffset );
+
+ // Write it to the log file in one big chunk.
+ _DDPRINT(( "DLOG: Debug chunk %d data writing to disk", iLastChunk ));
+ iLogFile.Write( data );
+ _DDPRINT(( "DLOG: Debug chunk %d data written to disk", iLastChunk ));
+
+ header->iOffset = 0;
+ header->iFlags |= ECatalogsDebugFlagFlushChunk;
+ }
+
+ // Enable log writes again.
+ iChunkMutex.Signal();
+ }
+
+void CCatalogsLoggerMsgQueueObserver::RunL()
+ {
+ // Read the chunk to flush
+ TInt msg;
+ iMsgQueue.Receive( msg );
+
+ _DDPRINT(( "DLOG: Debug chunk %d flushed, got message", msg ));
+
+ // Reissue message request.
+ iMsgQueue.NotifyDataAvailable( iStatus );
+ SetActive();
+
+ if( iIsLogging )
+ {
+ RChunk& chunk = msg == 0 ? iChunk1 : iChunk2;
+ iLastChunk = msg;
+
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)chunk.Base();
+
+ // Make a descriptor to hold the data in chunk.
+ TPtrC8 data( (TUint8*)(header+1), header->iOffset );
+
+ // Write it to the log file in one big chunk.
+ _DDPRINT(( "DLOG: Debug chunk %d writing to disk", msg ));
+ iLogFile.Write( data );
+ _DDPRINT(( "DLOG: Debug chunk %d written to disk", msg ));
+
+ iFunCounter++;
+ }
+
+ // Signal the write semaphore.
+ _DDPRINT(( "DLOG: Debug chunk write semaphore signal" ));
+ iChunkWriteSemaphore.Signal();
+ }
+
+void CCatalogsLoggerMsgQueueObserver::SetEnableFlags( TInt aFlags )
+ {
+ iEnableFlags = aFlags;
+ if( iIsLogging )
+ {
+ // Prevent log writes.
+ iChunkMutex.Wait();
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)iChunk1.Base();
+ header->iFlags = (header->iFlags & ECatalogsDebugFlagFlushChunk) | aFlags;
+ header = (TCatalogsDebugChunkHeader*)iChunk2.Base();
+ header->iFlags = (header->iFlags & ECatalogsDebugFlagFlushChunk) | aFlags;
+
+ // Enable log writes.
+ iChunkMutex.Signal();
+ }
+ }
+
+void CCatalogsLoggerMsgQueueObserver::DoCancel()
+ {
+ iMsgQueue.CancelDataAvailable();
+ }
+
+void ClearChunk( RChunk& aChunk, TInt aFlags )
+{
+ TCatalogsDebugChunkHeader* header = (TCatalogsDebugChunkHeader*)aChunk.Base();
+ header->iFlags = aFlags;
+ header->iOffset = 0;
+}
+
+void CCatalogsLoggerMsgQueueObserver::ConstructL()
+ {
+ // Open the log file for append
+ User::LeaveIfError( iFs.Connect() );
+
+ // Stuff log into MMC if available.
+#ifndef __WINS__
+ TVolumeInfo mmcVolume;
+ if ( iFs.Volume( mmcVolume, EDriveE ) == KErrNone )
+ {
+ iLogFileName.Copy( _L("e:") );
+ }
+ else
+#endif
+ {
+ iLogFileName.Copy( _L("c:") );
+ }
+ iLogFileName.Append( KCatalogsLoggerFileName );
+
+ TInt err = iFs.MkDirAll( iLogFileName );
+ if ( err != KErrNone && err != KErrAlreadyExists )
+ {
+ User::Leave( err );
+ }
+
+ User::LeaveIfError( iLogFile.Replace( iFs,
+ iLogFileName,
+ EFileShareAny | EFileWrite ) );
+
+ // Create global chunks for debug log data.
+ User::LeaveIfError( iChunk1.CreateGlobal(
+ KCatalogsDebugChunk1Name,
+ KCatalogsDebugChunkSize,
+ KCatalogsDebugChunkSize ) );
+
+ ClearChunk( iChunk1, iEnableFlags );
+
+ User::LeaveIfError( iChunk2.CreateGlobal(
+ KCatalogsDebugChunk2Name,
+ KCatalogsDebugChunkSize,
+ KCatalogsDebugChunkSize ) );
+
+ ClearChunk( iChunk2, iEnableFlags | ECatalogsDebugFlagFlushChunk );
+
+ // Create mutex for debug data chunks.
+ User::LeaveIfError( iChunkMutex.CreateGlobal(
+ KCatalogsDebugMutexName ) );
+
+ // Create semaphore for block write control.
+ User::LeaveIfError( iChunkWriteSemaphore.CreateGlobal(
+ KCatalogsDebugChunkWriteSemaphoreName, 1 ) );
+
+ // Create message queue.
+ User::LeaveIfError( iMsgQueue.CreateGlobal( KCatalogsDebugMsgQueueName,
+ KCatalogsLoggerNrOfSlots,
+ EOwnerProcess ) );
+ iMsgQueue.NotifyDataAvailable( iStatus );
+ SetActive();
+ }
+
+CCatalogsLoggerMsgQueueObserver::CCatalogsLoggerMsgQueueObserver()
+ : CActive( EPriorityStandard ), iLastChunk( 1 )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+void CCatalogsLoggerMsgQueueObserver::SendFileL()
+ {
+ TBool wasLogging = IsLogging();
+ if( IsLogging() )
+ {
+ StopLogging();
+ }
+ iLogFile.Close();
+
+ iObexSender = COsmObexSender::NewL( *this );
+ iObexSender->SendFileL( COsmObexSender::EOsmConnectionBT, iLogFileName );
+
+ CActiveScheduler::Start();
+
+ User::LeaveIfError( iObexSendError );
+
+ User::LeaveIfError( iLogFile.Open( iFs,
+ iLogFileName,
+ EFileShareAny | EFileWrite ) );
+ TInt pos = 0;
+ User::LeaveIfError( iLogFile.Seek( ESeekEnd, pos ) );
+
+ if( wasLogging )
+ {
+ StartLogging();
+ }
+
+ }
+
+void CCatalogsLoggerMsgQueueObserver::ObexFileSent()
+ {
+ iObexSender->StopL();
+ delete iObexSender;
+ iObexSender = NULL;
+
+ iObexSendError = KErrNone;
+ CActiveScheduler::Stop();
+ }
+
+void CCatalogsLoggerMsgQueueObserver::ObexDisconnected( TInt aError, TInt /*aState*/ )
+ {
+ iObexSender->StopL();
+ delete iObexSender;
+ iObexSender = NULL;
+
+ iObexSendError = aError;
+ CActiveScheduler::Stop();
+ }
+
+TInt CCatalogsLoggerMsgQueueObserver::ClearLog()
+ {
+ TInt err = iLogFile.SetSize( 0 );
+ if( err == KErrNone )
+ {
+ // Prevent log writes.
+ iChunkMutex.Wait();
+ ClearChunk( iChunk1, iEnableFlags );
+ ClearChunk( iChunk2, iEnableFlags | ECatalogsDebugFlagFlushChunk );
+ iLastChunk = 1;
+
+ // Enable log writes.
+ iChunkMutex.Signal();
+ }
+
+ return err;
+ }