diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 22:42:52 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 22:42:52 +0000 |
commit | 586acc5fe142f498261f52c66862fa417c3d52d2 (patch) | |
tree | c98b3417a883f2477029c8cd5888f4078681e24e /net/disk_cache/mem_backend_impl.cc | |
parent | a814a8d55429605fe6d7045045cd25b6bf624580 (diff) | |
download | chromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.zip chromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.tar.gz chromium_src-586acc5fe142f498261f52c66862fa417c3d52d2.tar.bz2 |
Add net to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache/mem_backend_impl.cc')
-rw-r--r-- | net/disk_cache/mem_backend_impl.cc | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/net/disk_cache/mem_backend_impl.cc b/net/disk_cache/mem_backend_impl.cc new file mode 100644 index 0000000..10aadb8 --- /dev/null +++ b/net/disk_cache/mem_backend_impl.cc @@ -0,0 +1,276 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "net/disk_cache/mem_backend_impl.h" + +#include "net/disk_cache/mem_entry_impl.h" + +namespace { + +const int kDefaultCacheSize = 10 * 1024 * 1024; +const int kCleanUpMargin = 1024 * 1024; + +int LowWaterAdjust(int high_water) { + if (high_water < kCleanUpMargin) + return 0; + + return high_water - kCleanUpMargin; +} + +} // namespace + +namespace disk_cache { + +Backend* CreateInMemoryCacheBackend(int max_bytes) { + MemBackendImpl* cache = new MemBackendImpl(); + cache->SetMaxSize(max_bytes); + if (cache->Init()) + return cache; + + delete cache; + LOG(ERROR) << "Unable to create cache"; + return NULL; +} + +// ------------------------------------------------------------------------ + +bool MemBackendImpl::Init() { + if (max_size_) + return true; + + MEMORYSTATUSEX memory_info; + memory_info.dwLength = sizeof(memory_info); + if (!GlobalMemoryStatusEx(&memory_info)) { + max_size_ = kDefaultCacheSize; + return true; + } + + // We want to use up to 2% of the computer's memory, with a limit of 50 MB, + // reached on systemd with more than 2.5 GB of RAM. + memory_info.ullTotalPhys = memory_info.ullTotalPhys * 2 / 100; + if (memory_info.ullTotalPhys > + static_cast<unsigned int>(kDefaultCacheSize * 5)) + max_size_ = kDefaultCacheSize * 5; + else + max_size_ = static_cast<int>(memory_info.ullTotalPhys); + + return true; +} + +MemBackendImpl::~MemBackendImpl() { + EntryMap::iterator it = entries_.begin(); + while (it != entries_.end()) { + it->second->Doom(); + it = entries_.begin(); + } + DCHECK(!current_size_); +} + +bool MemBackendImpl::SetMaxSize(int max_bytes) { + COMPILE_ASSERT(sizeof(max_bytes) == sizeof(max_size_), unsupported_int_model); + if (max_bytes < 0) + return false; + + // Zero size means use the default. + if (!max_bytes) + return true; + + max_size_ = max_bytes; + return true; +} + +int32 MemBackendImpl::GetEntryCount() const { + return static_cast<int32>(entries_.size()); +} + +bool MemBackendImpl::OpenEntry(const std::string& key, Entry** entry) { + EntryMap::iterator it = entries_.find(key); + if (it == entries_.end()) + return false; + + it->second->Open(); + + *entry = it->second; + return true; +} + +bool MemBackendImpl::CreateEntry(const std::string& key, Entry** entry) { + EntryMap::iterator it = entries_.find(key); + if (it != entries_.end()) + return false; + + MemEntryImpl* cache_entry = new MemEntryImpl(this); + if (!cache_entry->CreateEntry(key)) { + delete entry; + return false; + } + + rankings_.Insert(cache_entry); + entries_[key] = cache_entry; + + *entry = cache_entry; + return true; +} + +bool MemBackendImpl::DoomEntry(const std::string& key) { + Entry* entry; + if (!OpenEntry(key, &entry)) + return false; + + entry->Doom(); + entry->Close(); + return true; +} + +void MemBackendImpl::InternalDoomEntry(MemEntryImpl* entry) { + rankings_.Remove(entry); + EntryMap::iterator it = entries_.find(entry->GetKey()); + if (it != entries_.end()) + entries_.erase(it); + else + NOTREACHED(); + + entry->InternalDoom(); +} + +bool MemBackendImpl::DoomAllEntries() { + TrimCache(true); + return true; +} + +bool MemBackendImpl::DoomEntriesBetween(const Time initial_time, + const Time end_time) { + if (end_time.is_null()) + return DoomEntriesSince(initial_time); + + DCHECK(end_time >= initial_time); + + MemEntryImpl* next = rankings_.GetNext(NULL); + + // rankings_ is ordered by last used, this will descend through the cache + // and start dooming items before the end_time, and will stop once it reaches + // an item used before the initial time. + while (next) { + MemEntryImpl* node = next; + next = rankings_.GetNext(next); + + if (node->GetLastUsed() < initial_time) + break; + + if (node->GetLastUsed() < end_time) { + node->Doom(); + } + } + + return true; +} + +// We use OpenNextEntry to retrieve elements from the cache, until we get +// entries that are too old. +bool MemBackendImpl::DoomEntriesSince(const Time initial_time) { + for (;;) { + Entry* entry; + void* iter = NULL; + if (!OpenNextEntry(&iter, &entry)) + return true; + + if (initial_time > entry->GetLastUsed()) { + entry->Close(); + EndEnumeration(&iter); + return true; + } + + entry->Doom(); + entry->Close(); + EndEnumeration(&iter); // Dooming the entry invalidates the iterator. + } +} + +bool MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry) { + MemEntryImpl* current = reinterpret_cast<MemEntryImpl*>(*iter); + MemEntryImpl* node = rankings_.GetNext(current); + *next_entry = node; + *iter = node; + + if (node) + node->Open(); + + return NULL != node; +} + +void MemBackendImpl::EndEnumeration(void** iter) { + *iter = NULL; +} + +void MemBackendImpl::TrimCache(bool empty) { + MemEntryImpl* next = rankings_.GetPrev(NULL); + + DCHECK(next); + + int target_size = empty ? 0 : LowWaterAdjust(max_size_); + while (current_size_ > target_size && next) { + MemEntryImpl* node = next; + next = rankings_.GetPrev(next); + if (!node->InUse() || empty) { + node->Doom(); + } + } + + return; +} + +void MemBackendImpl::AddStorageSize(int32 bytes) { + current_size_ += bytes; + DCHECK(current_size_ >= 0); + + if (current_size_ > max_size_) + TrimCache(false); +} + +void MemBackendImpl::SubstractStorageSize(int32 bytes) { + current_size_ -= bytes; + DCHECK(current_size_ >= 0); +} + +void MemBackendImpl::ModifyStorageSize(int32 old_size, int32 new_size) { + if (old_size >= new_size) + SubstractStorageSize(old_size - new_size); + else + AddStorageSize(new_size - old_size); +} + +void MemBackendImpl::UpdateRank(MemEntryImpl* node) { + rankings_.UpdateRank(node); +} + +int MemBackendImpl::MaxFileSize() const { + return max_size_ / 8; +} + +} // namespace disk_cache |