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

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

Issue 2339933004: [BlobStorage] BlobMemoryController & tests (Closed)
Patch Set: comments and in_flight limit simplification (using min_page_file_size) 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 // * 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).
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 STORAGE_EXPORT 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 struct MemoryAllocation {
78 MemoryAllocation(base::WeakPtr<BlobMemoryController> controller,
79 uint64_t item_id,
80 size_t length);
81 ~MemoryAllocation();
82
83 private:
84 base::WeakPtr<BlobMemoryController> controller;
85 uint64_t item_id;
86 size_t length;
87
88 DISALLOW_COPY_AND_ASSIGN(MemoryAllocation);
89 };
90
91 class QuotaAllocationTask {
92 public:
93 // Operation is cancelled and the callback will NOT be called. This object
94 // will be destroyed by this call.
95 virtual void Cancel() = 0;
96
97 protected:
98 virtual ~QuotaAllocationTask();
99 };
100
101 // The bool argument is true if we successfully received memory quota.
102 using MemoryQuotaRequestCallback = base::Callback<void(bool)>;
103 // The bool argument is true if we successfully received file quota, and the
104 // vector argument provides the file info.
105 using FileQuotaRequestCallback =
106 base::Callback<void(bool, std::vector<FileCreationInfo>)>;
107
108 // We enable file paging if |file_runner| isn't a nullptr.
109 BlobMemoryController(const base::FilePath& storage_directory,
110 scoped_refptr<base::TaskRunner> file_runner);
111 ~BlobMemoryController();
112
113 // Disables file paging. This cancels all pending file creations and paging
114 // operations. Reason is recorded in UMA.
115 void DisableFilePaging(base::File::Error reason);
116
117 bool file_paging_enabled() const { return file_paging_enabled_; }
118
119 // Returns the strategy the transportation layer should use to transport the
120 // given memory. |preemptive_transported_bytes| are the number of transport
121 // bytes that are already populated for us, so we don't haved to request them
122 // from the renderer.
123 Strategy DetermineStrategy(size_t preemptive_transported_bytes,
124 uint64_t total_transportation_bytes) const;
125
126 // Checks to see if we can reserve quota (disk or memory) for the given size.
127 bool CanReserveQuota(uint64_t size) const;
128
129 // Reserves quota for the given |unreserved_memory_items|. The items must be
130 // bytes items in QUOTA_NEEDED state which we change to QUOTA_REQUESTED.
131 // After we reserve memory quota we change their state to QUOTA_GRANTED, set
132 // the 'memory_allocation' on the item, and call |done_callback|. This can
133 // happen synchronously.
134 // Returns a task handle if the request is asynchronous for cancellation.
135 // NOTE: We don't inspect quota limits and assume the user checked
136 // CanReserveQuota before calling this.
137 base::WeakPtr<QuotaAllocationTask> ReserveMemoryQuota(
138 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
139 const MemoryQuotaRequestCallback& done_callback);
140
141 // Reserves quota for the given |unreserved_file_items|. The items must be
142 // temporary file items (BlobDataBuilder::IsTemporaryFileItem returns true) in
143 // QUOTA_NEEDED state, which we change to QUOTA_REQUESTED. After we reserve
144 // file quota we change their state to QUOTA_GRANTED and call
145 // |done_callback|.
146 // Returns a task handle for cancellation.
147 // NOTE: We don't inspect quota limits and assume the user checked
148 // CanReserveQuota before calling this.
149 base::WeakPtr<QuotaAllocationTask> ReserveFileQuota(
150 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_file_items,
151 const FileQuotaRequestCallback& done_callback);
152
153 // Called when initially populated or upon later access.
154 void NotifyMemoryItemsUsed(
155 std::vector<scoped_refptr<ShareableBlobDataItem>>& items);
156
157 size_t memory_usage() const { return blob_memory_used_; }
158 uint64_t disk_usage() const { return disk_used_; }
159
160 const BlobStorageLimits& limits() const { return limits_; }
161 void set_limits_for_testing(const BlobStorageLimits& limits) {
162 limits_ = limits;
163 }
164
165 private:
166 template <typename T>
167 class BaseQuotaAllocationTask;
michaeln 2016/10/20 20:48:40 fyi: no longer needed
168 class FileQuotaAllocationTask;
169 class MemoryQuotaAllocationTask;
170
171 using PendingMemoryQuotaTaskList =
172 std::list<std::unique_ptr<MemoryQuotaAllocationTask>>;
173 using PendingFileQuotaTaskList =
174 std::list<std::unique_ptr<FileQuotaAllocationTask>>;
175
176 base::WeakPtr<QuotaAllocationTask> AppendMemoryTask(
177 uint64_t total_bytes_needed,
178 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items,
179 const MemoryQuotaRequestCallback& done_callback);
180
181 void MaybeGrantPendingMemoryRequests();
182
183 size_t CollectItemsForEviction(
184 std::vector<scoped_refptr<ShareableBlobDataItem>>* output);
185
186 // Schedule paging until our memory usage is below our memory limit.
187 void MaybeScheduleEvictionUntilSystemHealthy();
188
189 // Called when we've completed evicting a list of items to disk. This is where
190 // we swap the bytes items for file items, and update our bookkeeping.
191 void OnEvictionComplete(
192 scoped_refptr<ShareableFileReference> file_reference,
193 std::vector<scoped_refptr<ShareableBlobDataItem>> items,
194 size_t total_items_size,
195 FileCreationInfo result);
196
197 size_t GetAvailableMemoryForBlobs() const;
198 uint64_t GetAvailableFileSpaceForBlobs() const;
199
200 void GrantMemoryAllocations(
201 std::vector<scoped_refptr<ShareableBlobDataItem>>* items,
202 size_t total_bytes);
203 void RevokeMemoryAllocation(uint64_t item_id, size_t length);
204
205 // This is registered as a callback for file deletions on the file reference
206 // of our paging files. We decrement the disk space used.
207 void OnBlobFileDelete(uint64_t size, const base::FilePath& path);
208
209 base::FilePath GenerateNextPageFileName();
210
211 // This records diagnostic counters of our memory quotas. Called when usage
212 // changes.
213 void RecordTracingCounters() const;
214
215 BlobStorageLimits limits_;
216
217 // Memory bookkeeping. These numbers are all disjoint.
218 // This is the amount of memory we're using for blobs in RAM, including the
219 // in_flight_memory_used_.
220 size_t blob_memory_used_ = 0;
221 // This is memory we're temporarily using while we try to write blob items to
222 // disk.
223 size_t in_flight_memory_used_ = 0;
224 // This is the amount of memory we're using on disk.
225 uint64_t disk_used_ = 0;
226
227 // State for GenerateNextPageFileName.
228 uint64_t current_file_num_ = 0;
229
230 size_t pending_memory_quota_total_size_ = 0;
231 PendingMemoryQuotaTaskList pending_memory_quota_tasks_;
232 PendingFileQuotaTaskList pending_file_quota_tasks_;
233
234 int pending_evictions_ = 0;
235
236 bool file_paging_enabled_ = false;
237 base::FilePath blob_storage_dir_;
238 scoped_refptr<base::TaskRunner> file_runner_;
239
240 // Lifetime of the ShareableBlobDataItem objects is handled externally in the
241 // BlobStorageContext class.
242 base::MRUCache<uint64_t, ShareableBlobDataItem*> populated_memory_items_;
243 size_t populated_memory_items_bytes_ = 0;
244 // We need to keep track of items currently being paged to disk so that if
245 // another blob successfully grabs a ref, we can prevent it from adding the
246 // item to the recent_item_cache_ above.
247 std::unordered_set<uint64_t> items_paging_to_file_;
248
249 base::WeakPtrFactory<BlobMemoryController> ptr_factory_;
kinuko 2016/10/20 16:15:34 weak_factory_ to follow the convention?
dmurph 2016/10/20 21:05:23 Done.
250
251 DISALLOW_COPY_AND_ASSIGN(BlobMemoryController);
252 };
253 } // namespace storage
254 #endif // STORAGE_BROWSER_BLOB_BLOB_MEMORY_CONTROLLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698