videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfilecopy.cpp
changeset 35 3738fe97f027
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfilecopy.cpp	Thu Apr 01 23:32:44 2010 +0300
@@ -0,0 +1,294 @@
+/*
+* Copyright (c) 2008 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:    Asynchronous file copy, implemented with several small sync block copies.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <mpxlog.h>
+#include <bautils.h>
+#include "vcxmyvideosasyncfilecopy.h"
+
+/**
+* One block shouldn't take more than 1 second to copy to keep cancel
+* response fast enough. On the otherhand, the deleting the already
+* copied data may take several seconds. 
+*
+* Copying speed tests (from massmemory to memorycard):
+*
+* Block size       speed        response time
+*   6MB        ->  3.20 MB/s    ~2sec    (unacceptable response time, full speed)
+*   3MB        ->  3.17 MB/s    ~1sec    (poor response time, almost full speed)
+*   1MB        ->  3.16 MB/s    ~0.3sec  (good response time, almost full speed)
+* 0.5MB        ->  2.60 MB/s    ~0.19sec (good response time, some speed loss)
+*
+* -> 1MB is the best.
+*
+* * Copying speed tests (from memorycard to massmemory):
+*
+* Block size       speed        response time
+*   3MB        ->  5.470 MB/s    0.548sec
+*   1MB        ->  4.393 MB/s    0.228sec
+*
+* 1M gives slightly reduced speed, great response time. 3MB would be better than
+* 1M but can't use it since it gives 1sec response time in memorycard writing.
+*/
+const TInt KBigBufSize    = 1024 * 1024; // 1MB
+const TInt KMediumBufSize = 512 * 1024;  // 0.5MB
+const TInt KSmallBufSize  = 100 * 1024;  // 0.1MB
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileCopy* CVcxMyVideosAsyncFileCopy::NewL( RFs& aFs )
+    {
+    CVcxMyVideosAsyncFileCopy* self = new (ELeave) CVcxMyVideosAsyncFileCopy( aFs );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileCopy::~CVcxMyVideosAsyncFileCopy()
+    {
+    iSourceFile.Close();
+    iTargetFile.Close();
+    delete iFileBlockBuffer;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CVcxMyVideosAsyncFileCopy::CVcxMyVideosAsyncFileCopy( RFs& aFs )
+: iFs( aFs )
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileCopy::ConstructL ()
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileCopy::CopyL
+// ----------------------------------------------------------------------------
+//
+TBool CVcxMyVideosAsyncFileCopy::CopyL( const TDesC& aSourceFileName,
+        const TDesC& aTargetFileName )
+    {
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::CopyL() start");
+    
+    if ( iIsCopying )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    TInt error = iSourceFile.Open( iFs, aSourceFileName, EFileRead | EFileShareReadersOnly );
+
+    User::LeaveIfError( error );
+
+    error = iTargetFile.Replace( iFs, aTargetFileName, EFileWrite | EFileWriteDirectIO
+            | EFileShareExclusive );
+
+    if ( error == KErrPathNotFound )
+        {
+        error = iFs.MkDirAll( aTargetFileName );
+        if ( error == KErrNone )
+            {
+            error = iTargetFile.Create( iFs, aTargetFileName, EFileWrite
+                    | EFileWriteDirectIO | EFileShareExclusive );
+            }
+        }
+
+    User::LeaveIfError( error );
+    User::LeaveIfError( iSourceFile.Size( iDataRemaining ) );
+    User::LeaveIfError( iTargetFile.SetSize( iDataRemaining ) );
+
+    TInt suggestBlockSize;
+    if ( iDataRemaining > KBigBufSize )
+        {
+        suggestBlockSize = KBigBufSize;
+        }
+    else
+        {
+        suggestBlockSize = iDataRemaining;
+        }
+    AllocateFileBlockBufferL( suggestBlockSize );
+
+    iReadPos   = 0;
+    iIsCopying = ETrue;
+
+#ifdef _DEBUG
+    iStartTime.UniversalTime();
+#endif
+
+    DoNextBlockCopy();
+
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::CopyL() exit");    
+    return !iIsCopying;
+    }
+    
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileCopy::CopyIsOngoing
+// ----------------------------------------------------------------------------
+//
+TBool CVcxMyVideosAsyncFileCopy::CopyIsOngoing()
+    {
+    return iIsCopying;
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileCopy::DoNextBlockCopy
+// ----------------------------------------------------------------------------
+//
+TInt CVcxMyVideosAsyncFileCopy::DoNextBlockCopy()
+    {    
+	TInt err = KErrNone;
+	TPtr8 fileBufPtr = iFileBlockBuffer->Des();
+
+	TInt bytesToCopy = Min( iDataRemaining, fileBufPtr.MaxSize() );
+
+	err = iSourceFile.Read( iReadPos, fileBufPtr, bytesToCopy );
+	if ( err == KErrNone && fileBufPtr.Length() != bytesToCopy )
+	    {
+		err = KErrCorrupt;
+	    }
+	if ( err == KErrNone )
+	    {
+		err = iTargetFile.Write( iReadPos, fileBufPtr, bytesToCopy );
+	    }
+	if ( err != KErrNone )
+		{
+		EndCopy( ETrue /* remove target file */);
+		return err;
+		}
+
+	iReadPos       += bytesToCopy;
+	iDataRemaining -= bytesToCopy;
+
+	if ( iDataRemaining == 0 )
+		{
+		EndCopy( EFalse /* keep target file */);
+		}
+
+	return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileCopy::Cancel
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileCopy::Cancel()
+    {
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::Cancel() start");
+    
+    if ( iIsCopying )
+        {
+        EndCopy( ETrue /* remove target file */ );
+        }
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::Cancel() exit");
+    }
+
+// ----------------------------------------------------------------------------
+// CVcxMyVideosAsyncFileCopy::AllocateFileBlockBufferL
+// ----------------------------------------------------------------------------
+//
+void CVcxMyVideosAsyncFileCopy::AllocateFileBlockBufferL( TInt aFileSize )
+	{
+    delete iFileBlockBuffer;
+    iFileBlockBuffer = NULL;
+    
+	TInt big = Min( aFileSize, KBigBufSize );
+	iFileBlockBuffer = HBufC8::New( big );
+	if ( !iFileBlockBuffer )
+	    {
+		iFileBlockBuffer = HBufC8::New( KMediumBufSize );
+		}
+	if ( !iFileBlockBuffer )
+	    {
+		iFileBlockBuffer = HBufC8::NewL( KSmallBufSize );
+		}
+	}
+
+void CVcxMyVideosAsyncFileCopy::EndCopy( TBool aRemoveTargetFile )
+	{
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::EndCopy() start");
+
+    TTime modified;
+    iSourceFile.Modified( modified );
+    iTargetFile.SetModified( modified );
+
+#ifdef _DEBUG
+
+    TDateTime dT = modified.DateTime();
+    TBuf<200> buf;
+    buf.Format(_L("CVcxMyVideosAsyncFileCopy:: setting file modified date: %2d.%2d.%4d %2d:%2d:%2d"),
+            dT.Day()+1, dT.Month()+1, dT.Year(), dT.Hour(), dT.Minute(), dT.Second() ); 
+    MPX_DEBUG2("%S", &buf ); 
+
+    const TInt megaBytes = 0x100000;
+    const TInt kiloBytes = 1024;
+    TInt dataCopiedInMegaBytes = iReadPos / megaBytes;
+    TTime now;
+    now.UniversalTime();
+    TTimeIntervalSeconds interval;
+    now.SecondsFrom( iStartTime, interval );
+    TInt copyingSpeed = 0;
+    if ( interval.Int() > 0 )
+        {
+        copyingSpeed = (iReadPos / kiloBytes) / interval.Int();
+        }
+    MPX_DEBUG3("CVcxMyVideosAsyncFileCopy:: Data copied: %d (MB), %d kB/s", dataCopiedInMegaBytes, copyingSpeed);
+#endif
+	    
+	delete iFileBlockBuffer;
+	iFileBlockBuffer = NULL;
+	iReadPos       = 0;
+	iDataRemaining = 0;
+	iSourceFile.Close();
+	iIsCopying = EFalse;
+
+	if ( aRemoveTargetFile )
+	    {
+	    TFileName fileName;
+	    TInt err = iTargetFile.FullName( fileName );
+
+        iTargetFile.Close();	
+	    
+	    if ( err == KErrNone )
+	        {
+            MPX_DEBUG2("CVcxMyVideosAsyncFileCopy:: removing file: %S", &fileName);
+	        iFs.Delete( fileName );
+	        }
+	    }
+	else
+	    {
+        iTargetFile.Close();
+	    }
+
+    MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::EndCopy() exit");
+	}