webengine/osswebengine/cache/src/HttpCacheStreamHandler.cpp
changeset 1 7c90e6132015
parent 0 dd21522fd290
child 10 a359256acfc6
--- a/webengine/osswebengine/cache/src/HttpCacheStreamHandler.cpp	Mon Mar 30 12:54:55 2009 +0300
+++ b/webengine/osswebengine/cache/src/HttpCacheStreamHandler.cpp	Fri May 08 08:25:06 2009 +0300
@@ -30,7 +30,6 @@
 
 // CONSTANTS
 const TInt KHttpCacheActiveCount = 20;
-const TInt KBufferSize = 32768;
 #if 0
 const TInt KHttpCacheChunkSize = 2048;
 #endif // 0
@@ -49,454 +48,13 @@
 // ============================ MEMBER FUNCTIONS ===============================
 
 // -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::CHttpCacheStreamEntry
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-//
-CHttpCacheStreamEntry::CHttpCacheStreamEntry(
-    RFs& aRfs,
-    CHttpCacheEntry& aHttpCacheEntry,
-    TDriveUnit aDrive,
-    TInt64 aCriticalLevel )
-    : iRfs( aRfs ), iHttpCacheEntry( &aHttpCacheEntry ), iDrive( aDrive ), iCriticalLevel( aCriticalLevel )
-    {
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::ConstructL
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CHttpCacheStreamEntry::ConstructL()
-    {
-    // consistency check on header/body files
-    // open the file or create one
-    iFileOk = ( iHttpCacheEntry->State() == CHttpCacheEntry::ECacheUninitialized ? CreateNewFilesL() : OpenCacheFiles() );
-    if( !iFileOk )
-        {
-        User::Leave( KErrCorrupt );
-        }
-    else if( iFileOk && iHttpCacheEntry->State() == CHttpCacheEntry::ECacheUninitialized )
-        {
-        iHttpCacheEntry->SetState( CHttpCacheEntry::ECacheInitialized );
-        }
-    iCacheBuffer = HBufC8::NewL( KBufferSize );
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::NewL
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-//
-CHttpCacheStreamEntry* CHttpCacheStreamEntry::NewL(
-    RFs& aRfs,
-    CHttpCacheEntry& aHttpCacheEntry,
-    TDriveUnit aDrive,
-    TInt64 aCriticalLevel )
-    {
-    CHttpCacheStreamEntry* self = new( ELeave ) CHttpCacheStreamEntry( aRfs,
-        aHttpCacheEntry, aDrive, aCriticalLevel );
-
-    CleanupStack::PushL( self );
-    self->ConstructL();
-    CleanupStack::Pop();
-
-    return self;
-    }
-
-// Destructor
-CHttpCacheStreamEntry::~CHttpCacheStreamEntry()
-    {
-    // commit changes
-    if( iFileOk )
-        {
-        iHeaderFile.Close();
-        iBodyFile.Close();
-        }
-    delete iCacheBuffer;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::Erase
-//
-// -----------------------------------------------------------------------------
-//
-void CHttpCacheStreamEntry::Erase()
-    {
-    //
-    HttpCacheUtil::WriteUrlToLog( 0, _L( "erase files associated with" ), iHttpCacheEntry->Url() );
-    iHeaderFile.Close();
-    iBodyFile.Close();
-    // dont care about return vales
-    // as we cannot do much
-    TFileName bodyFileName;
-    // get body filename
-    BodyFileName( bodyFileName );
-
-    TFileName headerFileName;
-    HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
-    //
-    TInt status;
-    status = iRfs.Delete( bodyFileName );
-    HttpCacheUtil::WriteLog( 0, bodyFileName, status );
-    //
-    status = iRfs.Delete( headerFileName );
-    HttpCacheUtil::WriteLog( 0, headerFileName, status );
-    // do not close them twice
-    iFileOk = EFalse;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::HeadersL
-//
-// -----------------------------------------------------------------------------
-//
-HBufC8* CHttpCacheStreamEntry::HeadersL()
-    {
-    //
-    HBufC8* headerStr = NULL;
-    TInt headerLen( 0 );
-    TInt err( iHeaderFile.Size( headerLen ) );
-    //
-    if( err == KErrNone && headerLen > 0 )
-        {
-        headerStr = HBufC8::NewL( headerLen );
-        TPtr8 ptr( headerStr->Des() );
-        // read headers
-        iHeaderFile.Read( 0, ptr, headerLen );
-        }
-    return headerStr;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::NextChunkL
-//
-// -----------------------------------------------------------------------------
-//
-HBufC8* CHttpCacheStreamEntry::NextChunkL(
-    TBool& aLastChunk )
-    {
-    HBufC8* bodyStr = NULL;
-#if 0
-    // incremental chunk handling
-    TInt size;
-    TInt contentSize( iBodyFile.Size( size ) );
-    size = Min( KHttpCacheChunkSize, contentSize );
-
-    bodyStr = HBufC8::NewL( size );
-    TPtr8 ptr( bodyStr->Des() );
-    //
-    iBodyFile.Read( ptr, size );
-    // check if we are at the end of the file
-    aLastChunk = ( bodyStr->Length() != size );
-#else // 0
-    // read body
-    TInt size;
-    TInt err( iBodyFile.Size( size ) );
-    if( err == KErrNone && size > 0 )
-        {
-        bodyStr = HBufC8::NewL( size );
-        TPtr8 ptr( bodyStr->Des() );
-        //
-        iBodyFile.Read( ptr, size );
-        }
-    aLastChunk = ETrue;
-#endif // 0
-    return bodyStr;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::SaveHeaders
-//
-// -----------------------------------------------------------------------------
-//
-TInt CHttpCacheStreamEntry::SaveHeaders(
-    const TDesC8& aHeaderStr )
-    {
-    TInt save( KErrNone );
-
-    if( aHeaderStr.Length() )
-        {
-        // below critical level
-        TBool below( ETrue );
-
-        below = DiskSpaceBelowCriticalLevel( aHeaderStr.Length() );
-
-        if( !below )
-            {
-            // save headers
-            // Don't force a flush, as the File Server takes care of write and read consistency.
-            iHttpCacheEntry->SetHeaderSize( aHeaderStr.Length() );
-            save = iHeaderFile.Write( aHeaderStr );
-            }
-        else
-            {
-            save = KErrDiskFull;
-            }
-        }
-    return save;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::RemoveHeaders
-//
-// -----------------------------------------------------------------------------
-//
-void CHttpCacheStreamEntry::RemoveHeaders()
-    {
-    // destroy data
-    iHeaderFile.SetSize( 0 );
-    iHttpCacheEntry->SetHeaderSize( 0 );
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::SaveBodyData
-//
-// -----------------------------------------------------------------------------
-//
-TInt CHttpCacheStreamEntry::SaveBodyData(
-    const TDesC8& aBodyStr )
-    {
-    TBool save( KErrNone );
-    TInt bodyLength( aBodyStr.Length() );
-
-    if( bodyLength )
-        {
-        TPtr8 buffer( iCacheBuffer->Des() );
-        if( buffer.Length() + bodyLength > buffer.MaxLength() )
-            {
-            //
-            HBufC8* overflowBuffer = NULL;
-            TInt cut( -1 );
-            // running out of space
-            TPtrC8 writePtr;
-            if( buffer.Length() == 0 )
-                {
-                // buffer is empty and the body is bigger than the buffer
-                writePtr.Set( aBodyStr );
-                }
-            else
-                {
-                cut =  buffer.MaxLength() - buffer.Length();
-                // enough space for the leftover?
-                if( bodyLength - cut > buffer.MaxLength() )
-                    {
-                    // not enough
-                    // put the buffer and the body together and
-                    // write it in one go.
-                    overflowBuffer = HBufC8::New( buffer.Length() + bodyLength );
-                    if( !overflowBuffer )
-                        {
-                        return KErrNoMemory;
-                        }
-                    TPtr8 overflowPtr( overflowBuffer->Des() );
-                    overflowPtr.Copy( buffer );
-                    overflowPtr.Append( aBodyStr );
-                    writePtr.Set( overflowBuffer->Des() );
-                    // empty buffer
-                    buffer.Zero();
-                    // no leftover left
-                    cut = -1;
-                    }
-                else
-                    {
-                    // fill the 32k
-                    buffer.Append( aBodyStr.Left( cut ) );
-                    writePtr.Set( buffer );
-                    }
-                }
-
-            // write to the disk
-            TBool below;
-            below = DiskSpaceBelowCriticalLevel( writePtr.Length() );
-
-            if( !below )
-                {
-                // write body
-                save = iBodyFile.Write( writePtr );
-                }
-            else
-                {
-                save = KErrDiskFull;
-                // reset buffers
-                buffer.Zero();
-                }
-            //
-            if( save == KErrNone && cut >= 0 )
-                {
-                // copy the leftover in to the buffer
-                buffer.Copy( aBodyStr.Mid( cut ) );
-                }
-            delete overflowBuffer;
-            }
-        else
-            {
-            buffer.Append( aBodyStr );
-            save = KErrNone;
-            }
-        // update size information
-        iHttpCacheEntry->SetSize( iHttpCacheEntry->Size() + bodyLength );
-        }
-    return save;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::RemoveBodyData
-//
-// -----------------------------------------------------------------------------
-//
-void CHttpCacheStreamEntry::RemoveBodyData()
-    {
-    // destroy data
-    iCacheBuffer->Des().Zero();
-    iBodyFile.SetSize( 0 );
-    iHttpCacheEntry->SetSize( 0 );
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::Flush
-//
-// -----------------------------------------------------------------------------
-//
-TInt CHttpCacheStreamEntry::Flush()
-    {
-    TInt saveOk( KErrNone );
-
-    if( iCacheBuffer->Length() )
-        {
-        TPtr8 bufferPtr( iCacheBuffer->Des() );
-
-        TBool below;
-        below = DiskSpaceBelowCriticalLevel( bufferPtr.Length() );
-
-        if( !below )
-            {
-            // append body
-            saveOk = iBodyFile.Write( bufferPtr );
-            }
-        else
-            {
-            saveOk = KErrDiskFull;
-            }
-        bufferPtr.Zero();
-        }
-    return saveOk;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::OpenCacheFiles
-//
-// -----------------------------------------------------------------------------
-//
-TBool CHttpCacheStreamEntry::OpenCacheFiles()
-    {
-    TInt statusHeader;
-    TInt statusBody;
-    //
-    TFileName bodyFileName;
-    // get body filename
-    BodyFileName( bodyFileName );
-    // header filename
-    TFileName headerFileName;
-    //
-    HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
-
-    statusHeader = iHeaderFile.Open( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
-    statusBody = iBodyFile.Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite );
-    return ( statusHeader == KErrNone && statusBody == KErrNone );
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::CreateNewFilesL
-//
-// -----------------------------------------------------------------------------
-//
-TBool CHttpCacheStreamEntry::CreateNewFilesL()
-    {
-    TInt statusHeader( KErrNotFound );
-    TInt statusBody( KErrNotFound );
-    TPath sessionPath;
-    User::LeaveIfError( iRfs.SessionPath( sessionPath ) );
-
-    //Given the full URL, generates a fully qualified path for saving the HTTP response
-    HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( iHttpCacheEntry->Url(), sessionPath );
-    TPtrC bodyFileNamePtr( *bodyFileName );
-    // get header file name
-    TFileName headerFileName;
-    HttpCacheUtil::GetHeaderFileName( bodyFileNamePtr, headerFileName );
-
-    // create a file or replace if it exists. 
-    statusBody = iBodyFile.Replace( iRfs, bodyFileNamePtr, EFileShareExclusive | EFileWrite );
-    if( statusBody == KErrNone )
-        {
-        // header file should not fail
-        statusHeader = iHeaderFile.Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
-        }
-    //
-    TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
-#ifdef __CACHELOG__ 
-    HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, iHttpCacheEntry->Url() );
-#endif 
-
-    //
-    if( fileOk )
-        {
-        iHttpCacheEntry->SetFileNameL( bodyFileNamePtr );
-#ifdef __CACHELOG__ 
-        HttpCacheUtil::WriteUrlToLog( 0, _L8("files are fine") );
-#endif 
-        }
-    else
-        {
-        // corrupt entry. delete the file
-        if( statusBody == KErrNone )
-            {
-            iRfs.Delete( bodyFileNamePtr );
-            }
-        // ???
-        __ASSERT_DEBUG( EFalse,
-            User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-        }
-    CleanupStack::PopAndDestroy( bodyFileName );
-    return fileOk;
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::BodyFileName
-//
-// -----------------------------------------------------------------------------
-//
-void CHttpCacheStreamEntry::BodyFileName(
-    TFileName& aBodyFileName )
-    {
-    TFileName bodyFileName;
-    aBodyFileName.Copy( iHttpCacheEntry->Filename()  );
-    }
-
-// -----------------------------------------------------------------------------
-// CHttpCacheStreamEntry::BodyFileName
-//
-// -----------------------------------------------------------------------------
-//
-TBool CHttpCacheStreamEntry::DiskSpaceBelowCriticalLevel(
-    TInt aContentSize )
-    {
-    TVolumeInfo vinfo;
-    TInt errorCode = iRfs.Volume( vinfo, iDrive );
-
-    return( errorCode != KErrNone || ( vinfo.iFree - aContentSize ) <= iCriticalLevel );
-    }
-
-// -----------------------------------------------------------------------------
 // CHttpCacheStreamHandler::CHttpCacheStreamHandler
 // C++ default constructor can NOT contain any code, that
 // might leave.
 // -----------------------------------------------------------------------------
 //
-CHttpCacheStreamHandler::CHttpCacheStreamHandler() : iDiskFull( EFalse )
+CHttpCacheStreamHandler::CHttpCacheStreamHandler()
     {
-    // change the iDiskFull back to false if somebody freed some disk space.
     }
 
 // -----------------------------------------------------------------------------
@@ -511,7 +69,7 @@
     User::LeaveIfError( iRfs.Connect() );
     // set path for the entries
     iRfs.SetSessionPath( aDirectory );
-    iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheStreamEntry>( KHttpCacheActiveCount );
+    iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheActiveCount );
     // get drive letter for sysutil
     TParsePtrC pathParser( aDirectory );
     iDrive = pathParser.Drive();
@@ -536,14 +94,18 @@
     return self;
     }
 
+// -----------------------------------------------------------------------------
 // Destructor
+// -----------------------------------------------------------------------------
+//
 CHttpCacheStreamHandler::~CHttpCacheStreamHandler()
     {
-    if( iActiveEntries )
+    if ( iActiveEntries )
         {
         iActiveEntries->ResetAndDestroy();
         }
     delete iActiveEntries;
+
     iRfs.Close();
     }
 
@@ -552,36 +114,50 @@
 //
 // -----------------------------------------------------------------------------
 //
-TBool CHttpCacheStreamHandler::AttachL(
-    CHttpCacheEntry& aCacheEntry )
+TBool CHttpCacheStreamHandler::AttachL( CHttpCacheEntry& aCacheEntry )
     {
 #ifdef __CACHELOG__
     // check for duplicates
-    for( TInt i = 0; i < iActiveEntries->Count(); i++ )
+    for ( TInt i = 0; i < iActiveEntries->Count(); i++ )
         {
-        __ASSERT_DEBUG( iActiveEntries->At( i )->CacheEntry() != &aCacheEntry,
-            User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
+        __ASSERT_DEBUG( iActiveEntries->At( i ) != &aCacheEntry,
+        User::Panic( _L("cacheStreamHandler Panic"), KErrCorrupt )  );
         }
 #endif // __CACHELOG__
-    TBool attached( ETrue );
-    // create and save stream entry
-    CHttpCacheStreamEntry* streamEntry = NULL;
+   
+    TBool cacheFilesOpened( EFalse );
 
-    TRAPD( err, streamEntry = CHttpCacheStreamEntry::NewL( iRfs, aCacheEntry, iDrive, iCriticalLevel ) );
-    if( err == KErrCorrupt )
+    if ( aCacheEntry.CacheFilesOpened() )
         {
-        //
-        attached = EFalse;
+        // Cache files already opened, no need to reopen
+        cacheFilesOpened = ETrue;
+        }
+    else if ( aCacheEntry.State() == CHttpCacheEntry::ECacheUninitialized )
+        {
+        // Create new cache files, they don't already exist
+        cacheFilesOpened = CreateNewFilesL( aCacheEntry );
         }
-    else if( err == KErrNoMemory )
+    else
         {
-        User::Leave( err );
+        // Open existing cache files
+        cacheFilesOpened = OpenCacheFiles( aCacheEntry );
         }
-    else if( streamEntry )
+    
+    if ( cacheFilesOpened )
         {
-        iActiveEntries->AppendL( streamEntry );
+        // Add to our active array, if not already there
+        TInt index( -1 );
+        FindCacheEntryIndex( aCacheEntry, &index );
+        if ( index == -1 )
+            {
+            iActiveEntries->AppendL( &aCacheEntry );
+            }
         }
-    return attached;
+
+    aCacheEntry.SetCacheFilesOpened( cacheFilesOpened );
+
+    // Return ETrue, if files opened and attached
+    return cacheFilesOpened;
     }
 
 // -----------------------------------------------------------------------------
@@ -589,39 +165,90 @@
 //
 // -----------------------------------------------------------------------------
 //
-void CHttpCacheStreamHandler::Detach(
-    const CHttpCacheEntry& aCacheEntry )
+void CHttpCacheStreamHandler::Detach( CHttpCacheEntry& aCacheEntry )
     {
-    TInt index;
-    CHttpCacheStreamEntry* streamEntry = FindStreamEntry( aCacheEntry, &index );
-    __ASSERT_DEBUG( streamEntry != NULL, User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
+    // Close the files, this will commit changes
+    if ( aCacheEntry.CacheFilesOpened() )
+        {
+        aCacheEntry.BodyFile().Close();
+        aCacheEntry.HeaderFile().Close();
+        aCacheEntry.SetCacheFilesOpened( EFalse );
+        }
 
-    if( streamEntry )
+    // Delete from our active array
+    TInt index( -1 );
+    FindCacheEntryIndex( (const CHttpCacheEntry&)aCacheEntry, &index );
+    if ( index >= 0 )
         {
-        delete streamEntry;
         iActiveEntries->Delete( index );
         }
     }
 
 // -----------------------------------------------------------------------------
-// CHttpCacheStreamHandler::Erase
+// CHttpCacheStreamHandler::EraseCacheFile
 //
 // -----------------------------------------------------------------------------
 //
-void CHttpCacheStreamHandler::Erase(
-    const CHttpCacheEntry& aCacheEntry )
+void CHttpCacheStreamHandler::EraseCacheFile( CHttpCacheEntry& aCacheEntry )
     {
-    TInt index;
-    CHttpCacheStreamEntry* streamEntry = FindStreamEntry( aCacheEntry, &index );
-    __ASSERT_DEBUG( streamEntry != NULL, User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
+    HttpCacheUtil::WriteUrlToLog( 0, _L( "CHttpCacheStreamHandler::Erase - erase files associated with" ), aCacheEntry.Url() );
+
+    aCacheEntry.HeaderFile().Close();
+    aCacheEntry.BodyFile().Close();
+    aCacheEntry.SetCacheFilesOpened( EFalse );
+
+    // Get body filename
+    TFileName bodyFileName = aCacheEntry.Filename();
+
+    // Get header filename
+    TFileName headerFileName;
+    HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
+
+    TInt statusBody( KErrNotFound );
+    statusBody = iRfs.Delete( bodyFileName );
+
+    TInt statusHeader( KErrNotFound );
+    statusHeader = iRfs.Delete( headerFileName );
+
+    // Adjust the size
+    iContentSize -= aCacheEntry.BodySize();
+    iContentSize -= aCacheEntry.HeaderSize();
 
-    if( streamEntry )
-        {
-        streamEntry->Erase();
-        //
-        iContentSize-=aCacheEntry.Size();
-        iContentSize-=aCacheEntry.HeaderSize();
+#ifdef __CACHELOG__
+    if ( statusBody != KErrNone ) {
+        HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                           _L("CCHttpCacheStreamEntry::Erase - ERROR bodyFile delete"),
+                                           aCacheEntry.Filename(),
+                                           aCacheEntry.Url(),
+                                           statusBody,
+                                           ELogFileErrorCode );
+        }
+    else {
+        HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                           _L("CCHttpCacheStreamEntry::Erase - SUCCESS bodyFile delete"),
+                                           aCacheEntry.Filename(),
+                                           aCacheEntry.Url(),
+                                           aCacheEntry.BodySize(),
+                                           ELogEntrySize );
         }
+    if ( statusHeader != KErrNone ) {
+        HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                           _L("CCHttpCacheStreamEntry::Erase - ERROR headerFile delete"),
+                                           aCacheEntry.Filename(),
+                                           aCacheEntry.Url(),
+                                           statusHeader,
+                                           ELogFileErrorCode );
+        }
+    else {
+        HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                           _L("CCHttpCacheStreamEntry::Erase - SUCCESS headerFile delete"),
+                                           aCacheEntry.Filename(),
+                                           aCacheEntry.Url(),
+                                           aCacheEntry.BodySize(),
+                                           ELogEntrySize );
+        }
+#endif //__CACHELOG__
+
     }
 
 // -----------------------------------------------------------------------------
@@ -629,18 +256,26 @@
 //
 // -----------------------------------------------------------------------------
 //
-HBufC8* CHttpCacheStreamHandler::HeadersL(
-    CHttpCacheEntry& aCacheEntry )
+HBufC8* CHttpCacheStreamHandler::HeadersL( CHttpCacheEntry& aCacheEntry )
     {
-    CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
     HBufC8* headerStr = NULL;
-    //
-    __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-    //
-    if( entry )
+    TInt headerLen( 0 );
+    TInt err( KErrNone );
+
+    if ( !aCacheEntry.CacheFilesOpened() )
         {
-        headerStr = entry->HeadersL();
+        OpenCacheFiles( aCacheEntry );
         }
+
+    err = aCacheEntry.HeaderFile().Size( headerLen );
+    if ( err == KErrNone && headerLen > 0 )
+        {
+        headerStr = HBufC8::NewL( headerLen );
+        TPtr8 ptr( headerStr->Des() );
+        // read headers
+        aCacheEntry.HeaderFile().Read( 0, ptr, headerLen );
+        }
+
     return headerStr;
     }
 
@@ -653,16 +288,47 @@
     CHttpCacheEntry& aCacheEntry,
     TBool& aLastChunk )
     {
-    //
-    CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
     HBufC8* bodyStr = NULL;
-    //
-    __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-    //
-    if( entry )
+    // Read whole body
+    TInt size( 0 );
+    TInt sizeErr( KErrNone );
+
+    if ( !aCacheEntry.CacheFilesOpened() )
+        {
+        OpenCacheFiles( aCacheEntry );
+        }
+
+    sizeErr = aCacheEntry.BodyFile().Size( size );
+    if ( sizeErr == KErrNone && size > 0 )
         {
-        bodyStr = entry->NextChunkL( aLastChunk );
+        bodyStr = HBufC8::NewL( size );
+        TPtr8 ptr( bodyStr->Des() );
+
+        TInt readErr( KErrNone );
+        readErr = aCacheEntry.BodyFile().Read( ptr, size );
+
+#ifdef __CACHELOG__
+        if ( readErr != KErrNone ) {
+            HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                               _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
+                                               aCacheEntry.Filename(),
+                                               aCacheEntry.Url(),
+                                               readErr,
+                                               ELogFileErrorCode );
+            }
+        else {
+            HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                               _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"),
+                                               aCacheEntry.Filename(),
+                                               aCacheEntry.Url(),
+                                               ptr.Length(),
+                                               ELogEntrySize );
+            }
+#endif  // __CACHELOG__
+
         }
+    aLastChunk = ETrue;
+
     return bodyStr;
     }
 
@@ -675,28 +341,28 @@
     CHttpCacheEntry& aCacheEntry,
     const TDesC8& aHeaderStr )
     {
-    TBool saved( KErrGeneral );
-    if( !iDiskFull )
+    TBool headerSaved( EFalse );
+
+    if ( !aCacheEntry.CacheFilesOpened() )
         {
-        CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
-        //
-        __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-        //
-        if( entry )
+        OpenCacheFiles( aCacheEntry );
+        }
+
+    if ( aHeaderStr.Length() && IsDiskSpaceAvailable( aHeaderStr.Length() ) )
+        {
+        // We have space on disk, save headers. Don't force a flush, as the
+        // File Server takes care of write and read consistency.
+        TInt writeErr = aCacheEntry.HeaderFile().Write( aHeaderStr );
+
+        if ( writeErr == KErrNone )
             {
-            saved = entry->SaveHeaders( aHeaderStr );
-            // update content size in cache
-            if( saved == KErrNone )
-                {
-                iContentSize+=aHeaderStr.Length();
-                }
-            else if( saved == KErrDiskFull )
-                {
-                iDiskFull = ETrue;
-                }
+            aCacheEntry.SetHeaderSize( aHeaderStr.Length() );
+            iContentSize += aHeaderStr.Length();
+            headerSaved = ETrue;
             }
         }
-    return( saved == KErrNone );
+
+    return headerSaved;
     }
 
 // -----------------------------------------------------------------------------
@@ -704,18 +370,13 @@
 //
 // -----------------------------------------------------------------------------
 //
-void CHttpCacheStreamHandler::RemoveHeaders(
-    CHttpCacheEntry& aCacheEntry )
+void CHttpCacheStreamHandler::RemoveHeaders( CHttpCacheEntry& aCacheEntry )
     {
-    CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
-    //
-    __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-    //
-    if( entry )
-        {
-        iContentSize-=aCacheEntry.HeaderSize();
-        entry->RemoveHeaders();
-        }
+    iContentSize -= aCacheEntry.HeaderSize();
+
+    // Destroy data
+    aCacheEntry.HeaderFile().SetSize( 0 );
+    aCacheEntry.SetHeaderSize( 0 );
     }
 
 // -----------------------------------------------------------------------------
@@ -727,27 +388,101 @@
     CHttpCacheEntry& aCacheEntry,
     const TDesC8& aBodyStr )
     {
-    TInt saved( KErrGeneral );
-    if( !iDiskFull )
+    TInt bodySaved( EFalse );
+    TInt newBodyLength( aBodyStr.Length() );
+    TPtr8 buffer( aCacheEntry.CacheBuffer() );
+
+    if ( newBodyLength && buffer.MaxLength() )
         {
-        CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
-        //
-        __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-        //
-        if( entry )
+        // Calculate if we have enough space in the buffer for incoming body
+        if ( buffer.Length() + newBodyLength > buffer.MaxLength() )
             {
-            saved = entry->SaveBodyData( aBodyStr );
-            if( saved == KErrNone )
+            // Incoming data is too big for the buffer
+            HBufC8* overflowBuffer = NULL;
+            TInt bufferSpaceLeft( -1 );
+            TPtrC8 writePtr;
+
+            if ( buffer.Length() == 0 )
+                {
+                // Buffer is empty and the body is bigger than the buffer,
+                // just take all of the incoming data
+                writePtr.Set( aBodyStr );
+                }
+            else
                 {
-                iContentSize+=aBodyStr.Length();
+                // We have some data in buffer, how much space do we have left
+                bufferSpaceLeft = buffer.MaxLength() - buffer.Length();
+                
+                if ( newBodyLength - bufferSpaceLeft > buffer.MaxLength() )
+                    {
+                    // Not enough space, so lets put the buffer and the new
+                    // body together and write it in one go.
+                    overflowBuffer = HBufC8::New( buffer.Length() + newBodyLength );
+                    if ( !overflowBuffer )
+                        {
+                        return EFalse;
+                        }
+
+                    TPtr8 overflowPtr( overflowBuffer->Des() );
+                    overflowPtr.Copy( buffer );
+                    overflowPtr.Append( aBodyStr );
+                    writePtr.Set( overflowBuffer->Des() );
+
+                    // empty buffer
+                    buffer.Zero();
+                    // no leftover left
+                    bufferSpaceLeft = -1;
+                    }
+                else
+                    {
+                    // Copy what we have enough space for
+                    buffer.Append( aBodyStr.Left( bufferSpaceLeft ) );
+                    writePtr.Set( buffer );
+                    }
                 }
-            else if( saved == KErrDiskFull )
+
+            // Write to the disk, if we have disk space
+            TInt writeErr( KErrNone );
+            if ( IsDiskSpaceAvailable( writePtr.Length() ) )
                 {
-                iDiskFull = ETrue;
+
+                if ( !aCacheEntry.CacheFilesOpened() )
+                    {
+                    OpenCacheFiles( aCacheEntry );
+                    }
+
+                // We have enough disk space, save body
+                TInt writeErr = aCacheEntry.BodyFile().Write( writePtr );
+                bodySaved = ETrue;
+                }
+            else
+                {
+                // We don't have enough disk space, clean up 
+                bodySaved = EFalse;
+                buffer.Zero();
                 }
+
+            if ( writeErr == KErrNone && bufferSpaceLeft >= 0 )
+                {
+                // Copy what we can of the leftover in to the buffer
+                buffer.Copy( aBodyStr.Mid( bufferSpaceLeft ) );
+                }
+            delete overflowBuffer;
             }
+        else
+            {
+            // We have enough space in buffer, add and wait for next body
+            // before writing to file
+            buffer.Append( aBodyStr );
+            bodySaved = ETrue;
+            }
+
+        // Body saved, update state
+        aCacheEntry.SetBodySize( aCacheEntry.BodySize() + newBodyLength );
+        iContentSize += aBodyStr.Length();
         }
-    return( saved == KErrNone );
+
+    return bodySaved;
     }
 
 // -----------------------------------------------------------------------------
@@ -755,18 +490,22 @@
 //
 // -----------------------------------------------------------------------------
 //
-void CHttpCacheStreamHandler::RemoveBodyData(
-    CHttpCacheEntry& aCacheEntry )
+void CHttpCacheStreamHandler::RemoveBodyData( CHttpCacheEntry& aCacheEntry )
     {
-    CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
-    //
-    __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-    //
-    if( entry )
-        {
-        iContentSize-=aCacheEntry.Size();
-        entry->RemoveBodyData();
-        }
+#ifdef __CACHELOG__
+     HttpCacheUtil::WriteLogFilenameAndUrl( 0,
+                                           _L("CHttpCacheStreamHandler::RemoveBodyData - CLEAR iCacheBuffer, entrySize, and iBodyFile"),
+                                           aCacheEntry.Filename(),
+                                           aCacheEntry.Url(),
+                                           aCacheEntry.BodySize(),
+                                           ELogEntrySize );
+#endif
+
+    // Remove data 
+    iContentSize -= aCacheEntry.BodySize();
+    aCacheEntry.SetBodySize( 0 );
+    aCacheEntry.CacheBuffer().Zero();
+    aCacheEntry.BodyFile().SetSize( 0 );
     }
 
 // -----------------------------------------------------------------------------
@@ -774,55 +513,168 @@
 //
 // -----------------------------------------------------------------------------
 //
-TBool CHttpCacheStreamHandler::Flush(
-    CHttpCacheEntry& aCacheEntry )
+TBool CHttpCacheStreamHandler::Flush( CHttpCacheEntry& aCacheEntry )
     {
-    TInt saved( KErrGeneral );
-    if( !iDiskFull )
+    TBool saved( EFalse );
+    TInt writeErr( KErrGeneral );
+    TInt cacheBufferLen( aCacheEntry.CacheBuffer().Length() );
+
+    if ( cacheBufferLen && IsDiskSpaceAvailable( cacheBufferLen ) )
         {
-        CHttpCacheStreamEntry* entry = FindStreamEntry( aCacheEntry );
-        //
-        __ASSERT_DEBUG( entry != NULL,  User::Panic( _L("cacheHandler Panic"), KErrCorrupt )  );
-        //
-        if( entry )
+        // We have enough space, save cache buffer
+        TPtr8 bufferPtr( aCacheEntry.CacheBuffer() );
+        if ( bufferPtr.Length() )
             {
-            saved = entry->Flush();
-            //
-            if( saved == KErrDiskFull )
+            if ( !aCacheEntry.CacheFilesOpened() )
                 {
-                iDiskFull = ETrue;
+                OpenCacheFiles( aCacheEntry );
+                }
+
+            writeErr = aCacheEntry.BodyFile().Write( bufferPtr );
+            if ( writeErr == KErrNone )
+                {
+                saved = ETrue;
                 }
             }
+
+        // Clear the buffer
+        bufferPtr.Zero();
         }
-    return( saved == KErrNone );
+
+    return saved;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheStreamHandler::OpenCacheFiles
+//
+// -----------------------------------------------------------------------------
+//
+TBool CHttpCacheStreamHandler::OpenCacheFiles( CHttpCacheEntry& aCacheEntry )
+    {
+    TInt statusHeader( KErrNotFound );
+    TInt statusBody( KErrNotFound );
+
+    // get body filename
+    TFileName bodyFileName = aCacheEntry.Filename();
+
+    // header filename
+    TFileName headerFileName;
+    HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName );
+
+    statusHeader = aCacheEntry.HeaderFile().Open( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
+    statusBody = aCacheEntry.BodyFile().Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite );
+
+    TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
+    if ( fileOk )
+        {
+        aCacheEntry.SetCacheFilesOpened( ETrue );
+        }
+
+    return fileOk;
     }
 
 // -----------------------------------------------------------------------------
-// CHttpCacheStreamHandler::FindStreamEntry
+// CHttpCacheStreamHandler::CreateNewFilesL
 //
 // -----------------------------------------------------------------------------
 //
-CHttpCacheStreamEntry* CHttpCacheStreamHandler::FindStreamEntry(
+TBool CHttpCacheStreamHandler::CreateNewFilesL( CHttpCacheEntry& aCacheEntry )
+    {
+    TInt statusHeader( KErrNotFound );
+    TInt statusBody( KErrNotFound );
+    TPath sessionPath;
+    User::LeaveIfError( iRfs.SessionPath( sessionPath ) );
+    
+    // Given the full URL, generates a fully qualified path for saving the HTTP response
+    HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( aCacheEntry.Url(), sessionPath );
+    TPtrC bodyFileNamePtr( *bodyFileName );
+ 
+    // Create header file name from body file name
+    TFileName headerFileName;
+    HttpCacheUtil::GetHeaderFileName( bodyFileNamePtr, headerFileName );
+
+    // Create the body file or replace it, if it exists. 
+    statusBody = aCacheEntry.BodyFile().Replace( iRfs, bodyFileNamePtr, EFileShareExclusive | EFileWrite );
+    if ( statusBody == KErrNone )
+        {
+        // Header file should not fail
+        statusHeader = aCacheEntry.HeaderFile().Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite );
+        }
+
+#ifdef __CACHELOG__ 
+    HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, aCacheEntry.Url() );
+#endif 
+
+    TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone );
+    if ( fileOk )
+        {
+        // Both body and header files created correctly 
+        aCacheEntry.SetFileNameL( bodyFileNamePtr );
+        aCacheEntry.SetState( CHttpCacheEntry::ECacheInitialized );
+        }
+    else
+        {
+        // Only the body file created, no header file, delete body file 
+        iRfs.Delete( bodyFileNamePtr );
+        iRfs.Delete( headerFileName );
+
+        aCacheEntry.SetBodySize( 0 );
+        aCacheEntry.SetHeaderSize( 0 );
+
+#ifdef __CACHELOG__
+        HttpCacheUtil::WriteLog( 0, _L( "CHttpCacheEntry::CreateNewFilesL - DELETE body file, header file failed" ) );
+#endif
+//        __ASSERT_DEBUG( EFalse, User::Panic( _L("CHttpCacheHandler::CreateNewFilesL Panic"), KErrCorrupt )  );
+        }
+
+    CleanupStack::PopAndDestroy( bodyFileName );
+
+    return fileOk;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheStreamHandler::FindCacheEntryIndex
+//
+// -----------------------------------------------------------------------------
+//
+void CHttpCacheStreamHandler::FindCacheEntryIndex(
     const CHttpCacheEntry& aCacheEntry,
     TInt* aIndex )
     {
-    CHttpCacheStreamEntry* streamEntry = NULL;
-
-    for( TInt i = 0; i < iActiveEntries->Count(); i++ )
+    *aIndex = -1;
+    for ( TInt i = 0; i < iActiveEntries->Count(); i++ )
         {
-        CHttpCacheStreamEntry* entry = iActiveEntries->At( i );
+        CHttpCacheEntry* entry = iActiveEntries->At( i );
 
-        if( entry && entry->CacheEntry() == &aCacheEntry )
+        if ( entry == &aCacheEntry )
             {
-            streamEntry = entry;
-            if( aIndex )
+            if ( aIndex )
                 {
                 *aIndex = i;
                 }
             break;
             }
         }
-    return streamEntry;
+    }
+
+// -----------------------------------------------------------------------------
+// CHttpCacheStreamHandler::IsDiskSpaceAvailable
+//
+// -----------------------------------------------------------------------------
+//
+TBool CHttpCacheStreamHandler::IsDiskSpaceAvailable( TInt aContentSize )
+    {
+    TBool diskSpaceAvailable( EFalse );
+    TVolumeInfo vinfo;
+    TInt errorCode = iRfs.Volume( vinfo, iDrive );
+
+    if ( errorCode == KErrNone && ( vinfo.iFree - aContentSize ) > iCriticalLevel )
+        {
+        // We have space on the disk for the content
+        diskSpaceAvailable = ETrue;
+        }
+
+    return diskSpaceAvailable;
     }
 
 //  End of File