diff -r 88ee4cf65e19 -r 1aa8c82cb4cb remotestoragefw/remotefileengine/src/rsfwfetchandcachestatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotestoragefw/remotefileengine/src/rsfwfetchandcachestatemachine.cpp Wed Sep 01 12:15:08 2010 +0100 @@ -0,0 +1,373 @@ +/* +* Copyright (c) 2005-2006 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: State machine for fetching and caching files and directories +* +*/ + + +#include "rsfwfetchandcachestatemachine.h" +#include "rsfwfileentry.h" +#include "rsfwfiletable.h" +#include "rsfwinterface.h" +#include "rsfwvolumetable.h" +#include "rsfwvolume.h" +#include "rsfwrfeserver.h" +#include "mdebug.h" +#include "rsfwfileengine.h" +#include "rsfwdirent.h" + +_LIT8(KMimeTypeJpeg, "image/jpeg"); +_LIT8(KMimeTypeMpeg, "audio/mpeg"); + + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::CRsfwFetchAndCacheStateMachine +// ---------------------------------------------------------------------------- +// +CRsfwFetchAndCacheStateMachine::CRsfwFetchAndCacheStateMachine() + { + } + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::CompleteRequestL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwFetchAndCacheStateMachine::CompleteRequestL(TInt aError) + { + if (aError == KUpdateNotRequired) + { // discard + aError = KErrNone; + } + + iDirEnts.ResetAndDestroy(); + // last byte that was actually fetched, may be more than was requested + TRfeFetchOutArgs* outArgs = static_cast(iOutArgs); + outArgs->iLastByte = iLastByte; + CompleteAndDestroyState()->SetErrorCode(aError); + + // remove the fetching directory wait note + if (Node()->Type() == KNodeTypeDir) + { + DeleteWaitNoteL(ETrue); + } + + return CompleteAndDestroyState(); + } + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::TFetchDataState::TFetchDataState +// ---------------------------------------------------------------------------- +// +CRsfwFetchAndCacheStateMachine::TFetchDataState::TFetchDataState( + CRsfwFetchAndCacheStateMachine* aParent) + : iOperation(aParent) + { + + } + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::TFetchDataState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwFetchAndCacheStateMachine::TFetchDataState::EnterL() + { + TRfeFetchInArgs* inArgs = + static_cast(iOperation->iInArgs); + iOperation->iFirstByte = inArgs->iFirstByte; + iOperation->iLastByte = inArgs->iLastByte; + + TInt recognizerLimit; + TInt metadataLimit = 0; + TCachingMode cachingMode; + + if (!(iOperation->Node())) + { + User::Leave(KErrNotFound); + } + + // the cache file should be continuos + // i.e. we always add to the end of the cache + __ASSERT_DEBUG(iOperation->iFirstByte <= iOperation->Node()->iCachedSize, + User::Panic(KRfeServer, ECacheInconsistency)); + + cachingMode = + iOperation->Node()->iFileTable->Volume()->iVolumeTable->iCachingMode; + recognizerLimit = + iOperation-> + Node()->iFileTable->Volume()->iVolumeTable->iRecognizerLimit; + + + // for files, adjust lastByte based on the caching mode... + if (iOperation->Node()->Type() == KNodeTypeFile) + { + switch (cachingMode) + { + case EWholeFileCaching: + if (iOperation->iLastByte < recognizerLimit) + { + // iLastByte = 127 + iOperation->iLastByte = recognizerLimit-1; + } + else + { + // fetch the whole file + iOperation->iLastByte = iOperation->Node()->Size() -1; + } + + break; + case EFullIfa: + if (iOperation->iLastByte < recognizerLimit) + { + // iLastByte = 127 + iOperation->iLastByte = recognizerLimit-1; + } + // othewise no change + break; + case EMetadataIfa: + // set metadataLimit based on the MIME-type + if (iOperation->Node()->MimeType()) + { + if ((*iOperation->Node()->MimeType()).Compare( + KMimeTypeJpeg) == 0) + { + metadataLimit = + iOperation->Node()->iFileTable-> + Volume()->iVolumeTable->iImageJpegLimit; + } + + if ((*iOperation->Node()->MimeType()).Compare( + KMimeTypeMpeg) == 0) + { + metadataLimit = + iOperation->Node()->iFileTable-> + Volume()->iVolumeTable->iAudioMpegLimit; + } + + // set the lastbyte + if (iOperation->iLastByte < recognizerLimit) + { + // iLastByte = 127 + iOperation->iLastByte = recognizerLimit-1; + } + + else if (iOperation->iLastByte < metadataLimit) + { + // Fetch "enough" metadata to avoid + // unnecessary many round-trips... + iOperation->iLastByte = metadataLimit - 1; + } + else if (iOperation->iLastByte >= metadataLimit) + { + iOperation->iLastByte = iOperation->Node()->Size() - 1; + } + } + else + { + // MIME-type not recognized + if (iOperation->iLastByte < recognizerLimit) + { + // iLastByte = 127 + iOperation->iLastByte = recognizerLimit-1; + } + else + { + // fetch the whole file + iOperation->iLastByte = iOperation->Node()->Size() -1; + } + } + } + } + + // Now we know what actually will be fetched, write to debug... + // and put up wait notes. + if (iOperation->Node()->Type() == KNodeTypeFile) + { + + DEBUGSTRING(("FETCH for a file with fid %d, bytes %d - %d", + iOperation->Node()->Fid().iNodeId, + iOperation->iFirstByte, + iOperation->iLastByte)); + + DEBUGSTRING16(("name is '%S", + iOperation->Node()->Name())); + + DEBUGSTRING(("full size is %d, cached size is %d", + iOperation->Node()->Size(), + iOperation->Node()->iCachedSize)); + + + } + else if (iOperation->Node()->Type() == KNodeTypeDir) + { + + DEBUGSTRING(("FETCH for a directory with fid %d, bytes %d - %d", + iOperation->Node()->Fid().iNodeId, + iOperation->iFirstByte, + iOperation->iLastByte)); + + DEBUGSTRING16(("name is '%S", + iOperation->Node()->Name())); + DEBUGSTRING(("full size is %d, cached size is %d", + iOperation->Node()->Size(), + iOperation->Node()->iCachedSize)); + + } + + // whether cached data is used... + // for files: + if (((iOperation->Node()->Type() == KNodeTypeFile) && + (iOperation->FileEngine()->UseCachedData(*iOperation->Node())) && + ((iOperation->iLastByte <= iOperation->Node()->iCachedSize) || + iOperation->Node()->IsFullyCached())) || + + // for directories: + ((iOperation->Node()->Type() == KNodeTypeDir) && + (iOperation->FileEngine()->UseCachedAttributes(*iOperation->Node())) && + (iOperation->FileEngine()->UseCachedData(*iOperation->Node())))) + { + DEBUGSTRING(("using cached data")); + + if (iOperation->Node()->IsLocallyDirty()) + { + DEBUGSTRING16(("directory is locally dirty")); + + // This is a directory which has at least one kid + // that has been cached or flushed since the last opening + // of the directory. + iOperation->FileEngine()->UpdateDirectoryContainerL( + *iOperation->Node()); + } + // if the directory appeared to be childless add it to metadata LRU list + if ( iOperation->Node()->Type() == KNodeTypeDir && + iOperation->Node()->Kids()->Count() == 0 ) + { + iOperation->Volumes()->AddToMetadataLRUPriorityListL(iOperation->Node(), ECachePriorityNormal); + } + + iOperation->iLastByte = iOperation->Node()->Size(); + iOperation->HandleRemoteAccessResponse(0, KUpdateNotRequired); + } + else + { + DEBUGSTRING(("fetching data from server")); + // put up a wait note if getting a directory + // (for files no global wait notes, as that would take a too long time) + if (iOperation->Node()->Type() == KNodeTypeDir) + { + // directory - pu up a 'Retrieving...' global wait note + iOperation->ShowWaitNoteL( ERemoteOpDirDownloading ); + } + + + if (iOperation->iLastByte > iOperation->Node()->Size()) + { // Don't try to read beyond the end of the file... + // Don't try to read beyond the end of the file... + iOperation->iLastByte = iOperation->Node()->Size(); + } + + if (iOperation->iLastByte == 0) + { + iOperation->iLength = 0; + // aLastByte == 0 indicates "no partial caching..." + // i.e. range 0 - 0 + TUint transactionId = + iOperation->FileEngine()-> + FetchAndCacheL(*iOperation->Node(), + 0 , + &(iOperation->iLength), + &(iOperation->iDirEnts), + iOperation); + // transactionId = 0 means syncronous non-cancellable operation + if (transactionId > 0) + { + iOperation->iTransactionId = transactionId; + } + } + else + { + iOperation->iLength = + iOperation->iLastByte - iOperation->Node()->iCachedSize + 1; + // Continue filling the cache-file sequentially + TUint transactionId = + iOperation->FileEngine()-> + FetchAndCacheL(*iOperation->Node(), + iOperation->Node()->iCachedSize, + &(iOperation->iLength), + &(iOperation->iDirEnts), + iOperation); + // transactionId = 0 means syncronous non-cancellable operation + if (transactionId > 0) + { + iOperation->iTransactionId = transactionId; + } + } + } + } + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::TFetchDataState::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwFetchAndCacheStateMachine::TState* +CRsfwFetchAndCacheStateMachine::TFetchDataState::CompleteL() + { + iOperation->iLastByte = iOperation->FileEngine()->AddToCacheL( + *iOperation->Node(), + &iOperation->iDirEnts, + iOperation->FileEngine(), + iOperation->Node()->iCachedSize + + iOperation->iLength); + + return iOperation->CompleteRequestL(KErrNone); + } + +// ---------------------------------------------------------------------------- +// CRsfwFetchAndCacheStateMachine::TFetchDataState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwFetchAndCacheStateMachine::TState* +CRsfwFetchAndCacheStateMachine::TFetchDataState::ErrorL(TInt aCode) + { + // *********** from CRsfwFileEngine::GetDirectoryL() + if (iOperation->Node()->Type() == KNodeTypeDir) + { + TInt err = aCode; + if (aCode == KUpdateNotRequired) + { + err = KErrNone; + } + return iOperation->CompleteRequestL(err); + } + + // file + return iOperation->CompleteRequestL(aCode); + } + +// ---------------------------------------------------------------------------- +// CRsfwWaitNoteStateMachine::ErrorOnStateExit +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* CRsfwFetchAndCacheStateMachine::ErrorOnStateExit(TInt aError) + { + iDirEnts.ResetAndDestroy(); + // remove the fetching directory wait note + if (Node()->Type() == KNodeTypeDir) + { + TRAP_IGNORE(DeleteWaitNoteL(ETrue)); + } + + + return CRsfwRfeStateMachine::ErrorOnStateExit(aError); + }