videofeeds/livetvutils/src/CIptvEpgFileSwapper.cpp
changeset 0 96612d01cf9f
--- /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 <babackup.h>					// For CBaBackupSessionWrapper
+#include "MIptvEpgFileSwapObserver.h"
+#include <bautils.h>					// 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\<serviceId>
+			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