diff -r 5294c000a26d -r 112a725ff2c2 videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfilecopy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videocollection/mpxmyvideoscollection/src/vcxmyvideosasyncfilecopy.cpp Wed Mar 31 21:34:36 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 +#include +#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"); + }