summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/block_files.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/disk_cache/block_files.cc')
-rw-r--r--net/disk_cache/block_files.cc89
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);
}