| // Copyright (c) 2012 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. | |
| #ifndef NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ | |
| #define NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ | |
| #include <map> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "base/containers/linked_list.h" | |
| #include "base/gtest_prod_util.h" | |
| #include "base/macros.h" | |
| #include "base/memory/weak_ptr.h" | |
| #include "base/time/time.h" | |
| #include "base/trace_event/memory_usage_estimator.h" | |
| #include "net/base/interval.h" | |
| #include "net/base/net_export.h" | |
| #include "net/disk_cache/disk_cache.h" | |
| #include "net/log/net_log_with_source.h" | |
| #include "starboard/types.h" | |
| namespace net { | |
| class NetLog; | |
| } | |
| namespace disk_cache { | |
| class MemBackendImpl; | |
| // This class implements the Entry interface for the memory-only cache. An | |
| // object of this class represents a single entry on the cache. We use two types | |
| // of entries, parent and child to support sparse caching. | |
| // | |
| // A parent entry is non-sparse until a sparse method is invoked (i.e. | |
| // ReadSparseData, WriteSparseData, GetAvailableRange) when sparse information | |
| // is initialized. It then manages a list of child entries and delegates the | |
| // sparse API calls to the child entries. It creates and deletes child entries | |
| // and updates the list when needed. | |
| // | |
| // A child entry is used to carry partial cache content, non-sparse methods like | |
| // ReadData and WriteData cannot be applied to them. The lifetime of a child | |
| // entry is managed by the parent entry that created it except that the entry | |
| // can be evicted independently. A child entry does not have a key and it is not | |
| // registered in the backend's entry map. | |
| // | |
| // A sparse child entry has a fixed maximum size and can be partially | |
| // filled. There can only be one continous filled region in a sparse entry, as | |
| // illustrated by the following example: | |
| // | xxx ooooo | | |
| // x = unfilled region | |
| // o = filled region | |
| // It is guaranteed that there is at most one unfilled region and one filled | |
| // region, and the unfilled region (if there is one) is always before the filled | |
| // region. The book keeping for filled region in a sparse entry is done by using | |
| // the variable |child_first_pos_|. | |
| class NET_EXPORT_PRIVATE MemEntryImpl final | |
| : public Entry, | |
| public base::LinkNode<MemEntryImpl> { | |
| public: | |
| enum EntryType { | |
| PARENT_ENTRY, | |
| CHILD_ENTRY, | |
| }; | |
| // Provided to better document calls to |UpdateStateOnUse()|. | |
| enum EntryModified { | |
| ENTRY_WAS_NOT_MODIFIED, | |
| ENTRY_WAS_MODIFIED, | |
| }; | |
| // Constructor for parent entries. | |
| MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, | |
| const std::string& key, | |
| net::NetLog* net_log); | |
| // Constructor for child entries. | |
| MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, | |
| int child_id, | |
| MemEntryImpl* parent, | |
| net::NetLog* net_log); | |
| void Open(); | |
| bool InUse() const; | |
| EntryType type() const { return parent_ ? CHILD_ENTRY : PARENT_ENTRY; } | |
| const std::string& key() const { return key_; } | |
| const MemEntryImpl* parent() const { return parent_; } | |
| int child_id() const { return child_id_; } | |
| base::Time last_used() const { return last_used_; } | |
| // The in-memory size of this entry to use for the purposes of eviction. | |
| int GetStorageSize() const; | |
| // Update an entry's position in the backend LRU list and set |last_used_|. If | |
| // the entry was modified, also update |last_modified_|. | |
| void UpdateStateOnUse(EntryModified modified_enum); | |
| // From disk_cache::Entry: | |
| void Doom() override; | |
| void Close() override; | |
| std::string GetKey() const override; | |
| base::Time GetLastUsed() const override; | |
| base::Time GetLastModified() const override; | |
| int32_t GetDataSize(int index) const override; | |
| int ReadData(int index, | |
| int offset, | |
| IOBuffer* buf, | |
| int buf_len, | |
| CompletionOnceCallback callback) override; | |
| int WriteData(int index, | |
| int offset, | |
| IOBuffer* buf, | |
| int buf_len, | |
| CompletionOnceCallback callback, | |
| bool truncate) override; | |
| int ReadSparseData(int64_t offset, | |
| IOBuffer* buf, | |
| int buf_len, | |
| CompletionOnceCallback callback) override; | |
| int WriteSparseData(int64_t offset, | |
| IOBuffer* buf, | |
| int buf_len, | |
| CompletionOnceCallback callback) override; | |
| int GetAvailableRange(int64_t offset, | |
| int len, | |
| int64_t* start, | |
| CompletionOnceCallback callback) override; | |
| bool CouldBeSparse() const override; | |
| void CancelSparseIO() override {} | |
| net::Error ReadyForSparseIO(CompletionOnceCallback callback) override; | |
| void SetLastUsedTimeForTest(base::Time time) override; | |
| size_t EstimateMemoryUsage() const; | |
| private: | |
| MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, | |
| const std::string& key, | |
| int child_id, | |
| MemEntryImpl* parent, | |
| net::NetLog* net_log); | |
| using EntryMap = std::map<int, MemEntryImpl*>; | |
| static const int kNumStreams = 3; | |
| ~MemEntryImpl() override; | |
| // Do all the work for corresponding public functions. Implemented as | |
| // separate functions to make logging of results simpler. | |
| int InternalReadData(int index, int offset, IOBuffer* buf, int buf_len); | |
| int InternalWriteData(int index, int offset, IOBuffer* buf, int buf_len, | |
| bool truncate); | |
| int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len); | |
| int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len); | |
| int InternalGetAvailableRange(int64_t offset, int len, int64_t* start); | |
| // Initializes the children map and sparse info. This method is only called | |
| // on a parent entry. | |
| bool InitSparseInfo(); | |
| // Returns an entry responsible for |offset|. The returned entry can be a | |
| // child entry or this entry itself if |offset| points to the first range. | |
| // If such entry does not exist and |create| is true, a new child entry is | |
| // created. | |
| MemEntryImpl* GetChild(int64_t offset, bool create); | |
| // Returns an interval describing what's stored in the child entry pointed to | |
| // by i, in global coordinates. | |
| // Precondition: i != children_.end(); | |
| net::Interval<int64_t> ChildInterval( | |
| MemEntryImpl::EntryMap::const_iterator i); | |
| // Compact vectors to try to avoid over-allocation due to exponential growth. | |
| void Compact(); | |
| std::string key_; | |
| std::vector<char> data_[kNumStreams]; // User data. | |
| int ref_count_; | |
| int child_id_; // The ID of a child entry. | |
| int child_first_pos_; // The position of the first byte in a child | |
| // entry. | |
| // Pointer to the parent entry, or nullptr if this entry is a parent entry. | |
| MemEntryImpl* parent_; | |
| std::unique_ptr<EntryMap> children_; | |
| base::Time last_modified_; | |
| base::Time last_used_; | |
| base::WeakPtr<MemBackendImpl> backend_; // Back pointer to the cache. | |
| bool doomed_; // True if this entry was removed from the cache. | |
| net::NetLogWithSource net_log_; | |
| DISALLOW_COPY_AND_ASSIGN(MemEntryImpl); | |
| }; | |
| } // namespace disk_cache | |
| #endif // NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ |