76 // ----------------------------------------------------------------------------- |
86 // ----------------------------------------------------------------------------- |
77 // |
87 // |
78 void CHttpCacheHandler::ConstructL( |
88 void CHttpCacheHandler::ConstructL( |
79 const TDesC& aDirectory, |
89 const TDesC& aDirectory, |
80 const TDesC& aIndexFile, |
90 const TDesC& aIndexFile, |
81 TInt aCriticalLevel) |
91 TInt aCriticalLevel, |
82 { |
92 const THttpCachePostponeParameters& aPostpone) |
83 User::LeaveIfError(iRfs.Connect()); |
93 { |
|
94 User::LeaveIfError(iRfs.Connect()); |
84 // |
95 // |
85 iIndexFile = aIndexFile.AllocL(); |
96 iIndexFile = aIndexFile.AllocL(); |
86 // |
97 // |
87 iDirectory = aDirectory.AllocL(); |
98 iDirectory = aDirectory.AllocL(); |
88 // |
99 //1. Set up top-level cache directory if it doesn't exist. |
89 iEvictionHandler = CHttpCacheEvictionHandler::NewL(); |
|
90 // |
|
91 iStreamHandler = CHttpCacheStreamHandler::NewL( iDirectory->Des(), aCriticalLevel ); |
|
92 // |
|
93 iLookupTable = CHttpCacheLookupTable::NewL( *iEvictionHandler, *iStreamHandler ); |
|
94 //1. Set up top-level cache directory if it doesn't exist. |
|
95 TEntry entry; |
100 TEntry entry; |
96 TInt err( KErrNone ); |
101 TInt err( KErrNone ); |
97 if (iRfs.Entry(iDirectory->Des(), entry) != KErrNone) |
102 if ( iRfs.Entry(iDirectory->Des(), entry) != KErrNone ) |
98 { |
103 { |
99 err = iRfs.MkDirAll(iDirectory->Des()); |
104 err = iRfs.MkDirAll( iDirectory->Des() ); |
100 } |
105 } |
101 |
106 |
102 //2. Create subdirectories to store header/body files |
107 //2. Create subdirectories to store header/body files |
103 if ( err == KErrNone || err == KErrAlreadyExists ) { //harmless errors |
108 if ( err == KErrNone || err == KErrAlreadyExists ) { //harmless errors |
104 |
109 |
105 __ASSERT_DEBUG ( (iDirectory->Des().LocateReverse( KPathDelimiter ) == (iDirectory->Des().Length() - 1)), |
110 __ASSERT_DEBUG ( (iDirectory->Des().LocateReverse( KPathDelimiter ) == (iDirectory->Des().Length() - 1)), |
106 PanicCacheHandler( KErrCorrupt ) ); // We assume that iDirectory is terminated by a forward slash |
111 PanicCacheHandler( KErrCorrupt ) ); // We assume that iDirectory is terminated by a forward slash |
107 |
112 |
108 HBufC* subDir = HBufC::NewL(KMaxPath); // Base cache dir + subdir name + another delimiter |
113 HBufC* subDir = HBufC::NewL(KMaxPath); // Base cache dir + subdir name + another delimiter |
109 _LIT(KFormat,"%S%x%c"); |
114 _LIT(KFormat,"%S%x%c"); |
110 for (TUint i = 0; i < KCacheSubdirCount; i++) |
115 for ( TUint i = 0; i < KCacheSubdirCount; i++ ) |
111 { |
116 { |
112 TPtrC ptr (iDirectory->Des()); |
117 TPtrC ptr ( iDirectory->Des() ); |
113 subDir->Des().Format(KFormat, &ptr, i, KPathDelimiter); |
118 subDir->Des().Format( KFormat, &ptr, i, KPathDelimiter ); |
114 TInt err2 = iRfs.MkDir(subDir->Des()); |
119 TInt err2 = iRfs.MkDir( subDir->Des() ); |
115 __ASSERT_DEBUG ( (err2 == KErrNone || err2 == KErrAlreadyExists), PanicCacheHandler( err2 ) ); |
120 __ASSERT_DEBUG ( (err2 == KErrNone || err2 == KErrAlreadyExists), PanicCacheHandler( err2 ) ); |
116 } |
121 } |
117 delete subDir; |
122 delete subDir; |
118 //end cache dir + subdir creation |
123 //end cache dir + subdir creation |
119 } else { |
124 } else { |
120 User::Leave(err); |
125 User::Leave(err); |
121 } |
126 } |
122 |
127 |
123 OpenLookupTableL(); |
128 // set path for the entries |
|
129 iRfs.SetSessionPath( aDirectory ); |
|
130 #ifdef __USE_VALIDATION_FILES__ |
|
131 // create validation file |
|
132 TFileName validateFile; |
|
133 GenerateValidationFilename(validateFile, aIndexFile); |
|
134 |
|
135 TBool validateCacheEntries( EFalse ); |
|
136 RFile validate; |
|
137 TInt validateErr = validate.Create(iRfs, validateFile, EFileShareExclusive | EFileWrite); |
|
138 if ( validateErr != KErrNone ) |
|
139 { |
|
140 if ( validateErr == KErrAlreadyExists ) |
|
141 { |
|
142 validateCacheEntries = ETrue; |
|
143 } |
|
144 #ifdef _DEBUG |
|
145 else |
|
146 { |
|
147 // oh dear, we failed to create the file for some other reason, something must have gone properly wrong... |
|
148 User::Panic(_L("CacheHandler"), -9999); |
|
149 } |
|
150 #endif |
|
151 } |
|
152 validate.Close(); |
|
153 #endif |
|
154 // |
|
155 iEvictionHandler = CHttpCacheEvictionHandler::NewL(); |
|
156 // |
|
157 iStreamHandler = CHttpCacheStreamHandler::NewL( iDirectory->Des(), aCriticalLevel, iRfs ); |
|
158 // |
|
159 if ( aPostpone.iEnabled ) |
|
160 { |
|
161 iPostponeHandler = CHttpCacheFileWriteHandler::NewL(this, iStreamHandler, iRfs, aPostpone.iWriteTimeout); |
|
162 } |
|
163 // |
|
164 iLookupTable = CHttpCacheLookupTable::NewL( *iEvictionHandler, *iStreamHandler ); |
|
165 TRAP( err, OpenLookupTableL() ); |
|
166 if ( err != KErrNone ) |
|
167 { |
|
168 // failed to open the lookup table, delete the old one and start again. |
|
169 delete iLookupTable; |
|
170 iLookupTable = NULL; |
|
171 iLookupTable = CHttpCacheLookupTable::NewL( *iEvictionHandler, *iStreamHandler ); |
|
172 } |
|
173 #ifdef __USE_VALIDATION_FILES__ |
|
174 if ( validateCacheEntries ) |
|
175 #endif |
|
176 // ensure that the disk content matches the cache content |
|
177 ValidateCacheEntriesL(); |
|
178 |
124 // |
179 // |
125 iHttpCacheObserver = CHttpCacheObserver::NewL(iDirectory, iIndexFile, this); |
180 iHttpCacheObserver = CHttpCacheObserver::NewL(iDirectory, iIndexFile, this); |
126 iHttpCacheObserver->StartObserver(); |
181 iHttpCacheObserver->StartObserver(); |
127 } |
182 } |
128 |
183 |
185 THttpCacheEntry& aCacheEntry ) |
255 THttpCacheEntry& aCacheEntry ) |
186 { |
256 { |
187 #ifdef __CACHELOG__ |
257 #ifdef __CACHELOG__ |
188 HttpCacheUtil::WriteUrlToLog( 0, _L( "request item" ), aTrans.Request().URI().UriDes() ); |
258 HttpCacheUtil::WriteUrlToLog( 0, _L( "request item" ), aTrans.Request().URI().UriDes() ); |
189 #endif |
259 #endif |
190 |
|
191 TInt status( KErrNotFound ); |
260 TInt status( KErrNotFound ); |
192 CHttpCacheEntry* entry = NULL; |
261 CHttpCacheEntry* entry = NULL; |
193 // 0. check if we need to check cache at all (protected vs no cache mode) |
262 // 0. check if we need to check cache at all (protected vs no cache mode) |
194 // 1. check if the url is in the cache |
263 // 1. check if the url is in the cache |
195 // 2. check if it is complete |
264 // 2. check if it is complete |
196 // 3. see if it is useable |
265 // 3. see if it is useable |
197 |
266 |
198 // use protected item on reload |
267 // use protected item on reload |
199 // currently not and do not use cache for post |
268 // currently not and do not use cache for post |
200 if( aCacheMode != TBrCtlDefs::ECacheModeNoCache && |
269 if ( aCacheMode != TBrCtlDefs::ECacheModeNoCache && |
201 HttpCacheUtil::MethodFromStr( aTrans.Request().Method(), aTrans.Session().StringPool() ) != EMethodPost ) |
270 HttpCacheUtil::MethodFromStr( aTrans.Request().Method(), aTrans.Session().StringPool() ) != EMethodPost ) |
202 { |
271 { |
203 // If the cacheMode is noCache then it must ignore the cached entry. |
272 // If the cacheMode is noCache then it must ignore the cached entry. |
204 entry = iLookupTable->Find( aTrans.Request().URI().UriDes() ); |
273 entry = iLookupTable->Find( aTrans.Request().URI().UriDes() ); |
|
274 |
205 // check if the trailing slash is missing |
275 // check if the trailing slash is missing |
206 if( !entry ) |
276 if ( !entry ) |
207 { |
277 { |
208 TUriC8 uri = aTrans.Request().URI(); |
278 TUriC8 uri = aTrans.Request().URI(); |
209 |
279 |
210 if( uri.Extract( EUriPath ).Length() == 0 ) |
280 if ( uri.Extract( EUriPath ).Length() == 0 ) |
211 { |
281 { |
212 CUri8* fixeduri = CUri8::NewLC( uri ); |
282 CUri8* fixeduri = CUri8::NewLC( uri ); |
213 fixeduri->SetComponentL( _L8("/"), EUriPath ); |
283 fixeduri->SetComponentL( _L8("/"), EUriPath ); |
214 // |
284 // |
215 entry = iLookupTable->Find( fixeduri->Uri().UriDes() ); |
285 entry = iLookupTable->Find( fixeduri->Uri().UriDes() ); |
216 // |
286 // |
217 CleanupStack::PopAndDestroy(); // fixeduri |
287 CleanupStack::PopAndDestroy(); // fixeduri |
218 } |
288 } |
219 } |
289 } |
220 // |
290 // |
221 if( entry && entry->State() == CHttpCacheEntry::ECacheComplete ) |
291 if ( entry && entry->State() == CHttpCacheEntry::ECacheComplete ) |
222 { |
292 { |
223 #ifdef __CACHELOG__ |
293 #ifdef __CACHELOG__ |
224 HttpCacheUtil::WriteLog( 0, _L( "item is in the cache" ) ); |
294 HttpCacheUtil::WriteLog( 0, _L( "item is in the cache" ) ); |
225 #endif |
295 #endif |
226 // |
296 // |
227 status = CacheNeedsValidationL( *entry, aTrans, aCacheMode ) ? KErrNotReady : KErrNone; |
297 status = CacheNeedsValidationL( *entry, aTrans, aCacheMode ) ? KErrNotReady : KErrNone; |
228 // entry could be invalidated at this point. check for status to make sure |
298 // entry could be invalidated at this point. check for status to make sure |
229 // the entry is still valid |
299 // the entry is still valid |
|
300 |
230 } |
301 } |
231 // prepare stream for request |
302 // prepare stream for request |
232 if( status == KErrNone ) |
303 if ( status == KErrNone ) |
233 { |
304 { |
234 #ifdef __CACHELOG__ |
305 #ifdef __CACHELOG__ |
235 HttpCacheUtil::WriteLog( 0, _L( "prepare item for sending" ) ); |
306 HttpCacheUtil::WriteLog( 0, _L( "prepare item for sending" ) ); |
236 #endif |
307 #endif |
237 // attach entry to the stream |
308 // access the entry |
238 if( iStreamHandler->AttachL( *entry ) ) |
309 entry->SetState( CHttpCacheEntry::ECacheRequesting ); |
239 { |
310 entry->Accessed(); |
240 entry->SetState( CHttpCacheEntry::ECacheRequesting ); |
|
241 entry->Accessed(); |
|
242 } |
|
243 else |
|
244 { |
|
245 // cleanup on the corrupt entry |
|
246 DeleteCacheEntry( *entry ); |
|
247 entry = NULL; |
|
248 // item is not in cache |
|
249 status = KErrNotFound; |
|
250 } |
|
251 } |
311 } |
252 // cleanup |
312 // cleanup |
253 if( status == KErrNone && entry ) |
313 if ( status == KErrNone && entry ) |
254 { |
314 { |
255 // save handler and entry so that |
315 // save handler and entry so that |
256 // on next call we don't have to start a lookup again |
316 // on next call we don't have to start a lookup again |
257 aCacheEntry.iCacheHandler = this; |
317 aCacheEntry.iCacheHandler = this; |
258 aCacheEntry.iCacheEntry = entry; |
318 aCacheEntry.iCacheEntry = entry; |
661 ELogEntrySize ); |
710 ELogEntrySize ); |
662 #endif |
711 #endif |
663 |
712 |
664 if ( entry->State() == CHttpCacheEntry::ECacheResponding ) |
713 if ( entry->State() == CHttpCacheEntry::ECacheResponding ) |
665 { |
714 { |
666 // Flush the entry |
715 TBool postponed( EFalse ); |
667 if ( !iStreamHandler->Flush( *entry ) ) |
716 // flush the entry if necessary |
668 { |
717 if ( iPostponeHandler ) |
669 // We failed saving (flush), cleanup |
718 { |
670 iStreamHandler->Detach( *entry ); |
719 CHttpCacheFileWriteHandler::TAddStatus addStatus; |
671 |
720 TInt err = iPostponeHandler->AddEntry( addStatus, entry ); |
672 // Deleting the entry frees cache buffer |
721 |
673 DeleteCacheEntry( *entry ); |
722 switch ( addStatus ) |
674 entry = NULL; |
723 { |
675 aCacheEntry.iCacheEntry = NULL; |
724 case CHttpCacheFileWriteHandler::EAddedOk: |
676 } |
725 entry->SetState( CHttpCacheEntry::ECacheComplete ); |
677 else |
726 postponed = ETrue; |
678 { |
727 #ifdef __CACHELOG__ |
679 // We successfully saved (flush) body |
728 HttpCacheUtil::WriteLog( 0, _L(" Added object to postpone list.")); |
680 entry->SetState( CHttpCacheEntry::ECacheComplete ); |
729 #endif |
681 iStreamHandler->Detach( *entry ); |
730 break; |
682 |
731 case CHttpCacheFileWriteHandler::EBodySmallerThanThreshold: |
683 // Clear the flushed cache buffer, we were using for incoming body |
732 #ifdef __CACHELOG__ |
684 TRAP_IGNORE( entry->SetCacheBufferL( KBufferSizeZero ) ); |
733 HttpCacheUtil::WriteLog( 0, _L(" Not postponed. EBodySmallerThanThreshold")); |
685 } |
734 #endif |
686 } |
735 break; |
687 else if( entry->State() == CHttpCacheEntry::ECacheDestroyed ) |
736 case CHttpCacheFileWriteHandler::ENotEnoughFreeMemory: |
688 { |
737 #ifdef __CACHELOG__ |
689 iStreamHandler->Detach( *entry ); |
738 HttpCacheUtil::WriteLog( 0, _L(" Not postponed. ENotEnoughFreeMemory")); |
690 |
739 #endif |
691 // Deleting the entry frees cache buffer |
740 break; |
|
741 case CHttpCacheFileWriteHandler::ECheckReturn: |
|
742 #ifdef __CACHELOG__ |
|
743 HttpCacheUtil::WriteLog( 0, _L(" Not postponed. ECheckReturn - %d"), err ); |
|
744 #endif |
|
745 default: |
|
746 break; |
|
747 } |
|
748 } |
|
749 |
|
750 if ( !postponed ) |
|
751 { |
|
752 if ( !iStreamHandler->Flush( *entry ) ) |
|
753 { |
|
754 // remove entry |
|
755 DeleteCacheEntry( *entry ); |
|
756 entry = NULL; |
|
757 aCacheEntry.iCacheEntry = NULL; |
|
758 } |
|
759 else |
|
760 { |
|
761 // We successfully saved (flushed) body |
|
762 entry->SetState( CHttpCacheEntry::ECacheComplete ); |
|
763 } |
|
764 } |
|
765 } |
|
766 else if ( entry->State() == CHttpCacheEntry::ECacheDestroyed ) |
|
767 { |
692 DeleteCacheEntry( *entry, EFalse ); |
768 DeleteCacheEntry( *entry, EFalse ); |
693 entry = NULL; |
769 entry = NULL; |
694 aCacheEntry.iCacheEntry = NULL; |
770 aCacheEntry.iCacheEntry = NULL; |
695 } |
771 } |
696 } |
772 } |
697 } |
773 } |
698 |
774 |
699 // ----------------------------------------------------------------------------- |
775 // ----------------------------------------------------------------------------- |
700 // Removes all entries in the Cache lookup table, commits table to disk. |
776 // Removes all entries in the Cache lookup table, commits table to disk. |
701 // |
777 // |
702 // ----------------------------------------------------------------------------- |
778 // ----------------------------------------------------------------------------- |
703 // |
779 // |
704 TInt CHttpCacheHandler::RemoveAllL() |
780 TInt CHttpCacheHandler::RemoveAllL() |
705 { |
781 { |
706 #ifdef __CACHELOG__ |
782 #ifdef __CACHELOG__ |
707 HttpCacheUtil::WriteLog( 0, _L( "remove all items" ) ); |
783 HttpCacheUtil::WriteLog( 0, _L( "remove all items" ) ); |
708 #endif |
784 #endif |
709 TInt numberOfBytes; |
785 TInt numberOfBytes; |
|
786 |
|
787 // by definition, all entries in the postpone handler aren't active. |
|
788 if ( iPostponeHandler ) |
|
789 { |
|
790 iPostponeHandler->RemoveAll(); |
|
791 } |
|
792 |
710 // clear all the inactive entries |
793 // clear all the inactive entries |
711 numberOfBytes = iLookupTable->RemoveAll(); |
794 numberOfBytes = iLookupTable->RemoveAll(); |
|
795 |
712 // and save it. user initiated. no need to do idle save |
796 // and save it. user initiated. no need to do idle save |
713 SaveLookupTableL(); |
797 SaveLookupTableL(); |
714 return numberOfBytes; |
798 return numberOfBytes; |
715 } |
799 } |
716 |
800 |
889 // |
963 // |
890 // Note: Cache also set the cacheMode to PreferCache after a resource has |
964 // Note: Cache also set the cacheMode to PreferCache after a resource has |
891 // been validated -- that is when it tries to refetch an entry from |
965 // been validated -- that is when it tries to refetch an entry from |
892 // cache after receiving a 304 response. |
966 // cache after receiving a 304 response. |
893 // get cached headers |
967 // get cached headers |
894 if( iStreamHandler->AttachL( aCacheEntry ) ) |
968 HBufC8* headersStr = iStreamHandler->HeadersL( aCacheEntry ); |
895 { |
969 CleanupStack::PushL( headersStr ); |
896 HBufC8* headersStr = iStreamHandler->HeadersL( aCacheEntry ); |
970 // headersStr == NULL happens if you erase the cache directory |
897 CleanupStack::PushL( headersStr ); |
971 // using a file manager |
898 iStreamHandler->Detach( aCacheEntry ); |
972 if ( headersStr ) |
899 // headersStr == NULL happens if you erase the cache directory |
973 { |
900 // using a file manager |
974 // use response headers for retreiving cached headers |
901 if( headersStr ) |
975 RHTTPHeaders responseHeaders = aTrans.Response().GetHeaderCollection(); |
902 { |
976 RHTTPHeaders requestHeaders = aTrans.Request().GetHeaderCollection(); |
903 // use response headers for retreiving cached headers |
977 RStringPool strP = aTrans.Session().StringPool(); |
904 RHTTPHeaders responseHeaders = aTrans.Response().GetHeaderCollection(); |
978 // convert the buffer to httpHeader |
905 RHTTPHeaders requestHeaders = aTrans.Request().GetHeaderCollection(); |
979 HttpCacheUtil::BufferToHeadersL( headersStr->Des(), responseHeaders, strP ); |
906 RStringPool strP = aTrans.Session().StringPool(); |
980 |
907 // convert the buffer to httpHeader |
981 // check if we need to validate the cahce |
908 HttpCacheUtil::BufferToHeadersL( headersStr->Des(), responseHeaders, strP ); |
982 if ( aCacheMode == TBrCtlDefs::ECacheModeOnlyCache || aCacheMode == TBrCtlDefs::ECacheModeHistory ) |
909 |
983 { |
910 // check if we need to validate the cahce |
984 // no validation required |
911 if( aCacheMode == TBrCtlDefs::ECacheModeOnlyCache || aCacheMode == TBrCtlDefs::ECacheModeHistory ) |
985 #ifdef __CACHELOG__ |
912 { |
986 HttpCacheUtil::WriteLog( 0, _L( "prefer cache mode. no need to revalidate" ), aCacheMode ); |
913 // no validation required |
987 #endif |
914 #ifdef __CACHELOG__ |
988 mustRevalidate = EFalse; |
915 HttpCacheUtil::WriteLog( 0, _L( "prefer cache mode. no need to revalidate" ), aCacheMode ); |
989 } |
916 #endif |
990 else |
917 mustRevalidate = EFalse; |
991 { |
918 } |
992 // Get the pragma no-cache header from the headers |
919 else |
993 // no-cache on request header means "do not use cache" |
920 { |
994 if ( !HttpCacheUtil::PragmaNoCache( aTrans ) ) |
921 // Get the pragma no-cache header from the headers |
995 { |
922 // no-cache on request header means "do not use cache" |
996 if ( !HttpCacheUtil::CacheTimeIsFresh( requestHeaders, responseHeaders, strP ) ) |
923 if( !HttpCacheUtil::PragmaNoCache( aTrans ) ) |
|
924 { |
997 { |
925 if( !HttpCacheUtil::CacheTimeIsFresh( requestHeaders, responseHeaders, strP ) ) |
998 #ifdef __CACHELOG__ |
926 { |
999 HttpCacheUtil::WriteLog( 0, _L( "cache item is not fresh. needs revalidation" ) ); |
927 #ifdef __CACHELOG__ |
1000 #endif |
928 HttpCacheUtil::WriteLog( 0, _L( "cache item is not fresh. needs revalidation" ) ); |
1001 // Avoid removing cache entry here |
929 #endif |
1002 mustRevalidate = ETrue; |
930 // MKLE-7PRD27: Avoid removing cache entry here |
1003 // add headers like EIfModifiedSince, EETag, EIfNoneMatch |
931 mustRevalidate = ETrue; |
1004 HttpCacheUtil::AddValidationHeaders( responseHeaders, requestHeaders, strP ); |
932 // add headers like EIfModifiedSince, EETag, EIfNoneMatch |
|
933 HttpCacheUtil::AddValidationHeaders( responseHeaders, requestHeaders, strP ); |
|
934 } |
|
935 else |
|
936 { |
|
937 #ifdef __CACHELOG__ |
|
938 HttpCacheUtil::WriteLog( 0, _L( "cache item is fresh. needs no revalidation" ) ); |
|
939 #endif |
|
940 // |
|
941 mustRevalidate = EFalse; |
|
942 } |
|
943 } |
1005 } |
944 else |
1006 else |
945 { |
1007 { |
946 // needs validation |
1008 #ifdef __CACHELOG__ |
947 #ifdef __CACHELOG__ |
1009 HttpCacheUtil::WriteLog( 0, _L( "cache item is fresh. needs no revalidation" ) ); |
948 HttpCacheUtil::WriteLog( 0, _L( "no cache/no store header present. need revalidation" ) ); |
1010 #endif |
949 #endif |
1011 // |
950 mustRevalidate = ETrue; |
1012 mustRevalidate = EFalse; |
951 } |
1013 } |
952 |
1014 } |
953 } |
1015 else |
954 } |
1016 { |
955 CleanupStack::PopAndDestroy(); // headersStr |
1017 // needs validation |
956 } |
1018 #ifdef __CACHELOG__ |
957 else |
1019 HttpCacheUtil::WriteLog( 0, _L( "no cache/no store header present. need revalidation" ) ); |
958 { |
1020 #endif |
959 DeleteCacheEntry( aCacheEntry ); |
1021 mustRevalidate = ETrue; |
960 // needs validation |
1022 } |
961 mustRevalidate = ETrue; |
1023 } |
962 } |
1024 } |
|
1025 CleanupStack::PopAndDestroy(); // headersStr |
|
1026 |
963 return mustRevalidate; |
1027 return mustRevalidate; |
964 } |
1028 } |
965 |
1029 |
966 // ----------------------------------------------------------------------------- |
1030 // ----------------------------------------------------------------------------- |
967 // CHttpCacheHandler::CacheNeedsSpaceL |
1031 // CHttpCacheHandler::CacheNeedsSpaceL |
1144 // |
1189 // |
1145 TBool CHttpCacheHandler::HandleResponseNotModifiedL( |
1190 TBool CHttpCacheHandler::HandleResponseNotModifiedL( |
1146 CHttpCacheEntry& aEntry, |
1191 CHttpCacheEntry& aEntry, |
1147 RHTTPTransaction& aTrans ) |
1192 RHTTPTransaction& aTrans ) |
1148 { |
1193 { |
1149 // oos? -out of space |
1194 // Are we out of space ? |
1150 TBool saveOk( ETrue ); |
1195 TBool saveOk( ETrue ); |
1151 RHTTPHeaders responseHeader = aTrans.Response().GetHeaderCollection(); |
1196 RHTTPHeaders responseHeader = aTrans.Response().GetHeaderCollection(); |
1152 RStringPool strP = aTrans.Session().StringPool(); |
1197 RStringPool strP = aTrans.Session().StringPool(); |
1153 HBufC8* responseHeaderStr = HttpCacheUtil::HeadersToBufferLC( responseHeader, strP ); |
1198 HBufC8* responseHeaderStr = HttpCacheUtil::HeadersToBufferLC( responseHeader, strP ); |
1154 // If a cache uses a received 304 response to update a cache entry, |
1199 // If a cache uses a received 304 response to update a cache entry, |
1155 // the cache MUST update the entry to reflect any new field values given in the response. |
1200 // the cache MUST update the entry to reflect any new field values given in the response. |
1156 HBufC8* mergedHeadersStr = NULL; |
1201 HBufC8* mergedHeadersStr = NULL; |
1157 HBufC8* cachedHeaderStr = iStreamHandler->HeadersL( aEntry ); |
1202 HBufC8* cachedHeaderStr = iStreamHandler->HeadersL( aEntry ); |
1158 CleanupStack::PushL( cachedHeaderStr ); |
1203 CleanupStack::PushL( cachedHeaderStr ); |
|
1204 |
1159 // don't merge with empty headers |
1205 // don't merge with empty headers |
1160 if( cachedHeaderStr ) |
1206 if ( cachedHeaderStr ) |
1161 { |
1207 { |
1162 mergedHeadersStr = HttpCacheUtil::MergeHeadersLC( cachedHeaderStr->Des(), responseHeader, strP ); |
1208 mergedHeadersStr = HttpCacheUtil::MergeHeadersLC( cachedHeaderStr->Des(), responseHeader, strP ); |
1163 CleanupStack::Pop(); // mergedHeadersStr |
1209 CleanupStack::Pop(); // mergedHeadersStr |
1164 } |
1210 } |
1165 // don't update empty headers |
1211 // don't update empty headers |
1166 if( mergedHeadersStr || responseHeaderStr ) |
1212 if ( mergedHeadersStr || responseHeaderStr ) |
1167 { |
1213 { |
1168 // remove cached headers first |
1214 // remove cached headers first |
1169 iStreamHandler->RemoveHeaders( aEntry ); |
1215 iStreamHandler->RemoveHeaders( aEntry ); |
1170 // save merged headers (reponse + cached) |
1216 // save merged headers (reponse + cached) |
1171 if( mergedHeadersStr ) |
1217 if ( mergedHeadersStr ) |
1172 { |
1218 { |
1173 saveOk = SaveBuffer( aEntry, mergedHeadersStr->Des() ); |
1219 saveOk = SaveBuffer( aEntry, mergedHeadersStr->Des() ); |
1174 } |
1220 } |
1175 else if( responseHeaderStr ) |
1221 else if ( responseHeaderStr ) |
1176 { |
1222 { |
1177 // save responseheader instead |
1223 // save responseheader instead |
1178 saveOk = SaveBuffer( aEntry, responseHeaderStr->Des() ); |
1224 saveOk = SaveBuffer( aEntry, responseHeaderStr->Des() ); |
1179 } |
1225 } |
1180 // if save failed, let's see if we can save old |
1226 // if save failed, let's see if we can save old |
1181 // headers |
1227 // headers |
1182 if( !saveOk && cachedHeaderStr ) |
1228 if ( !saveOk && cachedHeaderStr ) |
1183 { |
1229 { |
1184 saveOk = SaveBuffer( aEntry, cachedHeaderStr->Des() ); |
1230 saveOk = SaveBuffer( aEntry, cachedHeaderStr->Des() ); |
1185 } |
1231 } |
1186 } |
1232 } |
1187 // do not remove the body as it was not modified |
1233 // do not remove the body as it was not modified |
1188 delete mergedHeadersStr; |
1234 delete mergedHeadersStr; |
1189 CleanupStack::PopAndDestroy( 2 ); // cachedHeaderStr, responseHeaderStr |
1235 CleanupStack::PopAndDestroy( 2 ); // cachedHeaderStr, responseHeaderStr |
1190 // check if save was ok. |
1236 // check if save was ok. |
1191 // or nothing was not saved at all |
1237 // or nothing was not saved at all |
1192 if( saveOk ) |
1238 if ( saveOk ) |
1193 { |
1239 { |
1194 // this item does not need update |
1240 // this item does not need update |
1195 aEntry.SetState( CHttpCacheEntry::ECacheComplete ); |
1241 aEntry.SetState( CHttpCacheEntry::ECacheComplete ); |
1196 iStreamHandler->Detach( aEntry ); |
1242 //iStreamHandler->Detach( aEntry ); |
1197 } |
1243 } |
|
1244 |
1198 return saveOk; |
1245 return saveOk; |
1199 } |
1246 } |
1200 |
1247 |
1201 // ----------------------------------------------------------------------------- |
1248 // ----------------------------------------------------------------------------- |
1202 // CHttpCacheHandler::OpenLookupTableL |
1249 // CHttpCacheHandler::OpenLookupTableL |
1203 // |
1250 // |
1204 // ----------------------------------------------------------------------------- |
1251 // ----------------------------------------------------------------------------- |
1205 // |
1252 // |
1206 void CHttpCacheHandler::OpenLookupTableL() |
1253 void CHttpCacheHandler::OpenLookupTableL() |
1207 { |
1254 { |
1208 OpenLookupTableL(iLookupTable); |
1255 OpenLookupTableL( iLookupTable ); |
1209 } |
1256 } |
1210 |
1257 |
1211 // ----------------------------------------------------------------------------- |
1258 // ----------------------------------------------------------------------------- |
1212 // CHttpCacheHandler::OpenLookupTableL |
1259 // CHttpCacheHandler::OpenLookupTableL |
1213 // Opens the index*.dat lookup table from file system. |
1260 // Opens the index*.dat lookup table from file system. |
1214 // ----------------------------------------------------------------------------- |
1261 // ----------------------------------------------------------------------------- |
1215 // |
1262 // |
1216 void CHttpCacheHandler::OpenLookupTableL(CHttpCacheLookupTable* aLookupTable) |
1263 void CHttpCacheHandler::OpenLookupTableL(CHttpCacheLookupTable* aLookupTable) |
1217 { |
1264 { |
|
1265 #if 0 |
1218 // read entries from index.dat |
1266 // read entries from index.dat |
1219 RFileReadStream readStream; |
1267 RFileReadStream readStream; |
1220 |
1268 |
1221 iRfs.SetSessionPath( iDirectory->Des() ); |
1269 iRfs.SetSessionPath( iDirectory->Des() ); |
1222 |
1270 |
1223 TInt ret = KErrNone; |
|
1224 TInt tryCount = 0; |
|
1225 for (tryCount = 0; tryCount < 5; tryCount++) |
|
1226 { |
|
1227 ret = readStream.Open( iRfs, iIndexFile->Des(), EFileRead | EFileShareAny ); |
|
1228 if (ret == KErrInUse) |
|
1229 { |
|
1230 // When the cache is full, it takes 65 - 85 miliseconds to write the index. |
|
1231 // So wait 50 miliseconds and try again |
|
1232 User::After(50000); |
|
1233 } |
|
1234 else |
|
1235 { |
|
1236 break; |
|
1237 } |
|
1238 } |
|
1239 if( ret == KErrNone ) |
|
1240 { |
|
1241 TRAPD ( err, aLookupTable->InternalizeL( readStream, iDirectory->Des() ) ); |
|
1242 readStream.Close(); |
|
1243 if ( err != KErrNone ) |
|
1244 { |
|
1245 // In case Bad Things Happen (TM), do RemoveAllL() which clears this cache's |
|
1246 // in-memory data structures + saves an updated lookup table to disk replacing the old one. |
|
1247 TRAP_IGNORE( RemoveAllL() ); |
|
1248 } |
|
1249 } |
|
1250 } |
|
1251 |
|
1252 // ----------------------------------------------------------------------------- |
|
1253 // CHttpCacheHandler::SaveLookupTableL |
|
1254 // |
|
1255 // ----------------------------------------------------------------------------- |
|
1256 // |
|
1257 void CHttpCacheHandler::SaveLookupTableL() |
|
1258 { |
|
1259 #ifdef __CACHELOG__ |
|
1260 HttpCacheUtil::WriteLog( 0, _L( "lookup table is saved" ) ); |
|
1261 #endif |
|
1262 // save entries to index.dat |
|
1263 RFileWriteStream writeStream; |
|
1264 |
|
1265 // Don't get notified about own changes |
|
1266 if ( iHttpCacheObserver ) |
|
1267 iHttpCacheObserver->Cancel(); |
|
1268 |
|
1269 TInt ret = KErrNone; |
1271 TInt ret = KErrNone; |
1270 TInt tryCount = 0; |
1272 TInt tryCount = 0; |
1271 for (tryCount = 0; tryCount < 5; tryCount++) |
1273 for (tryCount = 0; tryCount < 5; tryCount++) |
1272 { |
1274 { |
1273 ret = writeStream.Replace( iRfs, iIndexFile->Des(), EFileWrite ); |
1275 ret = readStream.Open( iRfs, iIndexFile->Des(), EFileRead | EFileShareAny ); |
1274 if (ret == KErrInUse) |
1276 if (ret == KErrInUse) |
1275 { |
1277 { |
1276 // When the cache is full, it takes 65 - 85 miliseconds to write the index. |
1278 // When the cache is full, it takes 65 - 85 miliseconds to write the index. |
1277 // So wait 50 miliseconds and try again |
1279 // So wait 50 miliseconds and try again |
1278 User::After(50000); |
1280 User::After(50000); |
1282 break; |
1284 break; |
1283 } |
1285 } |
1284 } |
1286 } |
1285 if( ret == KErrNone ) |
1287 if( ret == KErrNone ) |
1286 { |
1288 { |
|
1289 CleanupClosePushL( readStream ); |
|
1290 aLookupTable->InternalizeL( readStream, iDirectory->Des() ); |
|
1291 CleanupStack::PopAndDestroy(1); // readStream |
|
1292 } |
|
1293 #else |
|
1294 RFile readFile; |
|
1295 iRfs.SetSessionPath( iDirectory->Des() ); |
|
1296 |
|
1297 TInt ret = KErrNone; |
|
1298 TInt tryCount = 0; |
|
1299 for (tryCount = 0; tryCount < 5; tryCount++) |
|
1300 { |
|
1301 ret = readFile.Open( iRfs, iIndexFile->Des(), EFileRead | EFileShareAny ); |
|
1302 if (ret == KErrInUse) |
|
1303 { |
|
1304 // When the cache is full, it takes 65 - 85 miliseconds to write the index. |
|
1305 // So wait 50 miliseconds and try again |
|
1306 User::After(50000); |
|
1307 } |
|
1308 else |
|
1309 { |
|
1310 break; |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 if ( ret == KErrNone ) |
|
1315 { |
|
1316 CleanupClosePushL(readFile); |
|
1317 TInt size; |
|
1318 readFile.Size(size); |
|
1319 |
|
1320 if ( size ) |
|
1321 { |
|
1322 HBufC8* buffer = HBufC8::NewLC(size); |
|
1323 TPtr8 buf( buffer->Des() ); |
|
1324 User::LeaveIfError( readFile.Read(buf, size) ); |
|
1325 RDesReadStream readStream( buf ); |
|
1326 CleanupClosePushL(readStream); |
|
1327 aLookupTable->InternalizeL( readStream, iDirectory->Des() ); |
|
1328 CleanupStack::PopAndDestroy(3); // read stream, buffer then file |
|
1329 } |
|
1330 else |
|
1331 { |
|
1332 CleanupStack::PopAndDestroy(1); // close the file. |
|
1333 } |
|
1334 } |
|
1335 #endif |
|
1336 } |
|
1337 |
|
1338 // ----------------------------------------------------------------------------- |
|
1339 // CHttpCacheHandler::SaveLookupTableL |
|
1340 // |
|
1341 // ----------------------------------------------------------------------------- |
|
1342 // |
|
1343 void CHttpCacheHandler::SaveLookupTableL() |
|
1344 { |
|
1345 #ifdef __CACHELOG__ |
|
1346 HttpCacheUtil::WriteLog( 0, _L( "lookup table is saved" ) ); |
|
1347 #endif |
|
1348 // save entries to index.dat |
|
1349 RFileWriteStream writeStream; |
|
1350 |
|
1351 // Don't get notified about own changes |
|
1352 iHttpCacheObserver->Cancel(); |
|
1353 TInt ret = KErrNone; |
|
1354 TInt tryCount = 0; |
|
1355 for (tryCount = 0; tryCount < 5; tryCount++) |
|
1356 { |
|
1357 ret = writeStream.Replace( iRfs, iIndexFile->Des(), EFileWrite ); |
|
1358 if (ret == KErrInUse) |
|
1359 { |
|
1360 // When the cache is full, it takes 65 - 85 miliseconds to write the index. |
|
1361 // So wait 50 miliseconds and try again |
|
1362 User::After(50000); |
|
1363 } |
|
1364 else |
|
1365 { |
|
1366 break; |
|
1367 } |
|
1368 } |
|
1369 if ( ret == KErrNone ) |
|
1370 { |
1287 CleanupClosePushL( writeStream ); |
1371 CleanupClosePushL( writeStream ); |
1288 iLookupTable->ExternalizeL( writeStream ); |
1372 iLookupTable->ExternalizeL( writeStream , iDirectory->Des() ); |
1289 writeStream.CommitL(); |
1373 writeStream.CommitL(); |
1290 CleanupStack::PopAndDestroy(); // writeStream |
1374 CleanupStack::PopAndDestroy(); // writeStream |
1291 } |
1375 } |
1292 |
1376 iHttpCacheObserver->StartObserver(); |
1293 if ( iHttpCacheObserver ) |
|
1294 iHttpCacheObserver->StartObserver(); |
|
1295 } |
1377 } |
1296 |
1378 |
1297 // ----------------------------------------------------------------------------- |
1379 // ----------------------------------------------------------------------------- |
1298 // CHttpCacheHandler::DeleteCacheEntry |
1380 // CHttpCacheHandler::DeleteCacheEntry |
1299 // |
1381 // |
1300 // ----------------------------------------------------------------------------- |
1382 // ----------------------------------------------------------------------------- |
1301 // |
1383 // |
1302 void CHttpCacheHandler::DeleteCacheEntry( |
1384 void CHttpCacheHandler::DeleteCacheEntry( |
1303 CHttpCacheEntry& aEntry, |
1385 CHttpCacheEntry& aStrayEntry, |
1304 TBool aUpdate ) |
1386 TBool aUpdate ) |
1305 { |
1387 { |
1306 // suppress compiler and PC-lint warnings |
1388 (void)aUpdate;//suppress compiler and PC-lint warnings |
1307 (void)aUpdate; |
1389 #ifdef __CACHELOG__ |
1308 |
1390 HttpCacheUtil::WriteLog( 0, _L( "delete this stray entry" ) ); |
1309 #ifdef __CACHELOG__ |
1391 #endif |
1310 HttpCacheUtil::WriteLogFilenameAndUrl( 0, |
1392 |
1311 _L("CHttpCacheHandler::DeleteCacheEntry"), |
1393 // need to make sure this entry is removed from postpone handler, if it might be there. |
1312 aEntry.Filename(), |
1394 if ( iPostponeHandler ) |
1313 aEntry.Url(), |
1395 { |
1314 aEntry.BodySize(), |
1396 iPostponeHandler->RemoveEntry( &aStrayEntry ); |
1315 ELogEntrySize ); |
1397 } |
1316 #endif |
1398 |
1317 |
1399 // remove from the lookuptable |
1318 // Remove from the lookuptable |
1400 iLookupTable->EraseCacheEntry( aStrayEntry.Url() ); |
1319 iLookupTable->EraseCacheEntry( aEntry.Url() ); |
1401 } |
1320 } |
1402 |
1321 |
1403 // ----------------------------------------------------------------------------- |
1322 // ----------------------------------------------------------------------------- |
1404 // There used to be a CHttpCacheHandler::FixLookupTableL here. |
1323 // There used to be a CHttpCacheHandler::FixLookupTableL here. |
|
1324 // Go back in SVN to re-discover it :) |
1405 // Go back in SVN to re-discover it :) |
1325 // |
1406 // |
1326 // ----------------------------------------------------------------------------- |
1407 // ----------------------------------------------------------------------------- |
1327 |
1408 |
1328 // ----------------------------------------------------------------------------- |
1409 // ----------------------------------------------------------------------------- |
1348 { |
1429 { |
1349 // stop saving this entry |
1430 // stop saving this entry |
1350 HttpCacheUtil::WriteUrlToLog( 0, _L( "item cannot be saved. remove it please" ), aEntry.Url() ); |
1431 HttpCacheUtil::WriteUrlToLog( 0, _L( "item cannot be saved. remove it please" ), aEntry.Url() ); |
1351 } |
1432 } |
1352 #endif // __CACHELOG__ |
1433 #endif // __CACHELOG__ |
|
1434 |
1353 return ok; |
1435 return ok; |
1354 } |
1436 } |
1355 |
1437 |
1356 |
|
1357 // ----------------------------------------------------------------------------- |
1438 // ----------------------------------------------------------------------------- |
1358 // CHttpCacheHandler::UpdateLookupTable |
1439 // CHttpCacheHandler::UpdateLookupTable |
1359 // |
1440 // |
1360 // ----------------------------------------------------------------------------- |
1441 // ----------------------------------------------------------------------------- |
1361 // |
1442 // |
1362 void CHttpCacheHandler::UpdateLookupTable() |
1443 void CHttpCacheHandler::UpdateLookupTable() |
1363 { |
1444 { |
1364 TRAP_IGNORE(UpdateLookupTableL()); |
1445 TRAP_IGNORE(UpdateLookupTableL()); |
1365 |
1446 iHttpCacheObserver->StartObserver(); |
1366 if ( iHttpCacheObserver ) |
|
1367 iHttpCacheObserver->StartObserver(); |
|
1368 } |
1447 } |
1369 |
1448 |
1370 // ----------------------------------------------------------------------------- |
1449 // ----------------------------------------------------------------------------- |
1371 // CHttpCacheHandler::UpdateLookupTableL |
1450 // CHttpCacheHandler::UpdateLookupTableL |
1372 // Slow method due to much file-system interaction. Don't call it from performance critical code. |
1451 // Slow method due to much file-system interaction. Don't call it from performance critical code. |
1373 // ----------------------------------------------------------------------------- |
1452 // ----------------------------------------------------------------------------- |
1374 // |
1453 // |
1375 void CHttpCacheHandler::UpdateLookupTableL() |
1454 void CHttpCacheHandler::UpdateLookupTableL() |
1376 { |
1455 { |
1377 CHttpCacheEvictionHandler* evictionHandler = CHttpCacheEvictionHandler::NewL(); |
1456 CHttpCacheEvictionHandler* evictionHandler = CHttpCacheEvictionHandler::NewL(); |
1378 CleanupStack::PushL(evictionHandler); |
1457 CleanupStack::PushL(evictionHandler); |
1379 CHttpCacheLookupTable* lookupTable = CHttpCacheLookupTable::NewL( *evictionHandler, *iStreamHandler ); |
1458 CHttpCacheLookupTable* lookupTable = CHttpCacheLookupTable::NewL( *evictionHandler, *iStreamHandler ); |
1380 CleanupStack::PushL(lookupTable); |
1459 CleanupStack::PushL(lookupTable); |
1381 OpenLookupTableL(lookupTable); |
1460 OpenLookupTableL(lookupTable); |
1382 iLookupTable->MergeL(lookupTable, iRfs); |
1461 iLookupTable->MergeL(lookupTable, iRfs); |
1383 CleanupStack::PopAndDestroy(2); // lookupTable, evictionHandler |
1462 CleanupStack::PopAndDestroy(2); // lookupTable, evictionHandler |
|
1463 } |
|
1464 |
|
1465 // ----------------------------------------------------------------------------- |
|
1466 // CHttpCacheHandler::GenerateValidationFilename |
|
1467 // ----------------------------------------------------------------------------- |
|
1468 // |
|
1469 #ifdef __USE_VALIDATION_FILES__ |
|
1470 void CHttpCacheHandler::GenerateValidationFilename(TDes& aFilename, const TDesC& aIndexFilename) const |
|
1471 #else |
|
1472 void CHttpCacheHandler::GenerateValidationFilename(TDes& /*aFilename*/, const TDesC& /*aIndexFilename*/) const |
|
1473 #endif |
|
1474 { |
|
1475 #ifdef __USE_VALIDATION_FILES__ |
|
1476 _LIT(KValidationExtension, ".val"); |
|
1477 TParse filenameParser; |
|
1478 filenameParser.Set(aIndexFilename, NULL, NULL); |
|
1479 aFilename.Copy(filenameParser.DriveAndPath()); |
|
1480 aFilename.Append(filenameParser.Name()); |
|
1481 aFilename.Append(KValidationExtension); |
|
1482 #else |
|
1483 PanicCacheHandler(KErrNotSupported); |
|
1484 #endif |
|
1485 } |
|
1486 |
|
1487 // ----------------------------------------------------------------------------- |
|
1488 // DestroyBadUrlArray |
|
1489 // ----------------------------------------------------------------------------- |
|
1490 // |
|
1491 static void DestroyBadUrlArray(TAny* aPtr) |
|
1492 { |
|
1493 RPointerArray<HBufC8> *tmp = (RPointerArray<HBufC8>*)aPtr; |
|
1494 tmp->ResetAndDestroy(); |
|
1495 } |
|
1496 |
|
1497 // ----------------------------------------------------------------------------- |
|
1498 // CHttpCacheHandler::ValidateCacheEntriesL |
|
1499 // ----------------------------------------------------------------------------- |
|
1500 // |
|
1501 void CHttpCacheHandler::ValidateCacheEntriesL() |
|
1502 { |
|
1503 // iterate through entries and check if file is present. |
|
1504 // if not, add URL to a list of bad ones otherwise remove directory entry from list |
|
1505 // at the end, go through list of bad entries and remove them from cache, |
|
1506 // go through list of unreferenced files and delete them too. |
|
1507 THttpCacheLookupTableEntryIterator iter; |
|
1508 iLookupTable->BeginEntryIteration(iter); |
|
1509 #ifdef __CACHELOG__ |
|
1510 HttpCacheUtil::WriteLog(0, _L("CHttpCacheHandler::ValidateCacheEntriesL")); |
|
1511 #endif |
|
1512 // if the cache contains no items, we should still do this so we detect other files. |
|
1513 |
|
1514 // get list of files on disk |
|
1515 CCacheDirectoryFiles *dirFiles = CCacheDirectoryFiles::NewLC(iRfs, *iDirectory); |
|
1516 |
|
1517 // look for bad entries |
|
1518 RPointerArray<HBufC8> badEntries; |
|
1519 CleanupStack::PushL(TCleanupItem(DestroyBadUrlArray, &badEntries)); |
|
1520 const CHttpCacheEntry *tmpEntry; |
|
1521 while(tmpEntry = iLookupTable->NextEntry(iter), tmpEntry) |
|
1522 { |
|
1523 if(!dirFiles->ValidateEntryL(*tmpEntry)) |
|
1524 { |
|
1525 #ifdef __CACHELOG__ |
|
1526 HttpCacheUtil::WriteUrlToLog(0, _L("Bad Entry: "), tmpEntry->Url() ); |
|
1527 #endif |
|
1528 badEntries.AppendL(tmpEntry->Url().AllocL()); |
|
1529 } |
|
1530 } |
|
1531 |
|
1532 // remove bad entries |
|
1533 for(TInt i=0; i < badEntries.Count(); i++) |
|
1534 { |
|
1535 iLookupTable->Remove(badEntries[i]->Des()); |
|
1536 } |
|
1537 CleanupStack::PopAndDestroy(1); // bad entry list |
|
1538 |
|
1539 // remove orphan files |
|
1540 dirFiles->RemoveLeftoverFilesL(); |
|
1541 CleanupStack::PopAndDestroy(dirFiles); |
|
1542 } |
|
1543 |
|
1544 // ----------------------------------------------------------------------------- |
|
1545 // CCacheDirectoryFiles::NewL |
|
1546 // ----------------------------------------------------------------------------- |
|
1547 // |
|
1548 CCacheDirectoryFiles* CCacheDirectoryFiles::NewL(RFs aRfs, const TDesC& aDir) |
|
1549 { |
|
1550 CCacheDirectoryFiles* me = CCacheDirectoryFiles::NewLC(aRfs, aDir); |
|
1551 CleanupStack::Pop(me); |
|
1552 return me; |
|
1553 } |
|
1554 |
|
1555 // ----------------------------------------------------------------------------- |
|
1556 // CCacheDirectoryFiles::NewLC |
|
1557 // ----------------------------------------------------------------------------- |
|
1558 // |
|
1559 CCacheDirectoryFiles* CCacheDirectoryFiles::NewLC(RFs aRfs, const TDesC& aDir) |
|
1560 { |
|
1561 CCacheDirectoryFiles *me = new (ELeave) CCacheDirectoryFiles(aRfs, aDir); |
|
1562 CleanupStack::PushL(me); |
|
1563 me->ConstructL(); |
|
1564 return me; |
|
1565 } |
|
1566 |
|
1567 // ----------------------------------------------------------------------------- |
|
1568 // CCacheDirectoryFiles::ValidateEntryL |
|
1569 // ----------------------------------------------------------------------------- |
|
1570 // |
|
1571 TBool CCacheDirectoryFiles::ValidateEntryL(const CHttpCacheEntry& aEntry) |
|
1572 { |
|
1573 // check the files associated with the cache entry are present where they should be |
|
1574 // if the file is present, then remove it from the dir list |
|
1575 // if the file is present AND the size matches the entry, then return ETrue in aPresentAndValid |
|
1576 // otherwise, return EFalse there. |
|
1577 TBool presentAndValid = EFalse; |
|
1578 |
|
1579 TParse tmpParse; |
|
1580 tmpParse.Set(aEntry.Filename(), NULL, NULL); |
|
1581 // for this file to be part of the cache it must meet the following rules.. |
|
1582 // length of name is 8 chars |
|
1583 if(tmpParse.Name().Length() != 8) |
|
1584 return presentAndValid; |
|
1585 |
|
1586 // this filename has a chance of existing and we can assume correct format from now on |
|
1587 TUint32 cacheUintName; |
|
1588 if(TCompressedEntry::ConvertANameToUint32(tmpParse.Name(), cacheUintName)) |
|
1589 { |
|
1590 TInt arrayIndex = cacheUintName & 0x0000000F; |
|
1591 presentAndValid = iDirContent[arrayIndex]->ValidateCacheEntryL( aEntry ); |
|
1592 } |
|
1593 // after all cache entries have been checked against the list, it should only contain orphaned files |
|
1594 // files which match but are corrupt will have been removed from this list |
|
1595 // however they should be cleaned up when the 'corrupt' entries are removed at a later date. |
|
1596 return presentAndValid; |
|
1597 } |
|
1598 |
|
1599 // ----------------------------------------------------------------------------- |
|
1600 // CCacheDirectoryFiles::RemoveLeftoverFilesL |
|
1601 // ----------------------------------------------------------------------------- |
|
1602 // |
|
1603 void CCacheDirectoryFiles::RemoveLeftoverFilesL() |
|
1604 { |
|
1605 // delete all the files which are still listed. |
|
1606 TFileName tempFilename; |
|
1607 for (TInt subDir=0; subDir < 16; subDir++) |
|
1608 { |
|
1609 for (TInt fileIdx = 0; fileIdx < iDirContent[subDir]->Count(); fileIdx++ ) |
|
1610 { |
|
1611 // each file needs to have the full path prepended in order to delete |
|
1612 HBufC *name = iDirContent[subDir]->NameAtL(fileIdx); |
|
1613 tempFilename.Format(_L("%S%x\\%S"), &iDir, subDir, name); |
|
1614 #ifdef __CACHELOG__ |
|
1615 HttpCacheUtil::WriteFormatLog(0, _L("Deleting file %S"), &tempFilename); |
|
1616 #endif |
|
1617 iRfs.Delete(tempFilename); |
|
1618 delete name; |
|
1619 } |
|
1620 } |
|
1621 } |
|
1622 |
|
1623 // ----------------------------------------------------------------------------- |
|
1624 // CCacheDirectoryFiles::~CCacheDirectoryFiles |
|
1625 // ----------------------------------------------------------------------------- |
|
1626 // |
|
1627 CCacheDirectoryFiles::~CCacheDirectoryFiles() |
|
1628 { |
|
1629 iDirContent.ResetAndDestroy(); |
|
1630 } |
|
1631 |
|
1632 // ----------------------------------------------------------------------------- |
|
1633 // CCacheDirectoryFiles::ConstructL |
|
1634 // ----------------------------------------------------------------------------- |
|
1635 // |
|
1636 void CCacheDirectoryFiles::ConstructL() |
|
1637 { |
|
1638 CDir* baseDirs; |
|
1639 User::LeaveIfError(iRfs.GetDir(iDir,KEntryAttDir,ESortByName,baseDirs)); |
|
1640 CleanupStack::PushL(baseDirs); |
|
1641 |
|
1642 // we know that the cache format is a single letter directory from 0-f |
|
1643 // so we ignore any other directories - they might belong to other caches |
|
1644 // and our cache will not have written any files out into anywhere except the |
|
1645 // 0-f dirs, even if we lost track of something. |
|
1646 // See HttpCacheUtil::GenerateNameLC |
|
1647 iDirContent.ReserveL(16); |
|
1648 |
|
1649 TInt numdirs = baseDirs->Count(); |
|
1650 // storage for <c:/system/cache/> + '0/' |
|
1651 HBufC* currentDir = HBufC::NewLC( iDir.Length() + KSubdirNameLength ); |
|
1652 for(TInt i=0; i < numdirs; i++) |
|
1653 { |
|
1654 TInt arrayIndex = -1; |
|
1655 const TEntry& entry = (*baseDirs)[i]; |
|
1656 if(entry.IsDir() && entry.iName.Length()==1) |
|
1657 { |
|
1658 TUint16 chr = *(entry.iName.Right(1).Ptr()); |
|
1659 arrayIndex = TCompressedEntry::ConvertAsciiToIntSingleHexDigit(chr); |
|
1660 } |
|
1661 |
|
1662 if(arrayIndex >=0 && arrayIndex <= 15) |
|
1663 { |
|
1664 // initialise subdir name to base directory |
|
1665 currentDir->Des().Copy(iDir); |
|
1666 currentDir->Des().AppendFormat(_L("%x\\"), arrayIndex); // if base path wasn't terminated with trailing / we would have blown up at creation time. |
|
1667 |
|
1668 // get subdirectory content |
|
1669 CDir *dir; |
|
1670 iRfs.GetDir(currentDir->Des(), KEntryAttMatchExclude | KEntryAttDir, ESortByName, dir); // only files this time... |
|
1671 if(dir) |
|
1672 { |
|
1673 iDirContent.Insert( CCustomCacheDirList::NewL( dir ), arrayIndex ); |
|
1674 } |
|
1675 delete dir; |
|
1676 } |
|
1677 } |
|
1678 CleanupStack::PopAndDestroy(2); // baseDirs & currentDir |
|
1679 } |
|
1680 |
|
1681 // ----------------------------------------------------------------------------- |
|
1682 // CCustomCacheDirList::NewL |
|
1683 // ----------------------------------------------------------------------------- |
|
1684 // |
|
1685 CCustomCacheDirList* CCustomCacheDirList::NewL(CDir *aSrc) |
|
1686 { |
|
1687 CCustomCacheDirList *me = new (ELeave) CCustomCacheDirList; |
|
1688 CleanupStack::PushL( me ); |
|
1689 me->ConstructL( aSrc ); |
|
1690 CleanupStack::Pop( me ); |
|
1691 return me; |
|
1692 } |
|
1693 |
|
1694 // ----------------------------------------------------------------------------- |
|
1695 // CCustomCacheDirList::ValidateCacheEntryL |
|
1696 // ----------------------------------------------------------------------------- |
|
1697 // |
|
1698 TBool CCustomCacheDirList::ValidateCacheEntryL( const CHttpCacheEntry& aEntry ) |
|
1699 { |
|
1700 TBool presentAndValid = EFalse; |
|
1701 TUint32 shortName; |
|
1702 if( TCompressedEntry::ConvertANameToUint32( aEntry.Filename().Right(8), shortName) ) |
|
1703 { |
|
1704 for(TInt i=0; i<iDirList.Count(); i++) |
|
1705 { |
|
1706 if(iDirList[i]->IsCompressed() && |
|
1707 (iDirList[i]->GetCompressedName() == shortName) && |
|
1708 (iDirList[i]->GetSize() == aEntry.BodySize())) |
|
1709 { |
|
1710 presentAndValid = ETrue; |
|
1711 iDirList.Remove(i); |
|
1712 break; |
|
1713 } |
|
1714 } |
|
1715 } |
|
1716 return presentAndValid; |
|
1717 } |
|
1718 |
|
1719 // ----------------------------------------------------------------------------- |
|
1720 // CCustomCacheDirList::Count |
|
1721 // ----------------------------------------------------------------------------- |
|
1722 // |
|
1723 TInt CCustomCacheDirList::Count() |
|
1724 { |
|
1725 return iDirList.Count(); |
|
1726 } |
|
1727 |
|
1728 // ----------------------------------------------------------------------------- |
|
1729 // CCustomCacheDirList::NameAtL |
|
1730 // ----------------------------------------------------------------------------- |
|
1731 // |
|
1732 HBufC* CCustomCacheDirList::NameAtL( TInt aIndex ) |
|
1733 { |
|
1734 return iDirList[aIndex]->GetNameL(); |
|
1735 } |
|
1736 |
|
1737 // ----------------------------------------------------------------------------- |
|
1738 // CCustomCacheDirList::CCustomCacheDirList |
|
1739 // ----------------------------------------------------------------------------- |
|
1740 // |
|
1741 CCustomCacheDirList::CCustomCacheDirList() |
|
1742 { |
|
1743 } |
|
1744 |
|
1745 // ----------------------------------------------------------------------------- |
|
1746 // CCustomCacheDirList::ConstructL |
|
1747 // ----------------------------------------------------------------------------- |
|
1748 // |
|
1749 void CCustomCacheDirList::ConstructL(CDir *aSrc) |
|
1750 { |
|
1751 TInt items = aSrc->Count(); |
|
1752 if(items) |
|
1753 { |
|
1754 iDirList.ReserveL(items); |
|
1755 for(TInt i=0; i < items; i++) |
|
1756 { |
|
1757 TCompressedEntry *newDirEntry = TCompressedEntry::NewL( (*aSrc)[i] ); |
|
1758 iDirList.AppendL( newDirEntry ); |
|
1759 } |
|
1760 } |
|
1761 } |
|
1762 |
|
1763 // ----------------------------------------------------------------------------- |
|
1764 // TCompressedEntry::NewL |
|
1765 // ----------------------------------------------------------------------------- |
|
1766 // |
|
1767 TCompressedEntry *TCompressedEntry::NewL( const TEntry& aEntry ) |
|
1768 { |
|
1769 TCompressedEntry *newEntry = new (ELeave) TCompressedEntry; |
|
1770 CleanupStack::PushL( newEntry ); |
|
1771 newEntry->ConstructL( aEntry ); |
|
1772 CleanupStack::Pop( newEntry ); |
|
1773 |
|
1774 return newEntry; |
|
1775 } |
|
1776 |
|
1777 // ----------------------------------------------------------------------------- |
|
1778 // TCompressedEntry::ConstructL |
|
1779 // ----------------------------------------------------------------------------- |
|
1780 // |
|
1781 void TCompressedEntry::ConstructL( const TEntry& aEntry ) |
|
1782 { |
|
1783 TUint32 compressedName; |
|
1784 if ( ConvertANameToUint32(aEntry.iName, compressedName) ) |
|
1785 { |
|
1786 iFlags |= EFilenameStoredAsUint32; |
|
1787 iName.iNameAsUint32 = compressedName; |
|
1788 } |
|
1789 else |
|
1790 { |
|
1791 iName.iNameAsHBuf = aEntry.iName.AllocL(); |
|
1792 } |
|
1793 iSize = aEntry.iSize; |
|
1794 } |
|
1795 |
|
1796 // ----------------------------------------------------------------------------- |
|
1797 // TCompressedEntry::ConvertANameToUint32 |
|
1798 // ----------------------------------------------------------------------------- |
|
1799 // |
|
1800 TBool TCompressedEntry::ConvertANameToUint32( const TDesC& aName, TUint32& aConverted) |
|
1801 { |
|
1802 TBool success = EFalse; |
|
1803 aConverted = 0; |
|
1804 |
|
1805 if ( aName.Length() == 8 ) |
|
1806 { |
|
1807 TUint32 scratch = 0; |
|
1808 for ( TInt i=0; i < 8; i++ ) |
|
1809 { |
|
1810 scratch <<= 4; |
|
1811 TInt val = TCompressedEntry::ConvertAsciiToIntSingleHexDigit(aName[i]); |
|
1812 if ( val >= 0 ) |
|
1813 { |
|
1814 scratch += val & 0x0F; |
|
1815 } |
|
1816 else |
|
1817 break; |
|
1818 |
|
1819 if ( i==7 ) |
|
1820 { |
|
1821 aConverted = scratch; |
|
1822 success = ETrue; |
|
1823 } |
|
1824 } |
|
1825 } |
|
1826 |
|
1827 return success; |
|
1828 } |
|
1829 |
|
1830 // ----------------------------------------------------------------------------- |
|
1831 // TCompressedEntry::ConvertAsciiToIntSingleHexDigit |
|
1832 // ----------------------------------------------------------------------------- |
|
1833 // |
|
1834 TInt TCompressedEntry::ConvertAsciiToIntSingleHexDigit(const TUint16& aDigitChar) |
|
1835 { |
|
1836 if ( aDigitChar >=48 && aDigitChar <=57 ) |
|
1837 { |
|
1838 return (aDigitChar - 48); //numerals |
|
1839 } |
|
1840 else if ( aDigitChar >= 65 && aDigitChar <= 70 ) |
|
1841 { |
|
1842 return (aDigitChar - 55); // uppercase hex letters |
|
1843 } |
|
1844 else if ( aDigitChar >= 97 && aDigitChar <= 102 ) |
|
1845 { |
|
1846 return (aDigitChar - 87); // lowercase hex letters |
|
1847 } |
|
1848 |
|
1849 return -1; |
|
1850 } |
|
1851 |
|
1852 // ----------------------------------------------------------------------------- |
|
1853 // TCompressedEntry::GetNameL |
|
1854 // ----------------------------------------------------------------------------- |
|
1855 // |
|
1856 HBufC* TCompressedEntry::GetNameL() |
|
1857 { |
|
1858 if ( !IsCompressed() ) |
|
1859 { |
|
1860 return iName.iNameAsHBuf->AllocL(); |
|
1861 } |
|
1862 |
|
1863 HBufC* name = HBufC::NewL(8); |
|
1864 name->Des().Format(_L("%08x"), iName.iNameAsUint32); |
|
1865 |
|
1866 return name; |
1384 } |
1867 } |
1385 // End of File |
1868 // End of File |