diff -r 000000000000 -r 96612d01cf9f videofeeds/livetvutils/src/CIptvEpgFileSwapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videofeeds/livetvutils/src/CIptvEpgFileSwapper.cpp Mon Jan 18 20:21:12 2010 +0200 @@ -0,0 +1,240 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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 "CIptvEpgFileSwapper.h" +#include "IptvLiveLogger.h" +#include // For CBaBackupSessionWrapper +#include "MIptvEpgFileSwapObserver.h" +#include // For BaflUtils + +// Constants +const TInt KMicrosecondsToWasteAtOnce = 2000000; // 0.2 seconds +const TInt KMaxSwapTries = 10; // We wait max 10*0.2 seconds for file releases + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::NewL +// Symbian two phase constructor +// ----------------------------------------------------------------------------- +EXPORT_C CIptvEpgFileSwapper* CIptvEpgFileSwapper::NewL( const TFileName& aOldFileName, + const TFileName& aNewFileName, + MIptvEpgFileSwapObserver& aSwapObserver ) + { + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::NewL IN") ); + CIptvEpgFileSwapper* self = new (ELeave) CIptvEpgFileSwapper( aOldFileName, + aNewFileName, + aSwapObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::NewL OUT") ); + return self; + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::CIptvEpgFileSwapper +// Default constructor +// ----------------------------------------------------------------------------- +CIptvEpgFileSwapper::CIptvEpgFileSwapper( const TFileName& aOldFileName, + const TFileName& aNewFileName, + MIptvEpgFileSwapObserver& aSwapObserver ) : + CActive( EPriorityLow ), + iOldFileName( aOldFileName ), + iNewFileName( aNewFileName ), + iSwapObserver( aSwapObserver ) + { + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::ConstructL +// Second phase construction. +// ----------------------------------------------------------------------------- +void CIptvEpgFileSwapper::ConstructL() + { + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::ConstructL IN") ); + // First create backupwrapper + iBackupWrapper = CBaBackupSessionWrapper::NewL(); + User::LeaveIfError( iTimeWaster.CreateLocal() ); + User::LeaveIfError( iFs.Connect() ); + CActiveScheduler::Add( this ); + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::ConstructL OUT") ); + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::~CIptvEpgFileSwapper +// Destructor +// ----------------------------------------------------------------------------- +CIptvEpgFileSwapper::~CIptvEpgFileSwapper() + { + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::~CIptvEpgFileSwapper IN") ); + Cancel(); + iTimeWaster.Close(); + iFs.Close(); + delete iBackupWrapper; + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::~CIptvEpgFileSwapper OUT") ); + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::SwapFilesL +// +// ----------------------------------------------------------------------------- +EXPORT_C void CIptvEpgFileSwapper::SwapFilesL() + { + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::SwapFilesL IN") ); + // If one of the files to be swapped does not exist what do people expect + // us to do here? Yes, we'll leave! + if( !BaflUtils::FileExists( iFs, iNewFileName ) || + !BaflUtils::FileExists( iFs, iOldFileName ) ) + { + LIVE_TV_TRACE1( _L("Either iNewFileName or iOldFileName was not found -> we are leaving with KErrPathNotFound") ); + User::Leave( KErrPathNotFound ); + } + // Request backup wrapper to signalize observers to close handles to + // files to allow swapping. + iBackupWrapper->CloseFileL( iNewFileName, MBackupObserver::EReleaseLockNoAccess ); + iBackupWrapper->CloseFileL( iOldFileName, MBackupObserver::EReleaseLockNoAccess ); + Cancel(); + iTimeWaster.After( iStatus, KMicrosecondsToWasteAtOnce ); + SetActive(); + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::SwapFilesL OUT") ); + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::ReleaseFileLocks +// +// ----------------------------------------------------------------------------- +void CIptvEpgFileSwapper::ReleaseFileLocks() + { + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::ReleaseFileLocks IN") ); + iBackupWrapper->RestartFile( iOldFileName ); + iBackupWrapper->RestartFile( iNewFileName ); + iSwapTriesAmount = 0; + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::ReleaseFileLocks OUT") ); + } + +// Methods from CActive +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::RunL +// +// ----------------------------------------------------------------------------- +TInt CIptvEpgFileSwapper::RunError( TInt aError ) + { + LIVE_TV_TRACE2( _L("CIptvEpgFileSwapper::RunError( %d ) IN"), aError ); + if( aError != KErrNone ) + { + // What shall we do... Any ideas? Anyone? + } + // In any case we need to cancel backup requests -> Tell observer to allow + // files to be opened again. + ReleaseFileLocks(); + + iSwapObserver.FileSwapComplete( aError ); + + // Return KErrNone to avoid active scheduler panic + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::RunL +// +// ----------------------------------------------------------------------------- +void CIptvEpgFileSwapper::RunL() + { + LIVE_TV_TRACE2( _L("CIptvEpgFileSwapper::RunL IN, iStatus: %d"), iStatus.Int() ); + + if ( iStatus.Int() == KErrNone ) + { + // Check if both files are not used anymore + TBool oldFileOpen = ETrue; + TBool newFileOpen = ETrue; + + // Check if files are open... + User::LeaveIfError( iFs.IsFileOpen( iOldFileName, oldFileOpen ) ); + User::LeaveIfError( iFs.IsFileOpen( iNewFileName, newFileOpen ) ); + + if( !oldFileOpen && !newFileOpen ) // Both files are closed -> we can do the swap + { + LIVE_TV_TRACE1( _L("both files are closed -> we can start swapping") ); + + // Get path to the "official" directory + TFileName oldFileNamePath = BaflUtils::DriveAndPathFromFullName( iOldFileName ); + + // Get path to the temp directory that contains the new stuff + TFileName newFileNamePath = BaflUtils::DriveAndPathFromFullName( iNewFileName ); + + TInt error = KErrNone; + // Get rid of content in "official" directory (meaning the one under \videocenter\ecg\live\ + LIVE_TV_TRACE2( _L("Deleting all files from %S"), &oldFileNamePath ); + error = BaflUtils::DeleteFile( iFs, oldFileNamePath, CFileMan::ERecurse ); + if( error != KErrNone ) + { + LIVE_TV_TRACE2( _L("BaflUtils::DeleteFile( iFs, oldFileNamePath, ERecurse ); returned %d"), error ); + User::Leave( error ); + } + + LIVE_TV_TRACE3( _L("Moving all files from %S to %S"), &newFileNamePath, &oldFileNamePath ); + error = BaflUtils::RenameFile( iFs, newFileNamePath, oldFileNamePath, CFileMan::EOverWrite ); + + if( error != KErrNone ) + { + LIVE_TV_TRACE2( _L("BaflUtils::CopyFile( newFileNamePath, oldFileNamePath, EOverWrite ); returned %d"), error ); + User::Leave( error ); + } + + // Release file locks for the given files + ReleaseFileLocks(); + // Tell observer that everything went more than fine + iSwapObserver.FileSwapComplete( KErrNone ); + } + else // At least one of the files is open -> waste some more time... + { + // We dont have time to wait all day for the file releases. + // If things didn't happen in 2 seconds we are done here. + if( iSwapTriesAmount > KMaxSwapTries ) + { + LIVE_TV_TRACE3( _L("iSwapTriesAmount (%d) > KMaxSwapTries (%d) -> we are aborting the mission here"), iSwapTriesAmount, KMaxSwapTries ); + ReleaseFileLocks(); + iSwapObserver.FileSwapComplete( KErrAccessDenied ); + } + else // Let's try again + { + LIVE_TV_TRACE4( _L("oldFileOpen = %d, newFileOpen = %d -> Wasting more time to make those close. Time already wasted %d times"), oldFileOpen, newFileOpen, iSwapTriesAmount ); + iSwapTriesAmount++; + if ( !IsActive() ) + { + iTimeWaster.After( iStatus, KMicrosecondsToWasteAtOnce ); + SetActive(); + } + } + } + } + LIVE_TV_TRACE1( _L("CIptvEpgFileSwapper::RunL OUT") ); + } + +// ----------------------------------------------------------------------------- +// CIptvEpgFileSwapper::DoCancel +// +// ----------------------------------------------------------------------------- +void CIptvEpgFileSwapper::DoCancel() + { + iTimeWaster.Cancel(); + ReleaseFileLocks(); + } + +// End of file