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.
5 #include "net/disk_cache/blockfile/block_bitmaps_v3.h"
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"
12 using base::TimeTicks
;
14 namespace disk_cache
{
16 BlockBitmaps::BlockBitmaps() {
19 BlockBitmaps::~BlockBitmaps() {
22 void BlockBitmaps::Init(const BlockFilesBitmaps
& bitmaps
) {
26 bool BlockBitmaps::CreateBlock(FileType block_type
,
28 Addr
* block_address
) {
29 DCHECK_NE(block_type
, EXTERNAL
);
30 DCHECK_NE(block_type
, RANKINGS
);
31 if (block_count
< 1 || block_count
> kMaxNumBlocks
)
34 int header_num
= HeaderNumberForNewBlock(block_type
, block_count
);
39 if (!bitmaps_
[header_num
].CreateMapBlock(block_count
, &index
))
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.
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());
54 void BlockBitmaps::DeleteBlock(Addr address
) {
55 if (!address
.is_initialized() || address
.is_separate_file())
58 int header_num
= GetHeaderNumber(address
);
62 Trace("DeleteBlock 0x%x", address
.value());
63 bitmaps_
[header_num
].DeleteMapBlock(address
.start_block(),
64 address
.num_blocks());
67 void BlockBitmaps::Clear() {
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
]);
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]);
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);
88 bool BlockBitmaps::IsValid(Addr address
) {
92 if (!address
.is_initialized() || address
.is_separate_file())
95 int header_num
= GetHeaderNumber(address
);
99 bool rv
= bitmaps_
[header_num
].UsedMapBlock(address
.start_block(),
100 address
.num_blocks());
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())
112 int file_index
= address
.FileNumber();
113 if (static_cast<unsigned int>(file_index
) >= bitmaps_
.size())
119 int BlockBitmaps::HeaderNumberForNewBlock(FileType block_type
,
121 DCHECK_GT(block_type
, 0);
122 int header_num
= block_type
- 1;
125 TimeTicks start
= TimeTicks::Now();
126 while (bitmaps_
[header_num
].NeedToGrowBlockFile(block_count
)) {
127 header_num
= bitmaps_
[header_num
].NextFileId();
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
138 header_num
= block_type
- 1;
140 if (bitmaps_
[header_num
].CanAllocate(block_count
)) {
141 found
= true; // Make sure file 0 is not mistaken with a failure.
144 header_num
= bitmaps_
[header_num
].NextFileId();
145 } while (header_num
);
151 LOCAL_HISTOGRAM_TIMES("DiskCache.GetFileForNewBlock",
152 TimeTicks::Now() - start
);
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
) {
165 int capacity
= bitmaps_
[index
].Capacity();
166 int used
= capacity
- bitmaps_
[index
].EmptyBlocks();
169 max_blocks
+= capacity
;
172 index
= bitmaps_
[index
].NextFileId();
176 *load
= *used_count
* 100 / max_blocks
;
179 } // namespace disk_cache