1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This is an internal class that handles the address of a cache record.
6// See net/disk_cache/disk_cache.h for the public interface of the cache.
7
8#ifndef NET_DISK_CACHE_BLOCKFILE_ADDR_H_
9#define NET_DISK_CACHE_BLOCKFILE_ADDR_H_
10
11#include "net/base/net_export.h"
12#include "net/disk_cache/blockfile/disk_format_base.h"
13
14namespace disk_cache {
15
16enum FileType {
17  EXTERNAL = 0,
18  RANKINGS = 1,
19  BLOCK_256 = 2,
20  BLOCK_1K = 3,
21  BLOCK_4K = 4,
22  BLOCK_FILES = 5,
23  BLOCK_ENTRIES = 6,
24  BLOCK_EVICTED = 7
25};
26
27const int kMaxBlockSize = 4096 * 4;
28const int kMaxBlockFile = 255;
29const int kMaxNumBlocks = 4;
30const int kFirstAdditionalBlockFile = 4;
31const int kFirstAdditionalBlockFileV3 = 7;
32
33// Defines a storage address for a cache record
34//
35// Header:
36//   1000 0000 0000 0000 0000 0000 0000 0000 : initialized bit
37//   0111 0000 0000 0000 0000 0000 0000 0000 : file type
38//
39// File type values:
40//   0 = separate file on disk
41//   1 = rankings block file
42//   2 = 256 byte block file
43//   3 = 1k byte block file
44//   4 = 4k byte block file
45//   5 = external files block file
46//   6 = active entries block file
47//   7 = evicted entries block file
48//
49// If separate file:
50//   0000 1111 1111 1111 1111 1111 1111 1111 : file#  0 - 268,435,456 (2^28)
51//
52// If block file:
53//   0000 1100 0000 0000 0000 0000 0000 0000 : reserved bits
54//   0000 0011 0000 0000 0000 0000 0000 0000 : number of contiguous blocks 1-4
55//   0000 0000 1111 1111 0000 0000 0000 0000 : file selector 0 - 255
56//   0000 0000 0000 0000 1111 1111 1111 1111 : block#  0 - 65,535 (2^16)
57//
58// Note that an Addr can be used to "point" to a variety of different objects,
59// from a given type of entry to random blobs of data. Conceptually, an Addr is
60// just a number that someone can inspect to find out how to locate the desired
61// record. Most users will not care about the specific bits inside Addr, for
62// example, what parts of it point to a file number; only the code that has to
63// select a specific file would care about those specific bits.
64//
65// From a general point of view, an Addr has a total capacity of 2^24 entities,
66// in that it has 24 bits that can identify individual records. Note that the
67// address space is bigger for independent files (2^28), but that would not be
68// the general case.
69class NET_EXPORT_PRIVATE Addr {
70 public:
71  Addr() : value_(0) {}
72  explicit Addr(CacheAddr address) : value_(address) {}
73  Addr(FileType file_type, int max_blocks, int block_file, int index) {
74    value_ = ((file_type << kFileTypeOffset) & kFileTypeMask) |
75             (((max_blocks - 1) << kNumBlocksOffset) & kNumBlocksMask) |
76             ((block_file << kFileSelectorOffset) & kFileSelectorMask) |
77             (index  & kStartBlockMask) | kInitializedMask;
78  }
79
80  CacheAddr value() const { return value_; }
81  void set_value(CacheAddr address) {
82    value_ = address;
83  }
84
85  bool is_initialized() const {
86    return (value_ & kInitializedMask) != 0;
87  }
88
89  bool is_separate_file() const {
90    return (value_ & kFileTypeMask) == 0;
91  }
92
93  bool is_block_file() const {
94    return !is_separate_file();
95  }
96
97  FileType file_type() const {
98    return static_cast<FileType>((value_ & kFileTypeMask) >> kFileTypeOffset);
99  }
100
101  int FileNumber() const {
102    if (is_separate_file())
103      return value_ & kFileNameMask;
104    else
105      return ((value_ & kFileSelectorMask) >> kFileSelectorOffset);
106  }
107
108  int start_block() const;
109  int num_blocks() const;
110  bool SetFileNumber(int file_number);
111  int BlockSize() const {
112    return BlockSizeForFileType(file_type());
113  }
114
115  bool operator==(Addr other) const {
116    return value_ == other.value_;
117  }
118
119  bool operator!=(Addr other) const {
120    return value_ != other.value_;
121  }
122
123  static int BlockSizeForFileType(FileType file_type) {
124    switch (file_type) {
125      case RANKINGS:
126        return 36;
127      case BLOCK_256:
128        return 256;
129      case BLOCK_1K:
130        return 1024;
131      case BLOCK_4K:
132        return 4096;
133      case BLOCK_FILES:
134        return 8;
135      case BLOCK_ENTRIES:
136        return 104;
137      case BLOCK_EVICTED:
138        return 48;
139      default:
140        return 0;
141    }
142  }
143
144  static FileType RequiredFileType(int size) {
145    if (size < 1024)
146      return BLOCK_256;
147    else if (size < 4096)
148      return BLOCK_1K;
149    else if (size <= 4096 * 4)
150      return BLOCK_4K;
151    else
152      return EXTERNAL;
153  }
154
155  static int RequiredBlocks(int size, FileType file_type) {
156    int block_size = BlockSizeForFileType(file_type);
157    return (size + block_size - 1) / block_size;
158  }
159
160  // Returns true if this address looks like a valid one.
161  bool SanityCheckV2() const;
162  bool SanityCheckV3() const;
163  bool SanityCheckForEntryV2() const;
164  bool SanityCheckForEntryV3() const;
165  bool SanityCheckForRankings() const;
166
167 private:
168  uint32 reserved_bits() const {
169    return value_ & kReservedBitsMask;
170  }
171
172  static const uint32 kInitializedMask    = 0x80000000;
173  static const uint32 kFileTypeMask       = 0x70000000;
174  static const uint32 kFileTypeOffset     = 28;
175  static const uint32 kReservedBitsMask   = 0x0c000000;
176  static const uint32 kNumBlocksMask      = 0x03000000;
177  static const uint32 kNumBlocksOffset    = 24;
178  static const uint32 kFileSelectorMask   = 0x00ff0000;
179  static const uint32 kFileSelectorOffset = 16;
180  static const uint32 kStartBlockMask     = 0x0000FFFF;
181  static const uint32 kFileNameMask       = 0x0FFFFFFF;
182
183  CacheAddr value_;
184};
185
186}  // namespace disk_cache
187
188#endif  // NET_DISK_CACHE_BLOCKFILE_ADDR_H_
189