diff -r 491b3ed49290 -r 65326cf895ed filemanager/bkupengine/src/CMMCScBkupTransferReadRequest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filemanager/bkupengine/src/CMMCScBkupTransferReadRequest.cpp Wed Sep 01 12:31:07 2010 +0100 @@ -0,0 +1,517 @@ +/* +* Copyright (c) 2005 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: CMMCScBkupReadDataTransferRequestBase implementation +* +* +*/ + +#include "CMMCScBkupTransferReadRequest.h" + +// User includes +#include "MMCScBkupLogger.h" +#include "MMMCScBkupDriver.h" +#include "CMMCScBkupArchive.h" +#include "MMMCScBkupArchiveDataInterface.h" +#include "MMMCScBkupProgressObserver.h" +#include + +// Constants +const TBool KMMCScBkupDontUpdateOpSizes = EFalse; + + + +// ========================= MEMBER FUNCTIONS ================================ + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::CMMCScBkupReadDataTransferRequestBase() +// +// C++ constructor. +// --------------------------------------------------------------------------- +CMMCScBkupReadDataTransferRequestBase::CMMCScBkupReadDataTransferRequestBase( + MMMCScBkupDriver& aDriver, + TMMCScBkupOwnerDataType aElementType, + TInt aChunkSize, + TInt aPriority ) +: CMMCScBkupTransferRequestBase( aDriver, aElementType, KMMCScBkupDontUpdateOpSizes, aPriority ), + iReadChunkSize( aChunkSize ), + iCurrentIndex( -1 ) + { + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::~CMMCScBkupReadDataTransferRequestBase() +// +// Destructor. +// --------------------------------------------------------------------------- +CMMCScBkupReadDataTransferRequestBase::~CMMCScBkupReadDataTransferRequestBase() + { + delete iTransferType; + delete iTemporaryTransferSink; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::RequestL() +// +// +// --------------------------------------------------------------------------- +void CMMCScBkupReadDataTransferRequestBase::RequestL( CMMCScBkupDataOwnerInfo& aOwner, TRequestStatus& aObserver, const RArray& aEntries ) + { +#ifdef __MMCSCBKUPLOGGING_ENABLED__ + if ( ElementType() == EMMCScBkupOwnerDataTypeJavaData ) + { + HBufC* hash = MMCScBkupSBEUtils::JavaHashFromGenericLC( aOwner.Owner().Identifier() ); + __LOG2("CMMCScBkupReadDataTransferRequestBase::RequestL() - START - reading data from SBE for JavaHash: %S, ElementType: %S", hash, &MMCScBkupLogger::DataType( ElementType() )); + CleanupStack::PopAndDestroy( hash ); + } + else + { + __LOG2("CMMCScBkupReadDataTransferRequestBase::RequestL() - START - reading data from SBE for DO: 0x%08x, ElementType: %S", aOwner.SecureId().iId, &MMCScBkupLogger::DataType( ElementType() )); + } +#endif + + CMMCScBkupTransferRequestBase::RequestL( aOwner, aObserver ); + // + if ( !iTemporaryTransferSink ) + { + iTemporaryTransferSink = HBufC8::NewL( iReadChunkSize ); + } + // + iEntries = &aEntries; + iCurrentIndex = -1; // Increased by one in PrepareForNextEntry + // + TState nextState = EProcessData; + const TBool entryAvailable = PrepareForNextEntry(); + if ( !entryAvailable ) + { + nextState = EFinished; + } + // + SetState( nextState ); + CompleteSelf(); + __LOG1("CMMCScBkupReadDataTransferRequestBase::RequestL() - END - nextState: %d", nextState); + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() +// +// +// --------------------------------------------------------------------------- +TBool CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() + { + __ASSERT_ALWAYS( iCurrentIndex >= 0, User::Invariant() ); + + TBool callAgain = EFalse; + + // Do we need to move to the next entry? + TBool entryAvailable = ( iCurrentIndex < iEntries->Count() ); + if ( entryAvailable ) + { + // At least one more entry left to process.. but have we finished + // the current entry? If we've read all the data, then the + // answer is yes... + const TMMCScBkupArchiveDriveAndVector& entry = (*iEntries)[ iCurrentIndex ]; + const TInt endOffset = entry.iVector.EndOffset(); + +#ifdef __MMCSCBKUPLOGGING_ENABLED__ + if ( ElementType() == EMMCScBkupOwnerDataTypeJavaData ) + { + HBufC* hash = MMCScBkupSBEUtils::JavaHashFromGenericLC( DataOwner().Owner().Identifier() ); + __LOG6("CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() - START - JavaHash: %S, ElementType: %S, offset: %8d, length: %8d, endOffset: %8d, drive: %c:", hash, &MMCScBkupLogger::DataType( ElementType() ), entry.iVector.Offset(), entry.iVector.Length(), endOffset, entry.iDrive + 'A' ); + CleanupStack::PopAndDestroy( hash ); + } + else + { + __LOG6("CMMCScBkupReadDataTransferRequestBase::ProcessChunkOfDataL() - START - DO: 0x%08x, ElementType: %S, offset: %8d, length: %8d, endOffset: %8d, drive: %c:", DataOwner().SecureId().iId, &MMCScBkupLogger::DataType( ElementType() ), entry.iVector.Offset(), entry.iVector.Length(), endOffset, entry.iDrive + 'A' ); + } +#endif + + // Check bounds + if ( CurrentOffset() < 0 || CurrentOffset() > endOffset ) + { + ASSERT( EFalse ); + User::Leave( KErrCorrupt ); + } + // + if ( iCurrentOffset == endOffset ) + { + // We're done with this entry - move to the next + entryAvailable = PrepareForNextEntry(); + } + } + // + if ( entryAvailable ) + { + // We need to read more archive data in order to transfer this + // entry to the SBE + callAgain = DoProcessChunkOfDataL(); + } + else + { + // No more left to process - we're finished! + SetState( EFinished ); + CompleteSelf(); + } + // + return callAgain; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::PrepareDataTransferL() +// +// +// --------------------------------------------------------------------------- +void CMMCScBkupReadDataTransferRequestBase::PrepareDataTransferL() + { + __ASSERT_ALWAYS(iTransferChunkPointer != NULL, User::Invariant()); + const CSBGenericDataType& generic = DataOwner().Owner().Identifier(); + + // Prepare the transfer type with a virtual function call... + CSBGenericTransferType* transferType = PrepareTransferTypeL( generic, CurrentDrive(), + DataOwner().Version()); + delete iTransferType; + iTransferType = transferType; + +#ifdef __MMCSCBKUPLOGGING_ENABLED__ + TInt lengthOfDataReadyForTransfer = 0; + if ( iTransferChunkPointer != NULL ) + { + lengthOfDataReadyForTransfer = iTransferChunkPointer->Length(); + } + + if ( iTransferType->DerivedTypeL() == EJavaTransferDerivedType ) + { + HBufC* hash = MMCScBkupSBEUtils::JavaHashFromGenericLC( DataOwner().Owner().Identifier() ); + __LOG5("CMMCScBkupReadDataTransferRequestBase::PrepareDataTransferL() - supplying %d bytes of data for has: %S, drive: %c, iTransferChunkPointer addr: 0x%08x, iTransferChunkPointer length: %d", lengthOfDataReadyForTransfer, hash, 'A' + CurrentDrive(), iTransferChunkPointer->Ptr(), iTransferChunkPointer->Length() ); + CleanupStack::PopAndDestroy( hash ); + } + else + { + const TSecureId sid = DataOwner().SecureId(); + __LOG5("CMMCScBkupReadDataTransferRequestBase::PrepareDataTransferL() - supplying %d bytes of data for sid: 0x%08x, drive: %c, iTransferChunkPointer addr: 0x%08x, iTransferChunkPointer length: %d", lengthOfDataReadyForTransfer, sid.iId, 'A' + CurrentDrive(), iTransferChunkPointer->Ptr(), iTransferChunkPointer->Length() ); + } +#endif + + // + Driver().DrvSecureBackupClient().SupplyDataL( *iTransferType, iFinishedSupplyingData, iStatus ); + SetActive(); + + // Reset + ResetDataTransferCounter(); + iTransferChunkPointer = NULL; // Address is retrieved from global chunk in DoProcessChunkOfDataL + + __LOG("CMMCScBkupReadDataTransferRequestBase::PrepareDataTransferL() - data transmitted, waiting for request completion..."); + + // When the SBE informs us that it has read the data, we'll need to send it the next + // chunk. + SetState( EProcessData ); + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::ReadChunkL() +// +// +// --------------------------------------------------------------------------- +void CMMCScBkupReadDataTransferRequestBase::ReadChunkL( TDes8& aSink, TInt aLength ) + { + const TInt endOffset = CurrentReadInfo().EndOffset(); + __LOG4("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - START - aLength: %d, endOffset: %d, iCurrentOffset: %d, sinkLength: %d", aLength, endOffset, iCurrentOffset, aSink.Length()); + // + if ( iCurrentOffset >= 0 && iCurrentOffset <= endOffset ) + { + if ( aLength > 0 ) + { + MMMCScBkupArchiveDataInterface& archiveDataInterface = Driver().DrvADI(); + + // We read based upon the current offset and the specified length + TPtr8 sink( iTemporaryTransferSink->Des() ); + const TMMCScBkupArchiveVector readRequest( iCurrentOffset, aLength ); + const TMMCScBkupArchiveVector& readResult = archiveDataInterface.ADIReadL( sink, readRequest ); + __LOG2("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - read result - offset: %d, length: %d", readResult.Offset(), readResult.Length()); + + // Update offset + iCurrentOffset += readResult.Length(); + aSink.Append( sink ); + __LOG2("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - new offset (iCurrentOffset): %d, sink Length: %d", iCurrentOffset, aSink.Length()); + +#ifdef DEBUGGING_DATA_TRANSFER + TRAP_IGNORE( DumpTransferDataL( archiveDataInterface.ADIFsSession(), sink) ); +#endif + + if ( iCurrentOffset > CurrentReadInfo().EndOffset() ) + { + __LOG("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - Fatal Error - read went beyond archive entry boundary!"); + ASSERT( EFalse ); + User::Leave( KErrCorrupt ); + } + else + { + __LOG("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - read was okay - updating stats & reporting progress..."); + + // We managed to read the data okay, so let's update our stats + DataTransferred( readResult.Length() ); + + // ... and also update progress + Driver().DrvProgressHandler().MMCScBkupHandleProgress( readResult.Length() ); + } + } + } + else + { + __LOG("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - Fatal Error - current offset out of bounds!"); + ASSERT( EFalse ); + User::Leave( KErrCorrupt ); + } + + __LOG("CMMCScBkupReadDataTransferRequestBase::ReadChunkL() - END"); + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() +// +// +// --------------------------------------------------------------------------- +TBool CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() + { + MMMCScBkupDriver& driver = Driver(); + const TInt startingOffset = CurrentOffset(); + const TInt finalOffset = CurrentReadInfo().EndOffset(); + + // Calculate how much data is remaining + const TInt amountOfDataStillToBeRead = finalOffset - startingOffset; + + __LOG4("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - START - startingOffset: 0x%08x, finalOffset: 0x%08x, amountToBeRead: %8d, iFinishedSupplyingData: %d", + startingOffset, finalOffset, amountOfDataStillToBeRead, iFinishedSupplyingData); + + // Get a handle to the received data - but only if we don't already + // have a handle to it! Calling this method resets whatever is already + // in the transfer chunk - hence we must only call it once (at the beginning + // of a multi-chunked transfer) + if ( iTransferChunkPointer == NULL ) + { + iTransferChunkPointer = &driver.DrvSecureBackupClient().TransferDataAddressL(); + } + + // How much space is available? + const TInt spaceAvailable = iTransferChunkPointer->MaxLength() - iTransferChunkPointer->Length(); + const TInt amountToRead = Min( spaceAvailable, Min( iReadChunkSize, amountOfDataStillToBeRead ) ); + __LOG2("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - xfer space available: %8d, amountToRead: %8d", spaceAvailable, amountToRead); + + // Do the read + ReadChunkL( *iTransferChunkPointer, amountToRead ); + + // Was this the last time we needed to perform a read? + const TBool lastReadFromArchive = ( CurrentOffset() == finalOffset ); + __LOG1("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - read data okay - lastReadFromArchive: %d", lastReadFromArchive); + + // Check to see if the data sink chunk is full. If so then we need to let + // the SBE process what we've prepared so far, then we'll fill it with more + // data. + iFinishedSupplyingData = lastReadFromArchive; + TBool moreToBeRead = !lastReadFromArchive; + if ( !iFinishedSupplyingData && iTransferChunkPointer->Length() == iTransferChunkPointer->MaxLength() ) + { + // Also cope with the boundary condition that the sink is full + // but we've also just given it the last byte anyway. In which case, + // we don't need to request a repeat transfer. This is actually + // all the data in one go. + moreToBeRead = EFalse; + } + // + __LOG1("CMMCScBkupReadDataTransferRequestBase::DoProcessChunkOfDataL() - END - more to read: %d", moreToBeRead); + return moreToBeRead; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::PrepareForNextEntry() +// +// +// --------------------------------------------------------------------------- +TBool CMMCScBkupReadDataTransferRequestBase::PrepareForNextEntry() + { + TBool anotherEntryAvailable = EFalse; + + // Update our starting offset + iFinishedSupplyingData = EFalse; + iCurrentOffset = -1; + // + if ( ++iCurrentIndex < iEntries->Count() ) + { + const TMMCScBkupArchiveVector& currentReadInfo = CurrentReadInfo(); + iCurrentOffset = currentReadInfo.Offset(); + + __LOG3("CMMCScBkupReadDataTransferRequestBase::PrepareForNextEntry() - offset: %6d, length: %6d, drive: %c:", currentReadInfo.Offset(), currentReadInfo.Length(), 'A' + CurrentDrive() ); + + anotherEntryAvailable = ETrue; + } + // + return anotherEntryAvailable; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::CurrentDrive() +// +// +// --------------------------------------------------------------------------- +TDriveNumber CMMCScBkupReadDataTransferRequestBase::CurrentDrive() const + { + return CurrentEntry().iDrive; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::CurrentReadInfo() +// +// +// --------------------------------------------------------------------------- +const TMMCScBkupArchiveVector& CMMCScBkupReadDataTransferRequestBase::CurrentReadInfo() const + { + return CurrentEntry().iVector; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::CurrentEntry() +// +// +// --------------------------------------------------------------------------- +const TMMCScBkupArchiveDriveAndVector& CMMCScBkupReadDataTransferRequestBase::CurrentEntry() const + { + __ASSERT_ALWAYS( iCurrentIndex >= 0 && iCurrentIndex < iEntries->Count(), User::Invariant() ); + + // Get the next entry + const TMMCScBkupArchiveDriveAndVector& entry = (*iEntries)[ iCurrentIndex ]; + return entry; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::RunError() +// +// +// --------------------------------------------------------------------------- +TInt CMMCScBkupReadDataTransferRequestBase::RunError( TInt aError ) + { +#if defined(__MMCSCBKUPLOGGING_ENABLED__) + const TSecureId sid = DataOwner().SecureId(); + __LOGFILE3("CMMCScBkupReadDataTransferRequestBase::RunError() - **** - aError: %d, sid: 0x%08x, drive: %c", aError, sid.iId, 'A' + CurrentDrive() ); +#endif + + TInt ret = KErrNone; + + if ( aError == KErrNotFound ) + { + // KErrNotFound is treated as non-fatal. + const TBool entryAvailable = PrepareForNextEntry(); + + // Try the next entry (if any) + TState nextState = EProcessData; + if ( entryAvailable ) + { + __LOGFILE("CMMCScBkupReadDataTransferRequestBase::RunError() - **** - another drive available for same DO - trying the next drive..."); + nextState = EProcessData; + } + else + { + // Done + __LOGFILE("CMMCScBkupReadDataTransferRequestBase::RunError() - **** - no drives let for same DO..."); + nextState = EFinished; + } + + SetState( nextState ); + CompleteSelf(); + } + else + { + // Everything else is fatal + __LOGFILE1( "CMMCScBkupReadDataTransferRequestBase::RunError() - **** - FATAL ERROR (%d)", aError ); + ret = CMMCScBkupTransferRequestBase::RunError( aError ); + } + // + return ret; + } + + +// --------------------------------------------------------------------------- +// CMMCScBkupReadDataTransferRequestBase::DumpTransferDataL() +// +// +// --------------------------------------------------------------------------- +#ifdef DEBUGGING_DATA_TRANSFER +void CMMCScBkupReadDataTransferRequestBase::DumpTransferDataL( RFs& aFsSession, const TDesC8& aData ) const + { + TPtrC subDirectory( KNullDesC ); + // + switch( ElementType() ) + { + case EMMCScBkupOwnerDataTypeJavaData: + subDirectory.Set(KMMCScBkupDataTransferDebuggingPathDataJava); + break; + case EMMCScBkupOwnerDataTypeSystemData: + subDirectory.Set(KMMCScBkupDataTransferDebuggingPathDataSystem); + break; + case EMMCScBkupOwnerDataTypePassiveData: + subDirectory.Set(KMMCScBkupDataTransferDebuggingPathDataPassive); + break; + case EMMCScBkupOwnerDataTypeActiveData: + subDirectory.Set(KMMCScBkupDataTransferDebuggingPathDataActive); + break; + default: + User::Leave( KErrNotSupported ); + break; + } + // + const TSecureId secureId = DataOwner().SecureId(); + _LIT(KMMCScBkupFormatDes, "%S%S"); + TFileName transferDumpFileName; + const TDesC& path = PathInfo::MemoryCardRootPath(); + transferDumpFileName.Format(KMMCScBkupFormatDes, &path, &KMMCScBkupDataTransferDebuggingPathRoot); + + transferDumpFileName.Append( subDirectory ); + transferDumpFileName.Append( KMMCScBkupDataTransferDebuggingPathDataRestore ); + transferDumpFileName.AppendFormat( KMMCScBkupDataTransferDebuggingFileName, secureId.iId, 'a' + CurrentDrive() ); + // + RFile64 file; + TInt error = KErrNone; + TEntry entry; + if ( aFsSession.Entry( transferDumpFileName, entry ) == KErrNone ) + { + // Already exists - append data + error = file.Open( aFsSession, transferDumpFileName, EFileWrite | EFileStream | EFileShareExclusive ); + } + else + { + entry.iSize = 0; + error = file.Create( aFsSession, transferDumpFileName, EFileWrite | EFileStream | EFileShareExclusive ); + } + // + User::LeaveIfError( error ); + CleanupClosePushL( file ); + error = file.Write( entry.iSize, aData ); + CleanupStack::PopAndDestroy( &file ); + } +#endif + + + + + +