OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/disk_cache/blockfile/block_files.h" | 5 #include "net/disk_cache/blockfile/block_files.h" |
6 | 6 |
7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 128 |
129 // See what type of block will be available after we delete this one. | 129 // See what type of block will be available after we delete this one. |
130 int bits_at_end = 4 - size - index % 4; | 130 int bits_at_end = 4 - size - index % 4; |
131 uint8 end_mask = (0xf << (4 - bits_at_end)) & 0xf; | 131 uint8 end_mask = (0xf << (4 - bits_at_end)) & 0xf; |
132 bool update_counters = (map_block & end_mask) == 0; | 132 bool update_counters = (map_block & end_mask) == 0; |
133 uint8 new_value = map_block & ~(((1 << size) - 1) << (index % 4)); | 133 uint8 new_value = map_block & ~(((1 << size) - 1) << (index % 4)); |
134 int new_type = GetMapBlockType(new_value); | 134 int new_type = GetMapBlockType(new_value); |
135 | 135 |
136 disk_cache::FileLock lock(header_); | 136 disk_cache::FileLock lock(header_); |
137 STRESS_DCHECK((((1 << size) - 1) << (index % 8)) < 0x100); | 137 STRESS_DCHECK((((1 << size) - 1) << (index % 8)) < 0x100); |
138 uint8 to_clear = ((1 << size) - 1) << (index % 8); | 138 uint8 to_clear = ((1 << size) - 1) << (index % 8); |
139 STRESS_DCHECK((byte_map[byte_index] & to_clear) == to_clear); | 139 STRESS_DCHECK((byte_map[byte_index] & to_clear) == to_clear); |
140 byte_map[byte_index] &= ~to_clear; | 140 byte_map[byte_index] &= ~to_clear; |
141 | 141 |
142 if (update_counters) { | 142 if (update_counters) { |
143 if (bits_at_end) | 143 if (bits_at_end) |
144 header_->empty[bits_at_end - 1]--; | 144 header_->empty[bits_at_end - 1]--; |
145 header_->empty[new_type - 1]++; | 145 header_->empty[new_type - 1]++; |
146 STRESS_DCHECK(header_->empty[bits_at_end - 1] >= 0); | 146 STRESS_DCHECK(header_->empty[bits_at_end - 1] >= 0); |
147 } | 147 } |
148 base::subtle::MemoryBarrier(); | 148 base::subtle::MemoryBarrier(); |
149 header_->num_entries--; | 149 header_->num_entries--; |
150 STRESS_DCHECK(header_->num_entries >= 0); | 150 STRESS_DCHECK(header_->num_entries >= 0); |
151 HISTOGRAM_TIMES("DiskCache.DeleteBlock", TimeTicks::Now() - start); | 151 HISTOGRAM_TIMES("DiskCache.DeleteBlock", TimeTicks::Now() - start); |
152 } | 152 } |
153 | 153 |
154 // Note that this is a simplified version of DeleteMapBlock(). | 154 // Note that this is a simplified version of DeleteMapBlock(). |
155 bool BlockHeader::UsedMapBlock(int index, int size) { | 155 bool BlockHeader::UsedMapBlock(int index, int size) { |
156 if (size < 0 || size > kMaxNumBlocks) | 156 if (size < 0 || size > kMaxNumBlocks) |
157 return false; | 157 return false; |
158 | 158 |
159 int byte_index = index / 8; | 159 int byte_index = index / 8; |
160 uint8* byte_map = reinterpret_cast<uint8*>(header_->allocation_map); | 160 uint8* byte_map = reinterpret_cast<uint8*>(header_->allocation_map); |
161 uint8 map_block = byte_map[byte_index]; | 161 uint8 map_block = byte_map[byte_index]; |
162 | 162 |
163 if (index % 8 >= 4) | 163 if (index % 8 >= 4) |
164 map_block >>= 4; | 164 map_block >>= 4; |
165 | 165 |
166 STRESS_DCHECK((((1 << size) - 1) << (index % 8)) < 0x100); | 166 STRESS_DCHECK((((1 << size) - 1) << (index % 8)) < 0x100); |
167 uint8 to_clear = ((1 << size) - 1) << (index % 8); | 167 uint8 to_clear = ((1 << size) - 1) << (index % 8); |
168 return ((byte_map[byte_index] & to_clear) == to_clear); | 168 return ((byte_map[byte_index] & to_clear) == to_clear); |
169 } | 169 } |
170 | 170 |
171 void BlockHeader::FixAllocationCounters() { | 171 void BlockHeader::FixAllocationCounters() { |
172 for (int i = 0; i < kMaxNumBlocks; i++) { | 172 for (int i = 0; i < kMaxNumBlocks; i++) { |
173 header_->hints[i] = 0; | 173 header_->hints[i] = 0; |
174 header_->empty[i] = 0; | 174 header_->empty[i] = 0; |
175 } | 175 } |
176 | 176 |
177 for (int i = 0; i < header_->max_entries / 32; i++) { | 177 for (int i = 0; i < header_->max_entries / 32; i++) { |
178 uint32 map_block = header_->allocation_map[i]; | 178 uint32 map_block = header_->allocation_map[i]; |
179 | 179 |
180 for (int j = 0; j < 8; j++, map_block >>= 4) { | 180 for (int j = 0; j < 8; j++, map_block >>= 4) { |
181 int type = GetMapBlockType(map_block); | 181 int type = GetMapBlockType(map_block); |
182 if (type) | 182 if (type) |
183 header_->empty[type -1]++; | 183 header_->empty[type - 1]++; |
184 } | 184 } |
185 } | 185 } |
186 } | 186 } |
187 | 187 |
188 bool BlockHeader::NeedToGrowBlockFile(int block_count) const { | 188 bool BlockHeader::NeedToGrowBlockFile(int block_count) const { |
189 bool have_space = false; | 189 bool have_space = false; |
190 int empty_blocks = 0; | 190 int empty_blocks = 0; |
191 for (int i = 0; i < kMaxNumBlocks; i++) { | 191 for (int i = 0; i < kMaxNumBlocks; i++) { |
192 empty_blocks += header_->empty[i] * (i + 1); | 192 empty_blocks += header_->empty[i] * (i + 1); |
193 if (i >= block_count - 1 && header_->empty[i]) | 193 if (i >= block_count - 1 && header_->empty[i]) |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 if (static_cast<unsigned int>(file_index) >= block_files_.size() || | 308 if (static_cast<unsigned int>(file_index) >= block_files_.size() || |
309 !block_files_[file_index]) { | 309 !block_files_[file_index]) { |
310 // We need to open the file | 310 // We need to open the file |
311 if (!OpenBlockFile(file_index)) | 311 if (!OpenBlockFile(file_index)) |
312 return NULL; | 312 return NULL; |
313 } | 313 } |
314 DCHECK_GE(block_files_.size(), static_cast<unsigned int>(file_index)); | 314 DCHECK_GE(block_files_.size(), static_cast<unsigned int>(file_index)); |
315 return block_files_[file_index]; | 315 return block_files_[file_index]; |
316 } | 316 } |
317 | 317 |
318 bool BlockFiles::CreateBlock(FileType block_type, int block_count, | 318 bool BlockFiles::CreateBlock(FileType block_type, |
| 319 int block_count, |
319 Addr* block_address) { | 320 Addr* block_address) { |
320 DCHECK(thread_checker_->CalledOnValidThread()); | 321 DCHECK(thread_checker_->CalledOnValidThread()); |
321 DCHECK_NE(block_type, EXTERNAL); | 322 DCHECK_NE(block_type, EXTERNAL); |
322 DCHECK_NE(block_type, BLOCK_FILES); | 323 DCHECK_NE(block_type, BLOCK_FILES); |
323 DCHECK_NE(block_type, BLOCK_ENTRIES); | 324 DCHECK_NE(block_type, BLOCK_ENTRIES); |
324 DCHECK_NE(block_type, BLOCK_EVICTED); | 325 DCHECK_NE(block_type, BLOCK_EVICTED); |
325 if (block_count < 1 || block_count > kMaxNumBlocks) | 326 if (block_count < 1 || block_count > kMaxNumBlocks) |
326 return false; | 327 return false; |
327 | 328 |
328 if (!init_) | 329 if (!init_) |
(...skipping 25 matching lines...) Expand all Loading... |
354 zero_buffer_ = new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4]; | 355 zero_buffer_ = new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4]; |
355 memset(zero_buffer_, 0, Addr::BlockSizeForFileType(BLOCK_4K) * 4); | 356 memset(zero_buffer_, 0, Addr::BlockSizeForFileType(BLOCK_4K) * 4); |
356 } | 357 } |
357 MappedFile* file = GetFile(address); | 358 MappedFile* file = GetFile(address); |
358 if (!file) | 359 if (!file) |
359 return; | 360 return; |
360 | 361 |
361 Trace("DeleteBlock 0x%x", address.value()); | 362 Trace("DeleteBlock 0x%x", address.value()); |
362 | 363 |
363 size_t size = address.BlockSize() * address.num_blocks(); | 364 size_t size = address.BlockSize() * address.num_blocks(); |
364 size_t offset = address.start_block() * address.BlockSize() + | 365 size_t offset = |
365 kBlockHeaderSize; | 366 address.start_block() * address.BlockSize() + kBlockHeaderSize; |
366 if (deep) | 367 if (deep) |
367 file->Write(zero_buffer_, size, offset); | 368 file->Write(zero_buffer_, size, offset); |
368 | 369 |
369 BlockHeader file_header(file); | 370 BlockHeader file_header(file); |
370 file_header.DeleteMapBlock(address.start_block(), address.num_blocks()); | 371 file_header.DeleteMapBlock(address.start_block(), address.num_blocks()); |
371 file->Flush(); | 372 file->Flush(); |
372 | 373 |
373 if (!file_header.Header()->num_entries) { | 374 if (!file_header.Header()->num_entries) { |
374 // This file is now empty. Let's try to delete it. | 375 // This file is now empty. Let's try to delete it. |
375 FileType type = Addr::RequiredFileType(file_header.Header()->entry_size); | 376 FileType type = Addr::RequiredFileType(file_header.Header()->entry_size); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 | 427 |
427 BlockHeader header(file); | 428 BlockHeader header(file); |
428 bool rv = header.UsedMapBlock(address.start_block(), address.num_blocks()); | 429 bool rv = header.UsedMapBlock(address.start_block(), address.num_blocks()); |
429 DCHECK(rv); | 430 DCHECK(rv); |
430 | 431 |
431 static bool read_contents = false; | 432 static bool read_contents = false; |
432 if (read_contents) { | 433 if (read_contents) { |
433 scoped_ptr<char[]> buffer; | 434 scoped_ptr<char[]> buffer; |
434 buffer.reset(new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4]); | 435 buffer.reset(new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4]); |
435 size_t size = address.BlockSize() * address.num_blocks(); | 436 size_t size = address.BlockSize() * address.num_blocks(); |
436 size_t offset = address.start_block() * address.BlockSize() + | 437 size_t offset = |
437 kBlockHeaderSize; | 438 address.start_block() * address.BlockSize() + kBlockHeaderSize; |
438 bool ok = file->Read(buffer.get(), size, offset); | 439 bool ok = file->Read(buffer.get(), size, offset); |
439 DCHECK(ok); | 440 DCHECK(ok); |
440 } | 441 } |
441 | 442 |
442 return rv; | 443 return rv; |
443 #endif | 444 #endif |
444 } | 445 } |
445 | 446 |
446 bool BlockFiles::CreateBlockFile(int index, FileType file_type, bool force) { | 447 bool BlockFiles::CreateBlockFile(int index, FileType file_type, bool force) { |
447 base::FilePath name = Name(index); | 448 base::FilePath name = Name(index); |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 } | 722 } |
722 | 723 |
723 base::FilePath BlockFiles::Name(int index) { | 724 base::FilePath BlockFiles::Name(int index) { |
724 // The file format allows for 256 files. | 725 // The file format allows for 256 files. |
725 DCHECK(index < 256 && index >= 0); | 726 DCHECK(index < 256 && index >= 0); |
726 std::string tmp = base::StringPrintf("%s%d", kBlockName, index); | 727 std::string tmp = base::StringPrintf("%s%d", kBlockName, index); |
727 return path_.AppendASCII(tmp); | 728 return path_.AppendASCII(tmp); |
728 } | 729 } |
729 | 730 |
730 } // namespace disk_cache | 731 } // namespace disk_cache |
OLD | NEW |