remotestoragefw/remotefileengine/src/rsfwfetchandcachestatemachine.cpp
branchRCL_3
changeset 15 88ee4cf65e19
parent 12 87c71b25c937
child 16 1aa8c82cb4cb
equal deleted inserted replaced
12:87c71b25c937 15:88ee4cf65e19
     1 /*
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  State machine for fetching and caching files and directories
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "rsfwfetchandcachestatemachine.h"
       
    20 #include "rsfwfileentry.h"
       
    21 #include "rsfwfiletable.h"
       
    22 #include "rsfwinterface.h"
       
    23 #include "rsfwvolumetable.h"
       
    24 #include "rsfwvolume.h"
       
    25 #include "rsfwrfeserver.h"
       
    26 #include "mdebug.h"
       
    27 #include "rsfwfileengine.h"
       
    28 #include "rsfwdirent.h"
       
    29 
       
    30 _LIT8(KMimeTypeJpeg, "image/jpeg");
       
    31 _LIT8(KMimeTypeMpeg, "audio/mpeg");
       
    32 
       
    33 
       
    34 // ----------------------------------------------------------------------------
       
    35 // CRsfwFetchAndCacheStateMachine::CRsfwFetchAndCacheStateMachine
       
    36 // ----------------------------------------------------------------------------
       
    37 //
       
    38 CRsfwFetchAndCacheStateMachine::CRsfwFetchAndCacheStateMachine()
       
    39     {
       
    40     }
       
    41 
       
    42 // ----------------------------------------------------------------------------
       
    43 // CRsfwFetchAndCacheStateMachine::CompleteRequestL
       
    44 // ----------------------------------------------------------------------------
       
    45 //
       
    46 CRsfwRfeStateMachine::TState*
       
    47 CRsfwFetchAndCacheStateMachine::CompleteRequestL(TInt aError) 
       
    48     {    
       
    49     if (aError == KUpdateNotRequired) 
       
    50         {   // discard 
       
    51         aError = KErrNone;
       
    52         }
       
    53     
       
    54     iDirEnts.ResetAndDestroy();
       
    55     // last byte that was actually fetched, may be more than was requested
       
    56     TRfeFetchOutArgs* outArgs = static_cast<TRfeFetchOutArgs*>(iOutArgs);
       
    57     outArgs->iLastByte = iLastByte;
       
    58     CompleteAndDestroyState()->SetErrorCode(aError);  
       
    59     
       
    60     // remove the fetching directory wait note
       
    61     if (Node()->Type() == KNodeTypeDir) 
       
    62         {
       
    63         DeleteWaitNoteL(ETrue);   
       
    64         }
       
    65 
       
    66     return CompleteAndDestroyState();
       
    67     } 
       
    68 
       
    69 // ----------------------------------------------------------------------------
       
    70 // CRsfwFetchAndCacheStateMachine::TFetchDataState::TFetchDataState
       
    71 // ----------------------------------------------------------------------------
       
    72 //
       
    73 CRsfwFetchAndCacheStateMachine::TFetchDataState::TFetchDataState(
       
    74     CRsfwFetchAndCacheStateMachine* aParent)
       
    75     : iOperation(aParent)
       
    76     {
       
    77     
       
    78     }
       
    79 
       
    80 // ----------------------------------------------------------------------------
       
    81 // CRsfwFetchAndCacheStateMachine::TFetchDataState::EnterL
       
    82 // ----------------------------------------------------------------------------
       
    83 //
       
    84 void CRsfwFetchAndCacheStateMachine::TFetchDataState::EnterL() 
       
    85     {
       
    86     TRfeFetchInArgs* inArgs =
       
    87         static_cast<TRfeFetchInArgs*>(iOperation->iInArgs);
       
    88     iOperation->iFirstByte = inArgs->iFirstByte;
       
    89     iOperation->iLastByte = inArgs->iLastByte;
       
    90     
       
    91     TInt recognizerLimit;
       
    92     TInt metadataLimit = 0;
       
    93     TCachingMode cachingMode;
       
    94 
       
    95     if (!(iOperation->Node()))
       
    96         {
       
    97         User::Leave(KErrNotFound);
       
    98         }
       
    99 
       
   100     // the cache file should be continuos
       
   101     // i.e. we always add to the end of the cache
       
   102     __ASSERT_DEBUG(iOperation->iFirstByte <= iOperation->Node()->iCachedSize, 
       
   103                    User::Panic(KRfeServer, ECacheInconsistency));
       
   104 
       
   105     cachingMode =
       
   106         iOperation->Node()->iFileTable->Volume()->iVolumeTable->iCachingMode;
       
   107     recognizerLimit =
       
   108         iOperation->
       
   109         Node()->iFileTable->Volume()->iVolumeTable->iRecognizerLimit;
       
   110    
       
   111         
       
   112     // for files, adjust lastByte based on the caching mode...
       
   113     if (iOperation->Node()->Type() == KNodeTypeFile) 
       
   114         {
       
   115         switch (cachingMode)
       
   116             {
       
   117         case EWholeFileCaching:
       
   118             if (iOperation->iLastByte < recognizerLimit) 
       
   119                 {
       
   120                 // iLastByte = 127
       
   121                 iOperation->iLastByte = recognizerLimit-1;
       
   122                 } 
       
   123             else 
       
   124                 {
       
   125                 // fetch the whole file
       
   126                 iOperation->iLastByte = iOperation->Node()->Size() -1;
       
   127                 }
       
   128         
       
   129             break;
       
   130         case EFullIfa:
       
   131             if (iOperation->iLastByte < recognizerLimit) 
       
   132                 {
       
   133                 // iLastByte = 127
       
   134                 iOperation->iLastByte = recognizerLimit-1;
       
   135                 } 
       
   136             // othewise no change
       
   137             break;
       
   138         case EMetadataIfa:
       
   139             // set metadataLimit based on the MIME-type
       
   140             if (iOperation->Node()->MimeType())
       
   141                 {
       
   142                 if ((*iOperation->Node()->MimeType()).Compare(
       
   143                         KMimeTypeJpeg) == 0)
       
   144                     {
       
   145                     metadataLimit =
       
   146                         iOperation->Node()->iFileTable->
       
   147                         Volume()->iVolumeTable->iImageJpegLimit;
       
   148                     }
       
   149 
       
   150                 if ((*iOperation->Node()->MimeType()).Compare(
       
   151                         KMimeTypeMpeg) == 0)
       
   152                     {
       
   153                     metadataLimit =
       
   154                         iOperation->Node()->iFileTable->
       
   155                         Volume()->iVolumeTable->iAudioMpegLimit;
       
   156                     }
       
   157                 
       
   158                 // set the lastbyte
       
   159                 if (iOperation->iLastByte < recognizerLimit) 
       
   160                     {
       
   161                     // iLastByte = 127
       
   162                     iOperation->iLastByte = recognizerLimit-1;
       
   163                     }
       
   164                 
       
   165                 else if (iOperation->iLastByte < metadataLimit)
       
   166                     {
       
   167                     // Fetch "enough" metadata to avoid
       
   168                     // unnecessary many round-trips...
       
   169                     iOperation->iLastByte = metadataLimit - 1;
       
   170                     }
       
   171                 else if (iOperation->iLastByte >= metadataLimit)
       
   172                     {
       
   173                     iOperation->iLastByte = iOperation->Node()->Size() - 1;
       
   174                     }
       
   175                 }
       
   176             else 
       
   177             	{
       
   178             	// MIME-type not recognized
       
   179             	if (iOperation->iLastByte < recognizerLimit) 
       
   180                 	{
       
   181                 	// iLastByte = 127
       
   182                 	iOperation->iLastByte = recognizerLimit-1;
       
   183                 	} 
       
   184             	else 
       
   185                 	{
       
   186                 	// fetch the whole file
       
   187                 	iOperation->iLastByte = iOperation->Node()->Size() -1;
       
   188                 	}
       
   189             	}
       
   190             }
       
   191         }
       
   192         
       
   193     // Now we know what actually will be fetched, write to debug...
       
   194     // and put up wait notes. 
       
   195     if (iOperation->Node()->Type() == KNodeTypeFile) 
       
   196         {
       
   197         
       
   198         DEBUGSTRING(("FETCH for a file with fid %d, bytes %d - %d",
       
   199                      iOperation->Node()->Fid().iNodeId,
       
   200                      iOperation->iFirstByte,
       
   201                      iOperation->iLastByte));
       
   202                              
       
   203         DEBUGSTRING16(("name is '%S",
       
   204                         iOperation->Node()->Name()));               
       
   205                      
       
   206         DEBUGSTRING(("full size is %d, cached size is %d",
       
   207                      iOperation->Node()->Size(),
       
   208                      iOperation->Node()->iCachedSize));   
       
   209         
       
   210       
       
   211         }
       
   212     else if (iOperation->Node()->Type() == KNodeTypeDir) 
       
   213         {
       
   214         
       
   215         DEBUGSTRING(("FETCH for a directory with fid %d, bytes %d - %d",
       
   216                      iOperation->Node()->Fid().iNodeId,
       
   217                      iOperation->iFirstByte,
       
   218                      iOperation->iLastByte));
       
   219                      
       
   220         DEBUGSTRING16(("name is '%S",
       
   221                         iOperation->Node()->Name()));             
       
   222         DEBUGSTRING(("full size is %d, cached size is %d",
       
   223                      iOperation->Node()->Size(),
       
   224                      iOperation->Node()->iCachedSize));   
       
   225                      
       
   226         }
       
   227 
       
   228     // whether cached data is used...
       
   229     // for files:
       
   230     if (((iOperation->Node()->Type() == KNodeTypeFile) &&
       
   231          (iOperation->FileEngine()->UseCachedData(*iOperation->Node())) &&
       
   232          ((iOperation->iLastByte <= iOperation->Node()->iCachedSize) ||
       
   233           iOperation->Node()->IsFullyCached())) ||
       
   234           
       
   235         // for directories:
       
   236         ((iOperation->Node()->Type() == KNodeTypeDir) &&
       
   237          (iOperation->FileEngine()->UseCachedAttributes(*iOperation->Node())) &&
       
   238          (iOperation->FileEngine()->UseCachedData(*iOperation->Node()))))
       
   239         {
       
   240         DEBUGSTRING(("using cached data"));
       
   241 
       
   242         if (iOperation->Node()->IsLocallyDirty())
       
   243             {
       
   244             DEBUGSTRING16(("directory is locally dirty"));
       
   245                             
       
   246             // This is a directory which has at least one kid
       
   247             // that has been cached or flushed since the last opening
       
   248             // of the directory.
       
   249             iOperation->FileEngine()->UpdateDirectoryContainerL(
       
   250                 *iOperation->Node());
       
   251             }
       
   252         // if the directory appeared to be childless add it to metadata LRU list
       
   253         if ( iOperation->Node()->Type() == KNodeTypeDir && 
       
   254              iOperation->Node()->Kids()->Count() == 0 )
       
   255             {
       
   256             iOperation->Volumes()->AddToMetadataLRUPriorityListL(iOperation->Node(), ECachePriorityNormal);
       
   257             }
       
   258             
       
   259         iOperation->iLastByte = iOperation->Node()->Size();
       
   260         iOperation->HandleRemoteAccessResponse(0, KUpdateNotRequired);
       
   261         }
       
   262     else
       
   263         {
       
   264         DEBUGSTRING(("fetching data from server"));
       
   265         // put up a wait note if getting a directory
       
   266         // (for files no global wait notes, as that would take a too long time)
       
   267          if (iOperation->Node()->Type() == KNodeTypeDir) 
       
   268         	{
       
   269         	// directory - pu up a 'Retrieving...' global wait note
       
   270         	iOperation->ShowWaitNoteL( ERemoteOpDirDownloading ); 
       
   271         	}
       
   272 
       
   273             
       
   274         if (iOperation->iLastByte > iOperation->Node()->Size())
       
   275             {   // Don't try to read beyond the end of the file...
       
   276             // Don't try to read beyond the end of the file...
       
   277             iOperation->iLastByte = iOperation->Node()->Size();    
       
   278             }  
       
   279             
       
   280         if (iOperation->iLastByte == 0)
       
   281             {
       
   282             iOperation->iLength = 0;
       
   283             // aLastByte == 0 indicates "no partial caching..."
       
   284             // i.e. range 0 - 0
       
   285             TUint transactionId = 
       
   286                 iOperation->FileEngine()->
       
   287                 FetchAndCacheL(*iOperation->Node(),
       
   288                                0 ,
       
   289                                &(iOperation->iLength),
       
   290                                &(iOperation->iDirEnts),
       
   291                                iOperation);
       
   292                 // transactionId = 0 means syncronous non-cancellable operation    
       
   293     		if (transactionId > 0) 
       
   294    				{
       
   295     			iOperation->iTransactionId = transactionId;
       
   296     			}
       
   297             }
       
   298         else 
       
   299             {
       
   300             iOperation->iLength =
       
   301                 iOperation->iLastByte - iOperation->Node()->iCachedSize + 1;
       
   302             // Continue filling the cache-file sequentially
       
   303             TUint transactionId = 
       
   304                 iOperation->FileEngine()->
       
   305                 FetchAndCacheL(*iOperation->Node(),
       
   306                                iOperation->Node()->iCachedSize,
       
   307                                &(iOperation->iLength),
       
   308                                &(iOperation->iDirEnts),
       
   309                                iOperation);
       
   310             // transactionId = 0 means syncronous non-cancellable operation    
       
   311     		if (transactionId > 0) 
       
   312    				{
       
   313     			iOperation->iTransactionId = transactionId;
       
   314     			}
       
   315             }
       
   316         }
       
   317     }
       
   318 
       
   319 // ----------------------------------------------------------------------------
       
   320 // CRsfwFetchAndCacheStateMachine::TFetchDataState::CompleteL
       
   321 // ----------------------------------------------------------------------------
       
   322 //
       
   323 CRsfwFetchAndCacheStateMachine::TState*
       
   324 CRsfwFetchAndCacheStateMachine::TFetchDataState::CompleteL()
       
   325     {   
       
   326     iOperation->iLastByte = iOperation->FileEngine()->AddToCacheL(
       
   327         *iOperation->Node(), 
       
   328         &iOperation->iDirEnts, 
       
   329         iOperation->FileEngine(),
       
   330         iOperation->Node()->iCachedSize +
       
   331         iOperation->iLength); 
       
   332     
       
   333     return iOperation->CompleteRequestL(KErrNone);
       
   334     }
       
   335   
       
   336 // ----------------------------------------------------------------------------
       
   337 // CRsfwFetchAndCacheStateMachine::TFetchDataState::ErrorL
       
   338 // ----------------------------------------------------------------------------
       
   339 //    
       
   340 CRsfwFetchAndCacheStateMachine::TState*
       
   341 CRsfwFetchAndCacheStateMachine::TFetchDataState::ErrorL(TInt aCode)
       
   342     {   
       
   343     // *********** from CRsfwFileEngine::GetDirectoryL()
       
   344     if (iOperation->Node()->Type() == KNodeTypeDir)
       
   345         {
       
   346         TInt err = aCode;
       
   347         if (aCode == KUpdateNotRequired)
       
   348             {
       
   349             err = KErrNone;
       
   350             }
       
   351         return iOperation->CompleteRequestL(err);
       
   352         }
       
   353         
       
   354     // file
       
   355     return iOperation->CompleteRequestL(aCode);   
       
   356     }
       
   357 
       
   358 // ----------------------------------------------------------------------------
       
   359 // CRsfwWaitNoteStateMachine::ErrorOnStateExit
       
   360 // ----------------------------------------------------------------------------
       
   361 //
       
   362 CRsfwRfeStateMachine::TState* CRsfwFetchAndCacheStateMachine::ErrorOnStateExit(TInt aError)
       
   363     {
       
   364     iDirEnts.ResetAndDestroy();
       
   365         // remove the fetching directory wait note
       
   366     if (Node()->Type() == KNodeTypeDir) 
       
   367         {
       
   368         TRAP_IGNORE(DeleteWaitNoteL(ETrue));   
       
   369         }
       
   370 
       
   371         
       
   372     return CRsfwRfeStateMachine::ErrorOnStateExit(aError);
       
   373     }