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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: comments, more tests are next 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/containers/mru_cache.h"
21 #include "base/files/file.h"
22 #include "base/files/file_path.h"
23 #include "base/macros.h"
24 #include "base/memory/ref_counted.h"
25 #include "base/memory/weak_ptr.h"
26 #include "base/optional.h"
27 #include "base/time/time.h"
28 #include "storage/browser/storage_browser_export.h"
29 #include "storage/common/blob_storage/blob_storage_constants.h"
30
31 namespace base {
32 class TaskRunner;
33 }
34
35 namespace storage {
36 class DataElement;
37 class ShareableBlobDataItem;
38 class ShareableFileReference;
39
40 // This class's main responsability is deciding how blob data gets stored.
41 // This encompasses:
42 // * Keeping track of memory & file quota,
43 // * How to transport the blob data from the renderer (DetermineStrategy),
44 // * Allocating memory & file quota (ReserveMemoryQuota, ReserveFileQuota)
45 // * Freeing quota (MaybeFreeQuotaForItems)
46 // * Paging memory quota to disk when we're nearing our memory limit, and
47 // * Maintaining an LRU of memory items to choose candidates to page to disk
48 // (UpdateBlobItemInRecents, RemoveBlobItemInRecents).
michaeln 2016/10/04 00:11:55 the methods names in the comment are stale now
dmurph 2016/10/06 00:45:39 Done.
49 // This class can only be interacted with on the IO thread.
50 class STORAGE_EXPORT BlobMemoryController {
51 public:
52 enum class Strategy {
53 // We don't have enough memory for this blob.
54 TOO_LARGE,
55 // There isn't any memory that needs transporting.
56 NONE_NEEDED,
57 // Transportation strategies.
58 IPC,
59 SHARED_MEMORY,
60 FILE
61 };
62
63 struct FileCreationInfo {
64 FileCreationInfo();
65 ~FileCreationInfo();
66 FileCreationInfo(FileCreationInfo&& other);
67 FileCreationInfo& operator=(FileCreationInfo&&);
68
69 base::File::Error error = base::File::FILE_ERROR_FAILED;
70 base::File file;
71 base::FilePath path;
72 scoped_refptr<ShareableFileReference> file_reference;
73 base::Time last_modified;
74 };
75
76 // The bool argument is true if we successfully received memory quota.
77 using MemoryQuotaRequestCallback = base::Callback<void(bool)>;
78 // The bool argument is true if we successfully received file quota, and the
79 // vector argument provides the file info.
80 using FileQuotaRequestCallback =
81 base::Callback<void(bool, std::vector<FileCreationInfo>)>;
82
83 // IO thread only.
michaeln 2016/10/04 00:11:55 since the outerclass says io only, maybe this comm
dmurph 2016/10/06 00:45:39 Done.
84 class QuotaAllocationTask {
michaeln 2016/10/04 00:11:55 style nit: declaration order, i think the struct a
dmurph 2016/10/06 00:45:39 Done.
85 public:
86 // Operation is cancelled and the callback will NOT be called. This object
87 // will be destroyed by this call.
88 virtual void Cancel() = 0;
89
90 protected:
91 virtual ~QuotaAllocationTask();
92 };
93
94 // We enable file paging if |file_runner| isn't a nullptr.
95 BlobMemoryController(const base::FilePath& storage_directory,
96 scoped_refptr<base::TaskRunner> file_runner);
97 virtual ~BlobMemoryController();
98
99 // Disables the disk. This cancels all pending file creations and paging
100 // operations.
101 void DisableFilePaging();
102
103 bool file_paging_enabled() const { return file_paging_enabled_; }
104
105 // Returns the strategy the transportation layer should use to transport the
106 // given memory. |preemptive_transported_bytes| are the number of transport
107 // bytes that are already populated for us, so we don't haved to request them
108 // from the renderer.
109 Strategy DetermineStrategy(size_t preemptive_transported_bytes,
110 uint64_t total_transportation_bytes) const;
111
112 // Checks to see if we can reserve quota (disk or memory) for the given size.
113 bool CanReserveQuota(uint64_t size) const;
114
115 // Reserves quota for the given |unreserved_memory_items|. The items must be
116 // bytes items in QUOTA_NEEDED state, which we change to QUOTA_REQUESTED.
117 // After we reserve memory quota we change their state to QUOTA_GRANTED and
118 // call |done_callback|. This can happen synchronously.
119 // Returns a task handle if the request is asynchronous for cancellation.
120 // NOTE: We don't inspect quota limits and assume the user checked
121 // CanReserveQuota before calling this.
122 base::WeakPtr<QuotaAllocationTask> ReserveMemoryQuota(
123 std::vector<ShareableBlobDataItem*> unreserved_memory_items,
michaeln 2016/10/04 00:11:55 would it work to make the vector a const ref? its
dmurph 2016/10/06 00:45:39 So the file quota one always needs to grab a copy
124 const MemoryQuotaRequestCallback& done_callback);
125
126 // Reserves quota for the given |unreserved_file_items|. The items must be
127 // temporary file items (BlobDataBuilder::IsTemporaryFileItem returns true) in
128 // QUOTA_NEEDED state, which we change to QUOTA_REQUESTED. After we reserve
129 // file quota we change their state to QUOTA_GRANTED and call
130 // |done_callback|.
131 // Returns a task handle for cancellation.
132 // NOTE: We don't inspect quota limits and assume the user checked
133 // CanReserveQuota before calling this.
134 base::WeakPtr<QuotaAllocationTask> ReserveFileQuota(
135 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_file_items,
michaeln 2016/10/04 00:11:55 i'd suggest a const ref vector<> here too for symm
dmurph 2016/10/06 00:45:39 So we want to save this vector and send it to anot
136 const FileQuotaRequestCallback& done_callback);
137
138 // This frees quota for items that are not referenced by any blobs.
139 void MaybeFreeMemoryQuotaForItems(
140 const std::vector<scoped_refptr<ShareableBlobDataItem>>& items);
141 // Forcibly frees memory quota for given item. Item must have granted quota.
142 void ForceFreeMemoryQuotaForItem(
143 const scoped_refptr<ShareableBlobDataItem>& item);
144
145 // Called when initially populated or upon later access.
146 void NotifyMemoryItemUsed(ShareableBlobDataItem* item);
147
148 size_t memory_usage() const {
149 return blob_memory_used_ + in_flight_memory_used_;
150 }
151 uint64_t disk_usage() const { return disk_used_; }
152
153 const BlobStorageLimits& limits() const { return limits_; }
154 void SetLimitsForTesting(BlobStorageLimits limits) { limits_ = limits; }
michaeln 2016/10/04 00:11:55 nit: unix_hacker_naming()
dmurph 2016/10/06 00:45:39 Done.
155
156 private:
157 template <typename T>
158 class BaseQuotaAllocationTask;
159 class FileQuotaAllocationTask;
160 class MemoryQuotaAllocationTask;
161
162 using PendingMemoryQuotaTaskList =
163 std::list<std::unique_ptr<MemoryQuotaAllocationTask>>;
164 using PendingFileQuotaTaskList =
165 std::list<std::unique_ptr<FileQuotaAllocationTask>>;
166
167 // Removes the given blob item from our LRU list for paging.
168 void RemoveItemInRecents(const ShareableBlobDataItem& item);
169
170 void MaybeGrantPendingQuotaRequests();
171
172 size_t CollectItemsForEviction(
173 std::vector<scoped_refptr<ShareableBlobDataItem>>* output);
174
175 // Schedule paging until our memory usage is below our memory limit.
176 void MaybeScheduleEvictionUntilSystemHealthy();
177
178 // Called when we've completed evicting a list of items to disk. This is where
179 // we swap the bytes items for file items, and and update our bookkeeping.
180 void OnEvictionComplete(
181 scoped_refptr<ShareableFileReference> file_reference,
182 std::vector<scoped_refptr<ShareableBlobDataItem>> items,
183 size_t total_items_size,
184 FileCreationInfo result);
185
186 size_t GetAvailableMemoryForBlobs() const;
187 uint64_t GetAvailableFileSpaceForBlobs() const;
188
189 // This is registered as a callback for file deletions on the file reference
190 // of our paging files. We decrement the disk space used.
191 void OnBlobFileDelete(uint64_t size, const base::FilePath& path);
192
193 base::FilePath GenerateNextPageFileName();
194
195 // This records diagnostic counters of our memory quotas. Called when usage
196 // changes.
197 void RecordTracingCounters() const;
198
199 BlobStorageLimits limits_;
200
201 // Memory bookkeeping. These numbers are all disjoint.
202 // This is the amount of memory we're using for blobs in RAM.
203 size_t blob_memory_used_ = 0;
204 // This is memory we're temporarily using while we try to write blob items to
205 // disk.
206 size_t in_flight_memory_used_ = 0;
207 // This is the amount of memory we're using on disk.
208 uint64_t disk_used_ = 0;
209
210 // State for GenerateNextPageFileName.
211 uint64_t current_file_num_ = 0;
212
213 size_t pending_memory_quota_total_size_ = 0;
214 PendingMemoryQuotaTaskList pending_memory_quota_tasks_;
215 PendingFileQuotaTaskList pending_file_quota_tasks_;
216
217 size_t pending_evictions_ = 0;
218
219 bool file_paging_enabled_ = false;
220 base::FilePath blob_storage_dir_;
221 scoped_refptr<base::TaskRunner> file_runner_;
222
223 // Lifetime of the ShareableBlobDataItem objects is handled externally in the
224 // BlobStorageContext class.
225 base::MRUCache<uint64_t, ShareableBlobDataItem*> recent_item_cache_;
226 size_t recent_item_cache_bytes_ = 0;
227 // We need to keep track of items currently being paged to disk so that if
228 // another blob successfully grabs a ref, we can prevent it from adding the
229 // item to the recent_item_cache_ above.
michaeln 2016/10/04 00:11:55 would it make sense to represent this as a distinc
dmurph 2016/10/06 00:45:39 Acknowledged.
230 std::unordered_set<uint64_t> items_saving_to_disk_;
231
232 base::WeakPtrFactory<BlobMemoryController> weak_factory_;
233
234 DISALLOW_COPY_AND_ASSIGN(BlobMemoryController);
235 };
236 } // namespace storage
237 #endif // STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698