diff -r dd21522fd290 -r 7c90e6132015 webengine/osswebengine/cache/src/HttpCacheStreamHandler.cpp --- 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( KHttpCacheActiveCount ); + iActiveEntries = new( ELeave )CArrayPtrFlat( 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