Chromium Code Reviews| Index: net/disk_cache/backend_impl.cc |
| diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc |
| index 232b3f8b295ee2ad0580b47deb9bbbcf9898bda5..8ce6095ecb001e9a074e384a9c2cbb24370067aa 100644 |
| --- a/net/disk_cache/backend_impl.cc |
| +++ b/net/disk_cache/backend_impl.cc |
| @@ -39,6 +39,8 @@ using base::TimeTicks; |
| namespace { |
| +using disk_cache::Bitmap; |
| + |
| const char* kIndexName = "index"; |
| const int kMaxOldFolders = 100; |
| @@ -251,6 +253,30 @@ void FinalCleanupCallback(disk_cache::BackendImpl* backend) { |
| backend->CleanupCache(); |
| } |
| +bool IsPowerOfTwo(size_t number) { |
| + return !(number & (number - 1)); |
| +} |
| + |
| +bool IndexBitmapLookup(const Bitmap& bitmap, |
| + const std::string& key) { |
| + DCHECK_NE(0, bitmap.Size()) << "Call site should provide default behaviour"; |
|
rvargas (doing something else)
2013/02/12 01:58:33
nit: Can we just have the comment in the code (red
|
| + DCHECK(IsPowerOfTwo(bitmap.Size())); |
| + const uint32 mask = bitmap.Size() - 1; |
| + const uint32 hash = base::Hash(key); |
| + return bitmap.Get(hash & mask); |
| +} |
| + |
| +void IndexBitmapSetValue(Bitmap* bitmap, |
| + const std::string& key, |
| + bool value) { |
| + if (bitmap->Size() == 0) |
| + return; |
| + DCHECK(IsPowerOfTwo(bitmap->Size())); |
| + const uint32 mask = bitmap->Size() - 1; |
| + const uint32 hash = base::Hash(key); |
| + bitmap->Set(hash & mask, value); |
| +} |
| + |
| } // namespace |
| // ------------------------------------------------------------------------ |
| @@ -453,6 +479,20 @@ int BackendImpl::SyncInit() { |
| return net::ERR_FAILED; |
| } |
| + // TODO(gavinp): Consider clearing the |index_bitmap_| if the cache is being |
| + // |restarted_|. It's not strictly required, because any bits set in |
| + // |index_bitmap_| should not cause incorrect behaviour. |
| + if (!restarted_) { |
|
rvargas (doing something else)
2013/02/12 01:58:33
Maybe we should move this to InitBitmap()
|
| + // Although |index_bitmap_| is referenced on the IO thread, it is safe to |
| + // initialize on the cache thread when !restarted_, because the IO thread |
| + // waits on Init() completion before using the cache and also because the |
| + // callback PostTask includes a memory commit. |
| + DCHECK(IsPowerOfTwo(mask_ + 1)); |
| + index_bitmap_.Resize(mask_ + 1, false); |
| + for (size_t i = 0; i <= mask_; ++i) |
|
rvargas (doing something else)
2013/02/12 01:58:33
nit: int
|
| + index_bitmap_.Set(i, data_->table[i] != 0); |
| + } |
| + |
| if (!restarted_ && (create_files || !data_->header.num_entries)) |
| ReportError(ERR_CACHE_CREATED); |
| @@ -1281,6 +1321,10 @@ void BackendImpl::SetFlags(uint32 flags) { |
| user_flags_ |= flags; |
| } |
| +void BackendImpl::ClearIndexBitmapForTest() { |
| + index_bitmap_.Clear(); |
| +} |
| + |
| void BackendImpl::ClearRefCountForTest() { |
| num_refs_ = 0; |
| } |
| @@ -1359,6 +1403,10 @@ int32 BackendImpl::GetEntryCount() const { |
| int BackendImpl::OpenEntry(const std::string& key, Entry** entry, |
| const CompletionCallback& callback) { |
| DCHECK(!callback.is_null()); |
| + if (index_bitmap_.Size() != 0 && !IndexBitmapLookup(index_bitmap_, key)) { |
|
rvargas (doing something else)
2013/02/12 01:58:33
when would Size be 0?
|
| + VLOG(4) << "BackendImpl::OpenEntry missed on bitmap"; |
|
rvargas (doing something else)
2013/02/12 01:58:33
remove tracing before checking in.
|
| + return net::ERR_FAILED; |
| + } |
| background_queue_.OpenEntry(key, entry, callback); |
| return net::ERR_IO_PENDING; |
| } |
| @@ -1366,6 +1414,8 @@ int BackendImpl::OpenEntry(const std::string& key, Entry** entry, |
| int BackendImpl::CreateEntry(const std::string& key, Entry** entry, |
| const CompletionCallback& callback) { |
| DCHECK(!callback.is_null()); |
| + // TODO(gavinp): Only set index_bitmap_ when CreateEntry succeeds. |
| + IndexBitmapSetValue(&index_bitmap_, key, true); |
| background_queue_.CreateEntry(key, entry, callback); |
| return net::ERR_IO_PENDING; |
| } |
| @@ -1373,6 +1423,7 @@ int BackendImpl::CreateEntry(const std::string& key, Entry** entry, |
| int BackendImpl::DoomEntry(const std::string& key, |
| const CompletionCallback& callback) { |
| DCHECK(!callback.is_null()); |
| + // TODO(gavinp): Clear the index_bitmap_ when appropriate after Doom. |
| background_queue_.DoomEntry(key, callback); |
| return net::ERR_IO_PENDING; |
| } |