Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: net/disk_cache/v3/block_bitmaps.cc

Issue 15203004: Disk cache: Reference CL for the implementation of file format version 3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/v3/block_bitmaps.h ('k') | net/disk_cache/v3/disk_format_v3.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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 #include "net/disk_cache/v3/block_bitmaps.h"
6
7 #include "base/metrics/histogram.h"
8 #include "base/string_util.h"
9 #include "base/stringprintf.h"
10 #include "base/threading/thread_checker.h"
11 #include "base/time.h"
12 #include "net/disk_cache/cache_util.h"
13 #include "net/disk_cache/disk_format_base.h"
14 #include "net/disk_cache/file_lock.h"
15 #include "net/disk_cache/trace.h"
16 #include "net/disk_cache/v3/backend_impl_v3.h"
17
18 using base::TimeTicks;
19
20 namespace disk_cache {
21
22 BlockBitmaps::BlockBitmaps(BackendImplV3* backend) : backend_(backend) {
23 }
24
25 BlockBitmaps::~BlockBitmaps() {
26 }
27
28 void BlockBitmaps::Init(const BlockFilesBitmaps& bitmaps) {
29 bitmaps_ = bitmaps;
30 for (int i = 0; i < kFirstAdditionalBlockFileV3; i++)
31 empty_counts_[i] = EmptyBlocksForType(i);
32 }
33
34 bool BlockBitmaps::CreateBlock(FileType block_type, int block_count,
35 Addr* block_address) {
36 if (block_type < BLOCK_256 || block_count < 1 || block_count > 4)
37 return false;
38
39 int header_num = HeaderForNewBlock(block_type, block_count);
40 if (header_num < 0)
41 return false;
42
43 int target_size = 0;
44 for (int i = block_count; i <= 4; i++) {
45 if (bitmaps_[header_num]->empty[i - 1]) {
46 target_size = i;
47 break;
48 }
49 }
50
51 DCHECK(target_size);
52 int index;
53 if (!bitmaps_[header_num].CreateMapBlock(target_size, block_count, &index))
54 return false;
55
56 if (!index && (block_type == BLOCK_ENTRIES || block_type == BLOCK_EVICTED) &&
57 !bitmaps_[header_num].CreateMapBlock(target_size, block_count, &index)) {
58 // index 0 for entries is a reserved value.
59 return false;
60 }
61
62 // Yes, the count may be off by 1 when we start.
63 empty_counts_[target_size] -= block_count;
64 if (empty_counts_[target_size] < kNumExtraBlocks / 2)
65 backend_->GrowBlockFiles();
66
67 Addr address(block_type, block_count, bitmaps_[header_num]->this_file, index);
68 block_address->set_value(address.value());
69 Trace("CreateBlock 0x%x", address.value());
70 return true;
71 }
72
73 void BlockBitmaps::DeleteBlock(Addr address) {
74 if (!address.is_initialized() || address.is_separate_file())
75 return;
76
77 int header_num = GetHeaderNumber(address);
78 if (header_num < 0)
79 return;
80
81 Trace("DeleteBlock 0x%x", address.value());
82 bitmaps_[header_num].DeleteMapBlock(address.start_block(),
83 address.num_blocks());
84
85 if (!bitmaps_[header_num]->num_entries) {
86 // This file is now empty. Let's try to delete it.
87 //FileType type = Addr::RequiredFileType(header->entry_size);
88 //if (Addr::BlockSizeForFileType(RANKINGS) == header->entry_size)
89 // type = RANKINGS;
90 //RemoveEmptyFile(type); // Ignore failures.
91 }
92 }
93
94 void BlockBitmaps::Clear() {
95 bitmaps_.clear();
96 }
97
98 void BlockBitmaps::ReportStats() {
99 int used_blocks[kFirstAdditionalBlockFile];
100 int load[kFirstAdditionalBlockFile];
101 for (int i = 0; i < kFirstAdditionalBlockFile; i++) {
102 GetFileStats(i, &used_blocks[i], &load[i]);
103 }
104 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_0", used_blocks[0]);
105 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_1", used_blocks[1]);
106 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_2", used_blocks[2]);
107 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_3", used_blocks[3]);
108
109 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_0", load[0], 101);
110 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_1", load[1], 101);
111 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_2", load[2], 101);
112 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_3", load[3], 101);
113 }
114
115 bool BlockBitmaps::IsValid(Addr address) {
116 #ifdef NDEBUG
117 return true;
118 #else
119 if (!address.is_initialized() || address.is_separate_file())
120 return false;
121
122 int header_num = GetHeaderNumber(address);
123 if (header_num < 0)
124 return false;
125
126 bool rv = bitmaps_[header_num].UsedMapBlock(address.start_block(),
127 address.num_blocks());
128 DCHECK(rv);
129 return rv;
130 #endif
131 }
132
133 int BlockBitmaps::GetHeaderNumber(Addr address) {
134 DCHECK(bitmaps_.size() >= kFirstAdditionalBlockFileV3);
135 DCHECK(address.is_block_file() || !address.is_initialized());
136 if (!address.is_initialized())
137 return -1;
138
139 int file_index = address.FileNumber();
140 if (static_cast<unsigned int>(file_index) >= bitmaps_.size() ||
141 !bitmaps_[file_index].Get()) {
142 return -1;
143 }
144 DCHECK(bitmaps_.size() >= static_cast<unsigned int>(file_index));
145 return file_index;
146 }
147
148 int BlockBitmaps::EmptyBlocksForType(int next_file) {
149 int empty_blocks = 0;
150 do {
151 empty_blocks += bitmaps_[next_file].EmptyBlocks();
152 next_file = bitmaps_[next_file]->next_file;
153 } while (next_file);
154 return empty_blocks;
155 }
156
157 int BlockBitmaps::HeaderForNewBlock(FileType block_type, int block_count) {
158 COMPILE_ASSERT(RANKINGS == 1, invalid_file_type);
159 int header_num = block_type - 1;
160 bool found = true;
161
162 TimeTicks start = TimeTicks::Now();
163 while (bitmaps_[header_num].NeedToGrowBlockFile(block_count)) {
164 header_num = bitmaps_[header_num]->next_file;
165 if (!header_num) {
166 found = false;
167 break;
168 }
169 }
170
171 if (!found) {
172 // Restart the search, looking for any file with space.
173 header_num = block_type - 1;
174 do {
175 if (bitmaps_[header_num].CanAllocate(block_count))
176 found = true;
177 else
178 header_num = bitmaps_[header_num]->next_file;
179 } while (header_num && !found);
180 if (!found) {
181 NOTREACHED();
182 header_num = -1;
183 }
184 }
185
186 HISTOGRAM_TIMES("DiskCache.GetFileForNewBlock", TimeTicks::Now() - start);
187 return header_num;
188 }
189
190 // We are interested in the total number of blocks used by this file type, and
191 // the max number of blocks that we can store (reported as the percentage of
192 // used blocks). In order to find out the number of used blocks, we have to
193 // substract the empty blocks from the total blocks for each file in the chain.
194 void BlockBitmaps::GetFileStats(int index, int* used_count, int* load) {
195 int max_blocks = 0;
196 *used_count = 0;
197 *load = 0;
198 for (;;) {
199 BlockFileHeader* header = bitmaps_[index].Get();
200
201 max_blocks += header->max_entries;
202 int used = header->max_entries;
203 for (int i = 0; i < 4; i++) {
204 used -= header->empty[i] * (i + 1);
205 DCHECK_GE(used, 0);
206 }
207 *used_count += used;
208
209 if (!header->next_file)
210 break;
211 index = header->next_file;
212 }
213 if (max_blocks)
214 *load = *used_count * 100 / max_blocks;
215 }
216
217 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/v3/block_bitmaps.h ('k') | net/disk_cache/v3/disk_format_v3.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698