webengine/osswebengine/cache/src/HttpCacheStreamHandler.cpp
changeset 10 a359256acfc6
parent 1 7c90e6132015
child 11 c8a366e56285
equal deleted inserted replaced
5:10e98eab6f85 10:a359256acfc6
    51 // CHttpCacheStreamHandler::CHttpCacheStreamHandler
    51 // CHttpCacheStreamHandler::CHttpCacheStreamHandler
    52 // C++ default constructor can NOT contain any code, that
    52 // C++ default constructor can NOT contain any code, that
    53 // might leave.
    53 // might leave.
    54 // -----------------------------------------------------------------------------
    54 // -----------------------------------------------------------------------------
    55 //
    55 //
    56 CHttpCacheStreamHandler::CHttpCacheStreamHandler()
    56 CHttpCacheStreamHandler::CHttpCacheStreamHandler(RFs& aRFs)
       
    57     : iRfs( aRFs )
    57     {
    58     {
    58     }
    59     }
    59 
    60 
    60 // -----------------------------------------------------------------------------
    61 // -----------------------------------------------------------------------------
    61 // CHttpCacheStreamHandler::ConstructL
    62 // CHttpCacheStreamHandler::ConstructL
    62 // Symbian 2nd phase constructor can leave.
    63 // Symbian 2nd phase constructor can leave.
    63 // -----------------------------------------------------------------------------
    64 // -----------------------------------------------------------------------------
    64 //
    65 //
    65 void CHttpCacheStreamHandler::ConstructL(
    66 void CHttpCacheStreamHandler::ConstructL(
    66     const TDesC& aDirectory,
    67     const TDesC& aDirectory,
    67     TInt aCriticalLevel )
    68     TInt aCriticalLevel)
    68     {
    69     {
    69     User::LeaveIfError( iRfs.Connect() );
       
    70     // set path for the entries
       
    71     iRfs.SetSessionPath( aDirectory );
       
    72     iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheActiveCount );
    70     iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheActiveCount );
    73     // get drive letter for sysutil
    71     // get drive letter for sysutil
    74     TParsePtrC pathParser( aDirectory );
    72     TParsePtrC pathParser( aDirectory );
    75     iDrive = pathParser.Drive();
    73     iDrive = pathParser.Drive();
    76     iCriticalLevel = aCriticalLevel;
    74     iCriticalLevel = aCriticalLevel;
    81 // Two-phased constructor.
    79 // Two-phased constructor.
    82 // -----------------------------------------------------------------------------
    80 // -----------------------------------------------------------------------------
    83 //
    81 //
    84 CHttpCacheStreamHandler* CHttpCacheStreamHandler::NewL(
    82 CHttpCacheStreamHandler* CHttpCacheStreamHandler::NewL(
    85     const TDesC& aDirectory ,
    83     const TDesC& aDirectory ,
    86     TInt aCriticalLevel)
    84     TInt aCriticalLevel,
    87     {
    85     RFs& aRFs)
    88     CHttpCacheStreamHandler* self = new( ELeave ) CHttpCacheStreamHandler();
    86     {
       
    87     CHttpCacheStreamHandler* self = new( ELeave ) CHttpCacheStreamHandler(aRFs);
    89 
    88 
    90     CleanupStack::PushL( self );
    89     CleanupStack::PushL( self );
    91     self->ConstructL( aDirectory , aCriticalLevel);
    90     self->ConstructL( aDirectory , aCriticalLevel);
    92     CleanupStack::Pop();
    91     CleanupStack::Pop();
    93 
    92 
   103     if ( iActiveEntries )
   102     if ( iActiveEntries )
   104         {
   103         {
   105         iActiveEntries->ResetAndDestroy();
   104         iActiveEntries->ResetAndDestroy();
   106         }
   105         }
   107     delete iActiveEntries;
   106     delete iActiveEntries;
   108 
   107     }
   109     iRfs.Close();
   108 
   110     }
   109 // -----------------------------------------------------------------------------
   111 
   110 // CHttpCacheStreamHandler::InitialiseCacheEntryL
   112 // -----------------------------------------------------------------------------
   111 // -----------------------------------------------------------------------------
   113 // CHttpCacheStreamHandler::AttachL
   112 //
   114 //
   113 void CHttpCacheStreamHandler::InitialiseCacheEntryL(CHttpCacheEntry& aCacheEntry)
   115 // -----------------------------------------------------------------------------
   114     {
   116 //
   115     // create a filename for the cache entry.
   117 TBool CHttpCacheStreamHandler::AttachL( CHttpCacheEntry& aCacheEntry )
   116     TPath sessionPath;
   118     {
   117     User::LeaveIfError( iRfs.SessionPath( sessionPath ) );
   119 #ifdef __CACHELOG__
   118 
   120     // check for duplicates
   119     // Given the full URL, generates a fully qualified path for saving the HTTP response
   121     for ( TInt i = 0; i < iActiveEntries->Count(); i++ )
   120     HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( aCacheEntry.Url(), sessionPath );
   122         {
   121     TPtrC bodyFileNamePtr( *bodyFileName );
   123         __ASSERT_DEBUG( iActiveEntries->At( i ) != &aCacheEntry,
   122     aCacheEntry.SetFileNameL(bodyFileNamePtr);
   124         User::Panic( _L("cacheStreamHandler Panic"), KErrCorrupt )  );
   123 
   125         }
   124     CleanupStack::PopAndDestroy(bodyFileName);
   126 #endif // __CACHELOG__
   125 
   127    
   126     // any more one-time initialisation to go here.
   128     TBool cacheFilesOpened( EFalse );
   127     aCacheEntry.SetState( CHttpCacheEntry::ECacheInitialized );
   129 
   128 
   130     if ( aCacheEntry.CacheFilesOpened() )
   129     // since this only happens one time, we can check if we have files left over with no index entry
   131         {
   130     // we're too late to reuse any information stored in there, so lets just delete them.  This might prevent any
   132         // Cache files already opened, no need to reopen
   131     // problems later down the line..
   133         cacheFilesOpened = ETrue;
   132     iRfs.Delete(aCacheEntry.Filename());
   134         }
   133     // header filename
   135     else if ( aCacheEntry.State() == CHttpCacheEntry::ECacheUninitialized )
   134     TFileName headerFileName;
   136         {
   135     HttpCacheUtil::GetHeaderFileName( aCacheEntry.Filename(), headerFileName );
   137         // Create new cache files, they don't already exist
   136     iRfs.Delete(headerFileName);
   138         cacheFilesOpened = CreateNewFilesL( aCacheEntry );
   137     }
   139         }
   138 
   140     else
   139 // -----------------------------------------------------------------------------
   141         {
   140 // CHttpCacheStreamHandler::Erase
   142         // Open existing cache files
   141 //
   143         cacheFilesOpened = OpenCacheFiles( aCacheEntry );
   142 // -----------------------------------------------------------------------------
   144         }
   143 //
   145     
   144 void CHttpCacheStreamHandler::Erase( CHttpCacheEntry& aCacheEntry )
   146     if ( cacheFilesOpened )
       
   147         {
       
   148         // Add to our active array, if not already there
       
   149         TInt index( -1 );
       
   150         FindCacheEntryIndex( aCacheEntry, &index );
       
   151         if ( index == -1 )
       
   152             {
       
   153             iActiveEntries->AppendL( &aCacheEntry );
       
   154             }
       
   155         }
       
   156 
       
   157     aCacheEntry.SetCacheFilesOpened( cacheFilesOpened );
       
   158 
       
   159     // Return ETrue, if files opened and attached
       
   160     return cacheFilesOpened;
       
   161     }
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CHttpCacheStreamHandler::Detach
       
   165 //
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 void CHttpCacheStreamHandler::Detach( CHttpCacheEntry& aCacheEntry )
       
   169     {
       
   170     // Close the files, this will commit changes
       
   171     if ( aCacheEntry.CacheFilesOpened() )
       
   172         {
       
   173         aCacheEntry.BodyFile().Close();
       
   174         aCacheEntry.HeaderFile().Close();
       
   175         aCacheEntry.SetCacheFilesOpened( EFalse );
       
   176         }
       
   177 
       
   178     // Delete from our active array
       
   179     TInt index( -1 );
       
   180     FindCacheEntryIndex( (const CHttpCacheEntry&)aCacheEntry, &index );
       
   181     if ( index >= 0 )
       
   182         {
       
   183         iActiveEntries->Delete( index );
       
   184         }
       
   185     }
       
   186 
       
   187 // -----------------------------------------------------------------------------
       
   188 // CHttpCacheStreamHandler::EraseCacheFile
       
   189 //
       
   190 // -----------------------------------------------------------------------------
       
   191 //
       
   192 void CHttpCacheStreamHandler::EraseCacheFile( CHttpCacheEntry& aCacheEntry )
       
   193     {
   145     {
   194     HttpCacheUtil::WriteUrlToLog( 0, _L( "CHttpCacheStreamHandler::Erase - erase files associated with" ), aCacheEntry.Url() );
   146     HttpCacheUtil::WriteUrlToLog( 0, _L( "CHttpCacheStreamHandler::Erase - erase files associated with" ), aCacheEntry.Url() );
   195 
   147 
   196     aCacheEntry.HeaderFile().Close();
   148     // just in case it's busy being written out...
   197     aCacheEntry.BodyFile().Close();
   149     aCacheEntry.CancelBodyWrite();
   198     aCacheEntry.SetCacheFilesOpened( EFalse );
   150 
   199 
   151     // Delete body file
   200     // Get body filename
   152 #ifndef __CACHELOG__
   201     TFileName bodyFileName = aCacheEntry.Filename();
   153     iRfs.Delete( aCacheEntry.Filename() );
   202 
   154 #else
   203     // Get header filename
       
   204     TFileName headerFileName;
       
   205     HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
       
   206 
       
   207     TInt statusBody( KErrNotFound );
   155     TInt statusBody( KErrNotFound );
   208     statusBody = iRfs.Delete( bodyFileName );
   156     statusBody = iRfs.Delete( aCacheEntry.Filename() );
   209 
   157 #endif
   210     TInt statusHeader( KErrNotFound );
       
   211     statusHeader = iRfs.Delete( headerFileName );
       
   212 
       
   213     // Adjust the size
   158     // Adjust the size
   214     iContentSize -= aCacheEntry.BodySize();
   159     iContentSize -= aCacheEntry.BodySize();
   215     iContentSize -= aCacheEntry.HeaderSize();
   160     iContentSize -= aCacheEntry.HeaderSize();
   216 
   161 
   217 #ifdef __CACHELOG__
   162 #ifdef __CACHELOG__
   218     if ( statusBody != KErrNone ) {
   163     if ( statusBody == KErrNone )
       
   164         {
   219         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
   165         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
   220                                            _L("CCHttpCacheStreamEntry::Erase - ERROR bodyFile delete"),
   166                                            _L("CHttpCacheStreamHandler::Erase - SUCCESS bodyFile delete"),
       
   167                                            aCacheEntry.Filename(),
       
   168                                            aCacheEntry.Url(),
       
   169                                            aCacheEntry.BodySize(),
       
   170                                            ELogEntrySize );
       
   171         }
       
   172     else if ( statusBody == KErrNotFound )
       
   173         {
       
   174         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   175                                            _L("CHttpCacheStreamHandler::Erase - CHECK bodyFile not found."),
   221                                            aCacheEntry.Filename(),
   176                                            aCacheEntry.Filename(),
   222                                            aCacheEntry.Url(),
   177                                            aCacheEntry.Url(),
   223                                            statusBody,
   178                                            statusBody,
   224                                            ELogFileErrorCode );
   179                                            ELogFileErrorCode );
   225         }
   180         }
   226     else {
   181     else
   227         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
   182         {
   228                                            _L("CCHttpCacheStreamEntry::Erase - SUCCESS bodyFile delete"),
   183     HttpCacheUtil::WriteLogFilenameAndUrl( 0,
   229                                            aCacheEntry.Filename(),
   184                                        _L("CHttpCacheStreamHandler::Erase - ERROR bodyFile delete"),
   230                                            aCacheEntry.Url(),
   185                                        aCacheEntry.Filename(),
   231                                            aCacheEntry.BodySize(),
   186                                        aCacheEntry.Url(),
   232                                            ELogEntrySize );
   187                                        statusBody,
   233         }
   188                                        ELogFileErrorCode );
   234     if ( statusHeader != KErrNone ) {
       
   235         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   236                                            _L("CCHttpCacheStreamEntry::Erase - ERROR headerFile delete"),
       
   237                                            aCacheEntry.Filename(),
       
   238                                            aCacheEntry.Url(),
       
   239                                            statusHeader,
       
   240                                            ELogFileErrorCode );
       
   241         }
       
   242     else {
       
   243         HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   244                                            _L("CCHttpCacheStreamEntry::Erase - SUCCESS headerFile delete"),
       
   245                                            aCacheEntry.Filename(),
       
   246                                            aCacheEntry.Url(),
       
   247                                            aCacheEntry.BodySize(),
       
   248                                            ELogEntrySize );
       
   249         }
   189         }
   250 #endif //__CACHELOG__
   190 #endif //__CACHELOG__
   251 
       
   252     }
   191     }
   253 
   192 
   254 // -----------------------------------------------------------------------------
   193 // -----------------------------------------------------------------------------
   255 // CHttpCacheStreamHandler::HeadersL
   194 // CHttpCacheStreamHandler::HeadersL
   256 //
   195 //
   257 // -----------------------------------------------------------------------------
   196 // -----------------------------------------------------------------------------
   258 //
   197 //
   259 HBufC8* CHttpCacheStreamHandler::HeadersL( CHttpCacheEntry& aCacheEntry )
   198 HBufC8* CHttpCacheStreamHandler::HeadersL( CHttpCacheEntry& aCacheEntry )
   260     {
   199     {
   261     HBufC8* headerStr = NULL;
   200     return aCacheEntry.HeaderData().AllocL();
   262     TInt headerLen( 0 );
       
   263     TInt err( KErrNone );
       
   264 
       
   265     if ( !aCacheEntry.CacheFilesOpened() )
       
   266         {
       
   267         OpenCacheFiles( aCacheEntry );
       
   268         }
       
   269 
       
   270     err = aCacheEntry.HeaderFile().Size( headerLen );
       
   271     if ( err == KErrNone && headerLen > 0 )
       
   272         {
       
   273         headerStr = HBufC8::NewL( headerLen );
       
   274         TPtr8 ptr( headerStr->Des() );
       
   275         // read headers
       
   276         aCacheEntry.HeaderFile().Read( 0, ptr, headerLen );
       
   277         }
       
   278 
       
   279     return headerStr;
       
   280     }
   201     }
   281 
   202 
   282 // -----------------------------------------------------------------------------
   203 // -----------------------------------------------------------------------------
   283 // CHttpCacheStreamHandler::NextChunkL
   204 // CHttpCacheStreamHandler::NextChunkL
   284 //
   205 //
   286 //
   207 //
   287 HBufC8* CHttpCacheStreamHandler::NextChunkL(
   208 HBufC8* CHttpCacheStreamHandler::NextChunkL(
   288     CHttpCacheEntry& aCacheEntry,
   209     CHttpCacheEntry& aCacheEntry,
   289     TBool& aLastChunk )
   210     TBool& aLastChunk )
   290     {
   211     {
   291     HBufC8* bodyStr = NULL;
   212     HBufC8 *bodyStr = NULL;
   292     // Read whole body
   213 
   293     TInt size( 0 );
   214     if ( !aCacheEntry.BodyDataCached() && OpenBodyFile(aCacheEntry) )
   294     TInt sizeErr( KErrNone );
   215         {
   295 
   216         CleanupClosePushL( aCacheEntry.BodyFile() );
   296     if ( !aCacheEntry.CacheFilesOpened() )
   217 
   297         {
   218         // read body
   298         OpenCacheFiles( aCacheEntry );
   219         TInt size;
   299         }
   220         TInt err( aCacheEntry.BodyFile().Size( size ) );
   300 
   221         if ( err == KErrNone && size > 0 )
   301     sizeErr = aCacheEntry.BodyFile().Size( size );
   222             {
   302     if ( sizeErr == KErrNone && size > 0 )
   223             bodyStr = HBufC8::NewL( size );
   303         {
   224             TPtr8 ptr( bodyStr->Des() );
       
   225             //
       
   226             err = aCacheEntry.BodyFile().Read( ptr, size );
       
   227 #ifdef __CACHELOG__
       
   228             if ( err != KErrNone ) {
       
   229                 HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   230                                                    _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
       
   231                                                    aCacheEntry.Filename(),
       
   232                                                    aCacheEntry.Url(),
       
   233                                                    err,
       
   234                                                    ELogFileErrorCode );
       
   235                 }
       
   236             else {
       
   237                 HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   238                                                    _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
       
   239                                                    aCacheEntry.Filename(),
       
   240                                                    aCacheEntry.Url(),
       
   241                                                    ptr.Length(),
       
   242                                                    ELogEntrySize );
       
   243                 }
       
   244 #endif  // __CACHELOG__
       
   245             }
       
   246         // Close body file
       
   247         CleanupStack::PopAndDestroy(1);
       
   248         }
       
   249     else
       
   250         {
       
   251         // reuse stored data if we have any.
       
   252         CSegmentedHeapBuffer& buffer = aCacheEntry.BodyData();
       
   253         TInt size = buffer.Length();
   304         bodyStr = HBufC8::NewL( size );
   254         bodyStr = HBufC8::NewL( size );
   305         TPtr8 ptr( bodyStr->Des() );
   255         TPtr8 ptr(bodyStr->Des());
   306 
   256 
   307         TInt readErr( KErrNone );
   257         TInt readSegment = 0;
   308         readErr = aCacheEntry.BodyFile().Read( ptr, size );
   258         TInt count = buffer.Count();
   309 
   259         while(readSegment < count)
   310 #ifdef __CACHELOG__
   260             {
   311         if ( readErr != KErrNone ) {
   261             TPtrC8 source = buffer.GetSegmentData(readSegment);
   312             HttpCacheUtil::WriteLogFilenameAndUrl( 0,
   262             ptr.Append(source);
   313                                                _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
   263             }
   314                                                aCacheEntry.Filename(),
       
   315                                                aCacheEntry.Url(),
       
   316                                                readErr,
       
   317                                                ELogFileErrorCode );
       
   318             }
       
   319         else {
       
   320             HttpCacheUtil::WriteLogFilenameAndUrl( 0,
       
   321                                                _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
       
   322                                                aCacheEntry.Filename(),
       
   323                                                aCacheEntry.Url(),
       
   324                                                ptr.Length(),
       
   325                                                ELogEntrySize );
       
   326             }
       
   327 #endif  // __CACHELOG__
       
   328 
       
   329         }
   264         }
   330     aLastChunk = ETrue;
   265     aLastChunk = ETrue;
   331 
       
   332     return bodyStr;
   266     return bodyStr;
   333     }
   267     }
   334 
   268 
   335 // -----------------------------------------------------------------------------
   269 // -----------------------------------------------------------------------------
   336 // CHttpCacheStreamHandler::SaveHeaders
   270 // CHttpCacheStreamHandler::SaveHeaders
   340 TBool CHttpCacheStreamHandler::SaveHeaders(
   274 TBool CHttpCacheStreamHandler::SaveHeaders(
   341     CHttpCacheEntry& aCacheEntry,
   275     CHttpCacheEntry& aCacheEntry,
   342     const TDesC8& aHeaderStr )
   276     const TDesC8& aHeaderStr )
   343     {
   277     {
   344     TBool headerSaved( EFalse );
   278     TBool headerSaved( EFalse );
   345 
   279     TInt headerLen = aHeaderStr.Length();
   346     if ( !aCacheEntry.CacheFilesOpened() )
   280 
   347         {
   281     if ( headerLen && IsDiskSpaceAvailable( headerLen ) )
   348         OpenCacheFiles( aCacheEntry );
   282         {
   349         }
   283         TRAPD(err, aCacheEntry.CreateHeaderBufferL(aHeaderStr));
   350 
   284         if ( err == KErrNone )
   351     if ( aHeaderStr.Length() && IsDiskSpaceAvailable( aHeaderStr.Length() ) )
   285             {
   352         {
   286             iContentSize += aCacheEntry.HeaderSize();
   353         // We have space on disk, save headers. Don't force a flush, as the
       
   354         // File Server takes care of write and read consistency.
       
   355         TInt writeErr = aCacheEntry.HeaderFile().Write( aHeaderStr );
       
   356 
       
   357         if ( writeErr == KErrNone )
       
   358             {
       
   359             aCacheEntry.SetHeaderSize( aHeaderStr.Length() );
       
   360             iContentSize += aHeaderStr.Length();
       
   361             headerSaved = ETrue;
   287             headerSaved = ETrue;
   362             }
   288             }
   363         }
   289         }
   364 
       
   365     return headerSaved;
   290     return headerSaved;
   366     }
   291     }
   367 
   292 
   368 // -----------------------------------------------------------------------------
   293 // -----------------------------------------------------------------------------
   369 // CHttpCacheStreamHandler::RemoveHeaders
   294 // CHttpCacheStreamHandler::RemoveHeaders
   372 //
   297 //
   373 void CHttpCacheStreamHandler::RemoveHeaders( CHttpCacheEntry& aCacheEntry )
   298 void CHttpCacheStreamHandler::RemoveHeaders( CHttpCacheEntry& aCacheEntry )
   374     {
   299     {
   375     iContentSize -= aCacheEntry.HeaderSize();
   300     iContentSize -= aCacheEntry.HeaderSize();
   376 
   301 
   377     // Destroy data
   302     TRAP_IGNORE( aCacheEntry.CreateHeaderBufferL( 0 ) );
   378     aCacheEntry.HeaderFile().SetSize( 0 );
       
   379     aCacheEntry.SetHeaderSize( 0 );
       
   380     }
   303     }
   381 
   304 
   382 // -----------------------------------------------------------------------------
   305 // -----------------------------------------------------------------------------
   383 // CHttpCacheStreamHandler::SaveBodyData
   306 // CHttpCacheStreamHandler::SaveBodyData
   384 //
   307 //
   386 //
   309 //
   387 TBool CHttpCacheStreamHandler::SaveBodyData(
   310 TBool CHttpCacheStreamHandler::SaveBodyData(
   388     CHttpCacheEntry& aCacheEntry,
   311     CHttpCacheEntry& aCacheEntry,
   389     const TDesC8& aBodyStr )
   312     const TDesC8& aBodyStr )
   390     {
   313     {
   391     TInt bodySaved( EFalse );
   314     TInt bodySaved( KErrNone );
   392     TInt newBodyLength( aBodyStr.Length() );
   315     TInt newBodyLength( aBodyStr.Length() );
   393     TPtr8 buffer( aCacheEntry.CacheBuffer() );
   316 
   394 
   317     if ( newBodyLength )
   395     if ( newBodyLength && buffer.MaxLength() )
   318         {
   396         {
   319         TInt remainder = 0;
   397         // Calculate if we have enough space in the buffer for incoming body
   320         CSegmentedHeapBuffer& cacheBuffer = aCacheEntry.BodyData();
   398         if ( buffer.Length() + newBodyLength > buffer.MaxLength() )
   321 
   399             {
   322         // Add data to the buffer
   400             // Incoming data is too big for the buffer
   323         TRAPD( err, cacheBuffer.AppendL(remainder, aBodyStr) );
   401             HBufC8* overflowBuffer = NULL;
   324         if ( err == KErrNone )
   402             TInt bufferSpaceLeft( -1 );
   325             {
   403             TPtrC8 writePtr;
   326             aCacheEntry.SetBodyDataCached(ETrue);
   404 
   327             }
   405             if ( buffer.Length() == 0 )
   328         else
       
   329             {
       
   330             // We failed to allocate memory to store the new data in the current buffer.
       
   331             // Check to see if it's possible to write it to disk instead.
       
   332             TBool bodyFileCreated = CreateNewBodyFile( aCacheEntry );
       
   333             if ( !bodyFileCreated )
   406                 {
   334                 {
   407                 // Buffer is empty and the body is bigger than the buffer,
   335                 return EFalse;
   408                 // just take all of the incoming data
   336                 }
   409                 writePtr.Set( aBodyStr );
   337 
       
   338             TBool enoughSpace;
       
   339             enoughSpace = IsDiskSpaceAvailable( cacheBuffer.Length() + remainder );
       
   340             if ( enoughSpace )
       
   341                 {
       
   342                 // In this case, we have not been able to store all the data.
       
   343                 // if there is enough space on disk to write everything we know
       
   344                 // about now, we will flush the current buffer out synchronously.
       
   345                 TInt block=0;
       
   346                 TInt count = cacheBuffer.Count();
       
   347                 while ( bodySaved == KErrNone && count > block )
       
   348                     {
       
   349                     TPtrC8 buf = cacheBuffer.GetSegmentData(block);
       
   350                     bodySaved = aCacheEntry.BodyFile().Write(buf);
       
   351                     }
   410                 }
   352                 }
   411             else
   353             else
   412                 {
   354                 {
   413                 // We have some data in buffer, how much space do we have left
   355                 // disk too full, drop the cache data
   414                 bufferSpaceLeft = buffer.MaxLength() - buffer.Length();
   356                 bodySaved = KErrDiskFull;
   415                 
   357                 // reset buffers
   416                 if ( newBodyLength - bufferSpaceLeft > buffer.MaxLength() )
   358                 cacheBuffer.Reset();
   417                     {
       
   418                     // Not enough space, so lets put the buffer and the new
       
   419                     // body together and write it in one go.
       
   420                     overflowBuffer = HBufC8::New( buffer.Length() + newBodyLength );
       
   421                     if ( !overflowBuffer )
       
   422                         {
       
   423                         return EFalse;
       
   424                         }
       
   425 
       
   426                     TPtr8 overflowPtr( overflowBuffer->Des() );
       
   427                     overflowPtr.Copy( buffer );
       
   428                     overflowPtr.Append( aBodyStr );
       
   429                     writePtr.Set( overflowBuffer->Des() );
       
   430 
       
   431                     // empty buffer
       
   432                     buffer.Zero();
       
   433                     // no leftover left
       
   434                     bufferSpaceLeft = -1;
       
   435                     }
       
   436                 else
       
   437                     {
       
   438                     // Copy what we have enough space for
       
   439                     buffer.Append( aBodyStr.Left( bufferSpaceLeft ) );
       
   440                     writePtr.Set( buffer );
       
   441                     }
       
   442                 }
   359                 }
   443 
   360 
   444             // Write to the disk, if we have disk space
   361             if ( bodySaved == KErrNone )
   445             TInt writeErr( KErrNone );
       
   446             if ( IsDiskSpaceAvailable( writePtr.Length() ) )
       
   447                 {
   362                 {
   448 
   363                 // We have completed writing out the cached data, now
   449                 if ( !aCacheEntry.CacheFilesOpened() )
   364                 // try to save the new data if we haven't run out of disk space.
   450                     {
   365                 bodySaved = aCacheEntry.BodyFile().Write(aBodyStr.Right(remainder));
   451                     OpenCacheFiles( aCacheEntry );
       
   452                     }
       
   453 
       
   454                 // We have enough disk space, save body
       
   455                 TInt writeErr = aCacheEntry.BodyFile().Write( writePtr );
       
   456                 bodySaved = ETrue;
       
   457                 }
   366                 }
   458             else
   367             aCacheEntry.SetBodyDataCached(EFalse);
   459                 {
   368             aCacheEntry.BodyFile().Close();
   460                 // We don't have enough disk space, clean up 
   369             }
   461                 bodySaved = EFalse;
   370         // update size information
   462                 buffer.Zero();
       
   463                 }
       
   464 
       
   465             if ( writeErr == KErrNone && bufferSpaceLeft >= 0 )
       
   466                 {
       
   467                 // Copy what we can of the leftover in to the buffer
       
   468                 buffer.Copy( aBodyStr.Mid( bufferSpaceLeft ) );
       
   469                 }
       
   470             delete overflowBuffer;
       
   471             }
       
   472         else
       
   473             {
       
   474             // We have enough space in buffer, add and wait for next body
       
   475             // before writing to file
       
   476             buffer.Append( aBodyStr );
       
   477             bodySaved = ETrue;
       
   478             }
       
   479 
       
   480         // Body saved, update state
       
   481         aCacheEntry.SetBodySize( aCacheEntry.BodySize() + newBodyLength );
   371         aCacheEntry.SetBodySize( aCacheEntry.BodySize() + newBodyLength );
   482         iContentSize += aBodyStr.Length();
   372         iContentSize += aBodyStr.Length();
   483         }
   373         }
   484 
   374     return ( bodySaved == KErrNone );
   485     return bodySaved;
       
   486     }
   375     }
   487 
   376 
   488 // -----------------------------------------------------------------------------
   377 // -----------------------------------------------------------------------------
   489 // CHttpCacheStreamHandler::RemoveBodyData
   378 // CHttpCacheStreamHandler::RemoveBodyData
   490 //
   379 //
   499                                            aCacheEntry.Url(),
   388                                            aCacheEntry.Url(),
   500                                            aCacheEntry.BodySize(),
   389                                            aCacheEntry.BodySize(),
   501                                            ELogEntrySize );
   390                                            ELogEntrySize );
   502 #endif
   391 #endif
   503 
   392 
   504     // Remove data 
   393     // Remove data
   505     iContentSize -= aCacheEntry.BodySize();
   394     iContentSize -= aCacheEntry.BodySize();
   506     aCacheEntry.SetBodySize( 0 );
   395     aCacheEntry.SetBodySize( 0 );
   507     aCacheEntry.CacheBuffer().Zero();
   396     aCacheEntry.BodyData().Reset();
   508     aCacheEntry.BodyFile().SetSize( 0 );
   397     if ( OpenBodyFile(aCacheEntry) )
       
   398         {
       
   399         aCacheEntry.BodyFile().SetSize( 0 );
       
   400         aCacheEntry.BodyFile().Close();
       
   401         }
   509     }
   402     }
   510 
   403 
   511 // -----------------------------------------------------------------------------
   404 // -----------------------------------------------------------------------------
   512 // CHttpCacheStreamHandler::Flush
   405 // CHttpCacheStreamHandler::Flush
   513 //
   406 //
   514 // -----------------------------------------------------------------------------
   407 // -----------------------------------------------------------------------------
   515 //
   408 //
   516 TBool CHttpCacheStreamHandler::Flush( CHttpCacheEntry& aCacheEntry )
   409 TBool CHttpCacheStreamHandler::Flush( CHttpCacheEntry& aCacheEntry )
   517     {
   410     {
   518     TBool saved( EFalse );
   411     TInt err( KErrNone );
   519     TInt writeErr( KErrGeneral );
   412     TBool bFlushed( EFalse );
   520     TInt cacheBufferLen( aCacheEntry.CacheBuffer().Length() );
   413 
   521 
   414     TRAP( err, bFlushed = FlushL( aCacheEntry ) );
   522     if ( cacheBufferLen && IsDiskSpaceAvailable( cacheBufferLen ) )
   415     if ( err || !bFlushed )
   523         {
   416         {
   524         // We have enough space, save cache buffer
   417         return EFalse;
   525         TPtr8 bufferPtr( aCacheEntry.CacheBuffer() );
   418         }
   526         if ( bufferPtr.Length() )
   419 
   527             {
   420     return ETrue;
   528             if ( !aCacheEntry.CacheFilesOpened() )
   421     }
   529                 {
   422 
   530                 OpenCacheFiles( aCacheEntry );
   423 // -----------------------------------------------------------------------------
   531                 }
   424 // CHttpCacheStreamHandler::FlushL
   532 
   425 //
   533             writeErr = aCacheEntry.BodyFile().Write( bufferPtr );
   426 // -----------------------------------------------------------------------------
   534             if ( writeErr == KErrNone )
   427 //
   535                 {
   428 TBool CHttpCacheStreamHandler::FlushL( CHttpCacheEntry& aCacheEntry )
   536                 saved = ETrue;
   429     {
   537                 }
   430     TInt saveOk( KErrNone );
   538             }
   431 
   539 
   432 #ifdef __CACHELOG__
   540         // Clear the buffer
   433     HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:  >>StreamHander::Flush object %08x"), &aCacheEntry );
   541         bufferPtr.Zero();
   434 #endif
   542         }
   435     CSegmentedHeapBuffer& cacheBuffer = aCacheEntry.BodyData();
   543 
   436 
   544     return saved;
   437     TInt dataLength = cacheBuffer.Length() + aCacheEntry.HeaderData().Length();
   545     }
   438 
   546 
   439     if ( !IsDiskSpaceAvailable( dataLength ) || !CreateNewBodyFile( aCacheEntry ) )
   547 // -----------------------------------------------------------------------------
   440         {
   548 // CHttpCacheStreamHandler::OpenCacheFiles
   441 #ifdef __CACHELOG__
   549 //
   442         HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE:    Flush failed: not enough space or cannot create file."));
   550 // -----------------------------------------------------------------------------
   443 #endif
   551 //
   444         // can't flush if not enough space, or cannot create new files
   552 TBool CHttpCacheStreamHandler::OpenCacheFiles( CHttpCacheEntry& aCacheEntry )
   445         return EFalse;
       
   446         }
       
   447 
       
   448     // files are open, push them onto cleanup stack.
       
   449     CleanupClosePushL( aCacheEntry.BodyFile() );
       
   450 
       
   451     if ( aCacheEntry.BodyDataCached() )
       
   452         {
       
   453 #ifdef __CACHELOG__
       
   454         HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE:    Body Data is Cached"));
       
   455 #endif
       
   456         // append body
       
   457         TInt segment=0;
       
   458         TInt count=cacheBuffer.Count();
       
   459 #ifdef __CACHELOG__
       
   460         HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:    %d segments stored"), count);
       
   461 #endif
       
   462         while ( saveOk == KErrNone && count > segment )
       
   463             {
       
   464             TPtrC8 segBuf = cacheBuffer.GetSegmentData(segment);
       
   465             saveOk = aCacheEntry.BodyFile().Write( segBuf );
       
   466 #ifdef __CACHELOG__
       
   467             HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:    segment %d write returned %d"), (segment-1), saveOk );
       
   468 #endif
       
   469             }
       
   470 
       
   471         cacheBuffer.Reset();
       
   472         aCacheEntry.SetBodyDataCached(EFalse);
       
   473         }
       
   474     // close files
       
   475     CleanupStack::PopAndDestroy(1);
       
   476 
       
   477     return ( saveOk == KErrNone );
       
   478     }
       
   479 
       
   480 // -----------------------------------------------------------------------------
       
   481 // CHttpCacheStreamHandler::FlushAsync
       
   482 //
       
   483 // -----------------------------------------------------------------------------
       
   484 //
       
   485 TInt CHttpCacheStreamHandler::FlushAsync(CHttpCacheEntry& aEntry, TRequestStatus& aStatus)
       
   486     {
       
   487     TInt saveOk( KErrNone );
       
   488 
       
   489     TInt datalen = aEntry.BodyData().Length() + aEntry.HeaderData().Length();
       
   490 
       
   491 #ifdef __CACHELOG__
       
   492     HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheStreamEntry::FlushAsync called on object %08x. Cached data %d bytes"), &aEntry, datalen );
       
   493 #endif
       
   494 
       
   495     if ( datalen && aEntry.BodyData().Length() ) // don't bother writing files which have no body data
       
   496         {
       
   497         if ( IsDiskSpaceAvailable( datalen ) && CreateNewBodyFile( aEntry ) )
       
   498             {
       
   499 #ifdef __CACHELOG__
       
   500             HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:   Triggering Async write for object 0x%08x."), &aEntry);
       
   501 #endif
       
   502             // trim any spare space available.
       
   503             aEntry.BodyData().Compress();
       
   504             aEntry.WriteBodyDataAsync(aStatus);
       
   505             aEntry.SetDelayedWriteInProgress(ETrue);
       
   506             }
       
   507         else
       
   508             {
       
   509 #ifdef __CACHELOG__
       
   510             HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE:   FAILED FlushAsync."));
       
   511 #endif
       
   512             // !enoughSpace
       
   513             saveOk = KErrDiskFull;
       
   514             aEntry.BodyData().Reset();
       
   515             }
       
   516         }
       
   517     else
       
   518         {
       
   519 #ifdef __CACHELOG__
       
   520         HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:  Not writing file %S for entry %08x since it has no data."), &(aEntry.Filename()), &aEntry );
       
   521 #endif
       
   522         TRequestStatus* stat = &aStatus;
       
   523         User::RequestComplete(stat, KErrNone);
       
   524         }
       
   525 
       
   526     return ( saveOk == KErrNone );
       
   527     }
       
   528 
       
   529 // -----------------------------------------------------------------------------
       
   530 // CHttpCacheStreamHandler::OpenBodyFile
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 TBool CHttpCacheStreamHandler::OpenBodyFile( CHttpCacheEntry& aCacheEntry )
       
   534     {
       
   535     TInt statusBody( KErrNotFound );
       
   536 
       
   537     // get body filename
       
   538     TFileName bodyFileName = aCacheEntry.Filename();
       
   539 
       
   540     statusBody = aCacheEntry.BodyFile().Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite );
       
   541 
       
   542     return ( statusBody == KErrNone );
       
   543     }
       
   544 
       
   545 #if 0
       
   546 // -----------------------------------------------------------------------------
       
   547 // CHttpCacheStreamHandler::CreateNewFilesL
       
   548 //
       
   549 // -----------------------------------------------------------------------------
       
   550 //
       
   551 TBool CHttpCacheStreamHandler::CreateNewFilesL( CHttpCacheEntry& aCacheEntry )
   553     {
   552     {
   554     TInt statusHeader( KErrNotFound );
   553     TInt statusHeader( KErrNotFound );
   555     TInt statusBody( KErrNotFound );
   554     TInt statusBody( KErrNotFound );
   556 
   555 
   557     // get body filename
       
   558     TFileName bodyFileName = aCacheEntry.Filename();
       
   559 
       
   560     // header filename
       
   561     TFileName headerFileName;
       
   562     HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
       
   563 
       
   564     statusHeader = aCacheEntry.HeaderFile().Open( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
       
   565     statusBody = aCacheEntry.BodyFile().Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite );
       
   566 
       
   567     TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
       
   568     if ( fileOk )
       
   569         {
       
   570         aCacheEntry.SetCacheFilesOpened( ETrue );
       
   571         }
       
   572 
       
   573     return fileOk;
       
   574     }
       
   575 
       
   576 // -----------------------------------------------------------------------------
       
   577 // CHttpCacheStreamHandler::CreateNewFilesL
       
   578 //
       
   579 // -----------------------------------------------------------------------------
       
   580 //
       
   581 TBool CHttpCacheStreamHandler::CreateNewFilesL( CHttpCacheEntry& aCacheEntry )
       
   582     {
       
   583     TInt statusHeader( KErrNotFound );
       
   584     TInt statusBody( KErrNotFound );
       
   585     TPath sessionPath;
       
   586     User::LeaveIfError( iRfs.SessionPath( sessionPath ) );
       
   587     
       
   588     // Given the full URL, generates a fully qualified path for saving the HTTP response
       
   589     HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( aCacheEntry.Url(), sessionPath );
       
   590     TPtrC bodyFileNamePtr( *bodyFileName );
       
   591  
       
   592     // Create header file name from body file name
   556     // Create header file name from body file name
   593     TFileName headerFileName;
   557     TFileName headerFileName;
   594     HttpCacheUtil::GetHeaderFileName( bodyFileNamePtr, headerFileName );
   558     HttpCacheUtil::GetHeaderFileName( aCacheEntry.Filename(), headerFileName );
   595 
   559 
   596     // Create the body file or replace it, if it exists. 
   560     // Create the body file or replace it, if it exists.
   597     statusBody = aCacheEntry.BodyFile().Replace( iRfs, bodyFileNamePtr, EFileShareExclusive | EFileWrite );
   561     statusBody = aCacheEntry.BodyFile().Replace( iRfs, aCacheEntry.Filename(), EFileShareExclusive | EFileWrite );
   598     if ( statusBody == KErrNone )
   562     if ( statusBody == KErrNone )
   599         {
   563         {
   600         // Header file should not fail
   564         // Header file should not fail
   601         statusHeader = aCacheEntry.HeaderFile().Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
   565         statusHeader = aCacheEntry.HeaderFile().Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
   602         }
   566         }
   603 
   567 
   604 #ifdef __CACHELOG__ 
   568 #ifdef __CACHELOG__
   605     HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, aCacheEntry.Url() );
   569     HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, aCacheEntry.Url() );
   606 #endif 
   570 #endif
   607 
   571 
   608     TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
   572     TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
   609     if ( fileOk )
   573     if ( !fileOk )
   610         {
   574         {
   611         // Both body and header files created correctly 
   575         // Only the body file created, no header file, delete body file
   612         aCacheEntry.SetFileNameL( bodyFileNamePtr );
   576         iRfs.Delete( aCacheEntry.Filename() );
   613         aCacheEntry.SetState( CHttpCacheEntry::ECacheInitialized );
       
   614         }
       
   615     else
       
   616         {
       
   617         // Only the body file created, no header file, delete body file 
       
   618         iRfs.Delete( bodyFileNamePtr );
       
   619         iRfs.Delete( headerFileName );
   577         iRfs.Delete( headerFileName );
   620 
   578 
   621         aCacheEntry.SetBodySize( 0 );
   579         aCacheEntry.SetBodySize( 0 );
   622         aCacheEntry.SetHeaderSize( 0 );
   580         aCacheEntry.SetHeaderSize( 0 );
   623 
   581 
   625         HttpCacheUtil::WriteLog( 0, _L( "CHttpCacheEntry::CreateNewFilesL - DELETE body file, header file failed" ) );
   583         HttpCacheUtil::WriteLog( 0, _L( "CHttpCacheEntry::CreateNewFilesL - DELETE body file, header file failed" ) );
   626 #endif
   584 #endif
   627 //        __ASSERT_DEBUG( EFalse, User::Panic( _L("CHttpCacheHandler::CreateNewFilesL Panic"), KErrCorrupt )  );
   585 //        __ASSERT_DEBUG( EFalse, User::Panic( _L("CHttpCacheHandler::CreateNewFilesL Panic"), KErrCorrupt )  );
   628         }
   586         }
   629 
   587 
   630     CleanupStack::PopAndDestroy( bodyFileName );
       
   631 
       
   632     return fileOk;
   588     return fileOk;
       
   589     }
       
   590 #endif
       
   591 
       
   592 // -----------------------------------------------------------------------------
       
   593 // CHttpCacheStreamHandler::CreateNewBodyFile
       
   594 //
       
   595 // -----------------------------------------------------------------------------
       
   596 //
       
   597 TBool CHttpCacheStreamHandler::CreateNewBodyFile( CHttpCacheEntry& aCacheEntry )
       
   598     {
       
   599     TInt statusBody( KErrNotFound );
       
   600 
       
   601     // Create the body file or replace it, if it exists.
       
   602     statusBody = aCacheEntry.BodyFile().Replace( iRfs, aCacheEntry.Filename(), EFileShareExclusive | EFileWrite );
       
   603 
       
   604 #ifdef __CACHELOG__
       
   605     HttpCacheUtil::WriteUrlToLog( 0, aCacheEntry.Filename(), aCacheEntry.Url() );
       
   606 #endif
       
   607 
       
   608     if ( statusBody != KErrNone )
       
   609         {
       
   610         aCacheEntry.SetBodySize( 0 );
       
   611         aCacheEntry.BodyData().Reset();
       
   612 #ifdef __CACHELOG__
       
   613         HttpCacheUtil::WriteLog( 0, _L( "CHttpCacheEntry::CreateNewBodyFileL - create body file failed!" ) );
       
   614 #endif
       
   615         }
       
   616     return ( statusBody == KErrNone );
   633     }
   617     }
   634 
   618 
   635 // -----------------------------------------------------------------------------
   619 // -----------------------------------------------------------------------------
   636 // CHttpCacheStreamHandler::FindCacheEntryIndex
   620 // CHttpCacheStreamHandler::FindCacheEntryIndex
   637 //
   621 //
   639 //
   623 //
   640 void CHttpCacheStreamHandler::FindCacheEntryIndex(
   624 void CHttpCacheStreamHandler::FindCacheEntryIndex(
   641     const CHttpCacheEntry& aCacheEntry,
   625     const CHttpCacheEntry& aCacheEntry,
   642     TInt* aIndex )
   626     TInt* aIndex )
   643     {
   627     {
   644     *aIndex = -1;
       
   645     for ( TInt i = 0; i < iActiveEntries->Count(); i++ )
   628     for ( TInt i = 0; i < iActiveEntries->Count(); i++ )
   646         {
   629         {
   647         CHttpCacheEntry* entry = iActiveEntries->At( i );
   630         CHttpCacheEntry* entry = iActiveEntries->At( i );
   648 
   631 
   649         if ( entry == &aCacheEntry )
   632         if ( entry == &aCacheEntry )