1// Copyright (c) 2011 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_ADDR_H_
9#define NET_DISK_CACHE_ADDR_H_
10#pragma once
11
12#include "net/disk_cache/disk_format.h"
13
14namespace disk_cache {
15
16enum FileType {
17  EXTERNAL = 0,
18  RANKINGS = 1,
19  BLOCK_256,
20  BLOCK_1K,
21  BLOCK_4K,
22};
23
24const int kMaxBlockSize = 4096 * 4;
25const int kMaxBlockFile = 255;
26const int kMaxNumBlocks = 4;
27const int kFirstAdditionalBlockFile = 4;
28
29// Defines a storage address for a cache record
30//
31// Header:
32//   1000 0000 0000 0000 0000 0000 0000 0000 : initialized bit
33//   0111 0000 0000 0000 0000 0000 0000 0000 : file type
34//
35// File type values:
36//   0 = separate file on disk
37//   1 = rankings block file
38//   2 = 256 byte block file
39//   3 = 1k byte block file
40//   4 = 4k byte block file
41//
42// If separate file:
43//   0000 1111 1111 1111 1111 1111 1111 1111 : file#  0 - 268,435,456 (2^28)
44//
45// If block file:
46//   0000 1100 0000 0000 0000 0000 0000 0000 : reserved bits
47//   0000 0011 0000 0000 0000 0000 0000 0000 : number of contiguous blocks 1-4
48//   0000 0000 1111 1111 0000 0000 0000 0000 : file selector 0 - 255
49//   0000 0000 0000 0000 1111 1111 1111 1111 : block#  0 - 65,535 (2^16)
50class Addr {
51 public:
52  Addr() : value_(0) {}
53  explicit Addr(CacheAddr address) : value_(address) {}
54  Addr(FileType file_type, int max_blocks, int block_file, int index) {
55    value_ = ((file_type << kFileTypeOffset) & kFileTypeMask) |
56             (((max_blocks - 1) << kNumBlocksOffset) & kNumBlocksMask) |
57             ((block_file << kFileSelectorOffset) & kFileSelectorMask) |
58             (index  & kStartBlockMask) | kInitializedMask;
59  }
60
61  CacheAddr value() const { return value_; }
62  void set_value(CacheAddr address) {
63    value_ = address;
64  }
65
66  bool is_initialized() const {
67    return (value_ & kInitializedMask) != 0;
68  }
69
70  bool is_separate_file() const {
71    return (value_ & kFileTypeMask) == 0;
72  }
73
74  bool is_block_file() const {
75    return !is_separate_file();
76  }
77
78  FileType file_type() const {
79    return static_cast<FileType>((value_ & kFileTypeMask) >> kFileTypeOffset);
80  }
81
82  int FileNumber() const {
83    if (is_separate_file())
84      return value_ & kFileNameMask;
85    else
86      return ((value_ & kFileSelectorMask) >> kFileSelectorOffset);
87  }
88
89  int start_block() const;
90  int num_blocks() const;
91  bool SetFileNumber(int file_number);
92  int BlockSize() const {
93    return BlockSizeForFileType(file_type());
94  }
95
96  static int BlockSizeForFileType(FileType file_type) {
97    switch (file_type) {
98      case RANKINGS:
99        return 36;
100      case BLOCK_256:
101        return 256;
102      case BLOCK_1K:
103        return 1024;
104      case BLOCK_4K:
105        return 4096;
106      default:
107        return 0;
108    }
109  }
110
111  static FileType RequiredFileType(int size) {
112    if (size < 1024)
113      return BLOCK_256;
114    else if (size < 4096)
115      return BLOCK_1K;
116    else if (size <= 4096 * 4)
117      return BLOCK_4K;
118    else
119      return EXTERNAL;
120  }
121
122  // Returns true if this address looks like a valid one.
123  bool SanityCheck() const;
124
125 private:
126  static const uint32 kInitializedMask    = 0x80000000;
127  static const uint32 kFileTypeMask       = 0x70000000;
128  static const uint32 kFileTypeOffset     = 28;
129  static const uint32 kNumBlocksMask      = 0x03000000;
130  static const uint32 kNumBlocksOffset    = 24;
131  static const uint32 kFileSelectorMask   = 0x00ff0000;
132  static const uint32 kFileSelectorOffset = 16;
133  static const uint32 kStartBlockMask     = 0x0000FFFF;
134  static const uint32 kFileNameMask       = 0x0FFFFFFF;
135
136  CacheAddr value_;
137};
138
139}  // namespace disk_cache
140
141#endif  // NET_DISK_CACHE_ADDR_H_
142