diff -r 10e98eab6f85 -r a359256acfc6 webengine/osswebengine/cache/src/HttpCachePostponeWriteUtilities.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/cache/src/HttpCachePostponeWriteUtilities.cpp Thu Aug 27 07:44:59 2009 +0300 @@ -0,0 +1,444 @@ +/* +* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of CHttpCachePostponeWriteUtilities +* +*/ + +// INCLUDE FILES +#include "HttpCachePostponeWriteUtilities.h" +#include "HttpCacheUtil.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::CHttpCacheEntryAsyncWriteHelper +// ----------------------------------------------------------------------------- +// +CHttpCacheEntryAsyncWriteHelper::CHttpCacheEntryAsyncWriteHelper(TRequestStatus& aStatus, MHttpCacheWriteSource* aSource, TInt aPriority) + : CActive(aPriority), + iSignalStatus(aStatus), + iSource(aSource) + { + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::NewL +// ----------------------------------------------------------------------------- +// +CHttpCacheEntryAsyncWriteHelper* CHttpCacheEntryAsyncWriteHelper::NewL(MHttpCacheWriteSource* aSource, TRequestStatus& aStatus) + { + CHttpCacheEntryAsyncWriteHelper *obj = new (ELeave) CHttpCacheEntryAsyncWriteHelper(aStatus, aSource, EPriorityHigh); + CleanupStack::PushL(obj); + obj->ConstructL(); + CleanupStack::Pop(obj); + return obj; + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::~CHttpCacheEntryAsyncWriteHelper +// ----------------------------------------------------------------------------- +// +CHttpCacheEntryAsyncWriteHelper::~CHttpCacheEntryAsyncWriteHelper() + { + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::DoCancel +// ----------------------------------------------------------------------------- +// +void CHttpCacheEntryAsyncWriteHelper::DoCancel() + { + TRequestStatus *stat = &(TRequestStatus&)iSignalStatus; + User::RequestComplete(stat, KErrCancel); // Signal cancellation to the observer. + // cannot meaningfully do anything with the unwritten data assuming there is some. + // we will clean it up when we are deleted. + iSource->BodyFile().Close(); + iSource->BodyWriteComplete(); +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheEntryAsyncWriteHelper::DoCancel called on object %08x"), this); +#endif + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::WriteNextBodyBlock +// ----------------------------------------------------------------------------- +// +void CHttpCacheEntryAsyncWriteHelper::WriteNextBodyBlock() + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheEntryAsyncWriteHelper::WriteNextBodyBlock called on object %08x for block %d"), this, iBodyPart ); +#endif + + TPtrC8 bufferPtr( iSource->BodyData().GetSegmentData(iBodyPart) ); + iSource->BodyFile().Write(bufferPtr, iStatus); + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::RunL +// ----------------------------------------------------------------------------- +// +void CHttpCacheEntryAsyncWriteHelper::RunL() + { + /* General algorithm. + * Write out next section of body data unless done. Then write out header data. + */ +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheEntryAsyncWriteHelper::RunL called on object %08x"), this); +#endif + if ( iSource->BodyData().Count() > iBodyPart ) + { + WriteNextBodyBlock(); + SetActive(); + } + else + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: - body write completed with status code %d"), iStatus.Int()); +#endif + // Body file writing is complete + iSource->BodyFile().Close(); + iSource->BodyWriteComplete(); + TRequestStatus *stat = &(TRequestStatus&)iSignalStatus; + User::RequestComplete(stat, iStatus.Int()); // signal completion to observer + } + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::GetResult +// ----------------------------------------------------------------------------- +// +TInt CHttpCacheEntryAsyncWriteHelper::GetResult() + { + return iStatus.Int(); + } + +// ----------------------------------------------------------------------------- +// CHttpCacheEntryAsyncWriteHelper::ConstructL +// ----------------------------------------------------------------------------- +// +void CHttpCacheEntryAsyncWriteHelper::ConstructL() + { + CActiveScheduler::Add(this); + iSource->BodyWriteInProgress(); + // setup to arrive in RunL when next possible. + SetActive(); + TRequestStatus *stat = &(TRequestStatus&)iStatus; + User::RequestComplete(stat, KErrNone); + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::~CSegmentedHeapBuffer +// ----------------------------------------------------------------------------- +// +CSegmentedHeapBuffer::~CSegmentedHeapBuffer() + { + Reset(); + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::ConstructL +// ----------------------------------------------------------------------------- +// +void CSegmentedHeapBuffer::ConstructL() + { + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::NewL +// ----------------------------------------------------------------------------- +// +CSegmentedHeapBuffer *CSegmentedHeapBuffer::NewL(TInt aBufferSize, TInt aCompressGranularity) + { + CSegmentedHeapBuffer *obj= new (ELeave) CSegmentedHeapBuffer(aBufferSize, aCompressGranularity); + CleanupStack::PushL(obj); + obj->ConstructL(); + CleanupStack::Pop(obj); + + return obj; + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::AppendL +// ----------------------------------------------------------------------------- +// +void CSegmentedHeapBuffer::AppendL(TInt& aRemainder, const TDesC8& aDes) + { + aRemainder = aDes.Length(); // consumed nothing yet. + TInt workingLen; + TInt workingOffset=0; // read position in source descriptor + HBufC8* currentBuffer; + + TInt lastBuffer = iBufferList.Count()-1; + if ( lastBuffer < 0 ) + { + // TODO: Make the first block only equal to the size of data we need? + // Take some traces to see what happens. + + // no blocks allocated. May leave here if we can't get space. + currentBuffer = HBufC8::NewLC(iBufferSize); + iBufferList.AppendL(currentBuffer); + CleanupStack::Pop(currentBuffer); + lastBuffer = 0; + } + else + { + currentBuffer = iBufferList[lastBuffer]; + } + + // here, currentBuffer always points to a buffer we can use. + while ( aRemainder ) + { + workingLen = iBufferSize - currentBuffer->Length(); // workingLen = amount of space left in this segment + workingLen = (aRemainder > workingLen) ? workingLen : aRemainder; // workingLen = smaller of (amount of data left in source) or (amount of space left in current segment) + if ( workingLen ) + { + // we have some space in this block to store data. + TPtr8 ptr(currentBuffer->Des()); + ptr.Append(aDes.Mid(workingOffset ,workingLen)); + } + aRemainder -= workingLen; // track how much is consumed + workingOffset += workingLen; // remember where we get the next bit from in the source + if ( aRemainder ) + { + // we have more data to store, append another block. Might result in a leave. + currentBuffer = HBufC8::NewLC(iBufferSize); + iBufferList.AppendL(currentBuffer); + CleanupStack::Pop(currentBuffer); + } + } + // will only exit here if we consumed all data + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::Length +// ----------------------------------------------------------------------------- +// +TInt CSegmentedHeapBuffer::Length() + { + // all segments are same size except last one + TInt len = 0; + TInt count = iBufferList.Count(); + if ( count ) + { + len = iBufferSize * (count - 1); // all segments are same size except last one + len += iBufferList[count-1]->Length(); + } + return len; + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::SpareCapacity +// ----------------------------------------------------------------------------- +// +TInt CSegmentedHeapBuffer::SpareCapacity() + { + TInt len = 0; + TInt count = iBufferList.Count(); + if ( count ) + { + len = iBufferSize - (iBufferList[count-1]->Length()); + } + + // return how much is left in last segment. + return len; + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::Count +// ----------------------------------------------------------------------------- +// +TInt CSegmentedHeapBuffer::Count() + { + return iBufferList.Count(); // number of segments + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::GetSegmentData +// ----------------------------------------------------------------------------- +// +TPtrC8 CSegmentedHeapBuffer::GetSegmentData(TInt& aSegment) + { + return iBufferList[aSegment++]->Des(); + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::ReleaseSegmentData +// ----------------------------------------------------------------------------- +// +void CSegmentedHeapBuffer::ReleaseSegmentData(const TInt aSegment) + { + HBufC8* buf = iBufferList[aSegment]; + iBufferList[aSegment] = 0; // don't want to reshuffle contents + delete buf; + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::Compress +// ----------------------------------------------------------------------------- +// +void CSegmentedHeapBuffer::Compress() + { + TInt count = iBufferList.Count(); + if ( count ) + { + HBufC8* buf = iBufferList[count-1]; + // first, see if we can shrink by at least one iCompressGranularity + if ( iBufferSize - buf->Length() >= iCompressGranularity ) + { + // calculate new size + TInt newsize = (iCompressGranularity * (1 + (buf->Length() / iCompressGranularity))); + HBufC8 *newbuf = buf->ReAlloc(newsize); + // we should be realloc'ing in place since we're shrinking this piece, but you never know. + // don't care if realloc operation fails since it will leave original data alone. + if ( newbuf ) + { + iBufferList[count-1] = newbuf; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::Reset +// ----------------------------------------------------------------------------- +// +void CSegmentedHeapBuffer::Reset() + { + iBufferList.ResetAndDestroy(); // call delete on all buffers + } + +// ----------------------------------------------------------------------------- +// CSegmentedHeapBuffer::CSegmentedHeapBuffer +// ----------------------------------------------------------------------------- +// +CSegmentedHeapBuffer::CSegmentedHeapBuffer(TInt aBufferSize, TInt aCompressGranularity) : iBufferSize(aBufferSize), iCompressGranularity(aCompressGranularity) + { + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::CHttpCacheWriteTimeout +// ----------------------------------------------------------------------------- +// +CHttpCacheWriteTimeout::CHttpCacheWriteTimeout( const TInt aTimeout ) + : CActive(EPriorityStandard), + iTimeout(aTimeout) // Standard priority + { + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::NewLC +// ----------------------------------------------------------------------------- +// +CHttpCacheWriteTimeout* CHttpCacheWriteTimeout::NewLC(const TInt aTimeout) + { + CHttpCacheWriteTimeout* self = new ( ELeave ) CHttpCacheWriteTimeout(aTimeout); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::NewL +// ----------------------------------------------------------------------------- +// +CHttpCacheWriteTimeout* CHttpCacheWriteTimeout::NewL(const TInt aTimeout) + { + CHttpCacheWriteTimeout* self = CHttpCacheWriteTimeout::NewLC(aTimeout); + CleanupStack::Pop(); // self; + return self; + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::ConstructL +// ----------------------------------------------------------------------------- +// +void CHttpCacheWriteTimeout::ConstructL() + { + User::LeaveIfError(iTimer.CreateLocal()); // Initialize timer + CActiveScheduler::Add(this); // Add to scheduler + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::~CHttpCacheWriteTimeout +// ----------------------------------------------------------------------------- +// +CHttpCacheWriteTimeout::~CHttpCacheWriteTimeout() + { + Cancel(); // Cancel any request, if outstanding + iTimer.Close(); // Destroy the RTimer object + // Delete instance variables if any + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::DoCancel +// ----------------------------------------------------------------------------- +// +void CHttpCacheWriteTimeout::DoCancel() + { + iTimer.Cancel(); + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::Start +// ----------------------------------------------------------------------------- +// +void CHttpCacheWriteTimeout::Start(TCallBack aCallbackFn, TAny *aToken) + { + Cancel(); // Cancel any request, just to be sure + + iToken = aToken; + iCallbackFn = aCallbackFn; + + iTimer.After(iStatus, iTimeout); // Set for later + SetActive(); // Tell scheduler a request is active + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::RunL +// ----------------------------------------------------------------------------- +// +void CHttpCacheWriteTimeout::RunL() + { + iCallbackFn.iFunction(iToken); + } + +// ----------------------------------------------------------------------------- +// CHttpCacheWriteTimeout::RunError +// ----------------------------------------------------------------------------- +// +TInt CHttpCacheWriteTimeout::RunError(TInt aError) + { + return aError; + } + +// End of File