netwerk/cache/nsDiskCacheMap.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim:set ts=4 sw=4 sts=4 cin et: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef _nsDiskCacheMap_h_
michael@0 8 #define _nsDiskCacheMap_h_
michael@0 9
michael@0 10 #include "mozilla/MemoryReporting.h"
michael@0 11 #include <limits.h>
michael@0 12
michael@0 13 #include "prnetdb.h"
michael@0 14 #include "nsDebug.h"
michael@0 15 #include "nsError.h"
michael@0 16 #include "nsIFile.h"
michael@0 17 #include "nsITimer.h"
michael@0 18
michael@0 19 #include "nsDiskCache.h"
michael@0 20 #include "nsDiskCacheBlockFile.h"
michael@0 21
michael@0 22
michael@0 23 class nsDiskCacheBinding;
michael@0 24 struct nsDiskCacheEntry;
michael@0 25
michael@0 26 /******************************************************************************
michael@0 27 * nsDiskCacheRecord
michael@0 28 *
michael@0 29 * Cache Location Format
michael@0 30 *
michael@0 31 * 1000 0000 0000 0000 0000 0000 0000 0000 : initialized bit
michael@0 32 *
michael@0 33 * 0011 0000 0000 0000 0000 0000 0000 0000 : File Selector (0 = separate file)
michael@0 34 * 0000 0011 0000 0000 0000 0000 0000 0000 : number of extra contiguous blocks 1-4
michael@0 35 * 0100 1100 0000 0000 0000 0000 0000 0000 : reserved bits
michael@0 36 * 0000 0000 1111 1111 1111 1111 1111 1111 : block# 0-16777216 (2^24)
michael@0 37 *
michael@0 38 * 0000 0000 1111 1111 1111 1111 0000 0000 : eFileSizeMask (size of file in k: see note)
michael@0 39 * 0000 0000 0000 0000 0000 0000 1111 1111 : eFileGenerationMask
michael@0 40 *
michael@0 41 * File Selector:
michael@0 42 * 0 = separate file on disk
michael@0 43 * 1 = 256 byte block file
michael@0 44 * 2 = 1k block file
michael@0 45 * 3 = 4k block file
michael@0 46 *
michael@0 47 * eFileSizeMask note: Files larger than 65535 KiB have this limit stored in
michael@0 48 * the location. The file itself must be examined to
michael@0 49 * determine its actual size if necessary.
michael@0 50 *
michael@0 51 *****************************************************************************/
michael@0 52
michael@0 53 /*
michael@0 54 We have 3 block files with roughly the same max size (32MB)
michael@0 55 1 - block size 256B, number of blocks 131072
michael@0 56 2 - block size 1kB, number of blocks 32768
michael@0 57 3 - block size 4kB, number of blocks 8192
michael@0 58 */
michael@0 59 #define kNumBlockFiles 3
michael@0 60 #define SIZE_SHIFT(idx) (2 * ((idx) - 1))
michael@0 61 #define BLOCK_SIZE_FOR_INDEX(idx) ((idx) ? (256 << SIZE_SHIFT(idx)) : 0)
michael@0 62 #define BITMAP_SIZE_FOR_INDEX(idx) ((idx) ? (131072 >> SIZE_SHIFT(idx)) : 0)
michael@0 63
michael@0 64 // Min and max values for the number of records in the DiskCachemap
michael@0 65 #define kMinRecordCount 512
michael@0 66
michael@0 67 #define kSeparateFile 0
michael@0 68 #define kBuckets (1 << 5) // must be a power of 2!
michael@0 69
michael@0 70 // Maximum size in K which can be stored in the location (see eFileSizeMask).
michael@0 71 // Both data and metadata can be larger, but only up to kMaxDataSizeK can be
michael@0 72 // counted into total cache size. I.e. if there are entries where either data or
michael@0 73 // metadata is larger than kMaxDataSizeK, the total cache size will be
michael@0 74 // inaccurate (smaller) than the actual cache size. The alternative is to stat
michael@0 75 // the files to find the real size, which was decided against for performance
michael@0 76 // reasons. See bug #651100 comment #21.
michael@0 77 #define kMaxDataSizeK 0xFFFF
michael@0 78
michael@0 79 // preallocate up to 1MB of separate cache file
michael@0 80 #define kPreallocateLimit 1 * 1024 * 1024
michael@0 81
michael@0 82 // The minimum amount of milliseconds to wait before re-attempting to
michael@0 83 // revalidate the cache.
michael@0 84 #define kRevalidateCacheTimeout 3000
michael@0 85 #define kRevalidateCacheTimeoutTolerance 10
michael@0 86 #define kRevalidateCacheErrorTimeout 1000
michael@0 87
michael@0 88 class nsDiskCacheRecord {
michael@0 89
michael@0 90 private:
michael@0 91 uint32_t mHashNumber;
michael@0 92 uint32_t mEvictionRank;
michael@0 93 uint32_t mDataLocation;
michael@0 94 uint32_t mMetaLocation;
michael@0 95
michael@0 96 enum {
michael@0 97 eLocationInitializedMask = 0x80000000,
michael@0 98
michael@0 99 eLocationSelectorMask = 0x30000000,
michael@0 100 eLocationSelectorOffset = 28,
michael@0 101
michael@0 102 eExtraBlocksMask = 0x03000000,
michael@0 103 eExtraBlocksOffset = 24,
michael@0 104
michael@0 105 eReservedMask = 0x4C000000,
michael@0 106
michael@0 107 eBlockNumberMask = 0x00FFFFFF,
michael@0 108
michael@0 109 eFileSizeMask = 0x00FFFF00,
michael@0 110 eFileSizeOffset = 8,
michael@0 111 eFileGenerationMask = 0x000000FF,
michael@0 112 eFileReservedMask = 0x4F000000
michael@0 113
michael@0 114 };
michael@0 115
michael@0 116 public:
michael@0 117 nsDiskCacheRecord()
michael@0 118 : mHashNumber(0), mEvictionRank(0), mDataLocation(0), mMetaLocation(0)
michael@0 119 {
michael@0 120 }
michael@0 121
michael@0 122 bool ValidRecord()
michael@0 123 {
michael@0 124 if ((mDataLocation & eReservedMask) || (mMetaLocation & eReservedMask))
michael@0 125 return false;
michael@0 126 return true;
michael@0 127 }
michael@0 128
michael@0 129 // HashNumber accessors
michael@0 130 uint32_t HashNumber() const { return mHashNumber; }
michael@0 131 void SetHashNumber( uint32_t hashNumber) { mHashNumber = hashNumber; }
michael@0 132
michael@0 133 // EvictionRank accessors
michael@0 134 uint32_t EvictionRank() const { return mEvictionRank; }
michael@0 135 void SetEvictionRank( uint32_t rank) { mEvictionRank = rank ? rank : 1; }
michael@0 136
michael@0 137 // DataLocation accessors
michael@0 138 bool DataLocationInitialized() const { return 0 != (mDataLocation & eLocationInitializedMask); }
michael@0 139 void ClearDataLocation() { mDataLocation = 0; }
michael@0 140
michael@0 141 uint32_t DataFile() const
michael@0 142 {
michael@0 143 return (uint32_t)(mDataLocation & eLocationSelectorMask) >> eLocationSelectorOffset;
michael@0 144 }
michael@0 145
michael@0 146 void SetDataBlocks( uint32_t index, uint32_t startBlock, uint32_t blockCount)
michael@0 147 {
michael@0 148 // clear everything
michael@0 149 mDataLocation = 0;
michael@0 150
michael@0 151 // set file index
michael@0 152 NS_ASSERTION( index < (kNumBlockFiles + 1), "invalid location index");
michael@0 153 NS_ASSERTION( index > 0,"invalid location index");
michael@0 154 mDataLocation |= (index << eLocationSelectorOffset) & eLocationSelectorMask;
michael@0 155
michael@0 156 // set startBlock
michael@0 157 NS_ASSERTION(startBlock == (startBlock & eBlockNumberMask), "invalid block number");
michael@0 158 mDataLocation |= startBlock & eBlockNumberMask;
michael@0 159
michael@0 160 // set blockCount
michael@0 161 NS_ASSERTION( (blockCount>=1) && (blockCount<=4),"invalid block count");
michael@0 162 --blockCount;
michael@0 163 mDataLocation |= (blockCount << eExtraBlocksOffset) & eExtraBlocksMask;
michael@0 164
michael@0 165 mDataLocation |= eLocationInitializedMask;
michael@0 166 }
michael@0 167
michael@0 168 uint32_t DataBlockCount() const
michael@0 169 {
michael@0 170 return (uint32_t)((mDataLocation & eExtraBlocksMask) >> eExtraBlocksOffset) + 1;
michael@0 171 }
michael@0 172
michael@0 173 uint32_t DataStartBlock() const
michael@0 174 {
michael@0 175 return (mDataLocation & eBlockNumberMask);
michael@0 176 }
michael@0 177
michael@0 178 uint32_t DataBlockSize() const
michael@0 179 {
michael@0 180 return BLOCK_SIZE_FOR_INDEX(DataFile());
michael@0 181 }
michael@0 182
michael@0 183 uint32_t DataFileSize() const { return (mDataLocation & eFileSizeMask) >> eFileSizeOffset; }
michael@0 184 void SetDataFileSize(uint32_t size)
michael@0 185 {
michael@0 186 NS_ASSERTION((mDataLocation & eFileReservedMask) == 0, "bad location");
michael@0 187 mDataLocation &= ~eFileSizeMask; // clear eFileSizeMask
michael@0 188 mDataLocation |= (size << eFileSizeOffset) & eFileSizeMask;
michael@0 189 }
michael@0 190
michael@0 191 uint8_t DataFileGeneration() const
michael@0 192 {
michael@0 193 return (mDataLocation & eFileGenerationMask);
michael@0 194 }
michael@0 195
michael@0 196 void SetDataFileGeneration( uint8_t generation)
michael@0 197 {
michael@0 198 // clear everything, (separate file index = 0)
michael@0 199 mDataLocation = 0;
michael@0 200 mDataLocation |= generation & eFileGenerationMask;
michael@0 201 mDataLocation |= eLocationInitializedMask;
michael@0 202 }
michael@0 203
michael@0 204 // MetaLocation accessors
michael@0 205 bool MetaLocationInitialized() const { return 0 != (mMetaLocation & eLocationInitializedMask); }
michael@0 206 void ClearMetaLocation() { mMetaLocation = 0; }
michael@0 207 uint32_t MetaLocation() const { return mMetaLocation; }
michael@0 208
michael@0 209 uint32_t MetaFile() const
michael@0 210 {
michael@0 211 return (uint32_t)(mMetaLocation & eLocationSelectorMask) >> eLocationSelectorOffset;
michael@0 212 }
michael@0 213
michael@0 214 void SetMetaBlocks( uint32_t index, uint32_t startBlock, uint32_t blockCount)
michael@0 215 {
michael@0 216 // clear everything
michael@0 217 mMetaLocation = 0;
michael@0 218
michael@0 219 // set file index
michael@0 220 NS_ASSERTION( index < (kNumBlockFiles + 1), "invalid location index");
michael@0 221 NS_ASSERTION( index > 0, "invalid location index");
michael@0 222 mMetaLocation |= (index << eLocationSelectorOffset) & eLocationSelectorMask;
michael@0 223
michael@0 224 // set startBlock
michael@0 225 NS_ASSERTION(startBlock == (startBlock & eBlockNumberMask), "invalid block number");
michael@0 226 mMetaLocation |= startBlock & eBlockNumberMask;
michael@0 227
michael@0 228 // set blockCount
michael@0 229 NS_ASSERTION( (blockCount>=1) && (blockCount<=4),"invalid block count");
michael@0 230 --blockCount;
michael@0 231 mMetaLocation |= (blockCount << eExtraBlocksOffset) & eExtraBlocksMask;
michael@0 232
michael@0 233 mMetaLocation |= eLocationInitializedMask;
michael@0 234 }
michael@0 235
michael@0 236 uint32_t MetaBlockCount() const
michael@0 237 {
michael@0 238 return (uint32_t)((mMetaLocation & eExtraBlocksMask) >> eExtraBlocksOffset) + 1;
michael@0 239 }
michael@0 240
michael@0 241 uint32_t MetaStartBlock() const
michael@0 242 {
michael@0 243 return (mMetaLocation & eBlockNumberMask);
michael@0 244 }
michael@0 245
michael@0 246 uint32_t MetaBlockSize() const
michael@0 247 {
michael@0 248 return BLOCK_SIZE_FOR_INDEX(MetaFile());
michael@0 249 }
michael@0 250
michael@0 251 uint32_t MetaFileSize() const { return (mMetaLocation & eFileSizeMask) >> eFileSizeOffset; }
michael@0 252 void SetMetaFileSize(uint32_t size)
michael@0 253 {
michael@0 254 mMetaLocation &= ~eFileSizeMask; // clear eFileSizeMask
michael@0 255 mMetaLocation |= (size << eFileSizeOffset) & eFileSizeMask;
michael@0 256 }
michael@0 257
michael@0 258 uint8_t MetaFileGeneration() const
michael@0 259 {
michael@0 260 return (mMetaLocation & eFileGenerationMask);
michael@0 261 }
michael@0 262
michael@0 263 void SetMetaFileGeneration( uint8_t generation)
michael@0 264 {
michael@0 265 // clear everything, (separate file index = 0)
michael@0 266 mMetaLocation = 0;
michael@0 267 mMetaLocation |= generation & eFileGenerationMask;
michael@0 268 mMetaLocation |= eLocationInitializedMask;
michael@0 269 }
michael@0 270
michael@0 271 uint8_t Generation() const
michael@0 272 {
michael@0 273 if ((mDataLocation & eLocationInitializedMask) &&
michael@0 274 (DataFile() == 0))
michael@0 275 return DataFileGeneration();
michael@0 276
michael@0 277 if ((mMetaLocation & eLocationInitializedMask) &&
michael@0 278 (MetaFile() == 0))
michael@0 279 return MetaFileGeneration();
michael@0 280
michael@0 281 return 0; // no generation
michael@0 282 }
michael@0 283
michael@0 284 #if defined(IS_LITTLE_ENDIAN)
michael@0 285 void Swap()
michael@0 286 {
michael@0 287 mHashNumber = htonl(mHashNumber);
michael@0 288 mEvictionRank = htonl(mEvictionRank);
michael@0 289 mDataLocation = htonl(mDataLocation);
michael@0 290 mMetaLocation = htonl(mMetaLocation);
michael@0 291 }
michael@0 292 #endif
michael@0 293
michael@0 294 #if defined(IS_LITTLE_ENDIAN)
michael@0 295 void Unswap()
michael@0 296 {
michael@0 297 mHashNumber = ntohl(mHashNumber);
michael@0 298 mEvictionRank = ntohl(mEvictionRank);
michael@0 299 mDataLocation = ntohl(mDataLocation);
michael@0 300 mMetaLocation = ntohl(mMetaLocation);
michael@0 301 }
michael@0 302 #endif
michael@0 303
michael@0 304 };
michael@0 305
michael@0 306
michael@0 307 /******************************************************************************
michael@0 308 * nsDiskCacheRecordVisitor
michael@0 309 *****************************************************************************/
michael@0 310
michael@0 311 enum { kDeleteRecordAndContinue = -1,
michael@0 312 kStopVisitingRecords = 0,
michael@0 313 kVisitNextRecord = 1
michael@0 314 };
michael@0 315
michael@0 316 class nsDiskCacheRecordVisitor {
michael@0 317 public:
michael@0 318
michael@0 319 virtual int32_t VisitRecord( nsDiskCacheRecord * mapRecord) = 0;
michael@0 320 };
michael@0 321
michael@0 322
michael@0 323 /******************************************************************************
michael@0 324 * nsDiskCacheHeader
michael@0 325 *****************************************************************************/
michael@0 326
michael@0 327 struct nsDiskCacheHeader {
michael@0 328 uint32_t mVersion; // cache version.
michael@0 329 uint32_t mDataSize; // size of cache in units of 1024bytes.
michael@0 330 int32_t mEntryCount; // number of entries stored in cache.
michael@0 331 uint32_t mIsDirty; // dirty flag.
michael@0 332 int32_t mRecordCount; // Number of records
michael@0 333 uint32_t mEvictionRank[kBuckets]; // Highest EvictionRank of the bucket
michael@0 334 uint32_t mBucketUsage[kBuckets]; // Number of used entries in the bucket
michael@0 335
michael@0 336 nsDiskCacheHeader()
michael@0 337 : mVersion(nsDiskCache::kCurrentVersion)
michael@0 338 , mDataSize(0)
michael@0 339 , mEntryCount(0)
michael@0 340 , mIsDirty(true)
michael@0 341 , mRecordCount(0)
michael@0 342 {}
michael@0 343
michael@0 344 void Swap()
michael@0 345 {
michael@0 346 #if defined(IS_LITTLE_ENDIAN)
michael@0 347 mVersion = htonl(mVersion);
michael@0 348 mDataSize = htonl(mDataSize);
michael@0 349 mEntryCount = htonl(mEntryCount);
michael@0 350 mIsDirty = htonl(mIsDirty);
michael@0 351 mRecordCount = htonl(mRecordCount);
michael@0 352
michael@0 353 for (uint32_t i = 0; i < kBuckets ; i++) {
michael@0 354 mEvictionRank[i] = htonl(mEvictionRank[i]);
michael@0 355 mBucketUsage[i] = htonl(mBucketUsage[i]);
michael@0 356 }
michael@0 357 #endif
michael@0 358 }
michael@0 359
michael@0 360 void Unswap()
michael@0 361 {
michael@0 362 #if defined(IS_LITTLE_ENDIAN)
michael@0 363 mVersion = ntohl(mVersion);
michael@0 364 mDataSize = ntohl(mDataSize);
michael@0 365 mEntryCount = ntohl(mEntryCount);
michael@0 366 mIsDirty = ntohl(mIsDirty);
michael@0 367 mRecordCount = ntohl(mRecordCount);
michael@0 368
michael@0 369 for (uint32_t i = 0; i < kBuckets ; i++) {
michael@0 370 mEvictionRank[i] = ntohl(mEvictionRank[i]);
michael@0 371 mBucketUsage[i] = ntohl(mBucketUsage[i]);
michael@0 372 }
michael@0 373 #endif
michael@0 374 }
michael@0 375 };
michael@0 376
michael@0 377
michael@0 378 /******************************************************************************
michael@0 379 * nsDiskCacheMap
michael@0 380 *****************************************************************************/
michael@0 381
michael@0 382 class nsDiskCacheMap {
michael@0 383 public:
michael@0 384
michael@0 385 nsDiskCacheMap() :
michael@0 386 mCacheDirectory(nullptr),
michael@0 387 mMapFD(nullptr),
michael@0 388 mCleanFD(nullptr),
michael@0 389 mRecordArray(nullptr),
michael@0 390 mBufferSize(0),
michael@0 391 mBuffer(nullptr),
michael@0 392 mMaxRecordCount(16384), // this default value won't matter
michael@0 393 mIsDirtyCacheFlushed(false),
michael@0 394 mLastInvalidateTime(0)
michael@0 395 { }
michael@0 396
michael@0 397 ~nsDiskCacheMap()
michael@0 398 {
michael@0 399 (void) Close(true);
michael@0 400 }
michael@0 401
michael@0 402 /**
michael@0 403 * File Operations
michael@0 404 *
michael@0 405 * Open
michael@0 406 *
michael@0 407 * Creates a new cache map file if one doesn't exist.
michael@0 408 * Returns error if it detects change in format or cache wasn't closed.
michael@0 409 */
michael@0 410 nsresult Open( nsIFile * cacheDirectory,
michael@0 411 nsDiskCache::CorruptCacheInfo * corruptInfo,
michael@0 412 bool reportCacheCleanTelemetryData);
michael@0 413 nsresult Close(bool flush);
michael@0 414 nsresult Trim();
michael@0 415
michael@0 416 nsresult FlushHeader();
michael@0 417 nsresult FlushRecords( bool unswap);
michael@0 418
michael@0 419 void NotifyCapacityChange(uint32_t capacity);
michael@0 420
michael@0 421 /**
michael@0 422 * Record operations
michael@0 423 */
michael@0 424 nsresult AddRecord( nsDiskCacheRecord * mapRecord, nsDiskCacheRecord * oldRecord);
michael@0 425 nsresult UpdateRecord( nsDiskCacheRecord * mapRecord);
michael@0 426 nsresult FindRecord( uint32_t hashNumber, nsDiskCacheRecord * mapRecord);
michael@0 427 nsresult DeleteRecord( nsDiskCacheRecord * mapRecord);
michael@0 428 nsresult VisitRecords( nsDiskCacheRecordVisitor * visitor);
michael@0 429 nsresult EvictRecords( nsDiskCacheRecordVisitor * visitor);
michael@0 430
michael@0 431 /**
michael@0 432 * Disk Entry operations
michael@0 433 */
michael@0 434 nsresult DeleteStorage( nsDiskCacheRecord * record);
michael@0 435
michael@0 436 nsresult GetFileForDiskCacheRecord( nsDiskCacheRecord * record,
michael@0 437 bool meta,
michael@0 438 bool createPath,
michael@0 439 nsIFile ** result);
michael@0 440
michael@0 441 nsresult GetLocalFileForDiskCacheRecord( nsDiskCacheRecord * record,
michael@0 442 bool meta,
michael@0 443 bool createPath,
michael@0 444 nsIFile ** result);
michael@0 445
michael@0 446 // On success, this returns the buffer owned by nsDiskCacheMap,
michael@0 447 // so it must not be deleted by the caller.
michael@0 448 nsDiskCacheEntry * ReadDiskCacheEntry( nsDiskCacheRecord * record);
michael@0 449
michael@0 450 nsresult WriteDiskCacheEntry( nsDiskCacheBinding * binding);
michael@0 451
michael@0 452 nsresult ReadDataCacheBlocks(nsDiskCacheBinding * binding, char * buffer, uint32_t size);
michael@0 453 nsresult WriteDataCacheBlocks(nsDiskCacheBinding * binding, char * buffer, uint32_t size);
michael@0 454 nsresult DeleteStorage( nsDiskCacheRecord * record, bool metaData);
michael@0 455
michael@0 456 /**
michael@0 457 * Statistical Operations
michael@0 458 */
michael@0 459 void IncrementTotalSize( uint32_t delta)
michael@0 460 {
michael@0 461 mHeader.mDataSize += delta;
michael@0 462 mHeader.mIsDirty = true;
michael@0 463 }
michael@0 464
michael@0 465 void DecrementTotalSize( uint32_t delta)
michael@0 466 {
michael@0 467 NS_ASSERTION(mHeader.mDataSize >= delta, "disk cache size negative?");
michael@0 468 mHeader.mDataSize = mHeader.mDataSize > delta ? mHeader.mDataSize - delta : 0;
michael@0 469 mHeader.mIsDirty = true;
michael@0 470 }
michael@0 471
michael@0 472 inline void IncrementTotalSize( uint32_t blocks, uint32_t blockSize)
michael@0 473 {
michael@0 474 // Round up to nearest K
michael@0 475 IncrementTotalSize(((blocks*blockSize) + 0x03FF) >> 10);
michael@0 476 }
michael@0 477
michael@0 478 inline void DecrementTotalSize( uint32_t blocks, uint32_t blockSize)
michael@0 479 {
michael@0 480 // Round up to nearest K
michael@0 481 DecrementTotalSize(((blocks*blockSize) + 0x03FF) >> 10);
michael@0 482 }
michael@0 483
michael@0 484 uint32_t TotalSize() { return mHeader.mDataSize; }
michael@0 485
michael@0 486 int32_t EntryCount() { return mHeader.mEntryCount; }
michael@0 487
michael@0 488 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf);
michael@0 489
michael@0 490
michael@0 491 private:
michael@0 492
michael@0 493 /**
michael@0 494 * Private methods
michael@0 495 */
michael@0 496 nsresult OpenBlockFiles(nsDiskCache::CorruptCacheInfo * corruptInfo);
michael@0 497 nsresult CloseBlockFiles(bool flush);
michael@0 498 bool CacheFilesExist();
michael@0 499
michael@0 500 nsresult CreateCacheSubDirectories();
michael@0 501
michael@0 502 uint32_t CalculateFileIndex(uint32_t size);
michael@0 503
michael@0 504 nsresult GetBlockFileForIndex( uint32_t index, nsIFile ** result);
michael@0 505 uint32_t GetBlockSizeForIndex( uint32_t index) const {
michael@0 506 return BLOCK_SIZE_FOR_INDEX(index);
michael@0 507 }
michael@0 508 uint32_t GetBitMapSizeForIndex( uint32_t index) const {
michael@0 509 return BITMAP_SIZE_FOR_INDEX(index);
michael@0 510 }
michael@0 511
michael@0 512 // returns the bucket number
michael@0 513 uint32_t GetBucketIndex( uint32_t hashNumber) const {
michael@0 514 return (hashNumber & (kBuckets - 1));
michael@0 515 }
michael@0 516
michael@0 517 // Gets the size of the bucket (in number of records)
michael@0 518 uint32_t GetRecordsPerBucket() const {
michael@0 519 return mHeader.mRecordCount / kBuckets;
michael@0 520 }
michael@0 521
michael@0 522 // Gets the first record in the bucket
michael@0 523 nsDiskCacheRecord *GetFirstRecordInBucket(uint32_t bucket) const {
michael@0 524 return mRecordArray + bucket * GetRecordsPerBucket();
michael@0 525 }
michael@0 526
michael@0 527 uint32_t GetBucketRank(uint32_t bucketIndex, uint32_t targetRank);
michael@0 528
michael@0 529 int32_t VisitEachRecord(uint32_t bucketIndex,
michael@0 530 nsDiskCacheRecordVisitor * visitor,
michael@0 531 uint32_t evictionRank);
michael@0 532
michael@0 533 nsresult GrowRecords();
michael@0 534 nsresult ShrinkRecords();
michael@0 535
michael@0 536 nsresult EnsureBuffer(uint32_t bufSize);
michael@0 537
michael@0 538 // The returned structure will point to the buffer owned by nsDiskCacheMap,
michael@0 539 // so it must not be deleted by the caller.
michael@0 540 nsDiskCacheEntry * CreateDiskCacheEntry(nsDiskCacheBinding * binding,
michael@0 541 uint32_t * size);
michael@0 542
michael@0 543 // Initializes the _CACHE_CLEAN_ related functionality
michael@0 544 nsresult InitCacheClean(nsIFile * cacheDirectory,
michael@0 545 nsDiskCache::CorruptCacheInfo * corruptInfo,
michael@0 546 bool reportCacheCleanTelemetryData);
michael@0 547 // Writes out a value of '0' or '1' in the _CACHE_CLEAN_ file
michael@0 548 nsresult WriteCacheClean(bool clean);
michael@0 549 // Resets the timout for revalidating the cache
michael@0 550 nsresult ResetCacheTimer(int32_t timeout = kRevalidateCacheTimeout);
michael@0 551 // Invalidates the cache, calls WriteCacheClean and ResetCacheTimer
michael@0 552 nsresult InvalidateCache();
michael@0 553 // Determines if the cache is in a safe state
michael@0 554 bool IsCacheInSafeState();
michael@0 555 // Revalidates the cache by writting out the header, records, and finally
michael@0 556 // by calling WriteCacheClean(true).
michael@0 557 nsresult RevalidateCache();
michael@0 558 // Timer which revalidates the cache
michael@0 559 static void RevalidateTimerCallback(nsITimer *aTimer, void *arg);
michael@0 560
michael@0 561 /**
michael@0 562 * data members
michael@0 563 */
michael@0 564 private:
michael@0 565 nsCOMPtr<nsITimer> mCleanCacheTimer;
michael@0 566 nsCOMPtr<nsIFile> mCacheDirectory;
michael@0 567 PRFileDesc * mMapFD;
michael@0 568 PRFileDesc * mCleanFD;
michael@0 569 nsDiskCacheRecord * mRecordArray;
michael@0 570 nsDiskCacheBlockFile mBlockFile[kNumBlockFiles];
michael@0 571 uint32_t mBufferSize;
michael@0 572 char * mBuffer;
michael@0 573 nsDiskCacheHeader mHeader;
michael@0 574 int32_t mMaxRecordCount;
michael@0 575 bool mIsDirtyCacheFlushed;
michael@0 576 PRIntervalTime mLastInvalidateTime;
michael@0 577 };
michael@0 578
michael@0 579 #endif // _nsDiskCacheMap_h_

mercurial