OLD | NEW |
| (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/blockfile/block_bitmaps_v3.h" | |
6 | |
7 #include "base/metrics/histogram.h" | |
8 #include "base/time/time.h" | |
9 #include "net/disk_cache/blockfile/disk_format_base.h" | |
10 #include "net/disk_cache/blockfile/trace.h" | |
11 | |
12 using base::TimeTicks; | |
13 | |
14 namespace disk_cache { | |
15 | |
16 BlockBitmaps::BlockBitmaps() { | |
17 } | |
18 | |
19 BlockBitmaps::~BlockBitmaps() { | |
20 } | |
21 | |
22 void BlockBitmaps::Init(const BlockFilesBitmaps& bitmaps) { | |
23 bitmaps_ = bitmaps; | |
24 } | |
25 | |
26 bool BlockBitmaps::CreateBlock(FileType block_type, | |
27 int block_count, | |
28 Addr* block_address) { | |
29 DCHECK_NE(block_type, EXTERNAL); | |
30 DCHECK_NE(block_type, RANKINGS); | |
31 if (block_count < 1 || block_count > kMaxNumBlocks) | |
32 return false; | |
33 | |
34 int header_num = HeaderNumberForNewBlock(block_type, block_count); | |
35 if (header_num < 0) | |
36 return false; | |
37 | |
38 int index; | |
39 if (!bitmaps_[header_num].CreateMapBlock(block_count, &index)) | |
40 return false; | |
41 | |
42 if (!index && (block_type == BLOCK_ENTRIES || block_type == BLOCK_EVICTED) && | |
43 !bitmaps_[header_num].CreateMapBlock(block_count, &index)) { | |
44 // index 0 for entries is a reserved value. | |
45 return false; | |
46 } | |
47 | |
48 Addr address(block_type, block_count, bitmaps_[header_num].FileId(), index); | |
49 block_address->set_value(address.value()); | |
50 Trace("CreateBlock 0x%x", address.value()); | |
51 return true; | |
52 } | |
53 | |
54 void BlockBitmaps::DeleteBlock(Addr address) { | |
55 if (!address.is_initialized() || address.is_separate_file()) | |
56 return; | |
57 | |
58 int header_num = GetHeaderNumber(address); | |
59 if (header_num < 0) | |
60 return; | |
61 | |
62 Trace("DeleteBlock 0x%x", address.value()); | |
63 bitmaps_[header_num].DeleteMapBlock(address.start_block(), | |
64 address.num_blocks()); | |
65 } | |
66 | |
67 void BlockBitmaps::Clear() { | |
68 bitmaps_.clear(); | |
69 } | |
70 | |
71 void BlockBitmaps::ReportStats() { | |
72 int used_blocks[kFirstAdditionalBlockFile]; | |
73 int load[kFirstAdditionalBlockFile]; | |
74 for (int16 i = 0; i < kFirstAdditionalBlockFile; i++) { | |
75 GetFileStats(i, &used_blocks[i], &load[i]); | |
76 } | |
77 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_0", used_blocks[0]); | |
78 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_1", used_blocks[1]); | |
79 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_2", used_blocks[2]); | |
80 UMA_HISTOGRAM_COUNTS("DiskCache.Blocks_3", used_blocks[3]); | |
81 | |
82 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_0", load[0], 101); | |
83 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_1", load[1], 101); | |
84 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_2", load[2], 101); | |
85 UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_3", load[3], 101); | |
86 } | |
87 | |
88 bool BlockBitmaps::IsValid(Addr address) { | |
89 #ifdef NDEBUG | |
90 return true; | |
91 #else | |
92 if (!address.is_initialized() || address.is_separate_file()) | |
93 return false; | |
94 | |
95 int header_num = GetHeaderNumber(address); | |
96 if (header_num < 0) | |
97 return false; | |
98 | |
99 bool rv = bitmaps_[header_num].UsedMapBlock(address.start_block(), | |
100 address.num_blocks()); | |
101 DCHECK(rv); | |
102 return rv; | |
103 #endif | |
104 } | |
105 | |
106 int BlockBitmaps::GetHeaderNumber(Addr address) { | |
107 DCHECK_GE(bitmaps_.size(), kFirstAdditionalBlockFileV3); | |
108 DCHECK(address.is_block_file() || !address.is_initialized()); | |
109 if (!address.is_initialized()) | |
110 return -1; | |
111 | |
112 int file_index = address.FileNumber(); | |
113 if (static_cast<unsigned int>(file_index) >= bitmaps_.size()) | |
114 return -1; | |
115 | |
116 return file_index; | |
117 } | |
118 | |
119 int BlockBitmaps::HeaderNumberForNewBlock(FileType block_type, | |
120 int block_count) { | |
121 DCHECK_GT(block_type, 0); | |
122 int header_num = block_type - 1; | |
123 bool found = true; | |
124 | |
125 TimeTicks start = TimeTicks::Now(); | |
126 while (bitmaps_[header_num].NeedToGrowBlockFile(block_count)) { | |
127 header_num = bitmaps_[header_num].NextFileId(); | |
128 if (!header_num) { | |
129 found = false; | |
130 break; | |
131 } | |
132 } | |
133 | |
134 if (!found) { | |
135 // Restart the search, looking for any file with space. We know that all | |
136 // files of this type are low on free blocks, but we cannot grow any file | |
137 // at this time. | |
138 header_num = block_type - 1; | |
139 do { | |
140 if (bitmaps_[header_num].CanAllocate(block_count)) { | |
141 found = true; // Make sure file 0 is not mistaken with a failure. | |
142 break; | |
143 } | |
144 header_num = bitmaps_[header_num].NextFileId(); | |
145 } while (header_num); | |
146 | |
147 if (!found) | |
148 header_num = -1; | |
149 } | |
150 | |
151 LOCAL_HISTOGRAM_TIMES("DiskCache.GetFileForNewBlock", | |
152 TimeTicks::Now() - start); | |
153 return header_num; | |
154 } | |
155 | |
156 // We are interested in the total number of blocks used by this file type, and | |
157 // the max number of blocks that we can store (reported as the percentage of | |
158 // used blocks). In order to find out the number of used blocks, we have to | |
159 // substract the empty blocks from the total blocks for each file in the chain. | |
160 void BlockBitmaps::GetFileStats(int index, int* used_count, int* load) { | |
161 int max_blocks = 0; | |
162 *used_count = 0; | |
163 *load = 0; | |
164 do { | |
165 int capacity = bitmaps_[index].Capacity(); | |
166 int used = capacity - bitmaps_[index].EmptyBlocks(); | |
167 DCHECK_GE(used, 0); | |
168 | |
169 max_blocks += capacity; | |
170 *used_count += used; | |
171 | |
172 index = bitmaps_[index].NextFileId(); | |
173 } while (index); | |
174 | |
175 if (max_blocks) | |
176 *load = *used_count * 100 / max_blocks; | |
177 } | |
178 | |
179 } // namespace disk_cache | |
OLD | NEW |