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

Side by Side Diff: storage/browser/blob/blob_transport_strategy.cc

Issue 1098853003: [BlobAsync] Patch 4: Browser Classes & Logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix for template ambiguity Created 5 years, 7 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 2015 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 #include "storage/browser/blob/blob_transport_strategy.h"
6
7 #include <algorithm>
8
9 namespace storage {
10
11 namespace {
12
13 // This class handles the logic of how transported memory is going to be
14 // represented as storage in the browser. The main idea is that all the memory
15 // is now packed into file chunks, and the browser items will just reference
16 // the file with offsets and sizes.
17 struct FileStorageStrategy {
18 typedef uint64_t SizeType;
19
20 FileStorageStrategy(
21 std::vector<BlobTransportStrategy::MemoryItemRequest>* requests)
22 : requests(requests), storage_element_index(0) {}
23
24 void operator()(DataElement::Type type,
25 size_t element_index,
26 SizeType element_offset,
27 size_t segment_index,
28 SizeType segment_offset,
29 SizeType size) {
30 if (type != DataElement::TYPE_BYTES) {
31 storage_element_index++;
32 return;
33 }
34 BlobTransportStrategy::MemoryItemRequest request;
35 request.browser_item_index = storage_element_index;
36 request.browser_item_offset = 0;
37 request.message.request_number = requests->size();
38 request.message.transport_strategy = IPC_BLOB_ITEM_REQUEST_STRATEGY_FILE;
39 request.message.renderer_item_index = element_index;
40 request.message.renderer_item_offset = element_offset;
41 request.message.size = size;
42 request.message.handle_index = segment_index;
43 request.message.handle_offset = segment_offset;
44
45 requests->push_back(request);
46 storage_element_index++;
47 };
48
49 std::vector<BlobTransportStrategy::MemoryItemRequest>* requests;
50
51 size_t storage_element_index;
52 };
53
54 // This class handles the logic of storing memory that is transported as
55 // consolidated shared memory. The main hurdle is to re-separate memory blocks
56 // that cross file or blob boundaries.
57 struct SharedMemoryStorageStrategy {
58 typedef size_t SizeType;
59
60 SharedMemoryStorageStrategy(
61 SizeType max_segment_size,
62 std::vector<BlobTransportStrategy::MemoryItemRequest>* requests)
63 : requests(requests),
64 max_segment_size(max_segment_size),
65 storage_element_index(0),
66 storage_element_offset(0) {}
67
68 void operator()(DataElement::Type type,
69 size_t element_index,
70 SizeType element_offset,
71 size_t segment_index,
72 SizeType segment_offset,
73 SizeType size) {
74 if (type != DataElement::TYPE_BYTES) {
75 // We add 1 to skip the non-bytes storage element, and we add 1 again
76 // because we need to start a new request (requests don't span blob
77 // or file boundaries). Thus, +2.
78 storage_element_index += 2;
79 storage_element_offset = 0;
80 return;
81 }
82 if (storage_element_offset + size > max_segment_size) {
83 storage_element_index++;
84 storage_element_offset = 0;
85 }
86 BlobTransportStrategy::MemoryItemRequest request;
87 request.browser_item_index = storage_element_index;
88 request.browser_item_offset = storage_element_offset;
89 request.message.request_number = requests->size();
90 request.message.transport_strategy =
91 IPC_BLOB_ITEM_REQUEST_STRATEGY_SHARED_MEMORY;
92 request.message.renderer_item_index = element_index;
93 request.message.renderer_item_offset = element_offset;
94 request.message.size = size;
95 request.message.handle_index = segment_index;
96 request.message.handle_offset = segment_offset;
97
98 requests->push_back(request);
99 storage_element_offset += size;
100 };
101
102 std::vector<BlobTransportStrategy::MemoryItemRequest>* requests;
103
104 SizeType max_segment_size;
105 size_t storage_element_index;
106 SizeType storage_element_offset;
107 };
108 } // namespace
109
110 BlobTransportStrategy::BlobTransportStrategy()
111 : error_(BlobTransportStrategy::ERROR_NONE) {}
112
113 BlobTransportStrategy::~BlobTransportStrategy() {}
114
115 void BlobTransportStrategy::Initialize(
116 BlobTransportStrategy::Mode mode,
117 size_t max_ipc_memory_size,
118 size_t max_shared_memory_size,
119 uint64_t max_file_size,
120 size_t max_blob_in_memory_size,
121 uint64_t disk_space_left,
122 size_t memory_left,
123 const std::vector<DataElement>& blob_item_infos) {
124 file_handles_.clear();
125 shared_memory_handles_.clear();
126 requests_.clear();
127 error_ = BlobTransportStrategy::ERROR_NONE;
128
129 uint64_t total_memory_size = 0;
130 for (const auto& info : blob_item_infos) {
131 if (info.type() != DataElement::TYPE_BYTES) {
132 continue;
133 }
kinuko 2015/05/25 08:32:02 nit: no { } required for single-line body in chrom
dmurph 2015/06/13 00:13:10 Done.
134 total_memory_size += info.length();
135 }
136
137 switch (mode) {
138 case BlobTransportStrategy::MODE_DISK:
139 if (total_memory_size >
140 disk_space_left + static_cast<uint64_t>(memory_left)) {
141 error_ = BlobTransportStrategy::ERROR_TOO_LARGE;
142 return;
143 }
144 if (total_memory_size > max_blob_in_memory_size) {
145 if (total_memory_size > disk_space_left) {
146 error_ = BlobTransportStrategy::ERROR_TOO_LARGE;
147 return;
148 }
149 CreateHandleSizes(total_memory_size, max_file_size, &file_handles_);
150 FileStorageStrategy strategy(&requests_);
151 BlobTransportStrategy::ForEachWithSegment(blob_item_infos,
kinuko 2015/05/25 08:32:02 nit: we probably don't need BlobTransportStorategy
dmurph 2015/06/13 00:13:10 Done.
152 max_file_size, strategy);
153 return;
154 }
155 break;
156 case BlobTransportStrategy::MODE_NO_DISK:
157 if (total_memory_size > memory_left) {
158 error_ = BlobTransportStrategy::ERROR_TOO_LARGE;
159 return;
160 }
161 break;
162 default:
163 NOTREACHED() << "Invalid mode " << mode;
164 error_ = BlobTransportStrategy::ERROR_INVALID_PARAMS;
165 return;
166 }
167 if (total_memory_size > max_ipc_memory_size) {
168 CHECK_LE(total_memory_size, std::numeric_limits<size_t>::max());
169 CreateHandleSizes(static_cast<size_t>(total_memory_size),
170 max_shared_memory_size, &shared_memory_handles_);
171 SharedMemoryStorageStrategy strategy(max_shared_memory_size, &requests_);
172 BlobTransportStrategy::ForEachWithSegment(blob_item_infos,
173 max_shared_memory_size, strategy);
174 return;
175 }
176 size_t items_length = blob_item_infos.size();
177 for (size_t i = 0; i < items_length; i++) {
178 const auto& info = blob_item_infos.at(i);
179 if (info.type() != DataElement::TYPE_BYTES) {
180 continue;
181 }
182 BlobTransportStrategy::MemoryItemRequest request;
183 request.browser_item_index = i;
184 request.browser_item_offset = 0;
185 request.message.request_number = requests_.size();
186 request.message.transport_strategy =
187 storage::IPC_BLOB_ITEM_REQUEST_STRATEGY_IPC;
188 request.message.renderer_item_index = i;
189 request.message.renderer_item_offset = 0;
190 request.message.size = info.length();
191 requests_.push_back(request);
kinuko 2015/05/25 08:32:03 So in the current design the decision is basically
dmurph 2015/06/13 00:13:10 Yes.
192 }
193 }
194
195 template <typename ForEachFunctor, typename SizeType>
196 /* static */ void BlobTransportStrategy::ForEachWithSegment(
197 const std::vector<DataElement>& items,
198 SizeType max_segment_size,
199 ForEachFunctor function) {
200 DCHECK_GT(max_segment_size, 0ull);
201 size_t segment_index = 0;
202 SizeType segment_offset = 0;
203 size_t items_length = items.size();
204 for (size_t element_index = 0; element_index < items_length;
205 ++element_index) {
206 const auto& element = items.at(element_index);
207 if (element.type() != DataElement::TYPE_BYTES) {
208 function(element.type(), element_index, 0, 0, 0, 0);
209 continue;
210 }
211 SizeType element_memory_left = element.length();
212 SizeType element_offset = 0;
213 while (element_memory_left > 0) {
214 if (segment_offset == max_segment_size) {
215 ++segment_index;
216 segment_offset = 0;
217 }
218 SizeType memory_writing =
219 std::min(max_segment_size - segment_offset, element_memory_left);
220 function(DataElement::TYPE_BYTES, element_index, element_offset,
221 segment_index, segment_offset, memory_writing);
222 element_memory_left -= memory_writing;
223 segment_offset += memory_writing;
224 element_offset += memory_writing;
225 }
226 }
227 }
228
229 template <typename SizeType>
230 /* static */ void BlobTransportStrategy::CreateHandleSizes(
231 SizeType total_memory_size,
232 SizeType max_segment_size,
233 std::vector<SizeType>* segment_sizes) {
234 SizeType memory_left = total_memory_size;
235 SizeType segment_size;
236 for (; memory_left > 0; memory_left -= segment_size) {
237 segment_size = std::min(max_segment_size, memory_left);
238 segment_sizes->push_back(segment_size);
239 }
kinuko 2015/05/25 08:32:03 I have a feeling that this is a bit verbose and co
dmurph 2015/06/13 00:13:10 I'm scared that it will make that function too com
240 }
241
242 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698