webengine/osswebengine/cache/src/HttpCacheFileWriteHandler.cpp
changeset 11 c8a366e56285
parent 10 a359256acfc6
child 25 0ed94ceaa377
--- a/webengine/osswebengine/cache/src/HttpCacheFileWriteHandler.cpp	Thu Aug 27 07:44:59 2009 +0300
+++ b/webengine/osswebengine/cache/src/HttpCacheFileWriteHandler.cpp	Thu Sep 24 12:53:48 2009 +0300
@@ -22,6 +22,7 @@
 #include "HttpCacheStreamHandler.h"
 #include "HttpCachePostponeWriteUtilities.h"
 #include "HttpCacheUtil.h"
+#include "HttpCacheObserver.h"
 #include <HttpCacheManagerInternalCRKeys.h>
 #include <centralrepository.h>
 #include <hal.h>
@@ -69,7 +70,7 @@
 // -----------------------------------------------------------------------------
 //
 CHttpCacheFileWriteHandler::CHttpCacheFileWriteHandler(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs)
-    : CActive(EPriorityHigh),
+    : CActive(EPriorityIdle),
       iCacheHandler( aHandler ),
       iCacheStreamHandler(aStreamHandler),
       iFs(aRfs)
@@ -81,14 +82,17 @@
 // Symbian 2nd phase constructor can leave.
 // -----------------------------------------------------------------------------
 //
-void CHttpCacheFileWriteHandler::ConstructL(const TInt aWriteTimeout)
+void CHttpCacheFileWriteHandler::ConstructL(const THttpCachePostponeParameters& aParams)
     {
     iObjectQueue.Reset();
     iObjectQueue.ReserveL(32);
 
-    iWaitTimer = CHttpCacheWriteTimeout::NewL( aWriteTimeout );
+    iWaitTimer = CHttpCacheWriteTimeout::NewL( aParams.iWriteTimeout );
     CActiveScheduler::Add(this);
 
+    iFreeRamThreshold = aParams.iFreeRamThreshold;
+    iImmediateWriteThreshold = aParams.iImmediateWriteThreshold;
+    
     MemoryManager::AddCollector(this);
     }
 
@@ -97,14 +101,13 @@
 // Two-phased constructor.
 // -----------------------------------------------------------------------------
 //
-CHttpCacheFileWriteHandler* CHttpCacheFileWriteHandler::NewL(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs, const TInt aWriteTimeout)
+CHttpCacheFileWriteHandler* CHttpCacheFileWriteHandler::NewL(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs, const THttpCachePostponeParameters& aParams)
     {
     CHttpCacheFileWriteHandler* self = new( ELeave ) CHttpCacheFileWriteHandler(aHandler, aStreamHandler, aRfs);
 
     CleanupStack::PushL( self );
-    self->ConstructL(aWriteTimeout);
+    self->ConstructL(aParams);
     CleanupStack::Pop();
-
     return self;
     }
 
@@ -141,6 +144,7 @@
     for ( TInt i=0; i < iObjectQueue.Count(); i++ )
         {
         iCacheStreamHandler->Flush(*iObjectQueue[i]);
+        iObjectQueue[i]->ClearDeleteObserver();
         }
         iObjectQueue.Reset();
 #ifdef __CACHELOG__
@@ -185,15 +189,22 @@
         return;
         }
 
+    TInt skip = 0;
     TInt count = KMaxCollectCount;
     while ( aRequired && count && iObjectQueue.Count() )
         {
-        count--;
-        CHttpCacheEntry* entry = iObjectQueue[0];
-        iObjectQueue.Remove(0);
-        TInt size = entry->BodySize();
-        iCacheStreamHandler->Flush(*entry);
-        aRequired -= size;
+        CHttpCacheEntry* entry = iObjectQueue[skip];
+        if(entry != iObjectFlushing)
+            {
+            count--;
+            iObjectQueue.Remove(skip);
+            entry->ClearDeleteObserver();
+            TInt size = entry->BodySize();
+            iCacheStreamHandler->Flush(*entry);
+            aRequired -= size;
+            }
+        else
+            skip++;
         }
     }
 
@@ -247,29 +258,46 @@
     // if we get here, we're not in low memory state any more.
     iLowMemoryState = EFalse;
 
+    // If we re-request an item on the page which was non-cacheable, we will update it's content
+    // and add it back to the cache here, even though we have reused the same CHttpCache object.
+ 
+    // check for re-adding pre-existing objects with updated content - size may differ, so need to remove and reinsert.
+    TInt index = iObjectQueue.Find( aEntry ); 
+    if( index >= 0)
+        {
+        iObjectQueue.Remove( index );
+        }
     // add entry to queue
-    TInt err = iObjectQueue.InsertInOrderAllowRepeats(aEntry, TLinearOrder<CHttpCacheEntry>(CompareHttpCacheEntrySize));
+    TInt err = iObjectQueue.Append( aEntry );
 
-    #ifdef __CACHELOG__
-    HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler: Added object %08x to postpone queue."), aEntry);
-    OutputQueueContentToDebug();
-#endif
+    // sort by size
+    iObjectQueue.Sort(CompareHttpCacheEntrySize);
+    
+    switch( err )
+        {
+        case KErrNone:
 
-    // reset timer
-    if ( err == KErrNone )
-        {
-        aAddStatus = EAddedOk;
-        iWaitTimer->Start( CHttpCacheFileWriteHandler::WriteTimeout, this );
+            // set up notification of delete operation
+            aEntry->SetDeleteObserver(this);
+            
+        #ifdef __CACHELOG__
+            HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler: Added object %08x to postpone queue."), aEntry);
+            OutputQueueContentToDebug();
+        #endif
+
+            aAddStatus = EAddedOk;
+            iWaitTimer->Start( CHttpCacheFileWriteHandler::WriteTimeout, this );
+            break;
+        case KErrNoMemory:
+            aAddStatus = ENotEnoughFreeMemory;
+            break;
+        default:
+            aAddStatus = ECheckReturn;
+            break;
         }
-    else
-        {
-        aAddStatus = ECheckReturn;
-        }
-
 #ifdef __CACHELOG__
     HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: <<FileWriteHandler::AddEntry"));
 #endif
-
     return err;
     }
 
@@ -305,6 +333,8 @@
         if ( index >= 0 )
             {
             iObjectQueue.Remove( index );
+            aEntry->ClearDeleteObserver();
+            
             if ( !iObjectQueue.Count() )
                 {
 #ifdef __CACHELOG__
@@ -330,6 +360,11 @@
 void CHttpCacheFileWriteHandler::RemoveAll()
     {
     // empty list - note that HttpCacheEntries aren't owned.
+    // deregister for delete events.
+    for(TInt index = 0; index < iObjectQueue.Count(); index++)
+        {
+        iObjectQueue[index]->ClearDeleteObserver();
+        }
     iObjectQueue.Reset();
     // stop us if we're active
     Cancel();
@@ -363,6 +398,19 @@
 
     if ( !IsActive() )
         {
+#ifdef HTTPCACHE_FILEWRITEDEBUG_ALWAYS_FIRE_OBSERVER
+        // trigger index.dat observer
+        RFile tempIndexFile;
+        TInt err = tempIndexFile.Open(iFs, _L("C:\\system\\cache\\index.dat"), EFileWrite);
+        if(err == KErrNone)
+            {
+            tempIndexFile.Seek(ESeekEnd, err);
+            _LIT8(KIndexGarbage, "blahblah");
+            tempIndexFile.Write(KIndexGarbage());
+            tempIndexFile.Flush();
+            tempIndexFile.Close();
+            }
+#endif
 #ifdef __CACHELOG__
         HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:   Setting FileWriteHandler %08x to active."), this);
 #endif
@@ -424,6 +472,8 @@
 #endif
             // the object might not exist in the queue.. how can this happen?
             iObjectQueue.Remove(index);
+            iObjectFlushing->ClearDeleteObserver();
+            
             //
             if ( result != KErrNone )
                 {
@@ -453,21 +503,33 @@
         // remove any items from the top of the queue which have no body data.
         while ( iObjectQueue.Count() && iObjectQueue[0]->BodySize() == 0 )
             {
+            iObjectQueue[0]->ClearDeleteObserver();
             iObjectQueue.Remove(0);
             };
 
+        TBool goIdle = ETrue;
         // check to see if there is anything ready to write out
         if ( iObjectQueue.Count() )
             {
-            SetActive();
-            iStatus = KRequestPending;
-            iCacheStreamHandler->FlushAsync( *iObjectQueue[0], iStatus );
-            iObjectFlushing = iObjectQueue[0];
-#ifdef __CACHELOG__
-            HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:     FileWriteHandler::RunL continue cache flush, Starting object %08x."), iObjectFlushing);
-#endif
+            // merge index if it's changed
+            if(iCacheHandler->iHttpCacheObserver->Updated())
+                iCacheHandler->iHttpCacheObserver->RunL();
+            
+            // check again, merge may have removed all items
+            if( iObjectQueue.Count() && !IsActive() )    // Collect could be triggered during RunL execution and already have made this object active, we can't tell in 'collect' if we were in here or not.
+                {
+                iStatus = KRequestPending;
+                SetActive();
+                iCacheStreamHandler->FlushAsync( *iObjectQueue[0], iStatus );
+                iObjectFlushing = iObjectQueue[0];
+                goIdle = EFalse;
+    #ifdef __CACHELOG__
+                HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE:     FileWriteHandler::RunL continue cache flush, Starting object %08x."), iObjectFlushing);
+    #endif
+                }
             }
-        else
+        
+        if(goIdle)
             {   // nothing left to write, go idle.
     #ifdef __CACHELOG__
             HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE:     FileWriteHandler::RunL complete with nothing else to write."));
@@ -542,4 +604,9 @@
     return EFalse;
     }
 
+
+void CHttpCacheFileWriteHandler::EntryDeleted(CHttpCacheEntry *aEntry)
+    {
+    RemoveEntry(aEntry);
+    }
 //  End of File