|         |      1 /* | 
|         |      2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). | 
|         |      3 * All rights reserved. | 
|         |      4 * This component and the accompanying materials are made available | 
|         |      5 * under the terms of the License "Eclipse Public License v1.0" | 
|         |      6 * which accompanies this distribution, and is available | 
|         |      7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". | 
|         |      8 * | 
|         |      9 * Initial Contributors: | 
|         |     10 * Nokia Corporation - initial contribution. | 
|         |     11 * | 
|         |     12 * Contributors: | 
|         |     13 * | 
|         |     14 * Description:  Implementation of CHttpCacheLookupTable | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18 // INCLUDE FILES | 
|         |     19 #include "HttpCacheLookupTable.h" | 
|         |     20 #include "HttpCacheEntry.h" | 
|         |     21 #include "HttpCacheUtil.h" | 
|         |     22 #include "HttpCacheEvictionHandler.h" | 
|         |     23 #include "HttpCacheStreamHandler.h" | 
|         |     24 #include <e32cmn.h> | 
|         |     25  | 
|         |     26 // EXTERNAL DATA STRUCTURES | 
|         |     27  | 
|         |     28 // EXTERNAL FUNCTION PROTOTYPES | 
|         |     29  | 
|         |     30 // CONSTANTS | 
|         |     31 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's | 
|         |     32 // or anything like that. | 
|         |     33 const TUint KHashPHI = 0x9e3779b9U; | 
|         |     34 // | 
|         |     35 const TUint KHashStringLength = 16; | 
|         |     36 // kbyte | 
|         |     37 // | 
|         |     38 const TUint KHttpCacheLookupTableSize = 217; | 
|         |     39  | 
|         |     40 // MACROS | 
|         |     41  | 
|         |     42 // LOCAL CONSTANTS AND MACROS | 
|         |     43  | 
|         |     44 // MODULE DATA STRUCTURES | 
|         |     45  | 
|         |     46 // LOCAL FUNCTION PROTOTYPES | 
|         |     47  | 
|         |     48 // FORWARD DECLARATIONS | 
|         |     49  | 
|         |     50 // ============================= LOCAL FUNCTIONS =============================== | 
|         |     51  | 
|         |     52 // ============================ MEMBER FUNCTIONS =============================== | 
|         |     53  | 
|         |     54 // ----------------------------------------------------------------------------- | 
|         |     55 // CHttpCacheLookupTable::CHttpCacheLookupTable | 
|         |     56 // C++ default constructor can NOT contain any code, that | 
|         |     57 // might leave. | 
|         |     58 // ----------------------------------------------------------------------------- | 
|         |     59 // | 
|         |     60 CHttpCacheLookupTable::CHttpCacheLookupTable( | 
|         |     61     CHttpCacheEvictionHandler& aEvictionHandler, | 
|         |     62     CHttpCacheStreamHandler& aStreamHandler ) | 
|         |     63     : iEvictionHandler( &aEvictionHandler ), | 
|         |     64       iStreamHandler( &aStreamHandler ) | 
|         |     65     { | 
|         |     66     } | 
|         |     67  | 
|         |     68 // ----------------------------------------------------------------------------- | 
|         |     69 // CHttpCacheLookupTable::ConstructL | 
|         |     70 // Symbian 2nd phase constructor can leave. | 
|         |     71 // ----------------------------------------------------------------------------- | 
|         |     72 // | 
|         |     73 void CHttpCacheLookupTable::ConstructL() | 
|         |     74     { | 
|         |     75   iEntries = new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( KHttpCacheLookupTableSize ); | 
|         |     76     for( TInt i = 0; i < KHttpCacheLookupTableSize; i++ ) | 
|         |     77         { | 
|         |     78         iEntries->AppendL( NULL ); | 
|         |     79         } | 
|         |     80     } | 
|         |     81  | 
|         |     82 // ----------------------------------------------------------------------------- | 
|         |     83 // CHttpCacheLookupTable::NewL | 
|         |     84 // Two-phased constructor. | 
|         |     85 // ----------------------------------------------------------------------------- | 
|         |     86 // | 
|         |     87 CHttpCacheLookupTable* CHttpCacheLookupTable::NewL( | 
|         |     88     CHttpCacheEvictionHandler& aEvictionHandler, | 
|         |     89     CHttpCacheStreamHandler& aStreamHandler ) | 
|         |     90     { | 
|         |     91     CHttpCacheLookupTable* self = new( ELeave ) CHttpCacheLookupTable( aEvictionHandler, aStreamHandler ); | 
|         |     92  | 
|         |     93     CleanupStack::PushL( self ); | 
|         |     94     self->ConstructL(); | 
|         |     95     CleanupStack::Pop(); | 
|         |     96  | 
|         |     97     return self; | 
|         |     98     } | 
|         |     99  | 
|         |    100 // Destructor | 
|         |    101 CHttpCacheLookupTable::~CHttpCacheLookupTable() | 
|         |    102     { | 
|         |    103     // do not call ResetAndDestroy on iEntries | 
|         |    104     // as delete item are not set to NULL | 
|         |    105     if (iEntries) | 
|         |    106     { | 
|         |    107       for( TInt i = 0; i < iEntries->Count(); i++ ) | 
|         |    108           { | 
|         |    109           if( Valid( i ) ) | 
|         |    110               { | 
|         |    111               CHttpCacheEntry* entry = iEntries->At( i ); | 
|         |    112               delete entry; | 
|         |    113               } | 
|         |    114           } | 
|         |    115       iEntries->Reset(); | 
|         |    116     } | 
|         |    117  | 
|         |    118     delete iEntries; | 
|         |    119  | 
|         |    120     } | 
|         |    121  | 
|         |    122 // ----------------------------------------------------------------------------- | 
|         |    123 // CHttpCacheLookupTable::InsertL | 
|         |    124 // | 
|         |    125 // ----------------------------------------------------------------------------- | 
|         |    126 // | 
|         |    127 CHttpCacheEntry* CHttpCacheLookupTable::InsertL( | 
|         |    128     const TDesC8& aUrl ) | 
|         |    129     { | 
|         |    130     // create and insert the item | 
|         |    131     CHttpCacheEntry* entry = CHttpCacheEntry::NewLC( aUrl, *iEvictionHandler ); | 
|         |    132  | 
|         |    133     if( InsertL( entry ) == KErrCorrupt ) | 
|         |    134         { | 
|         |    135         // cleanup | 
|         |    136         CleanupStack::PopAndDestroy(); // entry | 
|         |    137         entry = NULL; | 
|         |    138         } | 
|         |    139     else | 
|         |    140         { | 
|         |    141         entry->Accessed(); | 
|         |    142         // lookuptable takes ownership | 
|         |    143         CleanupStack::Pop(); // entry | 
|         |    144         } | 
|         |    145     return entry; | 
|         |    146     } | 
|         |    147  | 
|         |    148 // ----------------------------------------------------------------------------- | 
|         |    149 // CHttpCacheLookupTable::Find | 
|         |    150 // | 
|         |    151 // ----------------------------------------------------------------------------- | 
|         |    152 // | 
|         |    153 CHttpCacheEntry* CHttpCacheLookupTable::Find( | 
|         |    154     const TDesC8& aUrl ) | 
|         |    155     { | 
|         |    156     CHttpCacheEntry* entry = NULL; | 
|         |    157   TInt pos( Probe( aUrl, EFalse ) ); | 
|         |    158     // | 
|         |    159   if( Valid( pos ) ) | 
|         |    160         { | 
|         |    161         entry = iEntries->At( pos ); | 
|         |    162         } | 
|         |    163   return entry; | 
|         |    164     } | 
|         |    165  | 
|         |    166 // ----------------------------------------------------------------------------- | 
|         |    167 // CHttpCacheLookupTable::Remove | 
|         |    168 // | 
|         |    169 // ----------------------------------------------------------------------------- | 
|         |    170 // | 
|         |    171 TInt CHttpCacheLookupTable::Remove( | 
|         |    172     const TDesC8& aUrl ) | 
|         |    173     { | 
|         |    174     TInt status( KErrNotFound ); | 
|         |    175   TInt pos( Probe( aUrl, EFalse ) ); | 
|         |    176     // | 
|         |    177   if( Valid( pos ) ) | 
|         |    178         { | 
|         |    179         // remove only nonactive entry | 
|         |    180         CHttpCacheEntry* entry = iEntries->At( pos ); | 
|         |    181         if( entry->State() == CHttpCacheEntry::ECacheComplete ) | 
|         |    182             { | 
|         |    183             Erase( pos ); | 
|         |    184             status = KErrNone; | 
|         |    185             HttpCacheUtil::WriteLog( 0, _L( "remove item" ), pos ); | 
|         |    186             } | 
|         |    187 #ifndef __CACHELOG__ | 
|         |    188         } | 
|         |    189 #else // __CACHELOG__ | 
|         |    190         else | 
|         |    191             { | 
|         |    192             HttpCacheUtil::WriteLog( 0, _L( "item is active. cannot be removed" ), pos ); | 
|         |    193             } | 
|         |    194         } | 
|         |    195     else | 
|         |    196         { | 
|         |    197         HttpCacheUtil::WriteLog( 0, _L( "item is not valid. cannot be removed" ), pos ); | 
|         |    198         } | 
|         |    199 #endif // __CACHELOG__ | 
|         |    200     return status; | 
|         |    201     } | 
|         |    202  | 
|         |    203 // ----------------------------------------------------------------------------- | 
|         |    204 // CHttpCacheLookupTable::EraseCorruptEntry | 
|         |    205 // | 
|         |    206 // ----------------------------------------------------------------------------- | 
|         |    207 // | 
|         |    208 void CHttpCacheLookupTable::EraseCorruptEntry( | 
|         |    209     const TDesC8& aUrl ) | 
|         |    210     { | 
|         |    211   TInt pos( Probe( aUrl, EFalse ) ); | 
|         |    212     // | 
|         |    213   if( Valid( pos ) ) | 
|         |    214         { | 
|         |    215         Erase( pos ); | 
|         |    216         HttpCacheUtil::WriteLog( 0, _L( "remove corrupt item" ), pos ); | 
|         |    217         } | 
|         |    218 #ifdef __CACHELOG__ | 
|         |    219     else | 
|         |    220         { | 
|         |    221         // there must be a valid position for this entry | 
|         |    222         __ASSERT_DEBUG( EFalse, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    223         HttpCacheUtil::WriteLog( 0, _L( "corrupt item is not valid" ), pos ); | 
|         |    224         } | 
|         |    225 #endif // __CACHELOG__ | 
|         |    226     } | 
|         |    227  | 
|         |    228 // ----------------------------------------------------------------------------- | 
|         |    229 // CHttpCacheLookupTable::RemoveAll | 
|         |    230 // | 
|         |    231 // ----------------------------------------------------------------------------- | 
|         |    232 // | 
|         |    233 TInt CHttpCacheLookupTable::RemoveAll() | 
|         |    234     { | 
|         |    235     TInt numberOfBytes( 0 ); | 
|         |    236     HttpCacheUtil::WriteLog( 0, _L( "remove 'em all" ) ); | 
|         |    237     // | 
|         |    238     for( TInt i = 0; i < iEntries->Count(); i++ ) | 
|         |    239         { | 
|         |    240         CHttpCacheEntry* entry = iEntries->At( i ); | 
|         |    241         // remove all nonactive entries | 
|         |    242         if( Valid( i ) && entry->State() == CHttpCacheEntry::ECacheComplete ) | 
|         |    243             { | 
|         |    244             numberOfBytes+= ( entry->HeaderSize() + entry->Size() ); | 
|         |    245             Erase( i ); | 
|         |    246             } | 
|         |    247         } | 
|         |    248 #ifdef __CACHELOG__ | 
|         |    249     HttpCacheUtil::WriteLog( 0, _L( "number of items left:" ), iCount ); | 
|         |    250     // check if there are pending items -should not be though | 
|         |    251     __ASSERT_DEBUG( iCount == 0, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    252 #endif // __CACHELOG__ | 
|         |    253     return numberOfBytes; | 
|         |    254     } | 
|         |    255  | 
|         |    256  | 
|         |    257 // ----------------------------------------------------------------------------- | 
|         |    258 // CHttpCacheLookupTable::ListFiles | 
|         |    259 // Adds all filenames known to this lookup table to aFilenameList | 
|         |    260 // No ownership transfer occurs, only pointers are added | 
|         |    261 // ----------------------------------------------------------------------------- | 
|         |    262 // | 
|         |    263 TInt CHttpCacheLookupTable::ListFiles(RPointerArray<TDesC>& aFilenameList) | 
|         |    264     { | 
|         |    265     TInt count( 0 ); | 
|         |    266     TInt error( KErrNone ); | 
|         |    267  | 
|         |    268     //1. Tally up  | 
|         |    269     for (TInt i = 0; i < iEntries->Count(); i++) | 
|         |    270         { | 
|         |    271         if (Valid(i)) count++; | 
|         |    272         } | 
|         |    273  | 
|         |    274     //2. Preallocation.  | 
|         |    275     TInt existing( aFilenameList.Count() ); | 
|         |    276     error = aFilenameList.Reserve( existing + count ); | 
|         |    277  | 
|         |    278     if (error == KErrNone) | 
|         |    279         { | 
|         |    280         //3. Iterate once more and add pointers to filename strings | 
|         |    281         for (TInt i = 0; i < iEntries->Count(); i++) | 
|         |    282             { | 
|         |    283             if (Valid(i)) | 
|         |    284                 { | 
|         |    285                 //add filename pointer to the array.  | 
|         |    286                 const TDesC* ptr = &(iEntries->At(i)->Filename()); | 
|         |    287                 aFilenameList.Append( ptr ); // no ownership transfer happens here | 
|         |    288                 } | 
|         |    289             } | 
|         |    290         } | 
|         |    291       | 
|         |    292     return error; | 
|         |    293  | 
|         |    294     } | 
|         |    295  | 
|         |    296 // ----------------------------------------------------------------------------- | 
|         |    297 // CHttpCacheLookupTable::Internalize | 
|         |    298 // | 
|         |    299 // ----------------------------------------------------------------------------- | 
|         |    300 // | 
|         |    301 void CHttpCacheLookupTable::InternalizeL( | 
|         |    302     RFileReadStream& aReadStream, | 
|         |    303     const TDesC& /*aDirectory*/ ) | 
|         |    304     { | 
|         |    305     // get number of entries | 
|         |    306     TInt version = 0; | 
|         |    307     TRAP_IGNORE( version = aReadStream.ReadInt32L() ); | 
|         |    308     if( version == KCacheVersionNumber ) | 
|         |    309         { | 
|         |    310         TInt count( aReadStream.ReadInt32L() ); | 
|         |    311         TInt contentSize( 0 ); | 
|         |    312         TInt err; | 
|         |    313         for( TInt i = 0; i < count; i++ ) | 
|         |    314             { | 
|         |    315             // create empty object | 
|         |    316             CHttpCacheEntry* entry = CHttpCacheEntry::NewLC( KNullDesC8, *iEvictionHandler ); | 
|         |    317             // read it | 
|         |    318             err = entry->Internalize( aReadStream ); | 
|         |    319             // leave only on no memory | 
|         |    320             if( err == KErrNone ) | 
|         |    321                 { | 
|         |    322                 // insert to the table | 
|         |    323                 InsertL( entry ); | 
|         |    324                 contentSize+=entry->HeaderSize(); | 
|         |    325                 contentSize+=entry->Size(); | 
|         |    326                 } | 
|         |    327             else if( err == KErrNoMemory ) | 
|         |    328                 { | 
|         |    329                 User::Leave( KErrNoMemory ); | 
|         |    330                 } | 
|         |    331             else | 
|         |    332                 { | 
|         |    333                 // suggestions? | 
|         |    334                 } | 
|         |    335             // takes ownership | 
|         |    336             CleanupStack::Pop(); // entry | 
|         |    337             } | 
|         |    338         // set startup cache size | 
|         |    339         HttpCacheUtil::WriteLog( 0, _L( "startup content size" ), contentSize ); | 
|         |    340         iStreamHandler->SetStartupCacheSize( contentSize ); | 
|         |    341         } | 
|         |    342     else | 
|         |    343         { | 
|         |    344         // cleanup index.dat? | 
|         |    345         } | 
|         |    346     } | 
|         |    347  | 
|         |    348 // ----------------------------------------------------------------------------- | 
|         |    349 // CHttpCacheLookupTable::Externalize | 
|         |    350 // | 
|         |    351 // ----------------------------------------------------------------------------- | 
|         |    352 // | 
|         |    353 void CHttpCacheLookupTable::ExternalizeL( | 
|         |    354     RFileWriteStream& aWriteStream ) | 
|         |    355     { | 
|         |    356     // write version number and the number of entries | 
|         |    357     TRAP_IGNORE( aWriteStream.WriteInt32L( KCacheVersionNumber ); | 
|         |    358     aWriteStream.WriteInt32L( iCount ) ); | 
|         |    359     for( TInt i = 0; i < iEntries->Count(); i++ ) | 
|         |    360         { | 
|         |    361         CHttpCacheEntry* entry = iEntries->At( i ); | 
|         |    362         // save complete entries only | 
|         |    363         if( Valid( i ) ) | 
|         |    364             { | 
|         |    365             // save entry | 
|         |    366             TInt err; | 
|         |    367             err = entry->Externalize( aWriteStream ); | 
|         |    368             // leave only on no memory | 
|         |    369             if( err == KErrNoMemory ) | 
|         |    370                 { | 
|         |    371                 User::Leave( KErrNoMemory ); | 
|         |    372                 } | 
|         |    373             } | 
|         |    374         } | 
|         |    375     } | 
|         |    376  | 
|         |    377 // ----------------------------------------------------------------------------- | 
|         |    378 // CHttpCacheLookupTable::InsertL | 
|         |    379 // | 
|         |    380 // ----------------------------------------------------------------------------- | 
|         |    381 // | 
|         |    382 TInt CHttpCacheLookupTable::InsertL( | 
|         |    383     CHttpCacheEntry* aCacheEntry ) | 
|         |    384     { | 
|         |    385     __ASSERT_DEBUG( aCacheEntry != NULL, | 
|         |    386         User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    387     // | 
|         |    388     TInt pos( -1 ); | 
|         |    389  | 
|         |    390     if( aCacheEntry ) | 
|         |    391         { | 
|         |    392         pos = Probe( aCacheEntry->Url(), ETrue ); | 
|         |    393         // double check | 
|         |    394         if( Valid( pos ) ) | 
|         |    395             { | 
|         |    396             // try to rehash the table if probe failed | 
|         |    397             ReHashL(); | 
|         |    398             pos = Probe( aCacheEntry->Url(), ETrue ); | 
|         |    399  | 
|         |    400             if( pos == -1 || Valid( pos ) ) | 
|         |    401                 { | 
|         |    402                 // completly failed | 
|         |    403                 pos = -1; | 
|         |    404                 } | 
|         |    405             } | 
|         |    406         // insert | 
|         |    407         if( pos != -1 ) | 
|         |    408             { | 
|         |    409             iEntries->At( pos ) = aCacheEntry; | 
|         |    410             iCount++; | 
|         |    411             HttpCacheUtil::WriteLog( 0, _L( "insert new item to the lookuptable" ), pos ); | 
|         |    412             // check if the hashtable is full | 
|         |    413             if( iCount > ( iEntries->Count() >> 1 ) ) | 
|         |    414                 { | 
|         |    415                 ReHashL(); | 
|         |    416                 } | 
|         |    417             } | 
|         |    418         else | 
|         |    419             { | 
|         |    420             // lose entry??? | 
|         |    421             __ASSERT_DEBUG( EFalse, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    422             } | 
|         |    423         } | 
|         |    424     return pos == -1 ? KErrCorrupt : KErrNone; | 
|         |    425     } | 
|         |    426  | 
|         |    427 // ----------------------------------------------------------------------------- | 
|         |    428 // CHttpCacheLookupTable::Probe | 
|         |    429 // | 
|         |    430 // ----------------------------------------------------------------------------- | 
|         |    431 // | 
|         |    432 TInt CHttpCacheLookupTable::Probe( | 
|         |    433     const TDesC8& aKey, | 
|         |    434     TBool aInsert ) | 
|         |    435     { | 
|         |    436     // | 
|         |    437   TInt collision( 0 ); | 
|         |    438   TInt pos( HashUrl( aKey ) ); | 
|         |    439  | 
|         |    440   if( aInsert ) | 
|         |    441         { | 
|         |    442         // insert | 
|         |    443         while( Valid( pos ) && ( collision < ( iEntries->Count() / 2 ) ) ) | 
|         |    444             { | 
|         |    445             pos += ++collision * 2 - 1; | 
|         |    446             pos = pos % iEntries->Count(); | 
|         |    447             } | 
|         |    448         } | 
|         |    449     else | 
|         |    450         { | 
|         |    451         // find | 
|         |    452       while( !Empty( pos ) ) | 
|         |    453             { | 
|         |    454             CHttpCacheEntry* entry = iEntries->At( pos ); | 
|         |    455             if( Valid( pos ) && entry && entry->Url().CompareF( aKey ) == 0 ) | 
|         |    456                 { | 
|         |    457                 break; | 
|         |    458                 } | 
|         |    459             if( collision > iEntries->Count() ) | 
|         |    460                 { | 
|         |    461                 return -1; | 
|         |    462                 } | 
|         |    463             pos += ++collision * 2 - 1; | 
|         |    464             pos = pos % iEntries->Count(); | 
|         |    465             } | 
|         |    466         } | 
|         |    467 #ifdef __CACHELOG__ | 
|         |    468     if( collision > 0 ) | 
|         |    469         { | 
|         |    470         HttpCacheUtil::WriteLog( 1, _L( "collision" ), collision ); | 
|         |    471         } | 
|         |    472 #endif // __CACHELOG__ | 
|         |    473   return pos; | 
|         |    474     } | 
|         |    475  | 
|         |    476 // ----------------------------------------------------------------------------- | 
|         |    477 // CHttpCacheLookupTable::HashUrl | 
|         |    478 // | 
|         |    479 // ----------------------------------------------------------------------------- | 
|         |    480 // | 
|         |    481 TInt CHttpCacheLookupTable::HashUrl( | 
|         |    482     const TDesC8& aUrl ) | 
|         |    483     { | 
|         |    484     // This hash algorithm comes from: | 
|         |    485     // http://burtleburtle.net/bob/hash/hashfaq.html | 
|         |    486     // http://burtleburtle.net/bob/hash/doobs.html | 
|         |    487     TUint len( aUrl.Length() ); | 
|         |    488     TUint h( KHashPHI ); | 
|         |    489  | 
|         |    490     h += len; | 
|         |    491     h += (h << 10); | 
|         |    492     h ^= (h << 6); | 
|         |    493     // | 
|         |    494     if( len ) | 
|         |    495         { | 
|         |    496         // hash backward to avoid collisions | 
|         |    497         // as the first part of the url is | 
|         |    498         // always the same http://www. | 
|         |    499         // take 16 characters by default | 
|         |    500         TUint hashStringLength( len < KHashStringLength ? len : KHashStringLength ); | 
|         |    501  | 
|         |    502         for( TUint i = ( len - 1 ); i > len - hashStringLength; i-- ) | 
|         |    503             { | 
|         |    504         h += aUrl[ i ]; | 
|         |    505         h += (h << 10); | 
|         |    506         h ^= (h << 6); | 
|         |    507           } | 
|         |    508         } | 
|         |    509     h += (h << 3); | 
|         |    510     h ^= (h >> 11); | 
|         |    511     h += (h << 15); | 
|         |    512  | 
|         |    513     // | 
|         |    514     h = h % iEntries->Count(); | 
|         |    515 #ifdef __CACHELOG__ | 
|         |    516     HttpCacheUtil::WriteUrlToLog( 1, aUrl, h ); | 
|         |    517 #endif // __CACHELOG__ | 
|         |    518     return h; | 
|         |    519     } | 
|         |    520  | 
|         |    521 // ----------------------------------------------------------------------------- | 
|         |    522 // CHttpCacheLookupTable::ReHashL | 
|         |    523 // | 
|         |    524 // ----------------------------------------------------------------------------- | 
|         |    525 // | 
|         |    526 void CHttpCacheLookupTable::ReHashL() | 
|         |    527     { | 
|         |    528     HttpCacheUtil::WriteLog( 1, _L( "Resize lookuptable!" ) ); | 
|         |    529     HttpCacheUtil::WriteLog( 1, _L( "count=" ), iCount ); | 
|         |    530     HttpCacheUtil::WriteLog( 1, _L( "Table size=" ), iEntries->Count() ); | 
|         |    531     // | 
|         |    532     TUint newSize( NextPrime( iEntries->Count() * 2 ) ); | 
|         |    533   CArrayPtrFlat<CHttpCacheEntry>* newEntries = | 
|         |    534         new( ELeave )CArrayPtrFlat<CHttpCacheEntry>( newSize ); | 
|         |    535     // hash must operate on the new table | 
|         |    536     CArrayPtrFlat<CHttpCacheEntry>* oldEntries = iEntries; | 
|         |    537     iEntries = newEntries; | 
|         |    538     CleanupStack::PushL( oldEntries ); | 
|         |    539     // fill list with 0 | 
|         |    540     for( TUint i = 0; i < newSize; i++ ) | 
|         |    541         { | 
|         |    542         iEntries->AppendL( NULL ); | 
|         |    543         } | 
|         |    544     // | 
|         |    545   for( TUint i = 0; i < oldEntries->Count(); i++ ) | 
|         |    546       { | 
|         |    547     CHttpCacheEntry* entry = oldEntries->At( i ); | 
|         |    548         // transfer valid entries only | 
|         |    549     if( entry && entry != (CHttpCacheEntry*)0xffffffff ) | 
|         |    550             { | 
|         |    551             TInt pos( Probe( entry->Url(), ETrue ) ); | 
|         |    552             // | 
|         |    553       if( pos != -1 && !Valid( pos ) ) | 
|         |    554                 { | 
|         |    555                 iEntries->At( pos ) = entry; | 
|         |    556                 // remove ownership | 
|         |    557                 oldEntries->At( i ) = NULL; | 
|         |    558                 } | 
|         |    559             // else lose the entry?? | 
|         |    560             else | 
|         |    561                 { | 
|         |    562                 // assert | 
|         |    563                 __ASSERT_DEBUG( EFalse, User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    564                 } | 
|         |    565         } | 
|         |    566       } | 
|         |    567 #ifdef __CACHELOG__ | 
|         |    568   for( TUint i = 0; i < iEntries->Count(); i++ ) | 
|         |    569         { | 
|         |    570     CHttpCacheEntry* entry = iEntries->At( i ); | 
|         |    571         if( entry && Valid( i ) ) | 
|         |    572             { | 
|         |    573             HttpCacheUtil::WriteUrlToLog( 1, entry->Url(), i ); | 
|         |    574             } | 
|         |    575         } | 
|         |    576 #endif // __CACHELOG__ | 
|         |    577     CleanupStack::PopAndDestroy(); // oldEntries | 
|         |    578     } | 
|         |    579  | 
|         |    580 // ----------------------------------------------------------------------------- | 
|         |    581 // CHttpCacheLookupTable::NextPrime | 
|         |    582 // | 
|         |    583 // ----------------------------------------------------------------------------- | 
|         |    584 // | 
|         |    585 TUint CHttpCacheLookupTable::NextPrime( | 
|         |    586     TUint aNum ) | 
|         |    587     { | 
|         |    588   if( aNum % 2 == 0 ) | 
|         |    589         { | 
|         |    590         aNum++; | 
|         |    591         } | 
|         |    592  | 
|         |    593   for( ;; ) | 
|         |    594         { | 
|         |    595     for( TUint i = 3; i * i <= aNum; i += 2 ) | 
|         |    596       if( aNum % i == 0 ) | 
|         |    597                 { | 
|         |    598         aNum += 2; | 
|         |    599         i = 1; | 
|         |    600         continue; | 
|         |    601       } | 
|         |    602     return aNum; | 
|         |    603       } | 
|         |    604     } | 
|         |    605  | 
|         |    606 // ----------------------------------------------------------------------------- | 
|         |    607 // CHttpCacheLookupTable::Erase | 
|         |    608 // | 
|         |    609 // ----------------------------------------------------------------------------- | 
|         |    610 // | 
|         |    611 void CHttpCacheLookupTable::Erase( | 
|         |    612     TInt aPos ) | 
|         |    613     { | 
|         |    614     // must be a valid pos | 
|         |    615     __ASSERT_DEBUG( Valid( aPos ),  User::Panic( _L("cacheHandler Panic"), KErrCorrupt ) ); | 
|         |    616     CHttpCacheEntry* entry = iEntries->At( aPos ); | 
|         |    617  | 
|         |    618     if( entry ) | 
|         |    619         { | 
|         |    620         // delete file associated with this entry | 
|         |    621         TBool attached( EFalse ); | 
|         |    622         TRAPD( err, attached = iStreamHandler->AttachL( *entry ) ); | 
|         |    623         if( err == KErrNone && attached ) | 
|         |    624             { | 
|         |    625             iStreamHandler->Erase( *entry ); | 
|         |    626             iStreamHandler->Detach( *entry ); | 
|         |    627             } | 
|         |    628         // | 
|         |    629         SetDeleted( aPos ); | 
|         |    630         delete entry; | 
|         |    631         iCount--; | 
|         |    632         } | 
|         |    633     } | 
|         |    634  | 
|         |    635 // ----------------------------------------------------------------------------- | 
|         |    636 // CHttpCacheLookupTable::Valid | 
|         |    637 // | 
|         |    638 // ----------------------------------------------------------------------------- | 
|         |    639 // | 
|         |    640 TBool CHttpCacheLookupTable::Valid( | 
|         |    641     TInt aPos ) | 
|         |    642     { | 
|         |    643     return( BoundaryCheck( aPos ) && !Empty( aPos ) && !Deleted( aPos ) ); | 
|         |    644     } | 
|         |    645  | 
|         |    646 // ----------------------------------------------------------------------------- | 
|         |    647 // CHttpCacheLookupTable::Empty | 
|         |    648 // | 
|         |    649 // ----------------------------------------------------------------------------- | 
|         |    650 // | 
|         |    651 TBool CHttpCacheLookupTable::Empty( | 
|         |    652     TInt aPos ) | 
|         |    653     { | 
|         |    654     return( BoundaryCheck( aPos ) && iEntries->At( aPos ) == NULL ); | 
|         |    655     } | 
|         |    656  | 
|         |    657 // ----------------------------------------------------------------------------- | 
|         |    658 // CHttpCacheLookupTable::Deleted | 
|         |    659 // | 
|         |    660 // ----------------------------------------------------------------------------- | 
|         |    661 // | 
|         |    662 TBool CHttpCacheLookupTable::Deleted( | 
|         |    663     TInt aPos ) | 
|         |    664     { | 
|         |    665     return( BoundaryCheck( aPos ) && iEntries->At( aPos ) == (CHttpCacheEntry*)0xffffffff ); | 
|         |    666     } | 
|         |    667  | 
|         |    668 // ----------------------------------------------------------------------------- | 
|         |    669 // CHttpCacheLookupTable::SetDeleted | 
|         |    670 // | 
|         |    671 // ----------------------------------------------------------------------------- | 
|         |    672 // | 
|         |    673 void CHttpCacheLookupTable::SetDeleted( | 
|         |    674     TInt aPos ) | 
|         |    675     { | 
|         |    676     if( BoundaryCheck( aPos ) ) | 
|         |    677         { | 
|         |    678         iEntries->At( aPos ) = (CHttpCacheEntry*)0xffffffff; | 
|         |    679         } | 
|         |    680     } | 
|         |    681  | 
|         |    682 // ----------------------------------------------------------------------------- | 
|         |    683 // CHttpCacheLookupTable::BoundaryCheck | 
|         |    684 // | 
|         |    685 // ----------------------------------------------------------------------------- | 
|         |    686 // | 
|         |    687 TBool CHttpCacheLookupTable::BoundaryCheck( | 
|         |    688     TInt aPos ) | 
|         |    689     { | 
|         |    690     return ( aPos >= 0 && aPos < iEntries->Count() ); | 
|         |    691     } | 
|         |    692  | 
|         |    693 // ----------------------------------------------------------------------------- | 
|         |    694 // CHttpCacheLookupTable::MergeL | 
|         |    695 // | 
|         |    696 // ----------------------------------------------------------------------------- | 
|         |    697 // | 
|         |    698 void CHttpCacheLookupTable::MergeL( CHttpCacheLookupTable* aHttpCacheLookupTable, RFs aRfs ) | 
|         |    699     { | 
|         |    700     TInt myCount = iEntries->Count(); | 
|         |    701     TInt i = 0; | 
|         |    702     for (i = myCount - 1; i >= 0; i--) | 
|         |    703         { | 
|         |    704         if ( Valid( i ) ) | 
|         |    705             { | 
|         |    706             CHttpCacheEntry* entry = iEntries->At(i); | 
|         |    707             CHttpCacheEntry* newEntry = aHttpCacheLookupTable->Find(entry->Url()); | 
|         |    708             if (newEntry) | 
|         |    709                 { | 
|         |    710                 // Entry is in the new index file | 
|         |    711                 if (newEntry->LastAccessed() > entry->LastAccessed()) | 
|         |    712                     { | 
|         |    713                     entry->Accessed(newEntry->LastAccessed(), newEntry->Ref()); | 
|         |    714                     } | 
|         |    715                 TInt pos = aHttpCacheLookupTable->Probe(newEntry->Url(), EFalse); | 
|         |    716                 if (aHttpCacheLookupTable->Valid(pos)) | 
|         |    717                     { | 
|         |    718                     aHttpCacheLookupTable->SetDeleted(pos); | 
|         |    719                     delete newEntry; | 
|         |    720                     aHttpCacheLookupTable->iCount--; | 
|         |    721                     } | 
|         |    722                 } | 
|         |    723             else // (newEntry) | 
|         |    724                 { | 
|         |    725                 // Entry is not in the new index file | 
|         |    726                 TUint att; | 
|         |    727                 if (aRfs.Att(entry->Filename(), att) != KErrNone) | 
|         |    728                     { | 
|         |    729                     TInt thePos = Probe(entry->Url(), EFalse); | 
|         |    730                     if (Valid(thePos)) | 
|         |    731                         { | 
|         |    732                         Erase(thePos); | 
|         |    733                         } | 
|         |    734                     } | 
|         |    735                 } | 
|         |    736             } | 
|         |    737         } | 
|         |    738  | 
|         |    739     TInt newCount = aHttpCacheLookupTable->iEntries->Count(); | 
|         |    740     for (i = newCount - 1; i >= 0; i--) | 
|         |    741         { | 
|         |    742         if ( aHttpCacheLookupTable->Valid( i ) ) | 
|         |    743             { | 
|         |    744             CHttpCacheEntry* newEntry = aHttpCacheLookupTable->iEntries->At(i); | 
|         |    745             TInt pos = aHttpCacheLookupTable->Probe(newEntry->Url(), EFalse); | 
|         |    746             TUint att; | 
|         |    747             if (aRfs.Att(newEntry->Filename(), att) == KErrNone) | 
|         |    748                 { | 
|         |    749                 CHttpCacheEntry* myEntry = InsertL(newEntry->Url()); | 
|         |    750                 myEntry->SetState( CHttpCacheEntry::ECacheComplete ); | 
|         |    751                 myEntry->Accessed(newEntry->LastAccessed(), newEntry->Ref()); | 
|         |    752                 }           | 
|         |    753             aHttpCacheLookupTable->SetDeleted(pos); | 
|         |    754             delete newEntry; | 
|         |    755             aHttpCacheLookupTable->iCount--; | 
|         |    756             } | 
|         |    757         } | 
|         |    758     } | 
|         |    759 //  End of File |