--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/clientmtms/src/CACHEMAN.CPP Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,838 @@
+// Copyright (c) 1999-2009 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:
+// CACHEMAN.CPP
+//
+
+#include "CACHEMAN.H"
+#include "MIUTHDR.H"
+#include <msvapi.h>
+#include <msvuids.h>
+#include <msvids.h>
+#include <mmsvattachmentmanager.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <cimprunemessage.h>
+#include "cimfinder.h"
+#include "timrfc822datefield.h"
+#include "msvconsts.h"
+#endif
+
+// The CImEntryStack implementation
+
+CImFinder::CImEntryStack* CImFinder::CImEntryStack::NewL()
+ {
+ CImFinder::CImEntryStack* self;
+ self = new (ELeave) CImFinder::CImEntryStack();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+CImFinder::CImEntryStack::~CImEntryStack()
+ {
+ delete iFolders;
+ }
+
+void CImFinder::CImEntryStack::PushL(TMsvId aId)
+ {
+ iFolders->AppendL(aId);
+ }
+
+void CImFinder::CImEntryStack::Reset()
+ {
+ iFolders->Reset();
+ }
+
+TMsvId CImFinder::CImEntryStack::PopL()
+ {
+ TInt32 count = iFolders->Count();
+ if (count == 0)
+ {
+ User::Leave(KErrOverflow);
+ }
+
+ TMsvId folderId = (*iFolders)[count - 1];
+ iFolders->Delete(count-1);
+ return folderId;
+ }
+
+void CImFinder::CImEntryStack::ConstructL()
+ {
+ iFolders = new (ELeave) CMsvEntrySelection;
+ }
+
+TBool CImFinder::CImEntryStack::Empty() const
+ {
+ return (iFolders->Count() == 0);
+ }
+
+
+// Implementation of abstract CImFinder class
+
+EXPORT_C void CImFinder::FindFirstL(TMsvId aRootEntry, TRequestStatus &aStatus)
+ {
+ iEntryStack->Reset();
+ iEntryStack->PushL(aRootEntry);
+ ASSERT(iState != EImmfFindingEntry);
+ FindNextL(aStatus);
+ }
+
+void CImFinder::FindFirstL(const CMsvEntrySelection& aInitialSelection, TRequestStatus &aStatus)
+ {
+ iEntryStack->Reset();
+
+ TInt index = aInitialSelection.Count();
+ while (index--)
+ // Push each given entry on the stack so that we will visit it later.
+ {
+ iEntryStack->PushL(aInitialSelection[index]);
+ }
+
+ ASSERT(iState != EImmfFindingEntry);
+ FindNextL(aStatus);
+ }
+
+EXPORT_C CImFinder::~CImFinder()
+ {
+ delete iEntryStack;
+ }
+
+void CImFinder::ConstructL()
+ {
+ iEntryStack = CImEntryStack::NewL();
+ CActiveScheduler::Add(this);
+ }
+
+void CImFinder::DoRunL()
+ {
+ if (iState == EImmfFindingEntry)
+ {
+ FindNextL(iStatus);
+ }
+ }
+
+CImFinder::CImFinder(CMsvEntry& aEntry) : CMsgActive(EPriorityStandard), iCurrentEntry(aEntry)
+ {
+ }
+
+EXPORT_C void CImFinder::FindNextL(TRequestStatus &aStatus)
+ {
+ TImmfState tempState = iState;
+
+ if (!(iEntryStack->Empty()))
+ // If there are entries on the stack then check them.
+ {
+ iCurrentEntry.SetEntryL(iEntryStack->PopL());
+ TUid entryType = iCurrentEntry.Entry().iType;
+
+ AddChildEntriesL();
+
+ iStatus=KRequestPending;
+ SetActive();
+ TRequestStatus* status=&iStatus;
+ User::RequestComplete(status, KErrNone);
+
+ if (IsRequiredEntryType(entryType))
+ // If the entry is of a required type then return it.
+ {
+ iState = EImmfEntryFound;
+ }
+ else
+ // Otherwise keep looking for one.
+ {
+ iState = EImmfFindingEntry;
+ }
+ }
+ else
+ // If there is nothing on the stack then there are no more entries.
+ {
+ iStatus=KRequestPending;
+ SetActive();
+ TRequestStatus* status=&iStatus;
+ User::RequestComplete(status, KErrNotFound);
+ iState = EImmfNothingFound;
+ }
+
+ if (tempState != EImmfFindingEntry)
+ {
+ Queue(aStatus);
+ }
+ }
+
+
+
+// Implementation of CImMessageFinder class
+
+EXPORT_C CImMessageFinder* CImMessageFinder::NewL(CMsvEntry& aEntry)
+ {
+ CImMessageFinder* self = CImMessageFinder::NewLC(aEntry);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+EXPORT_C CImMessageFinder* CImMessageFinder::NewLC(CMsvEntry& aEntry)
+ {
+ CImMessageFinder* self = new (ELeave) CImMessageFinder(aEntry);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CImMessageFinder::AddChildEntriesL()
+ {
+ if ((iCurrentEntry.Entry().iType == KUidMsvFolderEntry)
+ || (iCurrentEntry.Entry().iType == KUidMsvServiceEntry))
+ {
+ // Push the folders on to the entry stack
+ TMsvSelectionOrdering ordering;
+ ordering.SetShowInvisibleEntries(EFalse);
+ iCurrentEntry.SetSortTypeL(ordering);
+ CMsvEntrySelection* entrySelection = iCurrentEntry.ChildrenWithTypeL(KUidMsvFolderEntry);
+ CleanupStack::PushL(entrySelection);
+ TInt counter;
+ TInt count = entrySelection->Count();
+ for (counter = 0; counter < count; counter++)
+ {
+ iEntryStack->PushL((*entrySelection)[counter]);
+ }
+ CleanupStack::PopAndDestroy(); // entrySelection
+
+ // Push the messages on to the entry stack
+ entrySelection = iCurrentEntry.ChildrenWithTypeL(KUidMsvMessageEntry);
+ CleanupStack::PushL(entrySelection);
+ count = entrySelection->Count();
+ for (counter = 0; counter < count; counter++)
+ {
+ iEntryStack->PushL((*entrySelection)[counter]);
+ }
+ CleanupStack::PopAndDestroy(); // entrySelection
+ }
+ }
+
+TBool CImMessageFinder::IsRequiredEntryType(TUid aEntryType) const
+ {
+ if (aEntryType == KUidMsvMessageEntry)
+ return ETrue;
+ else
+ return EFalse;
+ }
+
+CImMessageFinder::CImMessageFinder(CMsvEntry& aEntry) : CImFinder(aEntry)
+ {
+ }
+
+
+
+// Implementation of CImMessageFinder class
+
+EXPORT_C CImEntryFinder* CImEntryFinder::NewL(CMsvEntry& aEntry)
+ {
+ CImEntryFinder* self = CImEntryFinder::NewLC(aEntry);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+EXPORT_C CImEntryFinder* CImEntryFinder::NewLC(CMsvEntry& aEntry)
+ {
+ CImEntryFinder* self = new (ELeave) CImEntryFinder(aEntry);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CImEntryFinder::AddChildEntriesL()
+ {
+ if (iCurrentEntry.Entry().Owner())
+ {
+ // Push the child entries on to the entry stack
+ TMsvSelectionOrdering ordering;
+ ordering.SetShowInvisibleEntries(ETrue);
+ iCurrentEntry.SetSortTypeL(ordering);
+ CMsvEntrySelection* entrySelection = iCurrentEntry.ChildrenL();
+ CleanupStack::PushL(entrySelection);
+ TInt counter;
+ TInt count = entrySelection->Count();
+ for (counter = 0; counter < count; counter++)
+ {
+ iEntryStack->PushL((*entrySelection)[counter]);
+ }
+ CleanupStack::PopAndDestroy(); // entrySelection
+ }
+ }
+
+TBool CImEntryFinder::IsRequiredEntryType(TUid /*aEntryType*/) const
+// Always true because all entry types are needed.
+ {
+ return ETrue;
+ }
+
+CImEntryFinder::CImEntryFinder(CMsvEntry& aEntry) : CImFinder(aEntry)
+ {
+ }
+
+
+
+// Implementation of CImMessage Finder
+
+EXPORT_C CImMessageCounter* CImMessageCounter::NewL(CMsvEntry& aEntry)
+ {
+ CImMessageCounter* self = CImMessageCounter::NewLC(aEntry);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+EXPORT_C CImMessageCounter* CImMessageCounter::NewLC(CMsvEntry& aEntry)
+ {
+ CImMessageCounter* self = new (ELeave) CImMessageCounter(aEntry);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+EXPORT_C TInt CImMessageCounter::Count()
+ {
+ return iCount;
+ }
+
+void CImMessageCounter::AddChildEntriesL()
+ {
+ if ((iCurrentEntry.Entry().iType == KUidMsvFolderEntry)
+ || (iCurrentEntry.Entry().iType == KUidMsvServiceEntry))
+ {
+ // Push the folders on to the entry stack
+ TMsvSelectionOrdering ordering;
+ ordering.SetShowInvisibleEntries(EFalse);
+ iCurrentEntry.SetSortTypeL(ordering);
+ CMsvEntrySelection* entrySelection = iCurrentEntry.ChildrenWithTypeL(KUidMsvFolderEntry);
+ CleanupStack::PushL(entrySelection);
+ TInt counter;
+ TInt count = entrySelection->Count();
+ for (counter = 0; counter < count; counter++)
+ {
+ iEntryStack->PushL((*entrySelection)[counter]);
+ }
+ CleanupStack::PopAndDestroy(); // entrySelection
+
+ // Count the messages in the folder
+ entrySelection = iCurrentEntry.ChildrenWithTypeL(KUidMsvMessageEntry);
+ CleanupStack::PushL(entrySelection);
+ iCount += entrySelection->Count();
+ CleanupStack::PopAndDestroy(); // entrySelection
+ }
+ else if (iCurrentEntry.Entry().iType == KUidMsvMessageEntry)
+ { // count itself if it's a message entry
+ iCount++;
+ }
+ }
+
+TBool CImMessageCounter::IsRequiredEntryType(TUid) const
+ {
+ // The message counter doesn't require any entry types to be returned.
+ return EFalse;
+ }
+
+CImMessageCounter::CImMessageCounter(CMsvEntry& aEntry) : CImFinder(aEntry)
+ {
+
+ }
+
+
+// Implementation of CImPruneMessage
+
+EXPORT_C CImPruneMessage* CImPruneMessage::NewL(CMsvEntry& aEntry, RFs& aFs)
+/** Allocates and constructs a new CImPruneMessage object.
+
+@param aEntry CMsvEntry for use by the object in performing the delete operations.
+It does not need to be set to any particular message context. The caller retains
+ownership.
+@param aFs Open file server session handle
+@return New CImPruneMessage object */
+ {
+ CImPruneMessage* self = CImPruneMessage::NewLC(aEntry, aFs);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+EXPORT_C CImPruneMessage* CImPruneMessage::NewLC(CMsvEntry& aEntry, RFs& aFs)
+/** Allocates and constructs a new CImPruneMessage object, leaving the object on
+the cleanup stack.
+
+@param aEntry CMsvEntry for use by the object in performing the delete operations.
+It does not need to be set to any particular message context. The caller retains
+ownership.
+@param aFs Open file server session handle
+@return New CImPruneMessage object */
+ {
+ CImPruneMessage* self = new (ELeave) CImPruneMessage(aEntry, aFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+EXPORT_C void CImPruneMessage::StartL(TMsvId aMessageEntry, TRequestStatus &aStatus)
+/** Starts the asynchronous message clean operation.
+
+@param aMessageEntry The ID of the entry from which to delete the body text
+and attachment data
+@param aStatus Asynchronous status word that completes with KErrNone when the
+body text and all of the attachments have been deleted. */
+ {
+ iCurrentEntry.SetEntryL(aMessageEntry);
+ TMsvEmailEntry entry(iCurrentEntry.Entry());
+
+ if (entry.Complete() || entry.BodyTextComplete())
+ {
+ entry.SetComplete(EFalse);
+ entry.SetBodyTextComplete(EFalse);
+ iChangeOperation = iCurrentEntry.ChangeL(entry, iStatus);
+ SetActive();
+ }
+ else
+ {
+ iStatus=KRequestPending;
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+
+ iState = EImPruneUpdatingFirstEntry;
+ Queue(aStatus);
+ iRootEntryId = aMessageEntry;
+ }
+
+CImPruneMessage::~CImPruneMessage()
+/** Destructor. */
+ {
+ Cancel();
+ delete iEntryFinder;
+ delete iFileManager;
+ delete iStore;
+ delete iChangeOperation;
+ }
+
+void CImPruneMessage::ConstructL()
+ {
+ CActiveScheduler::Add(this);
+ iEntryFinder = CImEntryFinder::NewL(iCurrentEntry);
+ iFileManager = CFileMan::NewL(iFs);
+ }
+
+void CImPruneMessage::DoRunL()
+ {
+ TInt error = KErrNone;
+ switch (iState)
+ {
+ case EImPruneUpdatingFirstEntry:
+ delete iChangeOperation;
+ iChangeOperation = 0;
+ PruneEntryL();
+ iState = EImPruneFindFirstEntry;
+ SetActive();
+ break;
+ case EImPruneFindFirstEntry:
+ ResetStoreL();
+ iEntryFinder->FindFirstL(iRootEntryId, iStatus);
+ iState = EImPruneFindingEntry;
+ SetActive();
+ break;
+ case EImPruneUpdatingEntry:
+ delete iChangeOperation;
+ iChangeOperation = 0;
+ PruneEntryL();
+ iState = EImPruneFindNextEntry;
+ SetActive();
+ break;
+ case EImPruneFindNextEntry:
+ ResetStoreL();
+ iEntryFinder->FindNextL(iStatus);
+ iState = EImPruneFindingEntry;
+ SetActive();
+ break;
+ case EImPruneFindingEntry:
+ delete iStore;
+ iStore = NULL;
+ if (iStatus == KErrNone)
+ // An entry has been found, so prune it.
+ {
+ // Ignore any error as it probably just means that the entry is locked.
+ // We can afford to skip locked entries.
+ if (iCurrentEntry.Entry().Complete())
+ {
+ TMsvEntry entry = iCurrentEntry.Entry();
+ entry.SetComplete(EFalse);
+ TRAPD(ignore, iChangeOperation = iCurrentEntry.ChangeL(entry, iStatus));
+ }
+
+ if (!iChangeOperation)
+ {
+ TRequestStatus* status = &iStatus;
+ iStatus=KRequestPending;
+ User::RequestComplete(status, KErrNone);
+ }
+ iState = EImPruneUpdatingEntry;
+ SetActive();
+ }
+ break;
+ }
+ }
+
+void CImPruneMessage::DoComplete(TInt& status)
+ {
+ if ((iState == EImPruneFindingEntry) && (status == KErrNotFound))
+ // The not found status is expected, it just means that the entry finder has already found all the entries.
+ {
+ status = KErrNone;
+ }
+ }
+
+void CImPruneMessage::DoCancel()
+ {
+ iEntryFinder->Cancel();
+ if (iChangeOperation)
+ iChangeOperation->Cancel();
+ CMsgActive::DoCancel();
+ }
+
+CImPruneMessage::CImPruneMessage(CMsvEntry& aEntry, RFs& aFs)
+ : CMsgActive(EPriorityStandard),
+ iCurrentEntry(aEntry),
+ iFs(aFs)
+ {
+ __DECLARE_NAME(_S("CImPruneMessage"));
+ }
+
+void CImPruneMessage::PruneEntryL()
+ {
+ // delete the rich text stream
+ iStore = iCurrentEntry.EditStoreL();
+ if (iStore->IsPresentL(KMsvEntryRichTextBody))
+ {
+ iStore->DeleteBodyTextL();
+ iStore->CommitL();
+ }
+
+ // If the entry has an attachment we need to remove it.
+ // In order to preserve the message structure, we won't delete the attachment
+ // completely, but instead we will set the file size to 0 and mark the attachment
+ // as not complete.
+
+ TBool completeSelf = ETrue;
+
+ MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
+
+ // as this is email attachment entry , it has one attachment per entry
+ if(attachmentMgr.AttachmentCount() > 0)
+ {
+ CMsvAttachment* attachmentInfo = attachmentMgr.GetAttachmentInfoL(0);
+ CleanupStack::PushL(attachmentInfo);
+
+ // We only want to remove file attachments
+ if (attachmentInfo->Type() == CMsvAttachment::EMsvFile)
+ {
+ RFile file = attachmentMgr.GetAttachmentFileForWriteL(0);
+ TInt error = file.SetSize(0);
+ file.Close();
+
+ if (error == KErrNone)
+ {
+ attachmentInfo->SetComplete(EFalse);
+ attachmentMgr.ModifyAttachmentInfoL(attachmentInfo, iStatus);
+ // ModifyAttachmentInfoL takes ownership of the attachment info, so just pop
+ // it off the cleanup stack and set the pointer to NULL to show we don't
+ // own it
+ CleanupStack::Pop(attachmentInfo);
+ attachmentInfo = NULL;
+
+ // We have called an async routine, so set the flag to show that we don't
+ // need to complete ourself
+ completeSelf = EFalse;
+ }
+ }
+
+ if (attachmentInfo != NULL)
+ {
+ CleanupStack::PopAndDestroy(attachmentInfo);
+ }
+ }
+
+ if (completeSelf)
+ {
+ TRequestStatus* status = &iStatus;
+ iStatus=KRequestPending;
+ User::RequestComplete(status, KErrNone);
+ }
+ }
+
+void CImPruneMessage::ResetStoreL()
+ {
+ if (iStore != NULL)
+ {
+ iStore->CommitL();
+ delete iStore;
+ iStore = NULL;
+ }
+ }
+
+// Implementation of CImCacheManager
+
+EXPORT_C void CImCacheManager::StartL(TMsvId aRootEntry, TRequestStatus &aStatus)
+/** Performs a recursive cache cleanup starting from a specified root entry.
+
+Cached data for entries below the specified root are cleaned-up if they meet
+the criteria specified by the implementation of Filter().
+
+@param aRootEntry Entry from which to start cache cleanup
+@param aStatus Asynchronous status word signalled when the operation is complete */
+ {
+ delete iMessagesToPrune;
+ iMessagesToPrune = 0;
+ iState = EImcmCountingMessages;
+ aStatus = KRequestPending;
+ iReport = &aStatus;
+ iMessageCounter->FindFirstL(aRootEntry, iStatus);
+ iRootEntry = aRootEntry;
+ SetActive();
+ }
+
+EXPORT_C void CImCacheManager::StartL(const CMsvEntrySelection& aSelection, TRequestStatus &aStatus)
+/** Performs a recursive cache cleanup for a specified selection of root entries.
+
+Cached data for entries below the specified roots are cleaned-up if they meet
+the criteria specified by the implementation of Filter().
+
+@param aSelection List of entries from which to start cache cleanup
+@param aStatus Asynchronous status word signalled when the operation is complete */
+ {
+ delete iMessagesToPrune;
+ iMessagesToPrune = 0;
+ iState = EImcmCountingMessages;
+ aStatus = KRequestPending;
+ iReport = &aStatus;
+
+ // Save the selection for later as we need it when we actually prune the messages
+ iMessagesToPrune = new (ELeave) CMsvEntrySelection();
+ TInt index = aSelection.Count();
+ while (index--)
+ {
+ iMessagesToPrune->AppendL(aSelection[index]);
+ }
+
+ // Set off the operation to count all the messages
+ iMessageCounter->FindFirstL(aSelection, iStatus);
+
+ SetActive();
+ }
+
+
+EXPORT_C void CImCacheManager::ConstructL()
+/** Second phase constructor.
+
+All classes derived from CImCacheManager must call this function before StartL()
+is called. */
+ {
+ TMsvSelectionOrdering ordering;
+ iCurrentEntry = CMsvEntry::NewL(iSession, KMsvRootIndexEntryId, ordering);
+ iMessageFinder = CImMessageFinder::NewL(*iCurrentEntry);
+ iMessageCounter = CImMessageCounter::NewL(*iCurrentEntry);
+ iProgress.iTotalMessages = 1;
+ iProgress.iMessagesProcessed = 0;
+ CActiveScheduler::Add(this);
+ }
+
+EXPORT_C const TDesC8& CImCacheManager::ProgressL()
+/** Gets information on the progress of the operation.
+
+@return Packaged TImCacheManagerProgress object holding operation progress
+details */
+ {
+ if (iProgress.iTotalMessages == 0)
+ {
+ iProgress.iTotalMessages = 1;
+ }
+
+ if (iProgress.iMessagesProcessed > iProgress.iTotalMessages)
+ {
+ iProgress.iMessagesProcessed = iProgress.iTotalMessages;
+ }
+
+ iProgressBuf = iProgress;
+ return iProgressBuf;
+ }
+
+/** Implements the active object completion protocol for a cache cleanup operation.
+
+@see CActive::RunL() */
+EXPORT_C void CImCacheManager::RunL()
+ {
+ TInt error = iStatus.Int();
+
+ if ((iState == EImcmCountingMessages)
+ && (error == KErrNotFound))
+ // A KErrNotFound is a normal condition from the message counter.
+ {
+ error = KErrNone;
+ }
+
+ if (error == KErrNone)
+ {
+ TRAP(error, DoRunL());
+ }
+
+ if(error != KErrNone)
+ {
+ if (error == KErrNotFound)
+ // A KErrNotFound is a normal condition from the message finder.
+ {
+ error = KErrNone;
+ }
+
+ User::RequestComplete(iReport, error);
+ }
+ }
+
+/** Implements the active object cancellation protocol for a cache cleanup operation.
+
+As the cache manager is an active object, a cache cleanup
+operation started by Start() can be cancelled using CActive::Cancel().
+
+Cancellation halts any further deletion of message data, but does
+not restore any data that has already been deleted by the cleanup operation.
+
+@see CActive::Cancel() */
+EXPORT_C void CImCacheManager::DoCancel()
+ {
+ iMessageFinder->Cancel();
+ iMessageCounter->Cancel();
+
+ if (iDeleteOperation)
+ iDeleteOperation->Cancel();
+
+ User::RequestComplete(iReport,KErrCancel);
+ }
+
+void CImCacheManager::DoRunL()
+ {
+ switch (iState)
+ {
+ case EImcmCountingMessages:
+ iProgress.iTotalMessages = iMessageCounter->Count();
+
+ if (iMessagesToPrune)
+ // If we are pruning a selection the prune from the selection
+ iMessageFinder->FindFirstL(*iMessagesToPrune, iStatus);
+ else
+ // otherwise start at the root entry
+ iMessageFinder->FindFirstL(iRootEntry, iStatus);
+
+ iState = EImcmLookingForMessage;
+ SetActive();
+ break;
+
+ case EImcmLookingForMessage:
+ if (iStatus == KErrNone)
+ {
+ if (Filter())
+ {
+ PruneMessageL();
+ }
+ else
+ {
+ iMessageFinder->FindNextL(iStatus);
+ iState = EImcmLookingForMessage;
+ SetActive();
+ }
+ }
+ iProgress.iMessagesProcessed++;
+ break;
+
+ case EImcmPruningMessages:
+ case EImcmSkippingPrune:
+ // The current message has been pruned, find another one.
+ if (iDeleteOperation)
+ {
+ delete iDeleteOperation;
+ iDeleteOperation = 0;
+ }
+ iMessageFinder->FindNextL(iStatus);
+ iState = EImcmLookingForMessage;
+ SetActive();
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+void CImCacheManager::PruneMessageL()
+ {
+ if (iCurrentEntry->Entry().Owner())
+ {
+ iState = EImcmPruningMessages;
+
+ // Remove any associated store
+ if (iCurrentEntry->HasStoreL())
+ {
+ CMsvStore* store=iCurrentEntry->EditStoreL();
+ CleanupStack::PushL(store);
+ store->DeleteL();
+ CleanupStack::PopAndDestroy(store);
+ }
+
+ // Get a list of the child entries
+ CMsvEntrySelection* children = iCurrentEntry->ChildrenL();
+ CleanupStack::PushL(children);
+
+ // Delete the child entries
+ // The Complete and BodyTextComplete flags are cleared by the
+ // server MTM when the delete is processed.
+ iDeleteOperation = iCurrentEntry->DeleteL(*children, iStatus);
+ SetActive();
+ CleanupStack::PopAndDestroy(children);
+ }
+ else
+ {
+ // If this entry doesn't own any children,
+ // or we can't do the ChangeL then skip this entry and move on.
+ iState = EImcmSkippingPrune;
+ iStatus=KRequestPending;
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+ }
+
+EXPORT_C CImCacheManager::CImCacheManager(CMsvSession& aSession, TRequestStatus& aObserverRequestStatus)
+ : CMsvOperation(aSession, EPriorityStandard, aObserverRequestStatus),
+ iSession(aSession)
+/** Constructor.
+
+@param aSession Message server session
+@param aObserverRequestStatus Unused */
+ {
+ __DECLARE_NAME(_S("CImCacheManager"));
+ }
+
+EXPORT_C CImCacheManager::~CImCacheManager()
+/** Destructor.
+
+This cancels any operation in progress. */
+ {
+ Cancel();
+ delete iCurrentEntry;
+ delete iMessageFinder;
+ delete iMessageCounter;
+ delete iMessagesToPrune;
+ delete iDeleteOperation;
+ }