1496 |
1443 |
1497 // ----------------------------------------------------------------------------- |
1444 // ----------------------------------------------------------------------------- |
1498 // CHttpCacheHandler::ValidateCacheEntriesL |
1445 // CHttpCacheHandler::ValidateCacheEntriesL |
1499 // ----------------------------------------------------------------------------- |
1446 // ----------------------------------------------------------------------------- |
1500 // |
1447 // |
1501 void CHttpCacheHandler::ValidateCacheEntriesL() |
1448 void CHttpCacheHandler::ValidateCacheEntriesL(CHttpCacheFileHash *aDiskContent) |
1502 { |
1449 { |
1503 // iterate through entries and check if file is present. |
1450 // 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 |
1451 // 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, |
1452 // 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; |
1453 THttpCacheLookupTableEntryIterator iter; |
1508 iLookupTable->BeginEntryIteration(iter); |
1454 iLookupTable->BeginEntryIteration(iter); |
1509 #ifdef __CACHELOG__ |
1455 #ifdef __CACHELOG__ |
1510 HttpCacheUtil::WriteLog(0, _L("CHttpCacheHandler::ValidateCacheEntriesL")); |
1456 HttpCacheUtil::WriteLog(0, _L("CHttpCacheHandler::ValidateCacheEntriesL")); |
1511 #endif |
1457 #endif |
1512 // if the cache contains no items, we should still do this so we detect other files. |
1458 |
1513 |
1459 // mark our index file as 'no delete' |
1514 // get list of files on disk |
1460 RHttpCacheFileHashMap& hashmap = aDiskContent->HashMap(); |
1515 CCacheDirectoryFiles *dirFiles = CCacheDirectoryFiles::NewLC(iRfs, *iDirectory); |
1461 TFileName indexFile; |
1516 |
1462 indexFile.Copy( iDirectory->Des() ); |
|
1463 indexFile.Append( iIndexFile->Des() ); |
|
1464 TFileInfo *info = hashmap.Find( indexFile ); |
|
1465 if( info ) |
|
1466 { |
|
1467 info->iUserInt = KCacheFileNoDelete; |
|
1468 } |
|
1469 |
1517 // look for bad entries |
1470 // look for bad entries |
1518 RPointerArray<HBufC8> badEntries; |
1471 RPointerArray<HBufC8> badEntries; |
1519 CleanupStack::PushL(TCleanupItem(DestroyBadUrlArray, &badEntries)); |
1472 CleanupStack::PushL(TCleanupItem(DestroyBadUrlArray, &badEntries)); |
1520 const CHttpCacheEntry *tmpEntry; |
1473 const CHttpCacheEntry *tmpEntry; |
1521 while(tmpEntry = iLookupTable->NextEntry(iter), tmpEntry) |
1474 while(tmpEntry = iLookupTable->NextEntry(iter), tmpEntry) |
1522 { |
1475 { |
1523 if(!dirFiles->ValidateEntryL(*tmpEntry)) |
1476 // check the files associated with the cache entry are present where they should be |
|
1477 // if the file is present AND the size matches the entry, mark the hashmap value with noDelete. |
|
1478 // otherwise, mark the hash map with delete and remove the entry. |
|
1479 info = hashmap.Find(tmpEntry->Filename()); |
|
1480 if(info && info->iFileSize == tmpEntry->BodySize()) |
|
1481 { |
|
1482 info->iUserInt = KCacheFileNoDelete; // noDelete |
|
1483 } |
|
1484 else |
1524 { |
1485 { |
1525 #ifdef __CACHELOG__ |
1486 #ifdef __CACHELOG__ |
1526 HttpCacheUtil::WriteUrlToLog(0, _L("Bad Entry: "), tmpEntry->Url() ); |
1487 HttpCacheUtil::WriteUrlToLog(0, _L("Bad Entry: "), tmpEntry->Url() ); |
1527 #endif |
1488 #endif |
1528 badEntries.AppendL(tmpEntry->Url().AllocL()); |
1489 badEntries.AppendL(tmpEntry->Url().AllocL()); |
1529 } |
1490 if(info) |
1530 } |
1491 info->iUserInt = KCacheFileNeedsDelete; // needs delete |
1531 |
1492 } |
1532 // remove bad entries |
1493 } |
|
1494 |
|
1495 // remove entries from cache where files don't match content on disk, either file is missing or size is incorrect. |
|
1496 // needed to save URIs because that's the only interface we have here. |
1533 for(TInt i=0; i < badEntries.Count(); i++) |
1497 for(TInt i=0; i < badEntries.Count(); i++) |
1534 { |
1498 { |
1535 iLookupTable->Remove(badEntries[i]->Des()); |
1499 iLookupTable->Remove(badEntries[i]->Des()); |
1536 } |
1500 } |
1537 CleanupStack::PopAndDestroy(1); // bad entry list |
1501 CleanupStack::PopAndDestroy(1); // bad entry list |
1538 |
1502 } |
1539 // remove orphan files |
1503 |
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; |
|
1867 } |
|
1868 // End of File |
1504 // End of File |