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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: Fix android & windows build errors 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.
kinuko 2016/10/12 15:26:42 responsability -> responsibility
dmurph 2016/10/13 00:39:31 Done.
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, ForceFreeMemoryQuotaForItem)
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 // (NotifyMemoryItemUsed, *FreeMemoryQuotaForItem*).
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 scoped_refptr<base::TaskRunner> file_deletion_runner;
72 base::FilePath path;
73 scoped_refptr<ShareableFileReference> file_reference;
74 base::Time last_modified;
75 };
76
77 class QuotaAllocationTask {
78 public:
79 // Operation is cancelled and the callback will NOT be called. This object
80 // will be destroyed by this call.
81 virtual void Cancel() = 0;
82
83 protected:
84 virtual ~QuotaAllocationTask();
85 };
86
87 // The bool argument is true if we successfully received memory quota.
88 using MemoryQuotaRequestCallback = base::Callback<void(bool)>;
89 // The bool argument is true if we successfully received file quota, and the
90 // vector argument provides the file info.
91 using FileQuotaRequestCallback =
92 base::Callback<void(bool, std::vector<FileCreationInfo>)>;
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
kinuko 2016/10/12 15:26:42 nit: disk -> file paging for consistency?
dmurph 2016/10/13 00:39:31 Done.
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<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
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,
136 const FileQuotaRequestCallback& done_callback);
137
138 // This frees quota for items that are not referenced by any blobs.
139 void MaybeFreeMemoryQuotaForItems(
michaeln 2016/10/11 20:55:24 What do think about making the "free" call a funct
dmurph 2016/10/13 00:39:31 Done.
140 const std::vector<scoped_refptr<ShareableBlobDataItem>>& items);
141 // Forcibly frees memory quota for given item. Item must have granted quota.
142 void ForceFreeMemoryQuotaForItem(
michaeln 2016/10/11 20:55:24 what is the usecase for this method? i don't see i
dmurph 2016/10/13 00:39:31 When we have created (and asked quota for) a 'futu
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 set_limits_for_testing(BlobStorageLimits limits) { limits_ = limits; }
kinuko 2016/10/12 15:26:42 nit: const BlobStorageLimits& limits
dmurph 2016/10/13 00:39:31 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 base::WeakPtr<QuotaAllocationTask> AppendMemoryTask(
168 uint64_t total_bytes_needed,
169 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
170 const MemoryQuotaRequestCallback& done_callback);
171
172 // Removes the given blob item from our LRU list for paging.
173 void RemoveItemInRecents(const ShareableBlobDataItem& item);
174
175 void MaybeGrantPendingQuotaRequests();
176
177 size_t CollectItemsForEviction(
178 std::vector<scoped_refptr<ShareableBlobDataItem>>* output);
179
180 // Schedule paging until our memory usage is below our memory limit.
181 void MaybeScheduleEvictionUntilSystemHealthy();
182
183 // Called when we've completed evicting a list of items to disk. This is where
184 // we swap the bytes items for file items, and and update our bookkeeping.
185 void OnEvictionComplete(
186 scoped_refptr<ShareableFileReference> file_reference,
187 std::vector<scoped_refptr<ShareableBlobDataItem>> items,
188 size_t total_items_size,
189 FileCreationInfo result);
190
191 size_t GetAvailableMemoryForBlobs() const;
192 uint64_t GetAvailableFileSpaceForBlobs() const;
193
194 // This is registered as a callback for file deletions on the file reference
195 // of our paging files. We decrement the disk space used.
196 void OnBlobFileDelete(uint64_t size, const base::FilePath& path);
197
198 base::FilePath GenerateNextPageFileName();
199
200 // This records diagnostic counters of our memory quotas. Called when usage
201 // changes.
202 void RecordTracingCounters() const;
203
204 BlobStorageLimits limits_;
205
206 // Memory bookkeeping. These numbers are all disjoint.
207 // This is the amount of memory we're using for blobs in RAM.
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*> recent_item_cache_;
231 size_t recent_item_cache_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_saving_to_disk_;
kinuko 2016/10/12 15:26:42 nit: saving_to_disk_ or paging_to_file_ ?
dmurph 2016/10/13 00:39:31 Done.
236
237 // We clear this when disabling paging to disable pending file tasks.
238 base::WeakPtrFactory<BlobMemoryController> file_task_factory_;
239 base::WeakPtrFactory<BlobMemoryController> file_destruction_factory_;
240
241 DISALLOW_COPY_AND_ASSIGN(BlobMemoryController);
242 };
243 } // namespace storage
244 #endif // STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698