| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This is an internal class that handles the address of a cache record. |
| // See net/disk_cache/disk_cache.h for the public interface of the cache. |
| |
| #ifndef NET_DISK_CACHE_BLOCKFILE_ADDR_H_ |
| #define NET_DISK_CACHE_BLOCKFILE_ADDR_H_ |
| |
| #include "base/logging.h" |
| #include "net/base/net_export.h" |
| #include "net/disk_cache/blockfile/disk_format_base.h" |
| #include "starboard/types.h" |
| |
| namespace disk_cache { |
| |
| enum FileType { |
| EXTERNAL = 0, |
| RANKINGS = 1, |
| BLOCK_256 = 2, |
| BLOCK_1K = 3, |
| BLOCK_4K = 4, |
| BLOCK_FILES = 5, |
| BLOCK_ENTRIES = 6, |
| BLOCK_EVICTED = 7 |
| }; |
| |
| const int kMaxBlockSize = 4096 * 4; |
| const int16_t kMaxBlockFile = 255; |
| const int kMaxNumBlocks = 4; |
| const int16_t kFirstAdditionalBlockFile = 4; |
| |
| // Defines a storage address for a cache record |
| // |
| // Header: |
| // 1000 0000 0000 0000 0000 0000 0000 0000 : initialized bit |
| // 0111 0000 0000 0000 0000 0000 0000 0000 : file type |
| // |
| // File type values: |
| // 0 = separate file on disk |
| // 1 = rankings block file |
| // 2 = 256 byte block file |
| // 3 = 1k byte block file |
| // 4 = 4k byte block file |
| // 5 = external files block file |
| // 6 = active entries block file |
| // 7 = evicted entries block file |
| // |
| // If separate file: |
| // 0000 1111 1111 1111 1111 1111 1111 1111 : file# 0 - 268,435,456 (2^28) |
| // |
| // If block file: |
| // 0000 1100 0000 0000 0000 0000 0000 0000 : reserved bits |
| // 0000 0011 0000 0000 0000 0000 0000 0000 : number of contiguous blocks 1-4 |
| // 0000 0000 1111 1111 0000 0000 0000 0000 : file selector 0 - 255 |
| // 0000 0000 0000 0000 1111 1111 1111 1111 : block# 0 - 65,535 (2^16) |
| // |
| // Note that an Addr can be used to "point" to a variety of different objects, |
| // from a given type of entry to random blobs of data. Conceptually, an Addr is |
| // just a number that someone can inspect to find out how to locate the desired |
| // record. Most users will not care about the specific bits inside Addr, for |
| // example, what parts of it point to a file number; only the code that has to |
| // select a specific file would care about those specific bits. |
| // |
| // From a general point of view, an Addr has a total capacity of 2^24 entities, |
| // in that it has 24 bits that can identify individual records. Note that the |
| // address space is bigger for independent files (2^28), but that would not be |
| // the general case. |
| class NET_EXPORT_PRIVATE Addr { |
| public: |
| Addr() : value_(0) {} |
| explicit Addr(CacheAddr address) : value_(address) {} |
| Addr(FileType file_type, int max_blocks, int block_file, int index) { |
| value_ = ((file_type << kFileTypeOffset) & kFileTypeMask) | |
| (((max_blocks - 1) << kNumBlocksOffset) & kNumBlocksMask) | |
| ((block_file << kFileSelectorOffset) & kFileSelectorMask) | |
| (index & kStartBlockMask) | kInitializedMask; |
| } |
| |
| CacheAddr value() const { return value_; } |
| void set_value(CacheAddr address) { |
| value_ = address; |
| } |
| |
| bool is_initialized() const { |
| return (value_ & kInitializedMask) != 0; |
| } |
| |
| bool is_separate_file() const { |
| return (value_ & kFileTypeMask) == 0; |
| } |
| |
| bool is_block_file() const { |
| return !is_separate_file(); |
| } |
| |
| FileType file_type() const { |
| return static_cast<FileType>((value_ & kFileTypeMask) >> kFileTypeOffset); |
| } |
| |
| int FileNumber() const { |
| if (is_separate_file()) |
| return value_ & kFileNameMask; |
| else |
| return ((value_ & kFileSelectorMask) >> kFileSelectorOffset); |
| } |
| |
| int start_block() const; |
| int num_blocks() const; |
| bool SetFileNumber(int file_number); |
| int BlockSize() const { |
| return BlockSizeForFileType(file_type()); |
| } |
| |
| bool operator==(Addr other) const { |
| return value_ == other.value_; |
| } |
| |
| bool operator!=(Addr other) const { |
| return value_ != other.value_; |
| } |
| |
| static int BlockSizeForFileType(FileType file_type) { |
| switch (file_type) { |
| case RANKINGS: |
| return 36; |
| case BLOCK_256: |
| return 256; |
| case BLOCK_1K: |
| return 1024; |
| case BLOCK_4K: |
| return 4096; |
| case BLOCK_FILES: |
| return 8; |
| case BLOCK_ENTRIES: |
| return 104; |
| case BLOCK_EVICTED: |
| return 48; |
| case EXTERNAL: |
| NOTREACHED(); |
| return 0; |
| } |
| return 0; |
| } |
| |
| static FileType RequiredFileType(int size) { |
| if (size < 1024) |
| return BLOCK_256; |
| else if (size < 4096) |
| return BLOCK_1K; |
| else if (size <= 4096 * 4) |
| return BLOCK_4K; |
| else |
| return EXTERNAL; |
| } |
| |
| static int RequiredBlocks(int size, FileType file_type) { |
| int block_size = BlockSizeForFileType(file_type); |
| return (size + block_size - 1) / block_size; |
| } |
| |
| // Returns true if this address looks like a valid one. |
| bool SanityCheck() const; |
| bool SanityCheckForEntry() const; |
| bool SanityCheckForRankings() const; |
| |
| private: |
| uint32_t reserved_bits() const { return value_ & kReservedBitsMask; } |
| |
| static const uint32_t kInitializedMask = 0x80000000; |
| static const uint32_t kFileTypeMask = 0x70000000; |
| static const uint32_t kFileTypeOffset = 28; |
| static const uint32_t kReservedBitsMask = 0x0c000000; |
| static const uint32_t kNumBlocksMask = 0x03000000; |
| static const uint32_t kNumBlocksOffset = 24; |
| static const uint32_t kFileSelectorMask = 0x00ff0000; |
| static const uint32_t kFileSelectorOffset = 16; |
| static const uint32_t kStartBlockMask = 0x0000FFFF; |
| static const uint32_t kFileNameMask = 0x0FFFFFFF; |
| |
| CacheAddr value_; |
| }; |
| |
| } // namespace disk_cache |
| |
| #endif // NET_DISK_CACHE_BLOCKFILE_ADDR_H_ |