| 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 |