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

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

Issue 1098853003: [BlobAsync] Patch 4: Browser Classes & Logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moving stuff around Created 5 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 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_async_builder_host.h"
6
7 #include "base/memory/shared_memory.h"
8 #include "base/stl_util.h"
9
10 namespace storage {
11
12 using MemoryItemRequest = BlobAsyncTransportStrategy::MemoryItemRequest;
13
14 BlobAsyncBuilderHost::BlobAsyncBuilderHost()
15 : max_ipc_memory_size_(kBlobStorageIPCThresholdBytes),
16 max_shared_memory_size_(kBlobStorageMaxSharedMemoryBytes),
17 max_file_size_(kBlobStorageMaxFileSizeBytes),
18 max_blob_in_memory_size_(kBlobStorageMaxBlobMemorySize) {}
19
20 BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {
21 STLDeleteContainerPairSecondPointers(async_blob_map_.begin(),
22 async_blob_map_.end());
23 }
24
25 void BlobAsyncBuilderHost::BuildBlobAsync(
26 const std::string& uuid,
27 const std::string& type,
28 const std::vector<DataElement>& descriptions,
29 size_t memory_available,
30 base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&,
31 const std::vector<base::SharedMemoryHandle>&,
32 const std::vector<IPC::PlatformFileForTransit>&)>
33 request_memory,
34 base::Callback<void(BlobDataBuilder*)> done,
35 base::Callback<void(IPCBlobCreationCancelCode)> cancel) {
36 if (BlobAsyncTransportStrategy::ShouldBeShortcut(descriptions,
37 memory_available)) {
38 // We have enough memory, and all the data is here, so we use the shortcut
39 // method and populate the old way.
40 BlobDataBuilder builder(uuid);
41 builder.set_content_type(type);
42 for (const DataElement& element : descriptions) {
43 builder.AppendDataElement(element);
44 }
45 done.Run(&builder);
kinuko 2015/11/17 14:51:41 Calling this synchronously while the method name t
dmurph 2015/11/17 20:40:19 Renamed, and clarified behavior in comment.
46 return;
47 }
48
49 DCHECK(async_blob_map_.find(uuid) == async_blob_map_.end());
50 BlobAsyncBuilderHost::BlobBuildingState* state =
51 new BlobAsyncBuilderHost::BlobBuildingState();
52 async_blob_map_[uuid] = state;
53 state->type = type;
54 state->request_memory = request_memory;
55 state->done = done;
56 state->cancel = cancel;
michaeln 2015/11/17 21:55:28 naming nit: consider appending _callback to reques
dmurph 2015/11/19 02:06:17 Done.
57
58 state->transport_strategy.Initialize(
59 BlobAsyncTransportStrategy::MODE_NO_DISK, max_ipc_memory_size_,
60 max_shared_memory_size_, max_file_size_, max_blob_in_memory_size_, 0,
61 memory_available, uuid, descriptions);
kinuko 2015/11/17 14:51:41 Can you add a comment for '0'? (disk_space_left?)
dmurph 2015/11/17 20:40:19 Done.
62 if (state->transport_strategy.error() !=
63 BlobAsyncTransportStrategy::ERROR_NONE) {
64 LOG(ERROR) << "Error initializing transport strategy: "
kinuko 2015/11/17 14:51:41 DVLOG ?
dmurph 2015/11/17 20:40:19 Done.
michaeln 2015/11/17 21:55:28 is the logging needed in a release build, here and
dmurph 2015/11/19 02:06:17 Can I log to debug? There's no way of telling what
65 << state->transport_strategy.error();
66 CancelAndCleanup(uuid, state->transport_strategy.error() ==
67 BlobAsyncTransportStrategy::ERROR_TOO_LARGE
68 ? IPCBlobCreationCancelCode::OUT_OF_MEMORY
69 : IPCBlobCreationCancelCode::UNKNOWN);
70 return;
71 }
72
73 ContinueBlobMemoryRequests(uuid);
74 }
75
76 void BlobAsyncBuilderHost::OnMemoryResponses(
77 const std::string& uuid,
78 const std::vector<BlobItemBytesResponse> responses) {
79 AsyncBlobMap::iterator state_it = async_blob_map_.find(uuid);
80 if (state_it == async_blob_map_.end()) {
michaeln 2015/11/17 21:55:27 is this indicative of a bad ipc message or could t
dmurph 2015/11/19 02:06:17 Bad IPC message. I could have the check happen ear
81 return;
82 }
83 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
84 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
85 bool populate_success = false;
86 const auto& requests = strategy.requests();
87 for (const BlobItemBytesResponse& response : responses) {
88 if (response.request_number >= requests.size()) {
89 LOG(ERROR) << "Invalid request number " << response.request_number;
michaeln 2015/11/17 21:55:28 we might want to treat this as a badipc?
dmurph 2015/11/19 02:06:17 See above resolution.
90 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
91 return;
92 }
93 const MemoryItemRequest& request = requests[response.request_number];
94 if (request.received) {
95 LOG(ERROR) << "Already received response for that request.";
michaeln 2015/11/17 21:55:28 and this one too, when would this be expected?
dmurph 2015/11/19 02:06:17 Done.
96 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
97 return;
98 }
99 switch (request.message.transport_strategy) {
100 case IPCBlobItemRequestStrategy::IPC:
101 if (response.inline_data.size() < request.message.size) {
michaeln 2015/11/17 21:55:28 ditto
dmurph 2015/11/19 02:06:17 Done.
102 LOG(ERROR) << "Invalid data size " << response.inline_data.size()
103 << " vs requested size of " << request.message.size;
104 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
105 return;
106 }
107 populate_success = strategy.blob_builder()->PopulateFutureData(
108 request.browser_item_index, &response.inline_data[0],
109 request.browser_item_offset, request.message.size);
110 break;
111 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
112 if (state->num_shared_memory_requests == 0) {
michaeln 2015/11/17 21:55:27 ditto
113 LOG(ERROR) << "Received too many responses for shared memory.";
114 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
115 return;
116 }
117 state->num_shared_memory_requests--;
118 if (!state->shared_memory_block->memory()) {
119 // We just map the whole block, as we'll probably be accessing the
120 // whole thing in this group of responses. Another option is to use
121 // MapAt, remove the mapped boolean, and then exclude the
122 // handle_offset below.
123 size_t handle_size = strategy.shared_memory_handles().at(
124 state->current_shared_memory_handle_index);
125 if (!state->shared_memory_block->Map(handle_size)) {
126 LOG(ERROR) << "Unable to map memory to size " << handle_size;
127 populate_success = false;
128 break;
129 }
130 }
131
132 populate_success = strategy.blob_builder()->PopulateFutureData(
133 request.browser_item_index,
134 static_cast<const char*>(state->shared_memory_block->memory()) +
135 request.message.handle_offset,
136 request.browser_item_offset, request.message.size);
137 break;
138 case IPCBlobItemRequestStrategy::FILE:
139 case IPCBlobItemRequestStrategy::UNKNOWN:
140 NOTREACHED() << "Not implemented yet.";
141 break;
142 }
143 if (!populate_success) {
144 LOG(ERROR) << "Unable to populate blob data.";
145 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
146 return;
147 }
148 state->num_fulfilled_requests++;
149 }
150 ContinueBlobMemoryRequests(uuid);
151 }
152
153 void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) {
154 AsyncBlobMap::iterator state_it = async_blob_map_.find(uuid);
155 if (state_it == async_blob_map_.end()) {
156 return;
157 }
158 delete state_it->second;
159 async_blob_map_.erase(state_it);
160 }
161
162 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState()
kinuko 2015/11/17 14:51:41 nit: could these inner-class definitions be placed
dmurph 2015/11/17 20:40:19 Done.
163 : next_request(0),
164 num_fulfilled_requests(0),
165 num_shared_memory_requests(0),
166 current_shared_memory_handle_index(0) {}
167
168 BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {}
169
170 void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) {
171 AsyncBlobMap::iterator state_it = async_blob_map_.find(uuid);
172 DCHECK(state_it != async_blob_map_.end());
173 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
174
175 const auto& requests = state->transport_strategy.requests();
kinuko 2015/11/17 14:51:41 nit: prefer using non-auto class here
dmurph 2015/11/17 20:40:19 Done.
176 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
177 size_t num_requests = requests.size();
178 if (state->num_fulfilled_requests == num_requests) {
179 DoneAndCleanup(uuid);
180 return;
181 }
182 DCHECK_LT(state->num_fulfilled_requests, num_requests);
183
184 std::vector<BlobItemBytesRequest> byte_requests;
185 std::vector<base::SharedMemoryHandle> shared_memory;
186 std::vector<IPC::PlatformFileForTransit> files;
187
188 if (state->next_request == num_requests) {
michaeln 2015/11/17 21:55:28 move this test/early exit up above the local vecto
dmurph 2015/11/19 02:06:17 Done.
189 // We are still waiting on other requests to come back.
190 return;
191 }
192
193 for (; state->next_request < num_requests; ++state->next_request) {
194 const MemoryItemRequest& request = requests[state->next_request];
195
196 bool stop_accumulating = false;
197 bool using_shared_memory_handle = state->num_shared_memory_requests > 0;
198 switch (request.message.transport_strategy) {
199 case IPCBlobItemRequestStrategy::IPC:
200 byte_requests.push_back(request.message);
201 break;
202 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
203 if (using_shared_memory_handle &&
204 state->current_shared_memory_handle_index !=
205 request.message.handle_index) {
206 // We only want one shared memory per requesting blob.
207 stop_accumulating = true;
208 break;
209 }
210 using_shared_memory_handle = true;
211 state->current_shared_memory_handle_index =
212 request.message.handle_index;
213 state->num_shared_memory_requests++;
214
215 if (!state->shared_memory_block) {
216 state->shared_memory_block.reset(new base::SharedMemory());
217 size_t size =
218 strategy.shared_memory_handles()[request.message.handle_index];
219 if (!state->shared_memory_block->CreateAnonymous(size)) {
220 LOG(ERROR) << "Unable to allocate shared memory for blob transfer.";
221 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
222 return;
223 }
224 }
225 shared_memory.push_back(state->shared_memory_block->handle());
226 byte_requests.push_back(request.message);
227 // Since we are only using one handle at a time, transform our handle
228 // index correctly back to 0.
229 byte_requests.back().handle_index = 0;
230 break;
231 case IPCBlobItemRequestStrategy::FILE:
232 case IPCBlobItemRequestStrategy::UNKNOWN:
233 NOTREACHED() << "Not implemented yet.";
234 break;
235 }
236 if (stop_accumulating) {
237 break;
238 }
239 }
240
241 DCHECK(!requests.empty());
242
243 state->request_memory.Run(byte_requests, shared_memory, files);
244 }
245
246 void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid,
247 IPCBlobCreationCancelCode code) {
248 AsyncBlobMap::iterator state_it = async_blob_map_.find(uuid);
249 if (state_it == async_blob_map_.end()) {
kinuko 2015/11/17 14:51:41 I feel this and the similar line in DoneAndCleanup
dmurph 2015/11/17 20:40:19 Done.
michaeln 2015/11/17 21:55:28 looks like this could be dcheck'able instead, i th
250 return;
251 }
252 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
253
254 state->cancel.Run(code);
255 delete state;
kinuko 2015/11/17 14:51:41 could use ScopedPtrMap or assign state_it->second
dmurph 2015/11/17 20:40:19 Done.
256 async_blob_map_.erase(state_it);
257 }
258
259 void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) {
260 AsyncBlobMap::iterator state_it = async_blob_map_.find(uuid);
261 if (state_it == async_blob_map_.end()) {
michaeln 2015/11/17 21:55:27 ditto
dmurph 2015/11/19 02:06:17 Changed to scoped ptr map, and cleaned this up a b
262 return;
263 }
264 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
265 BlobDataBuilder* builder = state->transport_strategy.blob_builder();
266 builder->set_content_type(state->type);
267 DCHECK(builder);
268 state->done.Run(builder);
269 delete state;
270 async_blob_map_.erase(state_it);
271 }
272
273 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698