diff -r 000000000000 -r 8e480a14352b messagingfw/msgsrvnstore/server/src/CMsvBackupHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/msgsrvnstore/server/src/CMsvBackupHandler.cpp Mon Jan 18 20:36:02 2010 +0200 @@ -0,0 +1,280 @@ +// Copyright (c) 2001-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: +// + +//#define __BACKUP_LOGGING + +#ifdef __BACKUP_LOGGING + #define _BACKUPLOG( a ) RFileLogger::WriteFormat(_L("msgs"),_L("backup.txt"),EFileLoggingModeAppend, a ); + #define _BACKUPLOGERR( a, b ) RFileLogger::WriteFormat(_L("msgs"),_L("backup.txt"),EFileLoggingModeAppend, a , b); +#else + #define _BACKUPLOG( a ) + #define _BACKUPLOGERR( a, b ) +#endif + +#include "CMsvBackupHandler.h" +#include "MSVSERV.H" +#include "MSVSTD.H" +#include "msvdbadapter.h" +#include "msvindexadapter.h" +#include +#include +#include +#include + +#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) +_LIT(KDBFileNamePath,"\\messaging.db"); +#else +_LIT(KDBFileNamePath,"\\private\\10281e17\\[1000484B]messaging.db"); +#endif + +CMsvBackupHandler* CMsvBackupHandler::NewL(CMsvServer& aServer) + { + CMsvBackupHandler* self=new (ELeave) CMsvBackupHandler(aServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return(self); + } + +CMsvBackupHandler::CMsvBackupHandler(CMsvServer& aServer) : iServer(aServer) + { + } + +CMsvBackupHandler::~CMsvBackupHandler() + { + _BACKUPLOG(_L("backup handler ending\r\n")); + + // Unregister ourselves with backup server + if (iBackup) + { + iBackup->DeregisterFile(iFileName); + delete iBackup; + } + } + +void CMsvBackupHandler::ConstructL() + { + _BACKUPLOG(_L("Backup handler started\r\n")) + + TParse parse; + + RFs fs; + CleanupClosePushL(fs); + User::LeaveIfError(fs.Connect()); + TPtrC driveName = TDriveUnit(MessageServer::CurrentDriveL(fs)).Name(); + iFileName = KDBFileNamePath; + parse.Set(iFileName, &driveName, NULL); + CleanupStack::PopAndDestroy(); // fs + iFileName=parse.FullName(); + iState=EHaveLock; + + // Create backup session + iBackup = CBaBackupSessionWrapper::NewL(); + + // Register with the backup server + iBackup->RegisterFileL(iFileName, *this); + // All done + _BACKUPLOGERR(_L("File Registered with Backup Server: \"%S\"\r\n"), &iFileName); + } + + +TBool CMsvBackupHandler::Locked() + { + if(iState==EHaveLock) + { + return(EFalse); + } + else + { + return(ETrue); + } + } + +#ifdef __BACKUP_LOGGING +void CMsvBackupHandler::ChangeFileLockL(const TDesC& aFileAffected, TFileLockFlags aFlags) +#else +void CMsvBackupHandler::ChangeFileLockL(const TDesC& /*aFileAffected*/, TFileLockFlags aFlags) +#endif + { + _BACKUPLOG(_L("Got backup event\r\n")) + _BACKUPLOGERR(_L("File affected: \"%S\"\r\n"), &aFileAffected); + + switch(aFlags) + { + case ETakeLock: // this state gives me the lock back after it has been taken away from me. + { + _BACKUPLOG(_L("Take lock\r\n")) + if(iState==EReleasedForBackup) + { + iState=EHaveLock; + _BACKUPLOG(_L("from backup\r\n")) + + + //Change error state to none + iServer.Context().IndexAdapter()->SetErrorState(KErrNone); + + //Change State + iServer.SetStartupState(EMsvNullNotification); + + _BACKUPLOG(_L("Reloading context\r\n")) + ReloadContextL(); + } + else if(iState==EReleasedForRestore) + { + // Reload context will result in this object being deleted + // therefore this is no longer valid; + iState=EHaveLock; + //reload as its a new db after restore + ReloadContextL(); + } + else + { + _BACKUPLOG(_L("bad state\r\n")) + __ASSERT_DEBUG(EFalse,PanicServer(EMsvBackupHandlerInUnkownState)); + } + break; + } + case EReleaseLockNoAccess: + { + // please release the lock and don't read or write to the file + _BACKUPLOG(_L("release no access\r\n")) + + // Need to find whether this file lock release request is due to a restore happening. + // It is possible that the file system may need us to release our locks for some other + // purpose such as formatting an MMC card. + TInt backupRestoreState = 0; + + RProperty property; + TInt err = property.Get(KUidSystemCategory, conn::KUidBackupRestoreKey, backupRestoreState); + property.Close(); + User::LeaveIfError(err); + + _BACKUPLOGERR(_L("backupRestoreStateValue: \"0x%08x\"\r\n"), backupRestoreState); + + if ((backupRestoreState & conn::EBURRestoreFull) || (backupRestoreState & conn::EBURRestorePartial)) + { + // This means they will be restoring the file so I will + // have to cope with a new index when I get the lock back. + if(DetachFromFile(KMsvIndexRestore)!=EFalse) + { + _BACKUPLOG(_L("A genuine restore is happening\r\n")) + iState=EReleasedForRestore; + } + } + else + { + // Not a restore operation, so no need to reload the index when + // I get the lock back. + // Use KMsvIndexRestore to tell the index not to write anything to disk + // while the file system is locked... + if(DetachFromFile(KMsvIndexRestore)!=EFalse) + { + // ...but use EReleasedForBackup here so that we don't reload the index from disk + // when we get the ETakeLock notification - this would overwrite any index + // changes that have happened while the file system was locked, which we want to + // keep if the file system was locked for any reason other than Restore. + _BACKUPLOG(_L("File system detached for read and write, but not for a restore\r\n")) + iState=EReleasedForBackup; + } + } + + _BACKUPLOG(_L("released for no access\r\n")) + break; + } + case EReleaseLockReadOnly: + { + // please release the lock and don't write to the file, I won't read + // or write but I also assume the file is being backed up and therefore + // the same index will be there when I have finished. + _BACKUPLOG(_L("release no read only\r\n")) + if(DetachFromFile(KMsvIndexBackup)!=EFalse) + { + iState=EReleasedForBackup; + } + _BACKUPLOG(_L("released for read only\r\n")) + break; + } + default: + { + _BACKUPLOG(_L("bad event\r\n")) + __ASSERT_DEBUG(EFalse,PanicServer(EMsvBackupObserverGotUnknownEvent)); + break; + } + } + }; + + +TBool CMsvBackupHandler::DetachFromFile(TInt aErrorState) + { + // if the context is currently in an error state don't do anything, + // the current implications of this are that when the disk is removed + // or the wrong disk is in the drive and we are asked to release a lock + // on the file we won't. + _BACKUPLOG(_L("detach to file\r\n")) + + TInt error = KErrNone; + error = iServer.Context().IndexAdapter()->ErrorState(); + + if(error == KErrNone) + { + _BACKUPLOG(_L("context good for closing\r\n")) + _BACKUPLOG(_L("closing\r\n")) + +#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) + TUint currDriveIndex = CMsvPreferredDriveList::GetDriveList()->CurrentDriveIndex(); + TDriveNumber currDriveNum = CMsvPreferredDriveList::GetDriveList()->CurrentDriveNumber(); + + // Flush Cache. This will also detach the DB. + TRAP(error, iServer.Context().IndexAdapter()->RemoveDriveL(KCurrentDriveId, currDriveIndex, EFalse)); + if(error) + return(EFalse); + // current drive is detached from DB, so cannot access any entries from Database, so will + // assing iDbAdpter pointer to temporary iTempDbAdapter pointer and assin NULL to iDbAdpter. + iServer.Context().IndexAdapter()->BackupDbAdpter(); + TRAP(error, CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(currDriveIndex, KCurrentDriveId)); + if(error) + return(EFalse); +#else + iEntry.iSize = iServer.Context().IndexAdapter()->GetDbAdapter()->Size(); + iServer.Context().IndexAdapter()->DeleteDbAdapter(); +#endif // #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) + + _BACKUPLOG(_L("closed\r\n")) + + iServer.Context().IndexAdapter()->SetErrorState(aErrorState); + iServer.SetStartupState(EMsvMediaUnavailable); + return(ETrue); + } + else + { + return(EFalse); + } + } + + + +// CreateIndexL will result in this object being deleted +// so this is no longer valid +void CMsvBackupHandler::ReloadContextL() + { +#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) + // for attaching current drive to main Database, assign iDbAdpter with iTempDbAdapter. + iServer.Context().IndexAdapter()->RestoreDbAdpter(); + iServer.Context().IndexAdapter()->ReloadCacheL(); +#else + iServer.CreateIndexL(ETrue); +#endif + } +