51 // CHttpCacheStreamHandler::CHttpCacheStreamHandler |
51 // CHttpCacheStreamHandler::CHttpCacheStreamHandler |
52 // C++ default constructor can NOT contain any code, that |
52 // C++ default constructor can NOT contain any code, that |
53 // might leave. |
53 // might leave. |
54 // ----------------------------------------------------------------------------- |
54 // ----------------------------------------------------------------------------- |
55 // |
55 // |
56 CHttpCacheStreamHandler::CHttpCacheStreamHandler() |
56 CHttpCacheStreamHandler::CHttpCacheStreamHandler(RFs& aRFs) |
|
57 : iRfs( aRFs ) |
57 { |
58 { |
58 } |
59 } |
59 |
60 |
60 // ----------------------------------------------------------------------------- |
61 // ----------------------------------------------------------------------------- |
61 // CHttpCacheStreamHandler::ConstructL |
62 // CHttpCacheStreamHandler::ConstructL |
62 // Symbian 2nd phase constructor can leave. |
63 // Symbian 2nd phase constructor can leave. |
63 // ----------------------------------------------------------------------------- |
64 // ----------------------------------------------------------------------------- |
64 // |
65 // |
65 void CHttpCacheStreamHandler::ConstructL( |
66 void CHttpCacheStreamHandler::ConstructL( |
66 const TDesC& aDirectory, |
67 const TDesC& aDirectory, |
67 TInt aCriticalLevel ) |
68 TInt aCriticalLevel) |
68 { |
69 { |
69 User::LeaveIfError( iRfs.Connect() ); |
|
70 // set path for the entries |
|
71 iRfs.SetSessionPath( aDirectory ); |
|
72 iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheActiveCount ); |
70 iActiveEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheActiveCount ); |
73 // get drive letter for sysutil |
71 // get drive letter for sysutil |
74 TParsePtrC pathParser( aDirectory ); |
72 TParsePtrC pathParser( aDirectory ); |
75 iDrive = pathParser.Drive(); |
73 iDrive = pathParser.Drive(); |
76 iCriticalLevel = aCriticalLevel; |
74 iCriticalLevel = aCriticalLevel; |
103 if ( iActiveEntries ) |
102 if ( iActiveEntries ) |
104 { |
103 { |
105 iActiveEntries->ResetAndDestroy(); |
104 iActiveEntries->ResetAndDestroy(); |
106 } |
105 } |
107 delete iActiveEntries; |
106 delete iActiveEntries; |
108 |
107 } |
109 iRfs.Close(); |
108 |
110 } |
109 // ----------------------------------------------------------------------------- |
111 |
110 // CHttpCacheStreamHandler::InitialiseCacheEntryL |
112 // ----------------------------------------------------------------------------- |
111 // ----------------------------------------------------------------------------- |
113 // CHttpCacheStreamHandler::AttachL |
112 // |
114 // |
113 void CHttpCacheStreamHandler::InitialiseCacheEntryL(CHttpCacheEntry& aCacheEntry) |
115 // ----------------------------------------------------------------------------- |
114 { |
116 // |
115 // create a filename for the cache entry. |
117 TBool CHttpCacheStreamHandler::AttachL( CHttpCacheEntry& aCacheEntry ) |
116 TPath sessionPath; |
118 { |
117 User::LeaveIfError( iRfs.SessionPath( sessionPath ) ); |
119 #ifdef __CACHELOG__ |
118 |
120 // check for duplicates |
119 // Given the full URL, generates a fully qualified path for saving the HTTP response |
121 for ( TInt i = 0; i < iActiveEntries->Count(); i++ ) |
120 HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( aCacheEntry.Url(), sessionPath ); |
122 { |
121 TPtrC bodyFileNamePtr( *bodyFileName ); |
123 __ASSERT_DEBUG( iActiveEntries->At( i ) != &aCacheEntry, |
122 aCacheEntry.SetFileNameL(bodyFileNamePtr); |
124 User::Panic( _L("cacheStreamHandler Panic"), KErrCorrupt ) ); |
123 |
125 } |
124 CleanupStack::PopAndDestroy(bodyFileName); |
126 #endif // __CACHELOG__ |
125 |
127 |
126 // any more one-time initialisation to go here. |
128 TBool cacheFilesOpened( EFalse ); |
127 aCacheEntry.SetState( CHttpCacheEntry::ECacheInitialized ); |
129 |
128 |
130 if ( aCacheEntry.CacheFilesOpened() ) |
129 // since this only happens one time, we can check if we have files left over with no index entry |
131 { |
130 // we're too late to reuse any information stored in there, so lets just delete them. This might prevent any |
132 // Cache files already opened, no need to reopen |
131 // problems later down the line.. |
133 cacheFilesOpened = ETrue; |
132 iRfs.Delete(aCacheEntry.Filename()); |
134 } |
133 // header filename |
135 else if ( aCacheEntry.State() == CHttpCacheEntry::ECacheUninitialized ) |
134 TFileName headerFileName; |
136 { |
135 HttpCacheUtil::GetHeaderFileName( aCacheEntry.Filename(), headerFileName ); |
137 // Create new cache files, they don't already exist |
136 iRfs.Delete(headerFileName); |
138 cacheFilesOpened = CreateNewFilesL( aCacheEntry ); |
137 } |
139 } |
138 |
140 else |
139 // ----------------------------------------------------------------------------- |
141 { |
140 // CHttpCacheStreamHandler::Erase |
142 // Open existing cache files |
141 // |
143 cacheFilesOpened = OpenCacheFiles( aCacheEntry ); |
142 // ----------------------------------------------------------------------------- |
144 } |
143 // |
145 |
144 void CHttpCacheStreamHandler::Erase( CHttpCacheEntry& aCacheEntry ) |
146 if ( cacheFilesOpened ) |
|
147 { |
|
148 // Add to our active array, if not already there |
|
149 TInt index( -1 ); |
|
150 FindCacheEntryIndex( aCacheEntry, &index ); |
|
151 if ( index == -1 ) |
|
152 { |
|
153 iActiveEntries->AppendL( &aCacheEntry ); |
|
154 } |
|
155 } |
|
156 |
|
157 aCacheEntry.SetCacheFilesOpened( cacheFilesOpened ); |
|
158 |
|
159 // Return ETrue, if files opened and attached |
|
160 return cacheFilesOpened; |
|
161 } |
|
162 |
|
163 // ----------------------------------------------------------------------------- |
|
164 // CHttpCacheStreamHandler::Detach |
|
165 // |
|
166 // ----------------------------------------------------------------------------- |
|
167 // |
|
168 void CHttpCacheStreamHandler::Detach( CHttpCacheEntry& aCacheEntry ) |
|
169 { |
|
170 // Close the files, this will commit changes |
|
171 if ( aCacheEntry.CacheFilesOpened() ) |
|
172 { |
|
173 aCacheEntry.BodyFile().Close(); |
|
174 aCacheEntry.HeaderFile().Close(); |
|
175 aCacheEntry.SetCacheFilesOpened( EFalse ); |
|
176 } |
|
177 |
|
178 // Delete from our active array |
|
179 TInt index( -1 ); |
|
180 FindCacheEntryIndex( (const CHttpCacheEntry&)aCacheEntry, &index ); |
|
181 if ( index >= 0 ) |
|
182 { |
|
183 iActiveEntries->Delete( index ); |
|
184 } |
|
185 } |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CHttpCacheStreamHandler::EraseCacheFile |
|
189 // |
|
190 // ----------------------------------------------------------------------------- |
|
191 // |
|
192 void CHttpCacheStreamHandler::EraseCacheFile( CHttpCacheEntry& aCacheEntry ) |
|
193 { |
145 { |
194 HttpCacheUtil::WriteUrlToLog( 0, _L( "CHttpCacheStreamHandler::Erase - erase files associated with" ), aCacheEntry.Url() ); |
146 HttpCacheUtil::WriteUrlToLog( 0, _L( "CHttpCacheStreamHandler::Erase - erase files associated with" ), aCacheEntry.Url() ); |
195 |
147 |
196 aCacheEntry.HeaderFile().Close(); |
148 // just in case it's busy being written out... |
197 aCacheEntry.BodyFile().Close(); |
149 aCacheEntry.CancelBodyWrite(); |
198 aCacheEntry.SetCacheFilesOpened( EFalse ); |
150 |
199 |
151 // Delete body file |
200 // Get body filename |
152 #ifndef __CACHELOG__ |
201 TFileName bodyFileName = aCacheEntry.Filename(); |
153 iRfs.Delete( aCacheEntry.Filename() ); |
202 |
154 #else |
203 // Get header filename |
|
204 TFileName headerFileName; |
|
205 HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName ); |
|
206 |
|
207 TInt statusBody( KErrNotFound ); |
155 TInt statusBody( KErrNotFound ); |
208 statusBody = iRfs.Delete( bodyFileName ); |
156 statusBody = iRfs.Delete( aCacheEntry.Filename() ); |
209 |
157 #endif |
210 TInt statusHeader( KErrNotFound ); |
|
211 statusHeader = iRfs.Delete( headerFileName ); |
|
212 |
|
213 // Adjust the size |
158 // Adjust the size |
214 iContentSize -= aCacheEntry.BodySize(); |
159 iContentSize -= aCacheEntry.BodySize(); |
215 iContentSize -= aCacheEntry.HeaderSize(); |
160 iContentSize -= aCacheEntry.HeaderSize(); |
216 |
161 |
217 #ifdef __CACHELOG__ |
162 #ifdef __CACHELOG__ |
218 if ( statusBody != KErrNone ) { |
163 if ( statusBody == KErrNone ) |
|
164 { |
219 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
165 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
220 _L("CCHttpCacheStreamEntry::Erase - ERROR bodyFile delete"), |
166 _L("CHttpCacheStreamHandler::Erase - SUCCESS bodyFile delete"), |
|
167 aCacheEntry.Filename(), |
|
168 aCacheEntry.Url(), |
|
169 aCacheEntry.BodySize(), |
|
170 ELogEntrySize ); |
|
171 } |
|
172 else if ( statusBody == KErrNotFound ) |
|
173 { |
|
174 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
175 _L("CHttpCacheStreamHandler::Erase - CHECK bodyFile not found."), |
221 aCacheEntry.Filename(), |
176 aCacheEntry.Filename(), |
222 aCacheEntry.Url(), |
177 aCacheEntry.Url(), |
223 statusBody, |
178 statusBody, |
224 ELogFileErrorCode ); |
179 ELogFileErrorCode ); |
225 } |
180 } |
226 else { |
181 else |
227 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
182 { |
228 _L("CCHttpCacheStreamEntry::Erase - SUCCESS bodyFile delete"), |
183 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
229 aCacheEntry.Filename(), |
184 _L("CHttpCacheStreamHandler::Erase - ERROR bodyFile delete"), |
230 aCacheEntry.Url(), |
185 aCacheEntry.Filename(), |
231 aCacheEntry.BodySize(), |
186 aCacheEntry.Url(), |
232 ELogEntrySize ); |
187 statusBody, |
233 } |
188 ELogFileErrorCode ); |
234 if ( statusHeader != KErrNone ) { |
|
235 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
236 _L("CCHttpCacheStreamEntry::Erase - ERROR headerFile delete"), |
|
237 aCacheEntry.Filename(), |
|
238 aCacheEntry.Url(), |
|
239 statusHeader, |
|
240 ELogFileErrorCode ); |
|
241 } |
|
242 else { |
|
243 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
244 _L("CCHttpCacheStreamEntry::Erase - SUCCESS headerFile delete"), |
|
245 aCacheEntry.Filename(), |
|
246 aCacheEntry.Url(), |
|
247 aCacheEntry.BodySize(), |
|
248 ELogEntrySize ); |
|
249 } |
189 } |
250 #endif //__CACHELOG__ |
190 #endif //__CACHELOG__ |
251 |
|
252 } |
191 } |
253 |
192 |
254 // ----------------------------------------------------------------------------- |
193 // ----------------------------------------------------------------------------- |
255 // CHttpCacheStreamHandler::HeadersL |
194 // CHttpCacheStreamHandler::HeadersL |
256 // |
195 // |
257 // ----------------------------------------------------------------------------- |
196 // ----------------------------------------------------------------------------- |
258 // |
197 // |
259 HBufC8* CHttpCacheStreamHandler::HeadersL( CHttpCacheEntry& aCacheEntry ) |
198 HBufC8* CHttpCacheStreamHandler::HeadersL( CHttpCacheEntry& aCacheEntry ) |
260 { |
199 { |
261 HBufC8* headerStr = NULL; |
200 return aCacheEntry.HeaderData().AllocL(); |
262 TInt headerLen( 0 ); |
|
263 TInt err( KErrNone ); |
|
264 |
|
265 if ( !aCacheEntry.CacheFilesOpened() ) |
|
266 { |
|
267 OpenCacheFiles( aCacheEntry ); |
|
268 } |
|
269 |
|
270 err = aCacheEntry.HeaderFile().Size( headerLen ); |
|
271 if ( err == KErrNone && headerLen > 0 ) |
|
272 { |
|
273 headerStr = HBufC8::NewL( headerLen ); |
|
274 TPtr8 ptr( headerStr->Des() ); |
|
275 // read headers |
|
276 aCacheEntry.HeaderFile().Read( 0, ptr, headerLen ); |
|
277 } |
|
278 |
|
279 return headerStr; |
|
280 } |
201 } |
281 |
202 |
282 // ----------------------------------------------------------------------------- |
203 // ----------------------------------------------------------------------------- |
283 // CHttpCacheStreamHandler::NextChunkL |
204 // CHttpCacheStreamHandler::NextChunkL |
284 // |
205 // |
286 // |
207 // |
287 HBufC8* CHttpCacheStreamHandler::NextChunkL( |
208 HBufC8* CHttpCacheStreamHandler::NextChunkL( |
288 CHttpCacheEntry& aCacheEntry, |
209 CHttpCacheEntry& aCacheEntry, |
289 TBool& aLastChunk ) |
210 TBool& aLastChunk ) |
290 { |
211 { |
291 HBufC8* bodyStr = NULL; |
212 HBufC8 *bodyStr = NULL; |
292 // Read whole body |
213 |
293 TInt size( 0 ); |
214 if ( !aCacheEntry.BodyDataCached() && OpenBodyFile(aCacheEntry) ) |
294 TInt sizeErr( KErrNone ); |
215 { |
295 |
216 CleanupClosePushL( aCacheEntry.BodyFile() ); |
296 if ( !aCacheEntry.CacheFilesOpened() ) |
217 |
297 { |
218 // read body |
298 OpenCacheFiles( aCacheEntry ); |
219 TInt size; |
299 } |
220 TInt err( aCacheEntry.BodyFile().Size( size ) ); |
300 |
221 if ( err == KErrNone && size > 0 ) |
301 sizeErr = aCacheEntry.BodyFile().Size( size ); |
222 { |
302 if ( sizeErr == KErrNone && size > 0 ) |
223 bodyStr = HBufC8::NewL( size ); |
303 { |
224 TPtr8 ptr( bodyStr->Des() ); |
|
225 // |
|
226 err = aCacheEntry.BodyFile().Read( ptr, size ); |
|
227 #ifdef __CACHELOG__ |
|
228 if ( err != KErrNone ) { |
|
229 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
230 _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"), |
|
231 aCacheEntry.Filename(), |
|
232 aCacheEntry.Url(), |
|
233 err, |
|
234 ELogFileErrorCode ); |
|
235 } |
|
236 else { |
|
237 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
238 _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"), |
|
239 aCacheEntry.Filename(), |
|
240 aCacheEntry.Url(), |
|
241 ptr.Length(), |
|
242 ELogEntrySize ); |
|
243 } |
|
244 #endif // __CACHELOG__ |
|
245 } |
|
246 // Close body file |
|
247 CleanupStack::PopAndDestroy(1); |
|
248 } |
|
249 else |
|
250 { |
|
251 // reuse stored data if we have any. |
|
252 CSegmentedHeapBuffer& buffer = aCacheEntry.BodyData(); |
|
253 TInt size = buffer.Length(); |
304 bodyStr = HBufC8::NewL( size ); |
254 bodyStr = HBufC8::NewL( size ); |
305 TPtr8 ptr( bodyStr->Des() ); |
255 TPtr8 ptr(bodyStr->Des()); |
306 |
256 |
307 TInt readErr( KErrNone ); |
257 TInt readSegment = 0; |
308 readErr = aCacheEntry.BodyFile().Read( ptr, size ); |
258 TInt count = buffer.Count(); |
309 |
259 while(readSegment < count) |
310 #ifdef __CACHELOG__ |
260 { |
311 if ( readErr != KErrNone ) { |
261 TPtrC8 source = buffer.GetSegmentData(readSegment); |
312 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
262 ptr.Append(source); |
313 _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"), |
263 } |
314 aCacheEntry.Filename(), |
|
315 aCacheEntry.Url(), |
|
316 readErr, |
|
317 ELogFileErrorCode ); |
|
318 } |
|
319 else { |
|
320 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
|
321 _L("CCHttpCacheStreamEntry::NextChunkL - bodyFile.read"), |
|
322 aCacheEntry.Filename(), |
|
323 aCacheEntry.Url(), |
|
324 ptr.Length(), |
|
325 ELogEntrySize ); |
|
326 } |
|
327 #endif // __CACHELOG__ |
|
328 |
|
329 } |
264 } |
330 aLastChunk = ETrue; |
265 aLastChunk = ETrue; |
331 |
|
332 return bodyStr; |
266 return bodyStr; |
333 } |
267 } |
334 |
268 |
335 // ----------------------------------------------------------------------------- |
269 // ----------------------------------------------------------------------------- |
336 // CHttpCacheStreamHandler::SaveHeaders |
270 // CHttpCacheStreamHandler::SaveHeaders |
386 // |
309 // |
387 TBool CHttpCacheStreamHandler::SaveBodyData( |
310 TBool CHttpCacheStreamHandler::SaveBodyData( |
388 CHttpCacheEntry& aCacheEntry, |
311 CHttpCacheEntry& aCacheEntry, |
389 const TDesC8& aBodyStr ) |
312 const TDesC8& aBodyStr ) |
390 { |
313 { |
391 TInt bodySaved( EFalse ); |
314 TInt bodySaved( KErrNone ); |
392 TInt newBodyLength( aBodyStr.Length() ); |
315 TInt newBodyLength( aBodyStr.Length() ); |
393 TPtr8 buffer( aCacheEntry.CacheBuffer() ); |
316 |
394 |
317 if ( newBodyLength ) |
395 if ( newBodyLength && buffer.MaxLength() ) |
318 { |
396 { |
319 TInt remainder = 0; |
397 // Calculate if we have enough space in the buffer for incoming body |
320 CSegmentedHeapBuffer& cacheBuffer = aCacheEntry.BodyData(); |
398 if ( buffer.Length() + newBodyLength > buffer.MaxLength() ) |
321 |
399 { |
322 // Add data to the buffer |
400 // Incoming data is too big for the buffer |
323 TRAPD( err, cacheBuffer.AppendL(remainder, aBodyStr) ); |
401 HBufC8* overflowBuffer = NULL; |
324 if ( err == KErrNone ) |
402 TInt bufferSpaceLeft( -1 ); |
325 { |
403 TPtrC8 writePtr; |
326 aCacheEntry.SetBodyDataCached(ETrue); |
404 |
327 } |
405 if ( buffer.Length() == 0 ) |
328 else |
|
329 { |
|
330 // We failed to allocate memory to store the new data in the current buffer. |
|
331 // Check to see if it's possible to write it to disk instead. |
|
332 TBool bodyFileCreated = CreateNewBodyFile( aCacheEntry ); |
|
333 if ( !bodyFileCreated ) |
406 { |
334 { |
407 // Buffer is empty and the body is bigger than the buffer, |
335 return EFalse; |
408 // just take all of the incoming data |
336 } |
409 writePtr.Set( aBodyStr ); |
337 |
|
338 TBool enoughSpace; |
|
339 enoughSpace = IsDiskSpaceAvailable( cacheBuffer.Length() + remainder ); |
|
340 if ( enoughSpace ) |
|
341 { |
|
342 // In this case, we have not been able to store all the data. |
|
343 // if there is enough space on disk to write everything we know |
|
344 // about now, we will flush the current buffer out synchronously. |
|
345 TInt block=0; |
|
346 TInt count = cacheBuffer.Count(); |
|
347 while ( bodySaved == KErrNone && count > block ) |
|
348 { |
|
349 TPtrC8 buf = cacheBuffer.GetSegmentData(block); |
|
350 bodySaved = aCacheEntry.BodyFile().Write(buf); |
|
351 } |
410 } |
352 } |
411 else |
353 else |
412 { |
354 { |
413 // We have some data in buffer, how much space do we have left |
355 // disk too full, drop the cache data |
414 bufferSpaceLeft = buffer.MaxLength() - buffer.Length(); |
356 bodySaved = KErrDiskFull; |
415 |
357 // reset buffers |
416 if ( newBodyLength - bufferSpaceLeft > buffer.MaxLength() ) |
358 cacheBuffer.Reset(); |
417 { |
|
418 // Not enough space, so lets put the buffer and the new |
|
419 // body together and write it in one go. |
|
420 overflowBuffer = HBufC8::New( buffer.Length() + newBodyLength ); |
|
421 if ( !overflowBuffer ) |
|
422 { |
|
423 return EFalse; |
|
424 } |
|
425 |
|
426 TPtr8 overflowPtr( overflowBuffer->Des() ); |
|
427 overflowPtr.Copy( buffer ); |
|
428 overflowPtr.Append( aBodyStr ); |
|
429 writePtr.Set( overflowBuffer->Des() ); |
|
430 |
|
431 // empty buffer |
|
432 buffer.Zero(); |
|
433 // no leftover left |
|
434 bufferSpaceLeft = -1; |
|
435 } |
|
436 else |
|
437 { |
|
438 // Copy what we have enough space for |
|
439 buffer.Append( aBodyStr.Left( bufferSpaceLeft ) ); |
|
440 writePtr.Set( buffer ); |
|
441 } |
|
442 } |
359 } |
443 |
360 |
444 // Write to the disk, if we have disk space |
361 if ( bodySaved == KErrNone ) |
445 TInt writeErr( KErrNone ); |
|
446 if ( IsDiskSpaceAvailable( writePtr.Length() ) ) |
|
447 { |
362 { |
448 |
363 // We have completed writing out the cached data, now |
449 if ( !aCacheEntry.CacheFilesOpened() ) |
364 // try to save the new data if we haven't run out of disk space. |
450 { |
365 bodySaved = aCacheEntry.BodyFile().Write(aBodyStr.Right(remainder)); |
451 OpenCacheFiles( aCacheEntry ); |
|
452 } |
|
453 |
|
454 // We have enough disk space, save body |
|
455 TInt writeErr = aCacheEntry.BodyFile().Write( writePtr ); |
|
456 bodySaved = ETrue; |
|
457 } |
366 } |
458 else |
367 aCacheEntry.SetBodyDataCached(EFalse); |
459 { |
368 aCacheEntry.BodyFile().Close(); |
460 // We don't have enough disk space, clean up |
369 } |
461 bodySaved = EFalse; |
370 // update size information |
462 buffer.Zero(); |
|
463 } |
|
464 |
|
465 if ( writeErr == KErrNone && bufferSpaceLeft >= 0 ) |
|
466 { |
|
467 // Copy what we can of the leftover in to the buffer |
|
468 buffer.Copy( aBodyStr.Mid( bufferSpaceLeft ) ); |
|
469 } |
|
470 delete overflowBuffer; |
|
471 } |
|
472 else |
|
473 { |
|
474 // We have enough space in buffer, add and wait for next body |
|
475 // before writing to file |
|
476 buffer.Append( aBodyStr ); |
|
477 bodySaved = ETrue; |
|
478 } |
|
479 |
|
480 // Body saved, update state |
|
481 aCacheEntry.SetBodySize( aCacheEntry.BodySize() + newBodyLength ); |
371 aCacheEntry.SetBodySize( aCacheEntry.BodySize() + newBodyLength ); |
482 iContentSize += aBodyStr.Length(); |
372 iContentSize += aBodyStr.Length(); |
483 } |
373 } |
484 |
374 return ( bodySaved == KErrNone ); |
485 return bodySaved; |
|
486 } |
375 } |
487 |
376 |
488 // ----------------------------------------------------------------------------- |
377 // ----------------------------------------------------------------------------- |
489 // CHttpCacheStreamHandler::RemoveBodyData |
378 // CHttpCacheStreamHandler::RemoveBodyData |
490 // |
379 // |
499 aCacheEntry.Url(), |
388 aCacheEntry.Url(), |
500 aCacheEntry.BodySize(), |
389 aCacheEntry.BodySize(), |
501 ELogEntrySize ); |
390 ELogEntrySize ); |
502 #endif |
391 #endif |
503 |
392 |
504 // Remove data |
393 // Remove data |
505 iContentSize -= aCacheEntry.BodySize(); |
394 iContentSize -= aCacheEntry.BodySize(); |
506 aCacheEntry.SetBodySize( 0 ); |
395 aCacheEntry.SetBodySize( 0 ); |
507 aCacheEntry.CacheBuffer().Zero(); |
396 aCacheEntry.BodyData().Reset(); |
508 aCacheEntry.BodyFile().SetSize( 0 ); |
397 if ( OpenBodyFile(aCacheEntry) ) |
|
398 { |
|
399 aCacheEntry.BodyFile().SetSize( 0 ); |
|
400 aCacheEntry.BodyFile().Close(); |
|
401 } |
509 } |
402 } |
510 |
403 |
511 // ----------------------------------------------------------------------------- |
404 // ----------------------------------------------------------------------------- |
512 // CHttpCacheStreamHandler::Flush |
405 // CHttpCacheStreamHandler::Flush |
513 // |
406 // |
514 // ----------------------------------------------------------------------------- |
407 // ----------------------------------------------------------------------------- |
515 // |
408 // |
516 TBool CHttpCacheStreamHandler::Flush( CHttpCacheEntry& aCacheEntry ) |
409 TBool CHttpCacheStreamHandler::Flush( CHttpCacheEntry& aCacheEntry ) |
517 { |
410 { |
518 TBool saved( EFalse ); |
411 TInt err( KErrNone ); |
519 TInt writeErr( KErrGeneral ); |
412 TBool bFlushed( EFalse ); |
520 TInt cacheBufferLen( aCacheEntry.CacheBuffer().Length() ); |
413 |
521 |
414 TRAP( err, bFlushed = FlushL( aCacheEntry ) ); |
522 if ( cacheBufferLen && IsDiskSpaceAvailable( cacheBufferLen ) ) |
415 if ( err || !bFlushed ) |
523 { |
416 { |
524 // We have enough space, save cache buffer |
417 return EFalse; |
525 TPtr8 bufferPtr( aCacheEntry.CacheBuffer() ); |
418 } |
526 if ( bufferPtr.Length() ) |
419 |
527 { |
420 return ETrue; |
528 if ( !aCacheEntry.CacheFilesOpened() ) |
421 } |
529 { |
422 |
530 OpenCacheFiles( aCacheEntry ); |
423 // ----------------------------------------------------------------------------- |
531 } |
424 // CHttpCacheStreamHandler::FlushL |
532 |
425 // |
533 writeErr = aCacheEntry.BodyFile().Write( bufferPtr ); |
426 // ----------------------------------------------------------------------------- |
534 if ( writeErr == KErrNone ) |
427 // |
535 { |
428 TBool CHttpCacheStreamHandler::FlushL( CHttpCacheEntry& aCacheEntry ) |
536 saved = ETrue; |
429 { |
537 } |
430 TInt saveOk( KErrNone ); |
538 } |
431 |
539 |
432 #ifdef __CACHELOG__ |
540 // Clear the buffer |
433 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: >>StreamHander::Flush object %08x"), &aCacheEntry ); |
541 bufferPtr.Zero(); |
434 #endif |
542 } |
435 CSegmentedHeapBuffer& cacheBuffer = aCacheEntry.BodyData(); |
543 |
436 |
544 return saved; |
437 TInt dataLength = cacheBuffer.Length() + aCacheEntry.HeaderData().Length(); |
545 } |
438 |
546 |
439 if ( !IsDiskSpaceAvailable( dataLength ) || !CreateNewBodyFile( aCacheEntry ) ) |
547 // ----------------------------------------------------------------------------- |
440 { |
548 // CHttpCacheStreamHandler::OpenCacheFiles |
441 #ifdef __CACHELOG__ |
549 // |
442 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: Flush failed: not enough space or cannot create file.")); |
550 // ----------------------------------------------------------------------------- |
443 #endif |
551 // |
444 // can't flush if not enough space, or cannot create new files |
552 TBool CHttpCacheStreamHandler::OpenCacheFiles( CHttpCacheEntry& aCacheEntry ) |
445 return EFalse; |
|
446 } |
|
447 |
|
448 // files are open, push them onto cleanup stack. |
|
449 CleanupClosePushL( aCacheEntry.BodyFile() ); |
|
450 |
|
451 if ( aCacheEntry.BodyDataCached() ) |
|
452 { |
|
453 #ifdef __CACHELOG__ |
|
454 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: Body Data is Cached")); |
|
455 #endif |
|
456 // append body |
|
457 TInt segment=0; |
|
458 TInt count=cacheBuffer.Count(); |
|
459 #ifdef __CACHELOG__ |
|
460 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: %d segments stored"), count); |
|
461 #endif |
|
462 while ( saveOk == KErrNone && count > segment ) |
|
463 { |
|
464 TPtrC8 segBuf = cacheBuffer.GetSegmentData(segment); |
|
465 saveOk = aCacheEntry.BodyFile().Write( segBuf ); |
|
466 #ifdef __CACHELOG__ |
|
467 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: segment %d write returned %d"), (segment-1), saveOk ); |
|
468 #endif |
|
469 } |
|
470 |
|
471 cacheBuffer.Reset(); |
|
472 aCacheEntry.SetBodyDataCached(EFalse); |
|
473 } |
|
474 // close files |
|
475 CleanupStack::PopAndDestroy(1); |
|
476 |
|
477 return ( saveOk == KErrNone ); |
|
478 } |
|
479 |
|
480 // ----------------------------------------------------------------------------- |
|
481 // CHttpCacheStreamHandler::FlushAsync |
|
482 // |
|
483 // ----------------------------------------------------------------------------- |
|
484 // |
|
485 TInt CHttpCacheStreamHandler::FlushAsync(CHttpCacheEntry& aEntry, TRequestStatus& aStatus) |
|
486 { |
|
487 TInt saveOk( KErrNone ); |
|
488 |
|
489 TInt datalen = aEntry.BodyData().Length() + aEntry.HeaderData().Length(); |
|
490 |
|
491 #ifdef __CACHELOG__ |
|
492 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: CHttpCacheStreamEntry::FlushAsync called on object %08x. Cached data %d bytes"), &aEntry, datalen ); |
|
493 #endif |
|
494 |
|
495 if ( datalen && aEntry.BodyData().Length() ) // don't bother writing files which have no body data |
|
496 { |
|
497 if ( IsDiskSpaceAvailable( datalen ) && CreateNewBodyFile( aEntry ) ) |
|
498 { |
|
499 #ifdef __CACHELOG__ |
|
500 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: Triggering Async write for object 0x%08x."), &aEntry); |
|
501 #endif |
|
502 // trim any spare space available. |
|
503 aEntry.BodyData().Compress(); |
|
504 aEntry.WriteBodyDataAsync(aStatus); |
|
505 aEntry.SetDelayedWriteInProgress(ETrue); |
|
506 } |
|
507 else |
|
508 { |
|
509 #ifdef __CACHELOG__ |
|
510 HttpCacheUtil::WriteLog(0, _L("CACHEPOSTPONE: FAILED FlushAsync.")); |
|
511 #endif |
|
512 // !enoughSpace |
|
513 saveOk = KErrDiskFull; |
|
514 aEntry.BodyData().Reset(); |
|
515 } |
|
516 } |
|
517 else |
|
518 { |
|
519 #ifdef __CACHELOG__ |
|
520 HttpCacheUtil::WriteFormatLog(0, _L("CACHEPOSTPONE: Not writing file %S for entry %08x since it has no data."), &(aEntry.Filename()), &aEntry ); |
|
521 #endif |
|
522 TRequestStatus* stat = &aStatus; |
|
523 User::RequestComplete(stat, KErrNone); |
|
524 } |
|
525 |
|
526 return ( saveOk == KErrNone ); |
|
527 } |
|
528 |
|
529 // ----------------------------------------------------------------------------- |
|
530 // CHttpCacheStreamHandler::OpenBodyFile |
|
531 // ----------------------------------------------------------------------------- |
|
532 // |
|
533 TBool CHttpCacheStreamHandler::OpenBodyFile( CHttpCacheEntry& aCacheEntry ) |
|
534 { |
|
535 TInt statusBody( KErrNotFound ); |
|
536 |
|
537 // get body filename |
|
538 TFileName bodyFileName = aCacheEntry.Filename(); |
|
539 |
|
540 statusBody = aCacheEntry.BodyFile().Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite ); |
|
541 |
|
542 return ( statusBody == KErrNone ); |
|
543 } |
|
544 |
|
545 #if 0 |
|
546 // ----------------------------------------------------------------------------- |
|
547 // CHttpCacheStreamHandler::CreateNewFilesL |
|
548 // |
|
549 // ----------------------------------------------------------------------------- |
|
550 // |
|
551 TBool CHttpCacheStreamHandler::CreateNewFilesL( CHttpCacheEntry& aCacheEntry ) |
553 { |
552 { |
554 TInt statusHeader( KErrNotFound ); |
553 TInt statusHeader( KErrNotFound ); |
555 TInt statusBody( KErrNotFound ); |
554 TInt statusBody( KErrNotFound ); |
556 |
555 |
557 // get body filename |
|
558 TFileName bodyFileName = aCacheEntry.Filename(); |
|
559 |
|
560 // header filename |
|
561 TFileName headerFileName; |
|
562 HttpCacheUtil::GetHeaderFileName( bodyFileName, headerFileName ); |
|
563 |
|
564 statusHeader = aCacheEntry.HeaderFile().Open( iRfs, headerFileName, EFileShareExclusive | EFileWrite ); |
|
565 statusBody = aCacheEntry.BodyFile().Open( iRfs, bodyFileName, EFileShareExclusive | EFileWrite ); |
|
566 |
|
567 TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone ); |
|
568 if ( fileOk ) |
|
569 { |
|
570 aCacheEntry.SetCacheFilesOpened( ETrue ); |
|
571 } |
|
572 |
|
573 return fileOk; |
|
574 } |
|
575 |
|
576 // ----------------------------------------------------------------------------- |
|
577 // CHttpCacheStreamHandler::CreateNewFilesL |
|
578 // |
|
579 // ----------------------------------------------------------------------------- |
|
580 // |
|
581 TBool CHttpCacheStreamHandler::CreateNewFilesL( CHttpCacheEntry& aCacheEntry ) |
|
582 { |
|
583 TInt statusHeader( KErrNotFound ); |
|
584 TInt statusBody( KErrNotFound ); |
|
585 TPath sessionPath; |
|
586 User::LeaveIfError( iRfs.SessionPath( sessionPath ) ); |
|
587 |
|
588 // Given the full URL, generates a fully qualified path for saving the HTTP response |
|
589 HBufC* bodyFileName = HttpCacheUtil::GenerateNameLC( aCacheEntry.Url(), sessionPath ); |
|
590 TPtrC bodyFileNamePtr( *bodyFileName ); |
|
591 |
|
592 // Create header file name from body file name |
556 // Create header file name from body file name |
593 TFileName headerFileName; |
557 TFileName headerFileName; |
594 HttpCacheUtil::GetHeaderFileName( bodyFileNamePtr, headerFileName ); |
558 HttpCacheUtil::GetHeaderFileName( aCacheEntry.Filename(), headerFileName ); |
595 |
559 |
596 // Create the body file or replace it, if it exists. |
560 // Create the body file or replace it, if it exists. |
597 statusBody = aCacheEntry.BodyFile().Replace( iRfs, bodyFileNamePtr, EFileShareExclusive | EFileWrite ); |
561 statusBody = aCacheEntry.BodyFile().Replace( iRfs, aCacheEntry.Filename(), EFileShareExclusive | EFileWrite ); |
598 if ( statusBody == KErrNone ) |
562 if ( statusBody == KErrNone ) |
599 { |
563 { |
600 // Header file should not fail |
564 // Header file should not fail |
601 statusHeader = aCacheEntry.HeaderFile().Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite ); |
565 statusHeader = aCacheEntry.HeaderFile().Replace( iRfs, headerFileName, EFileShareExclusive | EFileWrite ); |
602 } |
566 } |
603 |
567 |
604 #ifdef __CACHELOG__ |
568 #ifdef __CACHELOG__ |
605 HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, aCacheEntry.Url() ); |
569 HttpCacheUtil::WriteUrlToLog( 0, bodyFileNamePtr, aCacheEntry.Url() ); |
606 #endif |
570 #endif |
607 |
571 |
608 TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone ); |
572 TBool fileOk( statusHeader == KErrNone && statusBody == KErrNone ); |
609 if ( fileOk ) |
573 if ( !fileOk ) |
610 { |
574 { |
611 // Both body and header files created correctly |
575 // Only the body file created, no header file, delete body file |
612 aCacheEntry.SetFileNameL( bodyFileNamePtr ); |
576 iRfs.Delete( aCacheEntry.Filename() ); |
613 aCacheEntry.SetState( CHttpCacheEntry::ECacheInitialized ); |
|
614 } |
|
615 else |
|
616 { |
|
617 // Only the body file created, no header file, delete body file |
|
618 iRfs.Delete( bodyFileNamePtr ); |
|
619 iRfs.Delete( headerFileName ); |
577 iRfs.Delete( headerFileName ); |
620 |
578 |
621 aCacheEntry.SetBodySize( 0 ); |
579 aCacheEntry.SetBodySize( 0 ); |
622 aCacheEntry.SetHeaderSize( 0 ); |
580 aCacheEntry.SetHeaderSize( 0 ); |
623 |
581 |