remotestoragefw/remotefilesystemplugin/src/rsfwfsfilecb.cpp
branchRCL_3
changeset 19 88ee4cf65e19
parent 16 87c71b25c937
child 20 1aa8c82cb4cb
equal deleted inserted replaced
16:87c71b25c937 19:88ee4cf65e19
     1 /*
       
     2 * Copyright (c) 2003-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:  File server interface class representing an open file.
       
    15 *                Allows to access a specific remote file.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "rsfwfsfilecb.h"
       
    22 #include "rsfwfsmountcb.h"
       
    23 
       
    24 // -----------------------------------------------------------------------------
       
    25 // CRsfwFsFileCB::CRsfwFsFileCB
       
    26 // C++ default constructor can NOT contain any code, that
       
    27 // might leave.
       
    28 // -----------------------------------------------------------------------------
       
    29 //
       
    30 CRsfwFsFileCB::CRsfwFsFileCB()
       
    31     {
       
    32     iLastFlushFailed = ETrue;
       
    33     iPartialWriteSupported = ETrue;
       
    34     }
       
    35  
       
    36 // Destructor
       
    37 CRsfwFsFileCB::~CRsfwFsFileCB()
       
    38     {   
       
    39     // close the cache file first so that RFE can move/delete it if upload fails
       
    40     iContFile.Close(); 
       
    41     TUint flags = 0;
       
    42     if (iFileName)
       
    43         {
       
    44         if (!iLastFlushFailed) 
       
    45             {
       
    46             // Now the container file has been changed,
       
    47             // tell Remote File Engine to update it on the servers
       
    48             // RSessionL() should not leave here as the remote session surely is created by now...
       
    49             if (iAtt & KEntryAttModified) 
       
    50                 {
       
    51                 flags |= ECloseModified;
       
    52          
       
    53                 // File was modified use, flush to write data to the server
       
    54                 // We write the whole file always, if flush was never called we cannot
       
    55                 // know whether partial write is supported.
       
    56                 TRAP_IGNORE(static_cast<CRsfwFsMountCB&>
       
    57                     (Mount()).RSessionL()->Flush(iThisFid, 0, iCachedSize, iCachedSize));
       
    58                 }
       
    59             else 
       
    60                 {
       
    61                 flags |= ECloseNotModified;
       
    62                 }
       
    63                 
       
    64             }
       
    65         else 
       
    66             {
       
    67             // flush was called and failed
       
    68             // do not try to flush again if the application closes the file
       
    69             // instead indicate this to the close state machine
       
    70             flags |= ECloseLastFlushFailed;
       
    71             }
       
    72         }
       
    73         
       
    74      // close will release the write lock if possible
       
    75      // and also allows user to save the file locally if flush failed
       
    76      TRAP_IGNORE(static_cast<CRsfwFsMountCB&>
       
    77               (Mount()).RSessionL()->CloseFile(iThisFid, flags));
       
    78     
       
    79     }
       
    80     
       
    81           
       
    82 // -----------------------------------------------------------------------------
       
    83 // CRsfwFsFileCB::RenameL
       
    84 // Renames the file with the full file name provided. Because the full name of 
       
    85 // the file includes the path, the function can also be used to move the file.
       
    86 //
       
    87 // It can be assumed that no other sub-session has access to the file:
       
    88 // i.e. the file has not been opened in EFileShareAny share mode.
       
    89 // It can also be assumed that the file has been opened for writing. 
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 void CRsfwFsFileCB::RenameL(
       
    93     const TDesC& aNewName)
       
    94     {
       
    95    	static_cast<CRsfwFsMountCB&>(Mount()).RenameFidL(iParentFid, *iFileName, aNewName);
       
    96    	delete iFileName;
       
    97    	iFileName = NULL;
       
    98    	iFileName = aNewName.AllocL();
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CRsfwFsFileCB::ReadL
       
   103 // Reads a specified number of bytes from the open file starting at
       
   104 // the specified position, and writes the result into a descriptor.
       
   105 //    
       
   106 // It can be assumed that aPos is inside the file and aLength > 0.
       
   107 // The file should only be read up to its end regardless of
       
   108 // the value of aPos + aLength. The number of bytes read should be stored
       
   109 // in aLength on return.
       
   110 //
       
   111 // Implemented by sending FETCH request to Remote File Engine for the
       
   112 // specified data and subsequently reading the data from the local cache file.
       
   113 // Reading the local cache file sets aLength.
       
   114 // Note that we want to keept the cache file continuos. If the requested data
       
   115 // starts behind the end of the current cache file, the function sends FETCHDATA
       
   116 // and Remote File Engine puts this data into a temp cache file valid only 
       
   117 // for the duration of this operation if the caching mode is something else than 
       
   118 // Whole File Caching
       
   119 // (other items were commented in a header).
       
   120 // -----------------------------------------------------------------------------
       
   121 //
       
   122 void CRsfwFsFileCB::ReadL(
       
   123     TInt aPos,
       
   124     TInt& aLength,
       
   125     const TAny* /*aDes*/,
       
   126     const RMessagePtr2& aMessage)
       
   127 
       
   128     { 
       
   129           
       
   130     if (iCachedSize == 0) 
       
   131         {
       
   132         // iCachedSize possibly not up-to-date...
       
   133         iContFile.Size(iCachedSize);
       
   134         }
       
   135     
       
   136     HBufC8* data = HBufC8::NewMaxLC(aLength);
       
   137     TPtr8 buf(data->Des());
       
   138 
       
   139     if (aPos > iCachedSize) 
       
   140         {
       
   141         // Depending on the caching mode this type of request may bypass the 
       
   142         // normal cache file.
       
   143         TBool useTempCache = EFalse;
       
   144         HBufC* tmpCacheFile = HBufC::NewLC(KMaxPath);
       
   145         TPtr tmpCache(tmpCacheFile->Des());
       
   146         User::LeaveIfError(static_cast<CRsfwFsMountCB&>
       
   147             (Mount()).RSessionL()->FetchData(iThisFid, 
       
   148             								aPos, 
       
   149             								aPos + aLength - 1, 
       
   150             								tmpCache, 
       
   151             								useTempCache));
       
   152         if (useTempCache) 
       
   153         	{
       
   154         	// use "temp" in the same directory instead of the cache file
       
   155         	RFile tempFile;
       
   156         	TParse parser;
       
   157         	parser.Set(tmpCache, NULL, NULL);
       
   158         	HBufC* tempPath = HBufC::NewLC(KMaxPath);
       
   159             TPtr tempptr = tempPath->Des();
       
   160             tempptr.Append(parser.DriveAndPath());
       
   161             tempptr.Append(KTempFileName);
       
   162         	User::LeaveIfError(tempFile.Open(*(RFs* )Dll::Tls(),
       
   163                                          tempptr, EFileRead));
       
   164             CleanupStack::PopAndDestroy(tempPath);                       
       
   165         	CleanupClosePushL(tempFile);
       
   166        		User::LeaveIfError(tempFile.Read(buf, aLength));
       
   167        		CleanupStack::PopAndDestroy(&tempFile);
       
   168         	}
       
   169         else 
       
   170         	{
       
   171         	// read from the normal container file (Whole File Caching mode).
       
   172         	iContFile.Size(iCachedSize);
       
   173         	User::LeaveIfError(iContFile.Read(aPos, buf, aLength));
       
   174         	}
       
   175         CleanupStack::PopAndDestroy(tmpCacheFile); // tempcacheFile
       
   176         }
       
   177     else if ((aPos + aLength) > iCachedSize)
       
   178         {
       
   179         User::LeaveIfError(static_cast<CRsfwFsMountCB&>
       
   180        		(Mount()).RSessionL()->Fetch(iThisFid, 
       
   181        									 aPos, 
       
   182        									 aPos + aLength - 1, 
       
   183        									 iCachedSize)); 
       
   184        									  									 
       
   185         User::LeaveIfError(iContFile.Read(aPos, buf, aLength));
       
   186         }
       
   187     else 
       
   188         {
       
   189         User::LeaveIfError(iContFile.Read(aPos, buf, aLength));
       
   190         }
       
   191         
       
   192     aMessage.WriteL(0, buf, 0);     
       
   193     CleanupStack::PopAndDestroy(data);
       
   194     if (iCachedSize == iSize) 
       
   195     	{
       
   196     	// clear the remote attribute if the whole file has now been fetched
       
   197     	iAtt &= ~KEntryAttRemote;
       
   198     	}
       
   199     }
       
   200     
       
   201 // -----------------------------------------------------------------------------
       
   202 // CRsfwFsFileCB::WriteL
       
   203 // Writes data to the open file. iModified and iSize are set by the file server 
       
   204 // after this function has completed successfully.
       
   205 //
       
   206 // It can be assumed that aPos is within the file range and aLength > 0.
       
   207 // When aPos + aLength is greater than the file size then the file should
       
   208 // be enlarged using SetSizeL(). The number of bytes written should be
       
   209 // returned through the argument aLength.
       
   210 //
       
   211 // Implemented by writing to the local cache file. First requests Remote File
       
   212 // Engine whether there is enough space in the cache to write the file (this
       
   213 // also calls SysUtil::DiskSpaceBelowCritical()). FE attempts to free space 
       
   214 // from the cache if necessary Implementation notice: writes a large file in 
       
   215 // chunks of 64K.
       
   216 //  
       
   217 // (other items were commented in a header).
       
   218 // -----------------------------------------------------------------------------
       
   219 //
       
   220 void CRsfwFsFileCB::WriteL(
       
   221     TInt aPos,
       
   222     TInt& aLength,
       
   223     const TAny* /*aDes*/,
       
   224     const RMessagePtr2& aMessage)
       
   225     {
       
   226     
       
   227     if (iCachedSize == 0) 
       
   228         {
       
   229         // iCachedSize possibly not up-to-date...
       
   230         iContFile.Size(iCachedSize);
       
   231         }
       
   232     
       
   233    // if flush was cancelled, but we come again to write, again set iLastFlushFailed to EFalse
       
   234     iLastFlushFailed = EFalse;
       
   235     
       
   236  	// We must first fetch the file to the local cache
       
   237  	// unless aPos = 0 and aLength => iSize 
       
   238  	// Note that if files are written to they cannot be partially cached
       
   239  	// as the whole file will be sent to the server and overwrites the old file.
       
   240  	// That is why we must ensure that the whole file is cached as soon as we
       
   241  	// get the first write.
       
   242  	// in subsequent writes iCachedSize will equal iSize
       
   243  	// This may eventually change if we start to use some kind of "delta-PUT".
       
   244  	if (!((aPos == 0) && (aLength >= iSize)) && iCachedSize < iSize && !iFetchedBeforeWriting)
       
   245  		{
       
   246  		User::LeaveIfError(static_cast<CRsfwFsMountCB&>
       
   247  				(Mount()).RSessionL()->Fetch(iThisFid, iCachedSize, iSize-1, iCachedSize));
       
   248  		iFetchedBeforeWriting = ETrue;
       
   249         }
       
   250 
       
   251     // make sure that a potential cache addition still fits into the cache
       
   252     TInt sizeToBeWritten = 0;
       
   253     
       
   254  	if (iSize > iCachedSize)
       
   255  	    {
       
   256  	    // when current Write is executed as a part of Copy operation
       
   257  	    // then iSize has been set to final size, even before any writing started
       
   258  	    sizeToBeWritten = iSize - iCachedSize;
       
   259  	    }
       
   260     else if (aPos + aLength > iCachedSize)
       
   261         {
       
   262         sizeToBeWritten = aPos + aLength - iCachedSize + iWrittenSize;
       
   263         }
       
   264              	 
       
   265  	TBool okToWrite;
       
   266  	User::LeaveIfError(static_cast<CRsfwFsMountCB&> 
       
   267  			(Mount()).RSessionL()->OkToWrite(iThisFid, 
       
   268  											sizeToBeWritten,
       
   269  											okToWrite));
       
   270  											 											
       
   271     if (!okToWrite) 
       
   272         {
       
   273         User::Leave(KErrDiskFull);
       
   274         }
       
   275     
       
   276     TInt anOffset = 0;
       
   277     HBufC8* data = HBufC8::NewMaxLC(aLength);
       
   278     TPtr8 buf(data->Des());
       
   279    
       
   280     aMessage.ReadL(0, buf, anOffset);
       
   281   
       
   282     User::LeaveIfError(iContFile.Write(aPos, *data, aLength));
       
   283     User::LeaveIfError(iContFile.Flush());
       
   284     CleanupStack::PopAndDestroy(data);
       
   285 
       
   286     // update iCachedSize and iWrittenSize if the container file size has grown
       
   287     if (aPos + aLength > iCachedSize)
       
   288         {
       
   289         iCachedSize = aPos + aLength;
       
   290         iWrittenSize = sizeToBeWritten;
       
   291         }
       
   292     
       
   293     // for flush() calls after this call:
       
   294     // set iFlushedSize to aPos, so that changes will be flushed
       
   295     if (iFlushedSize > aPos) 
       
   296         {
       
   297         iFlushedSize = aPos;
       
   298         }
       
   299     
       
   300     }
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // CRsfwFsFileCB::SetSizeL
       
   304 // Emply implementation, upper class already set iSize
       
   305 // (other items were commented in a header).
       
   306 // -----------------------------------------------------------------------------
       
   307 //
       
   308 void CRsfwFsFileCB::SetSizeL(
       
   309     TInt aSize)
       
   310     {
       
   311     iReportedSize = aSize;
       
   312     // we cannot set the actual size of the remote file, but also we do not
       
   313     // return KErrNotSupported as that would cause problems with CFileMan
       
   314     // and File Manager, which use SetSize() as an optimization to set the 
       
   315     // target file size in copy.
       
   316     // Propably calling setsize() on remote files when for example just writing
       
   317     // to an existing file would cause weird results. 
       
   318     }
       
   319 
       
   320 // -----------------------------------------------------------------------------
       
   321 // CRsfwFsFileCB::SetEntryL
       
   322 // Sets the attribute mask, iAtt, and the modified time of the file, iModified.
       
   323 // If aMask|aVal does not equal zero, then aMask should be OR'ed with iAtt,
       
   324 // whilst the inverse of aVal should be AND'ed with iAtt.
       
   325 // If the modified flag is set in aMask then iModified should be set to aTime.
       
   326 //
       
   327 // Implemented by calling CRsfwFsMountCB::SetEntryL().
       
   328 // (other items were commented in a header).
       
   329 // -----------------------------------------------------------------------------
       
   330 //
       
   331 void CRsfwFsFileCB::SetEntryL(
       
   332     const TTime& aTime,
       
   333     TUint aMask,
       
   334     TUint aVal)
       
   335     {
       
   336     static_cast<CRsfwFsMountCB&>(Mount()).SetEntryL(*iFileName,
       
   337                                                       aTime,
       
   338                                                       aMask,
       
   339                                                       aVal);                                             
       
   340     }
       
   341 
       
   342 // -----------------------------------------------------------------------------
       
   343 // CRsfwFsFileCB::FlushAllL
       
   344 // Flushes, to disk, all cached file data (e.g. attributes, modification time,
       
   345 // file size). The modified bit in the file attributes mask should be cleared if
       
   346 // the flush was successful.
       
   347 //
       
   348 // File Server calls this before reading directory entries, getting an entry
       
   349 // details for a directory entry etc. The idea is to make sure that all the
       
   350 // information to be retrieved is up to date. We don't need to implement this,
       
   351 // as our framework does not have buffers that could cause this problem. 
       
   352 //
       
   353 // (other items were commented in a header).
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 void CRsfwFsFileCB::FlushAllL()
       
   357     {
       
   358     }
       
   359 
       
   360 // -----------------------------------------------------------------------------
       
   361 // CRsfwFsFileCB::FlushDataL
       
   362 // Flushes, to disk, the cached information necessary for the integrity
       
   363 // of recently written data, such as the file size.
       
   364 //
       
   365 // Called by File Server as a result of RFile::Flush() (if the file has been 
       
   366 // modified). In our framework the file should be written to the server.
       
   367 // We should also clear KEntryAttModified here.
       
   368 //
       
   369 // (other items were commented in a header).
       
   370 //
       
   371 // -----------------------------------------------------------------------------
       
   372 //
       
   373 void CRsfwFsFileCB::FlushDataL()
       
   374     {
       
   375     TInt err = KErrNone;
       
   376     
       
   377     // close the container file to make sure all the local changes are cached
       
   378     iContFile.Close();
       
   379         
       
   380     // if flush was cancelled, but we come again to write, 
       
   381     // again set lastflushfailed to EFale	
       
   382     iLastFlushFailed = EFalse;
       
   383     
       
   384     // may attempt to write part of the file or whole file
       
   385     // also we may or may not know for sure whether the 
       
   386     // server supports partial write
       
   387 starttoflush:
       
   388     if (!iPartialWriteSupported) 
       
   389         {
       
   390         // If we know that partial write is not supported
       
   391         // AND the client has reported the full size of 
       
   392         // the file, do not really flush until all the data
       
   393         // has been written to the cache file.
       
   394         // *
       
   395         // If we do not know the total size flush whatever is cached
       
   396         if ((iCachedSize == iReportedSize)  || iReportedSize == 0)
       
   397             {
       
   398             err = static_cast<CRsfwFsMountCB&>
       
   399     			(Mount()).RSessionL()->Flush(iThisFid,
       
   400     			                            0,
       
   401     			                            iCachedSize, 
       
   402     			                            iCachedSize);  			                            
       
   403             }
       
   404          // else do not do anything yet, only when the whole file is in cache
       
   405         }
       
   406      else 
       
   407         {
       
   408         // we "still" assume that partial write is supported
       
   409         err = static_cast<CRsfwFsMountCB&>
       
   410     		(Mount()).RSessionL()->Flush(iThisFid,
       
   411     			                         iFlushedSize,
       
   412     			                         iCachedSize, 
       
   413     			                         iReportedSize);
       
   414         if (err == KErrNotSupported) 
       
   415             {
       
   416             err = KErrNone; // reset the error
       
   417             // flushing the file not supported
       
   418             // probably because the access protol plugin does not support partial write
       
   419             iPartialWriteSupported = EFalse;
       
   420             // apply the flush logic again
       
   421             // this time with the knowledge that the server does not support partial
       
   422             // write
       
   423             goto starttoflush;
       
   424             }
       
   425          else 
       
   426             {
       
   427             iAtt &= ~KEntryAttModified; // clear KEntryAttModified if flush worked
       
   428             }
       
   429     			                         
       
   430         }
       
   431         
       
   432     // re-open the container file    
       
   433      User::LeaveIfError(iContFile.Open(*(RFs* )Dll::Tls(),
       
   434                                       iCachePath,
       
   435                                       EFileWrite | EFileShareAny)); 
       
   436     
       
   437         
       
   438     // handling the results    
       
   439     if (err == KErrNone) 
       
   440         {
       
   441         // the operation was successful
       
   442         iFlushedSize = iCachedSize;			                            
       
   443         }
       
   444     else if (err != KErrNone)
       
   445         {
       
   446         iLastFlushFailed = ETrue;
       
   447         User::Leave(err);
       
   448         }
       
   449    
       
   450     }
       
   451   
       
   452 // -----------------------------------------------------------------------------
       
   453 // CRsfwFsFileCB::SetContainerFileL
       
   454 // Opens the container file.
       
   455 // Called in CRsfwFsMountCB when the file is opened.
       
   456 // Implementation notice: If this file is only opened for reading, it would
       
   457 // seem sensible to open  EFileRead|EFileShareAny here, but when Remote 
       
   458 // File Engine then tries to open EFileWrite|EFileShareAny it fails unless
       
   459 // EFileWrite is specified here also...
       
   460 //
       
   461 // (other items were commented in a header).
       
   462 // -----------------------------------------------------------------------------
       
   463 //
       
   464 void CRsfwFsFileCB::SetContainerFileL(
       
   465     const TDesC& aPath)
       
   466     {
       
   467     iCachePath = aPath;
       
   468     User::LeaveIfError(iContFile.Open(*(RFs* )Dll::Tls(),
       
   469                                       aPath,
       
   470                                       EFileWrite | EFileShareAny)); 
       
   471     }
       
   472 
       
   473 // End of File