diff options
Diffstat (limited to 'net/disk_cache/block_files.cc')
-rw-r--r-- | net/disk_cache/block_files.cc | 89 |
1 files changed, 82 insertions, 7 deletions
diff --git a/net/disk_cache/block_files.cc b/net/disk_cache/block_files.cc index 48e5be3..a0fc6b6 100644 --- a/net/disk_cache/block_files.cc +++ b/net/disk_cache/block_files.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,9 +7,12 @@ #include "base/file_util.h" #include "base/histogram.h" #include "base/string_util.h" +#include "base/stringprintf.h" +#include "base/thread_checker.h" #include "base/time.h" #include "net/disk_cache/cache_util.h" #include "net/disk_cache/file_lock.h" +#include "net/disk_cache/trace.h" using base::TimeTicks; @@ -57,6 +60,7 @@ bool CreateMapBlock(int target, int size, disk_cache::BlockFileHeader* header, disk_cache::FileLock lock(header); int index_offset = j * 4 + 4 - target; *index = current * 32 + index_offset; + DCHECK_EQ(*index / 4, (*index + size - 1) / 4); uint32 to_add = ((1 << size) - 1) << index_offset; header->allocation_map[current] |= to_add; @@ -118,6 +122,25 @@ void DeleteMapBlock(int index, int size, disk_cache::BlockFileHeader* header) { HISTOGRAM_TIMES("DiskCache.DeleteBlock", TimeTicks::Now() - start); } +// Returns true if the specified block is used. Note that this is a simplified +// version of DeleteMapBlock(). +bool UsedMapBlock(int index, int size, disk_cache::BlockFileHeader* header) { + if (size < 0 || size > disk_cache::kMaxNumBlocks) { + NOTREACHED(); + return false; + } + int byte_index = index / 8; + uint8* byte_map = reinterpret_cast<uint8*>(header->allocation_map); + uint8 map_block = byte_map[byte_index]; + + if (index % 8 >= 4) + map_block >>= 4; + + DCHECK((((1 << size) - 1) << (index % 8)) < 0x100); + uint8 to_clear = ((1 << size) - 1) << (index % 8); + return ((byte_map[byte_index] & to_clear) == to_clear); +} + // Restores the "empty counters" and allocation hints. void FixAllocationCounters(disk_cache::BlockFileHeader* header) { for (int i = 0; i < disk_cache::kMaxNumBlocks; i++) { @@ -161,6 +184,10 @@ bool NeedToGrowBlockFile(const disk_cache::BlockFileHeader* header, namespace disk_cache { +BlockFiles::BlockFiles(const FilePath& path) + : init_(false), zero_buffer_(NULL), path_(path) { +} + BlockFiles::~BlockFiles() { if (zero_buffer_) delete[] zero_buffer_; @@ -172,6 +199,8 @@ bool BlockFiles::Init(bool create_files) { if (init_) return false; + thread_checker_.reset(new ThreadChecker); + block_files_.resize(kFirstAdditionalBlockFile); for (int i = 0; i < kFirstAdditionalBlockFile; i++) { if (create_files) @@ -190,6 +219,9 @@ bool BlockFiles::Init(bool create_files) { } void BlockFiles::CloseFiles() { + if (init_) { + DCHECK(thread_checker_->CalledOnValidThread()); + } init_ = false; for (unsigned int i = 0; i < block_files_.size(); i++) { if (block_files_[i]) { @@ -201,6 +233,7 @@ void BlockFiles::CloseFiles() { } void BlockFiles::ReportStats() { + DCHECK(thread_checker_->CalledOnValidThread()); int used_blocks[kFirstAdditionalBlockFile]; int load[kFirstAdditionalBlockFile]; for (int i = 0; i < kFirstAdditionalBlockFile; i++) { @@ -217,6 +250,36 @@ void BlockFiles::ReportStats() { UMA_HISTOGRAM_ENUMERATION("DiskCache.BlockLoad_3", load[3], 101); } +bool BlockFiles::IsValid(Addr address) { +#ifdef NDEBUG + return true; +#else + if (!address.is_initialized() || address.is_separate_file()) + return false; + + MappedFile* file = GetFile(address); + if (!file) + return false; + + BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer()); + bool rv = UsedMapBlock(address.start_block(), address.num_blocks(), header); + DCHECK(rv); + + static bool read_contents = false; + if (read_contents) { + scoped_array<char> buffer; + buffer.reset(new char[Addr::BlockSizeForFileType(BLOCK_4K) * 4]); + size_t size = address.BlockSize() * address.num_blocks(); + size_t offset = address.start_block() * address.BlockSize() + + kBlockHeaderSize; + bool ok = file->Read(buffer.get(), size, offset); + DCHECK(ok); + } + + return rv; +#endif +} + bool BlockFiles::CreateBlockFile(int index, FileType file_type, bool force) { FilePath name = Name(index); int flags = @@ -224,7 +287,7 @@ bool BlockFiles::CreateBlockFile(int index, FileType file_type, bool force) { flags |= base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE; scoped_refptr<File> file(new File( - base::CreatePlatformFile(name, flags, NULL))); + base::CreatePlatformFile(name, flags, NULL, NULL))); if (!file->IsValid()) return false; @@ -282,6 +345,7 @@ bool BlockFiles::OpenBlockFile(int index) { } MappedFile* BlockFiles::GetFile(Addr address) { + DCHECK(thread_checker_->CalledOnValidThread()); DCHECK(block_files_.size() >= 4); DCHECK(address.is_block_file() || !address.is_initialized()); if (!address.is_initialized()) @@ -402,10 +466,15 @@ void BlockFiles::RemoveEmptyFile(FileType block_type) { int file_index = header->next_file; header->next_file = next_header->next_file; DCHECK(block_files_.size() >= static_cast<unsigned int>(file_index)); + + // We get a new handle to the file and release the old one so that the + // file gets unmmaped... so we can delete it. + FilePath name = Name(file_index); + scoped_refptr<File> this_file(new File(false)); + this_file->Init(name); block_files_[file_index]->Release(); block_files_[file_index] = NULL; - FilePath name = Name(file_index); int failure = DeleteCacheFile(name) ? 0 : 1; UMA_HISTOGRAM_COUNTS("DiskCache.DeleteFailed2", failure); if (failure) @@ -420,6 +489,7 @@ void BlockFiles::RemoveEmptyFile(FileType block_type) { bool BlockFiles::CreateBlock(FileType block_type, int block_count, Addr* block_address) { + DCHECK(thread_checker_->CalledOnValidThread()); if (block_type < RANKINGS || block_type > BLOCK_4K || block_count < 1 || block_count > 4) return false; @@ -447,10 +517,12 @@ bool BlockFiles::CreateBlock(FileType block_type, int block_count, Addr address(block_type, block_count, header->this_file, index); block_address->set_value(address.value()); + Trace("CreateBlock 0x%x", address.value()); return true; } void BlockFiles::DeleteBlock(Addr address, bool deep) { + DCHECK(thread_checker_->CalledOnValidThread()); if (!address.is_initialized() || address.is_separate_file()) return; @@ -462,14 +534,17 @@ void BlockFiles::DeleteBlock(Addr address, bool deep) { if (!file) return; + Trace("DeleteBlock 0x%x", address.value()); + + BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer()); + DeleteMapBlock(address.start_block(), address.num_blocks(), header); + size_t size = address.BlockSize() * address.num_blocks(); size_t offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; if (deep) file->Write(zero_buffer_, size, offset); - BlockFileHeader* header = reinterpret_cast<BlockFileHeader*>(file->buffer()); - DeleteMapBlock(address.start_block(), address.num_blocks(), header); if (!header->num_entries) { // This file is now empty. Let's try to delete it. FileType type = Addr::RequiredFileType(header->entry_size); @@ -503,7 +578,7 @@ bool BlockFiles::FixBlockFileHeader(MappedFile* file) { return true; } -// We are interested in the total number of block used by this file type, and +// We are interested in the total number of blocks used by this file type, and // the max number of blocks that we can store (reported as the percentage of // used blocks). In order to find out the number of used blocks, we have to // substract the empty blocks from the total blocks for each file in the chain. @@ -537,7 +612,7 @@ void BlockFiles::GetFileStats(int index, int* used_count, int* load) { FilePath BlockFiles::Name(int index) { // The file format allows for 256 files. DCHECK(index < 256 || index >= 0); - std::string tmp = StringPrintf("%s%d", kBlockName, index); + std::string tmp = base::StringPrintf("%s%d", kBlockName, index); return path_.AppendASCII(tmp); } |