Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1539)

Side by Side Diff: storage/browser/blob/blob_memory_controller.h

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: switched back from file literal for windows compile Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
6 #define STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
7
8 #include <stdint.h>
9
10 #include <list>
11 #include <map>
12 #include <memory>
13 #include <string>
14 #include <unordered_map>
15 #include <unordered_set>
16 #include <utility>
17 #include <vector>
18
19 #include "base/callback.h"
20 #include "base/callback_helpers.h"
21 #include "base/containers/mru_cache.h"
22 #include "base/files/file.h"
23 #include "base/files/file_path.h"
24 #include "base/macros.h"
25 #include "base/memory/ref_counted.h"
26 #include "base/memory/weak_ptr.h"
27 #include "base/optional.h"
28 #include "base/time/time.h"
29 #include "storage/browser/storage_browser_export.h"
30 #include "storage/common/blob_storage/blob_storage_constants.h"
31
32 namespace base {
33 class TaskRunner;
34 }
35
36 namespace storage {
37 class DataElement;
38 class ShareableBlobDataItem;
39 class ShareableFileReference;
40
41 // This class's main responsibility is deciding how blob data gets stored.
42 // This encompasses:
43 // * Keeping track of memory & file quota,
44 // * How to transport the blob data from the renderer (DetermineStrategy),
45 // * Allocating memory & file quota (ReserveMemoryQuota, ReserveFileQuota)
46 // * Freeing quota (MaybeFreeQuotaForItems, ForceFreeMemoryQuotaForItem)
michaeln 2016/10/14 01:53:26 stale comments
47 // * Paging memory quota to disk when we're nearing our memory limit, and
48 // * Maintaining an LRU of memory items to choose candidates to page to disk
49 // (NotifyMemoryItemUsed, *FreeMemoryQuotaForItem*).
50 // This class can only be interacted with on the IO thread.
51 class STORAGE_EXPORT BlobMemoryController {
52 public:
53 enum class Strategy {
54 // We don't have enough memory for this blob.
55 TOO_LARGE,
56 // There isn't any memory that needs transporting.
57 NONE_NEEDED,
58 // Transportation strategies.
59 IPC,
60 SHARED_MEMORY,
61 FILE
62 };
63
64 struct FileCreationInfo {
65 FileCreationInfo();
66 ~FileCreationInfo();
67 FileCreationInfo(FileCreationInfo&& other);
68 FileCreationInfo& operator=(FileCreationInfo&&);
69
70 base::File::Error error = base::File::FILE_ERROR_FAILED;
71 base::File file;
72 scoped_refptr<base::TaskRunner> file_deletion_runner;
73 base::FilePath path;
74 scoped_refptr<ShareableFileReference> file_reference;
75 base::Time last_modified;
76 };
77
78 using MemoryAllocation = base::ScopedClosureRunner;
michaeln 2016/10/14 01:53:26 This scoped closure runner functions properly, but
dmurph 2016/10/14 23:31:48 Done.
michaeln 2016/10/18 00:56:24 thnx!
79
80 class QuotaAllocationTask {
81 public:
82 // Operation is cancelled and the callback will NOT be called. This object
83 // will be destroyed by this call.
84 virtual void Cancel() = 0;
85
86 protected:
87 virtual ~QuotaAllocationTask();
88 };
89
90 // The bool argument is true if we successfully received memory quota.
91 using MemoryQuotaRequestCallback = base::Callback<void(bool)>;
92 // The bool argument is true if we successfully received file quota, and the
93 // vector argument provides the file info.
94 using FileQuotaRequestCallback =
95 base::Callback<void(bool, std::vector<FileCreationInfo>)>;
96
97 // We enable file paging if |file_runner| isn't a nullptr.
98 BlobMemoryController(const base::FilePath& storage_directory,
99 scoped_refptr<base::TaskRunner> file_runner);
100 virtual ~BlobMemoryController();
101
102 // Disables file paging. This cancels all pending file creations and paging
103 // operations. Reason is recorded in UMA.
104 void DisableFilePaging(base::File::Error reason);
105
106 bool file_paging_enabled() const { return file_paging_enabled_; }
107
108 // Returns the strategy the transportation layer should use to transport the
109 // given memory. |preemptive_transported_bytes| are the number of transport
110 // bytes that are already populated for us, so we don't haved to request them
111 // from the renderer.
112 Strategy DetermineStrategy(size_t preemptive_transported_bytes,
113 uint64_t total_transportation_bytes) const;
114
115 // Checks to see if we can reserve quota (disk or memory) for the given size.
116 bool CanReserveQuota(uint64_t size) const;
117
118 // Reserves quota for the given |unreserved_memory_items|. The items must be
119 // bytes items in QUOTA_NEEDED state, which we change to QUOTA_REQUESTED.
120 // After we reserve memory quota we change their state to QUOTA_GRANTED and
121 // call |done_callback|. This can happen synchronously.
122 // Returns a task handle if the request is asynchronous for cancellation.
123 // NOTE: We don't inspect quota limits and assume the user checked
124 // CanReserveQuota before calling this.
125 base::WeakPtr<QuotaAllocationTask> ReserveMemoryQuota(
126 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
127 const MemoryQuotaRequestCallback& done_callback);
128
129 // Reserves quota for the given |unreserved_file_items|. The items must be
130 // temporary file items (BlobDataBuilder::IsTemporaryFileItem returns true) in
131 // QUOTA_NEEDED state, which we change to QUOTA_REQUESTED. After we reserve
132 // file quota we change their state to QUOTA_GRANTED and call
133 // |done_callback|.
134 // Returns a task handle for cancellation.
135 // NOTE: We don't inspect quota limits and assume the user checked
136 // CanReserveQuota before calling this.
137 base::WeakPtr<QuotaAllocationTask> ReserveFileQuota(
138 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_file_items,
139 const FileQuotaRequestCallback& done_callback);
140
141 // Called when initially populated or upon later access.
142 void NotifyMemoryItemUsed(ShareableBlobDataItem* item);
143
144 size_t memory_usage() const { return blob_memory_used_; }
145 uint64_t disk_usage() const { return disk_used_; }
146
147 const BlobStorageLimits& limits() const { return limits_; }
148 void set_limits_for_testing(const BlobStorageLimits& limits) {
149 limits_ = limits;
150 }
151
152 private:
153 template <typename T>
154 class BaseQuotaAllocationTask;
155 class FileQuotaAllocationTask;
156 class MemoryQuotaAllocationTask;
157
158 using PendingMemoryQuotaTaskList =
159 std::list<std::unique_ptr<MemoryQuotaAllocationTask>>;
160 using PendingFileQuotaTaskList =
161 std::list<std::unique_ptr<FileQuotaAllocationTask>>;
162
163 base::WeakPtr<QuotaAllocationTask> AppendMemoryTask(
164 uint64_t total_bytes_needed,
165 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
166 const MemoryQuotaRequestCallback& done_callback);
167
168 void MaybeGrantPendingMemoryRequests();
169
170 size_t CollectItemsForEviction(
171 std::vector<scoped_refptr<ShareableBlobDataItem>>* output);
172
173 // Schedule paging until our memory usage is below our memory limit.
174 void MaybeScheduleEvictionUntilSystemHealthy();
175
176 // Called when we've completed evicting a list of items to disk. This is where
177 // we swap the bytes items for file items, and and update our bookkeeping.
178 void OnEvictionComplete(
179 scoped_refptr<ShareableFileReference> file_reference,
180 std::vector<scoped_refptr<ShareableBlobDataItem>> items,
181 size_t total_items_size,
182 FileCreationInfo result);
183
184 size_t GetAvailableMemoryForBlobs() const;
185 uint64_t GetAvailableFileSpaceForBlobs() const;
186
187 void DecrementMemoryQuotaAndRemoveFromRecents(uint64_t item_id,
michaeln 2016/10/14 01:53:26 i'd vote to call these two methods something more
dmurph 2016/10/14 23:31:48 Done.
188 uint64_t size);
189
190 void SetGrantedAndMemoryAllocation(
191 std::vector<scoped_refptr<ShareableBlobDataItem>>* items);
192
193 // This is registered as a callback for file deletions on the file reference
194 // of our paging files. We decrement the disk space used.
195 void OnBlobFileDelete(uint64_t size, const base::FilePath& path);
196
197 base::FilePath GenerateNextPageFileName();
198
199 // This records diagnostic counters of our memory quotas. Called when usage
200 // changes.
201 void RecordTracingCounters() const;
202
203 BlobStorageLimits limits_;
204
205 // Memory bookkeeping. These numbers are all disjoint.
206 // This is the amount of memory we're using for blobs in RAM, including the
207 // in_flight_memory_used_.
208 size_t blob_memory_used_ = 0;
209 // This is memory we're temporarily using while we try to write blob items to
210 // disk.
211 size_t in_flight_memory_used_ = 0;
212 // This is the amount of memory we're using on disk.
213 uint64_t disk_used_ = 0;
214
215 // State for GenerateNextPageFileName.
216 uint64_t current_file_num_ = 0;
217
218 size_t pending_memory_quota_total_size_ = 0;
219 PendingMemoryQuotaTaskList pending_memory_quota_tasks_;
220 PendingFileQuotaTaskList pending_file_quota_tasks_;
221
222 size_t pending_evictions_ = 0;
223
224 bool file_paging_enabled_ = false;
225 base::FilePath blob_storage_dir_;
226 scoped_refptr<base::TaskRunner> file_runner_;
227
228 // Lifetime of the ShareableBlobDataItem objects is handled externally in the
229 // BlobStorageContext class.
230 base::MRUCache<uint64_t, ShareableBlobDataItem*> populated_memory_items_;
231 size_t populated_memory_items_bytes_ = 0;
232 // We need to keep track of items currently being paged to disk so that if
233 // another blob successfully grabs a ref, we can prevent it from adding the
234 // item to the recent_item_cache_ above.
235 std::unordered_set<uint64_t> items_paging_to_file_;
236
237 // We clear this when disabling paging to disable pending file tasks.
238 base::WeakPtrFactory<BlobMemoryController> file_task_factory_;
239 // Used for bookkeeping tasks, where we decrement our memory or disk usage.
240 base::WeakPtrFactory<BlobMemoryController> quota_bookkeeping_factory_;
241
242 DISALLOW_COPY_AND_ASSIGN(BlobMemoryController);
243 };
244 } // namespace storage
245 #endif // STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698