--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgerrorwatcher/src/MsgSentItemsObserver.cpp Wed Nov 03 09:52:46 2010 +0530
@@ -0,0 +1,412 @@
+/*
+* Copyright (c) 2002 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:
+* CMsgSentItemsObserver implementation file
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <watcher.h>
+#include <msvids.h>
+
+#include <centralrepository.h> // link against centralrepository.lib
+#include <cenrepnotifyhandler.h> // link against CenRepNotifHandler.lib
+#include <messaginginternalcrkeys.h> // for Central Repository keys
+#include <msvipc.h>
+
+#include "MsgSentItemsObserver.h"
+
+#ifdef USE_LOGGER
+#include "MsgErrorWatcherLogging.h"
+#endif
+
+// CONSTANTS
+//const TUid KUidMceApp = { 0x100058C5 }; //needed to request shared data notifications
+const TMsvId KWatcherSentFolderId = KMsvSentEntryIdValue;
+
+// Entry deletion could fail with KErrInUse if it is being operated by MW while deleting
+const TUint KMaxRetries = 3;
+const TInt KMaxNumOfItems = 20; //Deafult value in case of error reading CommsDb
+//const TInt KMsgErrorDiskSpaceForDelete = ( 5 * 1024 ); // minimum disk space needed when deleting messages
+//_LIT( KSentItemsInUseOff, "0" );
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::NewL
+//
+// Two-phased constructor.
+// ---------------------------------------------------------
+//
+CMsgSentItemsObserver* CMsgSentItemsObserver::NewL(
+ CMsgErrorWatcher* aWatcher,
+ CMsvSession* aSession )
+ {
+ CMsgSentItemsObserver* self = new ( ELeave )
+ CMsgSentItemsObserver( aWatcher, aSession );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::CMsgSentItemsObserver
+//
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------
+//
+CMsgSentItemsObserver::CMsgSentItemsObserver( CMsgErrorWatcher* aWatcher, CMsvSession* aSession )
+ : CActive( EPriorityStandard ),
+ iWatcher( aWatcher ),
+ iSession( aSession )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::~CMsgSentItemsObserver
+//
+// Destructor
+// ---------------------------------------------------------
+//
+CMsgSentItemsObserver::~CMsgSentItemsObserver()
+ {
+ Cancel();
+ if ( iNotifyHandler )
+ {
+ iNotifyHandler->StopListening();
+ }
+ delete iNotifyHandler;
+ delete iRepository;
+ if( iCleanupFlags & ESentItemsFolderObserverAdded )
+ {
+ iSentItemsFolder->RemoveObserver( *this );
+ }
+ delete iSentItemsFolder;
+ delete iEntry;
+ delete iOp;
+
+ delete iQudUPEntryBeingDeleted;
+ delete iQueuedUPEntriesToBeDeleted;
+
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::ConstructL
+//
+// Symbian OS default constructor can leave.
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::ConstructL()
+ {
+#ifdef USE_LOGGER
+ MEWLOGGER_ENTERFN( "SentItems: ConstructL" );
+#endif
+ //iMsgStoreDrive = MessageServer::CurrentDriveL( iSession->FileSession() );
+ //register as observer of sent items folder
+ TMsvSelectionOrdering sort( KMsvNoGrouping, EMsvSortByDateReverse );
+ iSentItemsFolder = CMsvEntry::NewL( *iSession, KWatcherSentFolderId, sort );
+ iSentItemsFolder->AddObserverL( *this );
+ iCleanupFlags |= ESentItemsFolderObserverAdded;
+
+ //register as observer of user settings for sent folder
+
+ // Central Repository
+ iRepository = CRepository::NewL( KCRUidMuiuSettings );
+ iNotifyHandler = CCenRepNotifyHandler::NewL( *this, *iRepository );
+ iNotifyHandler->StartListeningL();
+
+ iQudUPEntryBeingDeleted = new(ELeave) CMsvEntrySelection;
+ iQueuedUPEntriesToBeDeleted= new(ELeave) CMsvEntrySelection;
+
+#ifdef USE_LOGGER
+ MEWLOGGER_LEAVEFN( "SentItems: ConstructL" );
+#endif
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::RunL
+//
+// Will only run when messages have been deleted
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::RunL()
+ {
+ //iSession->FileSession().ReleaseReserveAccess( iMsgStoreDrive );
+ //Check if new messages have appeared into Sent Items while deleting
+ //the previous one(s).
+#ifdef USE_LOGGER
+ MEWLOGGER_WRITEF( _L("SentItems: Retries: %d"), iRetryCounter );
+#endif
+ if ( iRetryCounter < KMaxRetries )
+ {
+ iRetryCounter++;
+ TRAP_IGNORE( DeleteOldMessagesFromSentFolderL() );
+ }
+
+
+ const TDesC8& temp = iOp->ProgressL();
+ TMsvLocalOperationProgress* prog = ( (TMsvLocalOperationProgress*) temp.Ptr());
+
+#ifdef USE_LOGGER
+ MEWLOGGER_WRITEF( _L("SentItems: deletion iStatus %d"), iStatus.Int() );
+ // prog->iNumberFailed should be either 0(if successful) or 1(if failed) as we are deletingone entry at a time
+ MEWLOGGER_WRITEF( _L("Failed Deletions: %d"), prog->iNumberFailed );
+ MEWLOGGER_WRITEF( _L("Delete Error Code: %d"), prog->iError );
+#endif
+
+ if(iStatus.Int() == KErrNone && prog->iNumberFailed && prog->iError == KErrInUse && iRetryCounterIfEntryDelFailed < KMaxRetries)
+ {
+ DeleteSingleEntryL(iQudUPEntryBeingDeleted);
+ iRetryCounterIfEntryDelFailed ++;
+#ifdef USE_LOGGER
+ MEWLOGGER_WRITEF( _L("iRetryCounterIfEntryDelFailed : %d"), iRetryCounterIfEntryDelFailed );
+#endif
+ return;
+ }
+ iRetryCounterIfEntryDelFailed = 0;
+
+ if( iQueuedUPEntriesToBeDeleted->Count() )
+ {
+ iQudUPEntryBeingDeleted->Reset();
+ iQudUPEntryBeingDeleted->AppendL(iQueuedUPEntriesToBeDeleted->At(0));
+ iQueuedUPEntriesToBeDeleted->Delete(0);
+
+ DeleteSingleEntryL(iQudUPEntryBeingDeleted);
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::DoCancel
+//
+// From active object framework
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::DoCancel()
+ {
+ //iSession->FileSession().ReleaseReserveAccess( iMsgStoreDrive );
+ if ( iOp )
+ {
+ iOp->Cancel();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::HandleNotifyInt
+//
+// Notification from central repository
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::HandleNotifyInt( TUint32 aId, TInt aNewValue )
+ {
+ if ( ( aId == KMuiuSentItemsInUse && aNewValue != 0 ) ||
+ ( aId == KMuiuSentItemsCount && SentFolderIsBeingUsed() ) )
+ {
+ iRetryCounter = 0;
+ //This is non-leaving function...
+ TRAPD( dummy, DeleteOldMessagesFromSentFolderL() );
+ dummy=dummy; //Prevent arm5 build warning
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::HandleNotifyGeneric
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::HandleNotifyGeneric( TUint32 /*aId*/ )
+ {
+ //Nothing.
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::HandleNotifyError
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::HandleNotifyError( TUint32 /*aId*/, TInt /*error*/, CCenRepNotifyHandler* /*aHandler*/ )
+ {
+ //Nothing.
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::HandleEntryEventL
+//
+// Call back from msg that the sent items folder has changed
+// so check if messages need to be deleted.
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::HandleEntryEventL( TMsvEntryEvent aEvent, TAny* aArg1, TAny* /*aArg2*/, TAny* /*aArg3*/ )
+ {
+ switch( aEvent )
+ {
+ case EMsvNewChildren:
+ {
+ if( !SentFolderIsBeingUsed() )
+ {
+ //not taking ownership
+ CMsvEntrySelection* selection =
+ static_cast<CMsvEntrySelection*>( aArg1 );
+ iRetryCounter = 0;
+ DeleteMessagesFromSentFolderL( selection );
+ return;
+ }
+ if( iSentItemsFolder->Count() > SentFolderUpperLimit() )
+ {
+ iRetryCounter = 0;
+ DeleteOldMessagesFromSentFolderL();
+ return;
+ }
+ }
+ break;
+ case EMsvEntryChanged:
+ case EMsvDeletedChildren:
+ case EMsvChildrenChanged:
+ case EMsvEntryDeleted:
+ case EMsvContextInvalid:
+ case EMsvChildrenMissing:
+ case EMsvChildrenInvalid:
+ case EMsvEntryMoved:
+ default:
+ break;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::SentFolderIsBeingUsed
+//
+// Returns the user setting for use of the sent folder. If there
+// is an error then the default value of ON (i.e ETrue) will
+// be returned.
+// ---------------------------------------------------------
+//
+TBool CMsgSentItemsObserver::SentFolderIsBeingUsed()
+ {
+ TInt isUsed = 1;
+ iRepository->Get( KMuiuSentItemsInUse, isUsed );
+ return isUsed;
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::SentFolderUpperLimit
+//
+// Returns the user setting for max limit to the number of messages
+// in the sent folder. If there is an error then the default value of
+// KMaxNumOfItems will be returned
+// ---------------------------------------------------------
+//
+TInt CMsgSentItemsObserver::SentFolderUpperLimit()
+ {
+ TInt numItems = KMaxNumOfItems;
+ iRepository->Get( KMuiuSentItemsCount, numItems );
+ return numItems;
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::DeleteOldMessagesFromSentFolderL
+//
+// If there are more messages in the sent folder than the upper
+// limit set by the user then delete the oldest messages.
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::DeleteOldMessagesFromSentFolderL()
+ {
+ CMsvEntrySelection* children = iSentItemsFolder->ChildrenL();
+ CleanupStack::PushL( children );
+ TInt limit = SentFolderUpperLimit();
+ TInt sentMessageCount = children->Count();
+ if( sentMessageCount <= limit )
+ {
+ CleanupStack::PopAndDestroy( children );
+ return;
+ }
+ CMsvEntrySelection* messagesToBeDeleted = new ( ELeave ) CMsvEntrySelection;
+ CleanupStack::PushL( messagesToBeDeleted );
+ //oldest messages are at the end of the array
+ for( TInt index = sentMessageCount - 1; index >= limit; index-- )
+ {
+ messagesToBeDeleted->AppendL( children->At( index ) );
+ }
+ DeleteMessagesFromSentFolderL( messagesToBeDeleted );
+ CleanupStack::PopAndDestroy( messagesToBeDeleted );
+ CleanupStack::PopAndDestroy( children );
+ }
+
+// ---------------------------------------------------------
+// CMsgSentItemsObserver::DeleteMessagesFromSentFolderL
+//
+// Delete the messages specified by aSelection
+// ---------------------------------------------------------
+//
+void CMsgSentItemsObserver::DeleteMessagesFromSentFolderL( CMsvEntrySelection* aSelection )
+ {
+ iQueuedUPEntriesToBeDeleted->AppendL(aSelection->Back(0), aSelection->Count());
+ if ( !IsActive() )
+ {
+ iQudUPEntryBeingDeleted->Reset();
+ iQudUPEntryBeingDeleted->AppendL(iQueuedUPEntriesToBeDeleted->At(0));
+ iQueuedUPEntriesToBeDeleted->Delete(0);
+
+ // If multiple entries are sent for deletion, then it won't be possible to track
+ // the entries that failed to delete
+ DeleteSingleEntryL(iQudUPEntryBeingDeleted);
+ }
+
+ }
+
+
+void CMsgSentItemsObserver::DeleteSingleEntryL(CMsvEntrySelection* aSelection)
+ {
+
+#ifdef USE_LOGGER
+ MEWLOGGER_WRITEF( _L("SentItems: deleting %d messages from sent folder"), aSelection->Count() );
+#endif
+
+ const TMsvId id = aSelection->At( 0 );
+ delete iEntry;
+ iEntry = 0;
+ iEntry = iSession->GetEntryL( id );
+ iEntry->SetEntryL( iEntry->Entry().Parent() );
+
+ //if ( iSession->FileSession().ReserveDriveSpace( iMsgStoreDrive, KMsgErrorDiskSpaceForDelete ) == KErrNone )
+ // {
+ // iSession->FileSession().GetReserveAccess( iMsgStoreDrive );
+ // }
+
+ delete iOp;
+ iOp = 0;
+ //TRAPD( err,
+ // {
+ iOp = iEntry->DeleteL( *aSelection, iStatus ); //delete acts on returned CMsvOperation*
+ // } );
+ //if ( err )
+ // {
+ // iSession->FileSession().ReleaseReserveAccess( iMsgStoreDrive );
+ // User::Leave( err );
+ // }
+ //else
+ // {
+ SetActive();
+ // }
+
+ }
+
+
+// End of File
+