summaryrefslogtreecommitdiff
path: root/chromium/net/disk_cache/block_files.h
blob: 353c5663df08c17fb515f4796223d8afd6000fc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// 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.

// See net/disk_cache/disk_cache.h for the public interface.

#ifndef NET_DISK_CACHE_BLOCK_FILES_H_
#define NET_DISK_CACHE_BLOCK_FILES_H_

#include <vector>

#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
#include "net/disk_cache/addr.h"
#include "net/disk_cache/disk_format_base.h"
#include "net/disk_cache/mapped_file.h"

namespace base {
class ThreadChecker;
}

namespace disk_cache {

// An instance of this class represents the header of a block file in memory.
// Note that this class doesn't perform any file operation.
class NET_EXPORT_PRIVATE BlockHeader {
 public:
  BlockHeader();
  explicit BlockHeader(BlockFileHeader* header);
  explicit BlockHeader(MappedFile* file);
  BlockHeader(const BlockHeader& other);
  ~BlockHeader();

  // Creates a new entry on the allocation map, updating the apropriate
  // counters. |target| is the type of block to use (number of empty blocks),
  // and |size| is the actual number of blocks to use.
  bool CreateMapBlock(int target, int size, int* index);

  // Deletes the block pointed by |index|.
  void DeleteMapBlock(int index, int block_size);

  // Returns true if the specified block is used.
  bool UsedMapBlock(int index, int size);

  // Restores the "empty counters" and allocation hints.
  void FixAllocationCounters();

  // Returns true if the current block file should not be used as-is to store
  // more records. |block_count| is the number of blocks to allocate.
  bool NeedToGrowBlockFile(int block_count);

  // Returns the number of empty blocks for this file.
  int EmptyBlocks() const;

  // Returns true if the counters look OK.
  bool ValidateCounters() const;

  // Returns the size of the wrapped structure (BlockFileHeader).
  int Size() const;

  BlockFileHeader* operator->() { return header_; }
  void operator=(const BlockHeader& other) { header_ = other.header_; }
  BlockFileHeader* Get() { return header_; }

 private:
  BlockFileHeader* header_;
};

typedef std::vector<BlockHeader> BlockFilesBitmaps;

// This class handles the set of block-files open by the disk cache.
class NET_EXPORT_PRIVATE BlockFiles {
 public:
  explicit BlockFiles(const base::FilePath& path);
  ~BlockFiles();

  // Performs the object initialization. create_files indicates if the backing
  // files should be created or just open.
  bool Init(bool create_files);

  // Returns the file that stores a given address.
  MappedFile* GetFile(Addr address);

  // Creates a new entry on a block file. block_type indicates the size of block
  // to be used (as defined on cache_addr.h), block_count is the number of
  // blocks to allocate, and block_address is the address of the new entry.
  bool CreateBlock(FileType block_type, int block_count, Addr* block_address);

  // Removes an entry from the block files. If deep is true, the storage is zero
  // filled; otherwise the entry is removed but the data is not altered (must be
  // already zeroed).
  void DeleteBlock(Addr address, bool deep);

  // Close all the files and set the internal state to be initializad again. The
  // cache is being purged.
  void CloseFiles();

  // Sends UMA stats.
  void ReportStats();

  // Returns true if the blocks pointed by a given address are currently used.
  // This method is only intended for debugging.
  bool IsValid(Addr address);

 private:
  // Set force to true to overwrite the file if it exists.
  bool CreateBlockFile(int index, FileType file_type, bool force);
  bool OpenBlockFile(int index);

  // Attemp to grow this file. Fails if the file cannot be extended anymore.
  bool GrowBlockFile(MappedFile* file, BlockFileHeader* header);

  // Returns the appropriate file to use for a new block.
  MappedFile* FileForNewBlock(FileType block_type, int block_count);

  // Returns the next block file on this chain, creating new files if needed.
  MappedFile* NextFile(MappedFile* file);

  // Creates an empty block file and returns its index.
  int CreateNextBlockFile(FileType block_type);

  // Removes a chained block file that is now empty.
  bool RemoveEmptyFile(FileType block_type);

  // Restores the header of a potentially inconsistent file.
  bool FixBlockFileHeader(MappedFile* file);

  // Retrieves stats for the given file index.
  void GetFileStats(int index, int* used_count, int* load);

  // Returns the filename for a given file index.
  base::FilePath Name(int index);

  bool init_;
  char* zero_buffer_;  // Buffer to speed-up cleaning deleted entries.
  base::FilePath path_;  // Path to the backing folder.
  std::vector<MappedFile*> block_files_;  // The actual files.
  scoped_ptr<base::ThreadChecker> thread_checker_;

  FRIEND_TEST_ALL_PREFIXES(DiskCacheTest, BlockFiles_ZeroSizeFile);
  FRIEND_TEST_ALL_PREFIXES(DiskCacheTest, BlockFiles_TruncatedFile);
  FRIEND_TEST_ALL_PREFIXES(DiskCacheTest, BlockFiles_InvalidFile);
  FRIEND_TEST_ALL_PREFIXES(DiskCacheTest, BlockFiles_Stats);

  DISALLOW_COPY_AND_ASSIGN(BlockFiles);
};

}  // namespace disk_cache

#endif  // NET_DISK_CACHE_BLOCK_FILES_H_