20 #include "HttpCacheEntry.h" |
20 #include "HttpCacheEntry.h" |
21 #include "HttpCacheHandler.h" |
21 #include "HttpCacheHandler.h" |
22 #include "HttpCacheStreamHandler.h" |
22 #include "HttpCacheStreamHandler.h" |
23 #include "HttpCachePostponeWriteUtilities.h" |
23 #include "HttpCachePostponeWriteUtilities.h" |
24 #include "HttpCacheUtil.h" |
24 #include "HttpCacheUtil.h" |
|
25 #include "HttpCacheObserver.h" |
25 #include <HttpCacheManagerInternalCRKeys.h> |
26 #include <HttpCacheManagerInternalCRKeys.h> |
26 #include <centralrepository.h> |
27 #include <centralrepository.h> |
27 #include <hal.h> |
28 #include <hal.h> |
28 #include <f32file.h> |
29 #include <f32file.h> |
29 |
30 |
67 // C++ default constructor can NOT contain any code, that |
68 // C++ default constructor can NOT contain any code, that |
68 // might leave. |
69 // might leave. |
69 // ----------------------------------------------------------------------------- |
70 // ----------------------------------------------------------------------------- |
70 // |
71 // |
71 CHttpCacheFileWriteHandler::CHttpCacheFileWriteHandler(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs) |
72 CHttpCacheFileWriteHandler::CHttpCacheFileWriteHandler(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs) |
72 : CActive(EPriorityHigh), |
73 : CActive(EPriorityIdle), |
73 iCacheHandler( aHandler ), |
74 iCacheHandler( aHandler ), |
74 iCacheStreamHandler(aStreamHandler), |
75 iCacheStreamHandler(aStreamHandler), |
75 iFs(aRfs) |
76 iFs(aRfs) |
76 { |
77 { |
77 } |
78 } |
79 // ----------------------------------------------------------------------------- |
80 // ----------------------------------------------------------------------------- |
80 // CHttpCacheFileWriteHandler::ConstructL |
81 // CHttpCacheFileWriteHandler::ConstructL |
81 // Symbian 2nd phase constructor can leave. |
82 // Symbian 2nd phase constructor can leave. |
82 // ----------------------------------------------------------------------------- |
83 // ----------------------------------------------------------------------------- |
83 // |
84 // |
84 void CHttpCacheFileWriteHandler::ConstructL(const TInt aWriteTimeout) |
85 void CHttpCacheFileWriteHandler::ConstructL(const THttpCachePostponeParameters& aParams) |
85 { |
86 { |
86 iObjectQueue.Reset(); |
87 iObjectQueue.Reset(); |
87 iObjectQueue.ReserveL(32); |
88 iObjectQueue.ReserveL(32); |
88 |
89 |
89 iWaitTimer = CHttpCacheWriteTimeout::NewL( aWriteTimeout ); |
90 iWaitTimer = CHttpCacheWriteTimeout::NewL( aParams.iWriteTimeout ); |
90 CActiveScheduler::Add(this); |
91 CActiveScheduler::Add(this); |
91 |
92 |
|
93 iFreeRamThreshold = aParams.iFreeRamThreshold; |
|
94 iImmediateWriteThreshold = aParams.iImmediateWriteThreshold; |
|
95 |
92 MemoryManager::AddCollector(this); |
96 MemoryManager::AddCollector(this); |
93 } |
97 } |
94 |
98 |
95 // ----------------------------------------------------------------------------- |
99 // ----------------------------------------------------------------------------- |
96 // CHttpCacheFileWriteHandler::NewL |
100 // CHttpCacheFileWriteHandler::NewL |
97 // Two-phased constructor. |
101 // Two-phased constructor. |
98 // ----------------------------------------------------------------------------- |
102 // ----------------------------------------------------------------------------- |
99 // |
103 // |
100 CHttpCacheFileWriteHandler* CHttpCacheFileWriteHandler::NewL(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs, const TInt aWriteTimeout) |
104 CHttpCacheFileWriteHandler* CHttpCacheFileWriteHandler::NewL(CHttpCacheHandler* aHandler, CHttpCacheStreamHandler* aStreamHandler, RFs& aRfs, const THttpCachePostponeParameters& aParams) |
101 { |
105 { |
102 CHttpCacheFileWriteHandler* self = new( ELeave ) CHttpCacheFileWriteHandler(aHandler, aStreamHandler, aRfs); |
106 CHttpCacheFileWriteHandler* self = new( ELeave ) CHttpCacheFileWriteHandler(aHandler, aStreamHandler, aRfs); |
103 |
107 |
104 CleanupStack::PushL( self ); |
108 CleanupStack::PushL( self ); |
105 self->ConstructL(aWriteTimeout); |
109 self->ConstructL(aParams); |
106 CleanupStack::Pop(); |
110 CleanupStack::Pop(); |
107 |
|
108 return self; |
111 return self; |
109 } |
112 } |
110 |
113 |
111 // ----------------------------------------------------------------------------- |
114 // ----------------------------------------------------------------------------- |
112 // Destructor |
115 // Destructor |
139 OutputQueueContentToDebug(); |
142 OutputQueueContentToDebug(); |
140 #endif |
143 #endif |
141 for ( TInt i=0; i < iObjectQueue.Count(); i++ ) |
144 for ( TInt i=0; i < iObjectQueue.Count(); i++ ) |
142 { |
145 { |
143 iCacheStreamHandler->Flush(*iObjectQueue[i]); |
146 iCacheStreamHandler->Flush(*iObjectQueue[i]); |
|
147 iObjectQueue[i]->ClearDeleteObserver(); |
144 } |
148 } |
145 iObjectQueue.Reset(); |
149 iObjectQueue.Reset(); |
146 #ifdef __CACHELOG__ |
150 #ifdef __CACHELOG__ |
147 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: <<FileWriteHandler::DumpAllObjects")); |
151 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: <<FileWriteHandler::DumpAllObjects")); |
148 #endif |
152 #endif |
183 if ( !iObjectQueue.Count() ) |
187 if ( !iObjectQueue.Count() ) |
184 { |
188 { |
185 return; |
189 return; |
186 } |
190 } |
187 |
191 |
|
192 TInt skip = 0; |
188 TInt count = KMaxCollectCount; |
193 TInt count = KMaxCollectCount; |
189 while ( aRequired && count && iObjectQueue.Count() ) |
194 while ( aRequired && count && iObjectQueue.Count() ) |
190 { |
195 { |
191 count--; |
196 CHttpCacheEntry* entry = iObjectQueue[skip]; |
192 CHttpCacheEntry* entry = iObjectQueue[0]; |
197 if(entry != iObjectFlushing) |
193 iObjectQueue.Remove(0); |
198 { |
194 TInt size = entry->BodySize(); |
199 count--; |
195 iCacheStreamHandler->Flush(*entry); |
200 iObjectQueue.Remove(skip); |
196 aRequired -= size; |
201 entry->ClearDeleteObserver(); |
|
202 TInt size = entry->BodySize(); |
|
203 iCacheStreamHandler->Flush(*entry); |
|
204 aRequired -= size; |
|
205 } |
|
206 else |
|
207 skip++; |
197 } |
208 } |
198 } |
209 } |
199 |
210 |
200 // ----------------------------------------------------------------------------- |
211 // ----------------------------------------------------------------------------- |
201 // CHttpCacheFileWriteHandler::AddEntry |
212 // CHttpCacheFileWriteHandler::AddEntry |
245 } |
256 } |
246 |
257 |
247 // if we get here, we're not in low memory state any more. |
258 // if we get here, we're not in low memory state any more. |
248 iLowMemoryState = EFalse; |
259 iLowMemoryState = EFalse; |
249 |
260 |
|
261 // If we re-request an item on the page which was non-cacheable, we will update it's content |
|
262 // and add it back to the cache here, even though we have reused the same CHttpCache object. |
|
263 |
|
264 // check for re-adding pre-existing objects with updated content - size may differ, so need to remove and reinsert. |
|
265 TInt index = iObjectQueue.Find( aEntry ); |
|
266 if( index >= 0) |
|
267 { |
|
268 iObjectQueue.Remove( index ); |
|
269 } |
250 // add entry to queue |
270 // add entry to queue |
251 TInt err = iObjectQueue.InsertInOrderAllowRepeats(aEntry, TLinearOrder<CHttpCacheEntry>(CompareHttpCacheEntrySize)); |
271 TInt err = iObjectQueue.Append( aEntry ); |
252 |
272 |
253 #ifdef __CACHELOG__ |
273 // sort by size |
254 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler: Added object %08x to postpone queue."), aEntry); |
274 iObjectQueue.Sort(CompareHttpCacheEntrySize); |
255 OutputQueueContentToDebug(); |
275 |
256 #endif |
276 switch( err ) |
257 |
277 { |
258 // reset timer |
278 case KErrNone: |
259 if ( err == KErrNone ) |
279 |
260 { |
280 // set up notification of delete operation |
261 aAddStatus = EAddedOk; |
281 aEntry->SetDeleteObserver(this); |
262 iWaitTimer->Start( CHttpCacheFileWriteHandler::WriteTimeout, this ); |
282 |
263 } |
283 #ifdef __CACHELOG__ |
264 else |
284 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler: Added object %08x to postpone queue."), aEntry); |
265 { |
285 OutputQueueContentToDebug(); |
266 aAddStatus = ECheckReturn; |
286 #endif |
267 } |
287 |
268 |
288 aAddStatus = EAddedOk; |
|
289 iWaitTimer->Start( CHttpCacheFileWriteHandler::WriteTimeout, this ); |
|
290 break; |
|
291 case KErrNoMemory: |
|
292 aAddStatus = ENotEnoughFreeMemory; |
|
293 break; |
|
294 default: |
|
295 aAddStatus = ECheckReturn; |
|
296 break; |
|
297 } |
269 #ifdef __CACHELOG__ |
298 #ifdef __CACHELOG__ |
270 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: <<FileWriteHandler::AddEntry")); |
299 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: <<FileWriteHandler::AddEntry")); |
271 #endif |
300 #endif |
272 |
|
273 return err; |
301 return err; |
274 } |
302 } |
275 |
303 |
276 // ----------------------------------------------------------------------------- |
304 // ----------------------------------------------------------------------------- |
277 // CHttpCacheFileWriteHandler::RemoveEntry |
305 // CHttpCacheFileWriteHandler::RemoveEntry |
303 #endif |
331 #endif |
304 TInt index = iObjectQueue.Find( aEntry ); |
332 TInt index = iObjectQueue.Find( aEntry ); |
305 if ( index >= 0 ) |
333 if ( index >= 0 ) |
306 { |
334 { |
307 iObjectQueue.Remove( index ); |
335 iObjectQueue.Remove( index ); |
|
336 aEntry->ClearDeleteObserver(); |
|
337 |
308 if ( !iObjectQueue.Count() ) |
338 if ( !iObjectQueue.Count() ) |
309 { |
339 { |
310 #ifdef __CACHELOG__ |
340 #ifdef __CACHELOG__ |
311 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler::RemoveEntry - nothing left on list, stopping timer.")); |
341 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: CHttpCacheFileWriteHandler::RemoveEntry - nothing left on list, stopping timer.")); |
312 #endif |
342 #endif |
328 // ----------------------------------------------------------------------------- |
358 // ----------------------------------------------------------------------------- |
329 // |
359 // |
330 void CHttpCacheFileWriteHandler::RemoveAll() |
360 void CHttpCacheFileWriteHandler::RemoveAll() |
331 { |
361 { |
332 // empty list - note that HttpCacheEntries aren't owned. |
362 // empty list - note that HttpCacheEntries aren't owned. |
|
363 // deregister for delete events. |
|
364 for(TInt index = 0; index < iObjectQueue.Count(); index++) |
|
365 { |
|
366 iObjectQueue[index]->ClearDeleteObserver(); |
|
367 } |
333 iObjectQueue.Reset(); |
368 iObjectQueue.Reset(); |
334 // stop us if we're active |
369 // stop us if we're active |
335 Cancel(); |
370 Cancel(); |
336 } |
371 } |
337 |
372 |
361 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: >>FileWriteHandler::BeginWriting")); |
396 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: >>FileWriteHandler::BeginWriting")); |
362 #endif |
397 #endif |
363 |
398 |
364 if ( !IsActive() ) |
399 if ( !IsActive() ) |
365 { |
400 { |
|
401 #ifdef HTTPCACHE_FILEWRITEDEBUG_ALWAYS_FIRE_OBSERVER |
|
402 // trigger index.dat observer |
|
403 RFile tempIndexFile; |
|
404 TInt err = tempIndexFile.Open(iFs, _L("C:\\system\\cache\\index.dat"), EFileWrite); |
|
405 if(err == KErrNone) |
|
406 { |
|
407 tempIndexFile.Seek(ESeekEnd, err); |
|
408 _LIT8(KIndexGarbage, "blahblah"); |
|
409 tempIndexFile.Write(KIndexGarbage()); |
|
410 tempIndexFile.Flush(); |
|
411 tempIndexFile.Close(); |
|
412 } |
|
413 #endif |
366 #ifdef __CACHELOG__ |
414 #ifdef __CACHELOG__ |
367 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: Setting FileWriteHandler %08x to active."), this); |
415 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: Setting FileWriteHandler %08x to active."), this); |
368 #endif |
416 #endif |
369 iStatus = KRequestPending; |
417 iStatus = KRequestPending; |
370 SetActive(); |
418 SetActive(); |
422 #ifdef __CACHELOG__ |
470 #ifdef __CACHELOG__ |
423 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: iObjectFlushing (%08x) is at position %d in list"), iObjectFlushing, index); |
471 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: iObjectFlushing (%08x) is at position %d in list"), iObjectFlushing, index); |
424 #endif |
472 #endif |
425 // the object might not exist in the queue.. how can this happen? |
473 // the object might not exist in the queue.. how can this happen? |
426 iObjectQueue.Remove(index); |
474 iObjectQueue.Remove(index); |
|
475 iObjectFlushing->ClearDeleteObserver(); |
|
476 |
427 // |
477 // |
428 if ( result != KErrNone ) |
478 if ( result != KErrNone ) |
429 { |
479 { |
430 #ifdef __CACHELOG__ |
480 #ifdef __CACHELOG__ |
431 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL Failure while writing object %08x"), iObjectFlushing); |
481 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL Failure while writing object %08x"), iObjectFlushing); |
451 else |
501 else |
452 { |
502 { |
453 // remove any items from the top of the queue which have no body data. |
503 // remove any items from the top of the queue which have no body data. |
454 while ( iObjectQueue.Count() && iObjectQueue[0]->BodySize() == 0 ) |
504 while ( iObjectQueue.Count() && iObjectQueue[0]->BodySize() == 0 ) |
455 { |
505 { |
|
506 iObjectQueue[0]->ClearDeleteObserver(); |
456 iObjectQueue.Remove(0); |
507 iObjectQueue.Remove(0); |
457 }; |
508 }; |
458 |
509 |
|
510 TBool goIdle = ETrue; |
459 // check to see if there is anything ready to write out |
511 // check to see if there is anything ready to write out |
460 if ( iObjectQueue.Count() ) |
512 if ( iObjectQueue.Count() ) |
461 { |
513 { |
462 SetActive(); |
514 // merge index if it's changed |
463 iStatus = KRequestPending; |
515 if(iCacheHandler->iHttpCacheObserver->Updated()) |
464 iCacheStreamHandler->FlushAsync( *iObjectQueue[0], iStatus ); |
516 iCacheHandler->iHttpCacheObserver->RunL(); |
465 iObjectFlushing = iObjectQueue[0]; |
517 |
466 #ifdef __CACHELOG__ |
518 // check again, merge may have removed all items |
467 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL continue cache flush, Starting object %08x."), iObjectFlushing); |
519 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. |
468 #endif |
520 { |
|
521 iStatus = KRequestPending; |
|
522 SetActive(); |
|
523 iCacheStreamHandler->FlushAsync( *iObjectQueue[0], iStatus ); |
|
524 iObjectFlushing = iObjectQueue[0]; |
|
525 goIdle = EFalse; |
|
526 #ifdef __CACHELOG__ |
|
527 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL continue cache flush, Starting object %08x."), iObjectFlushing); |
|
528 #endif |
|
529 } |
469 } |
530 } |
470 else |
531 |
|
532 if(goIdle) |
471 { // nothing left to write, go idle. |
533 { // nothing left to write, go idle. |
472 #ifdef __CACHELOG__ |
534 #ifdef __CACHELOG__ |
473 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL complete with nothing else to write.")); |
535 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: FileWriteHandler::RunL complete with nothing else to write.")); |
474 #endif |
536 #endif |
475 iCacheHandler->SaveLookupTableL(); |
537 iCacheHandler->SaveLookupTableL(); |