1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/cache/nsDiskCacheMap.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,579 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim:set ts=4 sw=4 sts=4 cin et: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef _nsDiskCacheMap_h_ 1.11 +#define _nsDiskCacheMap_h_ 1.12 + 1.13 +#include "mozilla/MemoryReporting.h" 1.14 +#include <limits.h> 1.15 + 1.16 +#include "prnetdb.h" 1.17 +#include "nsDebug.h" 1.18 +#include "nsError.h" 1.19 +#include "nsIFile.h" 1.20 +#include "nsITimer.h" 1.21 + 1.22 +#include "nsDiskCache.h" 1.23 +#include "nsDiskCacheBlockFile.h" 1.24 + 1.25 + 1.26 +class nsDiskCacheBinding; 1.27 +struct nsDiskCacheEntry; 1.28 + 1.29 +/****************************************************************************** 1.30 + * nsDiskCacheRecord 1.31 + * 1.32 + * Cache Location Format 1.33 + * 1.34 + * 1000 0000 0000 0000 0000 0000 0000 0000 : initialized bit 1.35 + * 1.36 + * 0011 0000 0000 0000 0000 0000 0000 0000 : File Selector (0 = separate file) 1.37 + * 0000 0011 0000 0000 0000 0000 0000 0000 : number of extra contiguous blocks 1-4 1.38 + * 0100 1100 0000 0000 0000 0000 0000 0000 : reserved bits 1.39 + * 0000 0000 1111 1111 1111 1111 1111 1111 : block# 0-16777216 (2^24) 1.40 + * 1.41 + * 0000 0000 1111 1111 1111 1111 0000 0000 : eFileSizeMask (size of file in k: see note) 1.42 + * 0000 0000 0000 0000 0000 0000 1111 1111 : eFileGenerationMask 1.43 + * 1.44 + * File Selector: 1.45 + * 0 = separate file on disk 1.46 + * 1 = 256 byte block file 1.47 + * 2 = 1k block file 1.48 + * 3 = 4k block file 1.49 + * 1.50 + * eFileSizeMask note: Files larger than 65535 KiB have this limit stored in 1.51 + * the location. The file itself must be examined to 1.52 + * determine its actual size if necessary. 1.53 + * 1.54 + *****************************************************************************/ 1.55 + 1.56 +/* 1.57 + We have 3 block files with roughly the same max size (32MB) 1.58 + 1 - block size 256B, number of blocks 131072 1.59 + 2 - block size 1kB, number of blocks 32768 1.60 + 3 - block size 4kB, number of blocks 8192 1.61 +*/ 1.62 +#define kNumBlockFiles 3 1.63 +#define SIZE_SHIFT(idx) (2 * ((idx) - 1)) 1.64 +#define BLOCK_SIZE_FOR_INDEX(idx) ((idx) ? (256 << SIZE_SHIFT(idx)) : 0) 1.65 +#define BITMAP_SIZE_FOR_INDEX(idx) ((idx) ? (131072 >> SIZE_SHIFT(idx)) : 0) 1.66 + 1.67 +// Min and max values for the number of records in the DiskCachemap 1.68 +#define kMinRecordCount 512 1.69 + 1.70 +#define kSeparateFile 0 1.71 +#define kBuckets (1 << 5) // must be a power of 2! 1.72 + 1.73 +// Maximum size in K which can be stored in the location (see eFileSizeMask). 1.74 +// Both data and metadata can be larger, but only up to kMaxDataSizeK can be 1.75 +// counted into total cache size. I.e. if there are entries where either data or 1.76 +// metadata is larger than kMaxDataSizeK, the total cache size will be 1.77 +// inaccurate (smaller) than the actual cache size. The alternative is to stat 1.78 +// the files to find the real size, which was decided against for performance 1.79 +// reasons. See bug #651100 comment #21. 1.80 +#define kMaxDataSizeK 0xFFFF 1.81 + 1.82 +// preallocate up to 1MB of separate cache file 1.83 +#define kPreallocateLimit 1 * 1024 * 1024 1.84 + 1.85 +// The minimum amount of milliseconds to wait before re-attempting to 1.86 +// revalidate the cache. 1.87 +#define kRevalidateCacheTimeout 3000 1.88 +#define kRevalidateCacheTimeoutTolerance 10 1.89 +#define kRevalidateCacheErrorTimeout 1000 1.90 + 1.91 +class nsDiskCacheRecord { 1.92 + 1.93 +private: 1.94 + uint32_t mHashNumber; 1.95 + uint32_t mEvictionRank; 1.96 + uint32_t mDataLocation; 1.97 + uint32_t mMetaLocation; 1.98 + 1.99 + enum { 1.100 + eLocationInitializedMask = 0x80000000, 1.101 + 1.102 + eLocationSelectorMask = 0x30000000, 1.103 + eLocationSelectorOffset = 28, 1.104 + 1.105 + eExtraBlocksMask = 0x03000000, 1.106 + eExtraBlocksOffset = 24, 1.107 + 1.108 + eReservedMask = 0x4C000000, 1.109 + 1.110 + eBlockNumberMask = 0x00FFFFFF, 1.111 + 1.112 + eFileSizeMask = 0x00FFFF00, 1.113 + eFileSizeOffset = 8, 1.114 + eFileGenerationMask = 0x000000FF, 1.115 + eFileReservedMask = 0x4F000000 1.116 + 1.117 + }; 1.118 + 1.119 +public: 1.120 + nsDiskCacheRecord() 1.121 + : mHashNumber(0), mEvictionRank(0), mDataLocation(0), mMetaLocation(0) 1.122 + { 1.123 + } 1.124 + 1.125 + bool ValidRecord() 1.126 + { 1.127 + if ((mDataLocation & eReservedMask) || (mMetaLocation & eReservedMask)) 1.128 + return false; 1.129 + return true; 1.130 + } 1.131 + 1.132 + // HashNumber accessors 1.133 + uint32_t HashNumber() const { return mHashNumber; } 1.134 + void SetHashNumber( uint32_t hashNumber) { mHashNumber = hashNumber; } 1.135 + 1.136 + // EvictionRank accessors 1.137 + uint32_t EvictionRank() const { return mEvictionRank; } 1.138 + void SetEvictionRank( uint32_t rank) { mEvictionRank = rank ? rank : 1; } 1.139 + 1.140 + // DataLocation accessors 1.141 + bool DataLocationInitialized() const { return 0 != (mDataLocation & eLocationInitializedMask); } 1.142 + void ClearDataLocation() { mDataLocation = 0; } 1.143 + 1.144 + uint32_t DataFile() const 1.145 + { 1.146 + return (uint32_t)(mDataLocation & eLocationSelectorMask) >> eLocationSelectorOffset; 1.147 + } 1.148 + 1.149 + void SetDataBlocks( uint32_t index, uint32_t startBlock, uint32_t blockCount) 1.150 + { 1.151 + // clear everything 1.152 + mDataLocation = 0; 1.153 + 1.154 + // set file index 1.155 + NS_ASSERTION( index < (kNumBlockFiles + 1), "invalid location index"); 1.156 + NS_ASSERTION( index > 0,"invalid location index"); 1.157 + mDataLocation |= (index << eLocationSelectorOffset) & eLocationSelectorMask; 1.158 + 1.159 + // set startBlock 1.160 + NS_ASSERTION(startBlock == (startBlock & eBlockNumberMask), "invalid block number"); 1.161 + mDataLocation |= startBlock & eBlockNumberMask; 1.162 + 1.163 + // set blockCount 1.164 + NS_ASSERTION( (blockCount>=1) && (blockCount<=4),"invalid block count"); 1.165 + --blockCount; 1.166 + mDataLocation |= (blockCount << eExtraBlocksOffset) & eExtraBlocksMask; 1.167 + 1.168 + mDataLocation |= eLocationInitializedMask; 1.169 + } 1.170 + 1.171 + uint32_t DataBlockCount() const 1.172 + { 1.173 + return (uint32_t)((mDataLocation & eExtraBlocksMask) >> eExtraBlocksOffset) + 1; 1.174 + } 1.175 + 1.176 + uint32_t DataStartBlock() const 1.177 + { 1.178 + return (mDataLocation & eBlockNumberMask); 1.179 + } 1.180 + 1.181 + uint32_t DataBlockSize() const 1.182 + { 1.183 + return BLOCK_SIZE_FOR_INDEX(DataFile()); 1.184 + } 1.185 + 1.186 + uint32_t DataFileSize() const { return (mDataLocation & eFileSizeMask) >> eFileSizeOffset; } 1.187 + void SetDataFileSize(uint32_t size) 1.188 + { 1.189 + NS_ASSERTION((mDataLocation & eFileReservedMask) == 0, "bad location"); 1.190 + mDataLocation &= ~eFileSizeMask; // clear eFileSizeMask 1.191 + mDataLocation |= (size << eFileSizeOffset) & eFileSizeMask; 1.192 + } 1.193 + 1.194 + uint8_t DataFileGeneration() const 1.195 + { 1.196 + return (mDataLocation & eFileGenerationMask); 1.197 + } 1.198 + 1.199 + void SetDataFileGeneration( uint8_t generation) 1.200 + { 1.201 + // clear everything, (separate file index = 0) 1.202 + mDataLocation = 0; 1.203 + mDataLocation |= generation & eFileGenerationMask; 1.204 + mDataLocation |= eLocationInitializedMask; 1.205 + } 1.206 + 1.207 + // MetaLocation accessors 1.208 + bool MetaLocationInitialized() const { return 0 != (mMetaLocation & eLocationInitializedMask); } 1.209 + void ClearMetaLocation() { mMetaLocation = 0; } 1.210 + uint32_t MetaLocation() const { return mMetaLocation; } 1.211 + 1.212 + uint32_t MetaFile() const 1.213 + { 1.214 + return (uint32_t)(mMetaLocation & eLocationSelectorMask) >> eLocationSelectorOffset; 1.215 + } 1.216 + 1.217 + void SetMetaBlocks( uint32_t index, uint32_t startBlock, uint32_t blockCount) 1.218 + { 1.219 + // clear everything 1.220 + mMetaLocation = 0; 1.221 + 1.222 + // set file index 1.223 + NS_ASSERTION( index < (kNumBlockFiles + 1), "invalid location index"); 1.224 + NS_ASSERTION( index > 0, "invalid location index"); 1.225 + mMetaLocation |= (index << eLocationSelectorOffset) & eLocationSelectorMask; 1.226 + 1.227 + // set startBlock 1.228 + NS_ASSERTION(startBlock == (startBlock & eBlockNumberMask), "invalid block number"); 1.229 + mMetaLocation |= startBlock & eBlockNumberMask; 1.230 + 1.231 + // set blockCount 1.232 + NS_ASSERTION( (blockCount>=1) && (blockCount<=4),"invalid block count"); 1.233 + --blockCount; 1.234 + mMetaLocation |= (blockCount << eExtraBlocksOffset) & eExtraBlocksMask; 1.235 + 1.236 + mMetaLocation |= eLocationInitializedMask; 1.237 + } 1.238 + 1.239 + uint32_t MetaBlockCount() const 1.240 + { 1.241 + return (uint32_t)((mMetaLocation & eExtraBlocksMask) >> eExtraBlocksOffset) + 1; 1.242 + } 1.243 + 1.244 + uint32_t MetaStartBlock() const 1.245 + { 1.246 + return (mMetaLocation & eBlockNumberMask); 1.247 + } 1.248 + 1.249 + uint32_t MetaBlockSize() const 1.250 + { 1.251 + return BLOCK_SIZE_FOR_INDEX(MetaFile()); 1.252 + } 1.253 + 1.254 + uint32_t MetaFileSize() const { return (mMetaLocation & eFileSizeMask) >> eFileSizeOffset; } 1.255 + void SetMetaFileSize(uint32_t size) 1.256 + { 1.257 + mMetaLocation &= ~eFileSizeMask; // clear eFileSizeMask 1.258 + mMetaLocation |= (size << eFileSizeOffset) & eFileSizeMask; 1.259 + } 1.260 + 1.261 + uint8_t MetaFileGeneration() const 1.262 + { 1.263 + return (mMetaLocation & eFileGenerationMask); 1.264 + } 1.265 + 1.266 + void SetMetaFileGeneration( uint8_t generation) 1.267 + { 1.268 + // clear everything, (separate file index = 0) 1.269 + mMetaLocation = 0; 1.270 + mMetaLocation |= generation & eFileGenerationMask; 1.271 + mMetaLocation |= eLocationInitializedMask; 1.272 + } 1.273 + 1.274 + uint8_t Generation() const 1.275 + { 1.276 + if ((mDataLocation & eLocationInitializedMask) && 1.277 + (DataFile() == 0)) 1.278 + return DataFileGeneration(); 1.279 + 1.280 + if ((mMetaLocation & eLocationInitializedMask) && 1.281 + (MetaFile() == 0)) 1.282 + return MetaFileGeneration(); 1.283 + 1.284 + return 0; // no generation 1.285 + } 1.286 + 1.287 +#if defined(IS_LITTLE_ENDIAN) 1.288 + void Swap() 1.289 + { 1.290 + mHashNumber = htonl(mHashNumber); 1.291 + mEvictionRank = htonl(mEvictionRank); 1.292 + mDataLocation = htonl(mDataLocation); 1.293 + mMetaLocation = htonl(mMetaLocation); 1.294 + } 1.295 +#endif 1.296 + 1.297 +#if defined(IS_LITTLE_ENDIAN) 1.298 + void Unswap() 1.299 + { 1.300 + mHashNumber = ntohl(mHashNumber); 1.301 + mEvictionRank = ntohl(mEvictionRank); 1.302 + mDataLocation = ntohl(mDataLocation); 1.303 + mMetaLocation = ntohl(mMetaLocation); 1.304 + } 1.305 +#endif 1.306 + 1.307 +}; 1.308 + 1.309 + 1.310 +/****************************************************************************** 1.311 + * nsDiskCacheRecordVisitor 1.312 + *****************************************************************************/ 1.313 + 1.314 +enum { kDeleteRecordAndContinue = -1, 1.315 + kStopVisitingRecords = 0, 1.316 + kVisitNextRecord = 1 1.317 +}; 1.318 + 1.319 +class nsDiskCacheRecordVisitor { 1.320 + public: 1.321 + 1.322 + virtual int32_t VisitRecord( nsDiskCacheRecord * mapRecord) = 0; 1.323 +}; 1.324 + 1.325 + 1.326 +/****************************************************************************** 1.327 + * nsDiskCacheHeader 1.328 + *****************************************************************************/ 1.329 + 1.330 +struct nsDiskCacheHeader { 1.331 + uint32_t mVersion; // cache version. 1.332 + uint32_t mDataSize; // size of cache in units of 1024bytes. 1.333 + int32_t mEntryCount; // number of entries stored in cache. 1.334 + uint32_t mIsDirty; // dirty flag. 1.335 + int32_t mRecordCount; // Number of records 1.336 + uint32_t mEvictionRank[kBuckets]; // Highest EvictionRank of the bucket 1.337 + uint32_t mBucketUsage[kBuckets]; // Number of used entries in the bucket 1.338 + 1.339 + nsDiskCacheHeader() 1.340 + : mVersion(nsDiskCache::kCurrentVersion) 1.341 + , mDataSize(0) 1.342 + , mEntryCount(0) 1.343 + , mIsDirty(true) 1.344 + , mRecordCount(0) 1.345 + {} 1.346 + 1.347 + void Swap() 1.348 + { 1.349 +#if defined(IS_LITTLE_ENDIAN) 1.350 + mVersion = htonl(mVersion); 1.351 + mDataSize = htonl(mDataSize); 1.352 + mEntryCount = htonl(mEntryCount); 1.353 + mIsDirty = htonl(mIsDirty); 1.354 + mRecordCount = htonl(mRecordCount); 1.355 + 1.356 + for (uint32_t i = 0; i < kBuckets ; i++) { 1.357 + mEvictionRank[i] = htonl(mEvictionRank[i]); 1.358 + mBucketUsage[i] = htonl(mBucketUsage[i]); 1.359 + } 1.360 +#endif 1.361 + } 1.362 + 1.363 + void Unswap() 1.364 + { 1.365 +#if defined(IS_LITTLE_ENDIAN) 1.366 + mVersion = ntohl(mVersion); 1.367 + mDataSize = ntohl(mDataSize); 1.368 + mEntryCount = ntohl(mEntryCount); 1.369 + mIsDirty = ntohl(mIsDirty); 1.370 + mRecordCount = ntohl(mRecordCount); 1.371 + 1.372 + for (uint32_t i = 0; i < kBuckets ; i++) { 1.373 + mEvictionRank[i] = ntohl(mEvictionRank[i]); 1.374 + mBucketUsage[i] = ntohl(mBucketUsage[i]); 1.375 + } 1.376 +#endif 1.377 + } 1.378 +}; 1.379 + 1.380 + 1.381 +/****************************************************************************** 1.382 + * nsDiskCacheMap 1.383 + *****************************************************************************/ 1.384 + 1.385 +class nsDiskCacheMap { 1.386 +public: 1.387 + 1.388 + nsDiskCacheMap() : 1.389 + mCacheDirectory(nullptr), 1.390 + mMapFD(nullptr), 1.391 + mCleanFD(nullptr), 1.392 + mRecordArray(nullptr), 1.393 + mBufferSize(0), 1.394 + mBuffer(nullptr), 1.395 + mMaxRecordCount(16384), // this default value won't matter 1.396 + mIsDirtyCacheFlushed(false), 1.397 + mLastInvalidateTime(0) 1.398 + { } 1.399 + 1.400 + ~nsDiskCacheMap() 1.401 + { 1.402 + (void) Close(true); 1.403 + } 1.404 + 1.405 +/** 1.406 + * File Operations 1.407 + * 1.408 + * Open 1.409 + * 1.410 + * Creates a new cache map file if one doesn't exist. 1.411 + * Returns error if it detects change in format or cache wasn't closed. 1.412 + */ 1.413 + nsresult Open( nsIFile * cacheDirectory, 1.414 + nsDiskCache::CorruptCacheInfo * corruptInfo, 1.415 + bool reportCacheCleanTelemetryData); 1.416 + nsresult Close(bool flush); 1.417 + nsresult Trim(); 1.418 + 1.419 + nsresult FlushHeader(); 1.420 + nsresult FlushRecords( bool unswap); 1.421 + 1.422 + void NotifyCapacityChange(uint32_t capacity); 1.423 + 1.424 +/** 1.425 + * Record operations 1.426 + */ 1.427 + nsresult AddRecord( nsDiskCacheRecord * mapRecord, nsDiskCacheRecord * oldRecord); 1.428 + nsresult UpdateRecord( nsDiskCacheRecord * mapRecord); 1.429 + nsresult FindRecord( uint32_t hashNumber, nsDiskCacheRecord * mapRecord); 1.430 + nsresult DeleteRecord( nsDiskCacheRecord * mapRecord); 1.431 + nsresult VisitRecords( nsDiskCacheRecordVisitor * visitor); 1.432 + nsresult EvictRecords( nsDiskCacheRecordVisitor * visitor); 1.433 + 1.434 +/** 1.435 + * Disk Entry operations 1.436 + */ 1.437 + nsresult DeleteStorage( nsDiskCacheRecord * record); 1.438 + 1.439 + nsresult GetFileForDiskCacheRecord( nsDiskCacheRecord * record, 1.440 + bool meta, 1.441 + bool createPath, 1.442 + nsIFile ** result); 1.443 + 1.444 + nsresult GetLocalFileForDiskCacheRecord( nsDiskCacheRecord * record, 1.445 + bool meta, 1.446 + bool createPath, 1.447 + nsIFile ** result); 1.448 + 1.449 + // On success, this returns the buffer owned by nsDiskCacheMap, 1.450 + // so it must not be deleted by the caller. 1.451 + nsDiskCacheEntry * ReadDiskCacheEntry( nsDiskCacheRecord * record); 1.452 + 1.453 + nsresult WriteDiskCacheEntry( nsDiskCacheBinding * binding); 1.454 + 1.455 + nsresult ReadDataCacheBlocks(nsDiskCacheBinding * binding, char * buffer, uint32_t size); 1.456 + nsresult WriteDataCacheBlocks(nsDiskCacheBinding * binding, char * buffer, uint32_t size); 1.457 + nsresult DeleteStorage( nsDiskCacheRecord * record, bool metaData); 1.458 + 1.459 + /** 1.460 + * Statistical Operations 1.461 + */ 1.462 + void IncrementTotalSize( uint32_t delta) 1.463 + { 1.464 + mHeader.mDataSize += delta; 1.465 + mHeader.mIsDirty = true; 1.466 + } 1.467 + 1.468 + void DecrementTotalSize( uint32_t delta) 1.469 + { 1.470 + NS_ASSERTION(mHeader.mDataSize >= delta, "disk cache size negative?"); 1.471 + mHeader.mDataSize = mHeader.mDataSize > delta ? mHeader.mDataSize - delta : 0; 1.472 + mHeader.mIsDirty = true; 1.473 + } 1.474 + 1.475 + inline void IncrementTotalSize( uint32_t blocks, uint32_t blockSize) 1.476 + { 1.477 + // Round up to nearest K 1.478 + IncrementTotalSize(((blocks*blockSize) + 0x03FF) >> 10); 1.479 + } 1.480 + 1.481 + inline void DecrementTotalSize( uint32_t blocks, uint32_t blockSize) 1.482 + { 1.483 + // Round up to nearest K 1.484 + DecrementTotalSize(((blocks*blockSize) + 0x03FF) >> 10); 1.485 + } 1.486 + 1.487 + uint32_t TotalSize() { return mHeader.mDataSize; } 1.488 + 1.489 + int32_t EntryCount() { return mHeader.mEntryCount; } 1.490 + 1.491 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); 1.492 + 1.493 + 1.494 +private: 1.495 + 1.496 + /** 1.497 + * Private methods 1.498 + */ 1.499 + nsresult OpenBlockFiles(nsDiskCache::CorruptCacheInfo * corruptInfo); 1.500 + nsresult CloseBlockFiles(bool flush); 1.501 + bool CacheFilesExist(); 1.502 + 1.503 + nsresult CreateCacheSubDirectories(); 1.504 + 1.505 + uint32_t CalculateFileIndex(uint32_t size); 1.506 + 1.507 + nsresult GetBlockFileForIndex( uint32_t index, nsIFile ** result); 1.508 + uint32_t GetBlockSizeForIndex( uint32_t index) const { 1.509 + return BLOCK_SIZE_FOR_INDEX(index); 1.510 + } 1.511 + uint32_t GetBitMapSizeForIndex( uint32_t index) const { 1.512 + return BITMAP_SIZE_FOR_INDEX(index); 1.513 + } 1.514 + 1.515 + // returns the bucket number 1.516 + uint32_t GetBucketIndex( uint32_t hashNumber) const { 1.517 + return (hashNumber & (kBuckets - 1)); 1.518 + } 1.519 + 1.520 + // Gets the size of the bucket (in number of records) 1.521 + uint32_t GetRecordsPerBucket() const { 1.522 + return mHeader.mRecordCount / kBuckets; 1.523 + } 1.524 + 1.525 + // Gets the first record in the bucket 1.526 + nsDiskCacheRecord *GetFirstRecordInBucket(uint32_t bucket) const { 1.527 + return mRecordArray + bucket * GetRecordsPerBucket(); 1.528 + } 1.529 + 1.530 + uint32_t GetBucketRank(uint32_t bucketIndex, uint32_t targetRank); 1.531 + 1.532 + int32_t VisitEachRecord(uint32_t bucketIndex, 1.533 + nsDiskCacheRecordVisitor * visitor, 1.534 + uint32_t evictionRank); 1.535 + 1.536 + nsresult GrowRecords(); 1.537 + nsresult ShrinkRecords(); 1.538 + 1.539 + nsresult EnsureBuffer(uint32_t bufSize); 1.540 + 1.541 + // The returned structure will point to the buffer owned by nsDiskCacheMap, 1.542 + // so it must not be deleted by the caller. 1.543 + nsDiskCacheEntry * CreateDiskCacheEntry(nsDiskCacheBinding * binding, 1.544 + uint32_t * size); 1.545 + 1.546 + // Initializes the _CACHE_CLEAN_ related functionality 1.547 + nsresult InitCacheClean(nsIFile * cacheDirectory, 1.548 + nsDiskCache::CorruptCacheInfo * corruptInfo, 1.549 + bool reportCacheCleanTelemetryData); 1.550 + // Writes out a value of '0' or '1' in the _CACHE_CLEAN_ file 1.551 + nsresult WriteCacheClean(bool clean); 1.552 + // Resets the timout for revalidating the cache 1.553 + nsresult ResetCacheTimer(int32_t timeout = kRevalidateCacheTimeout); 1.554 + // Invalidates the cache, calls WriteCacheClean and ResetCacheTimer 1.555 + nsresult InvalidateCache(); 1.556 + // Determines if the cache is in a safe state 1.557 + bool IsCacheInSafeState(); 1.558 + // Revalidates the cache by writting out the header, records, and finally 1.559 + // by calling WriteCacheClean(true). 1.560 + nsresult RevalidateCache(); 1.561 + // Timer which revalidates the cache 1.562 + static void RevalidateTimerCallback(nsITimer *aTimer, void *arg); 1.563 + 1.564 +/** 1.565 + * data members 1.566 + */ 1.567 +private: 1.568 + nsCOMPtr<nsITimer> mCleanCacheTimer; 1.569 + nsCOMPtr<nsIFile> mCacheDirectory; 1.570 + PRFileDesc * mMapFD; 1.571 + PRFileDesc * mCleanFD; 1.572 + nsDiskCacheRecord * mRecordArray; 1.573 + nsDiskCacheBlockFile mBlockFile[kNumBlockFiles]; 1.574 + uint32_t mBufferSize; 1.575 + char * mBuffer; 1.576 + nsDiskCacheHeader mHeader; 1.577 + int32_t mMaxRecordCount; 1.578 + bool mIsDirtyCacheFlushed; 1.579 + PRIntervalTime mLastInvalidateTime; 1.580 +}; 1.581 + 1.582 +#endif // _nsDiskCacheMap_h_