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

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: Removed temp file, and fixed tests Created 5 years, 1 month 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
9 namespace storage {
10
11 using MemoryItemRequest = BlobAsyncTransportStrategy::RendererMemoryItemRequest;
12
13 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState()
14 : next_request(0),
15 num_fulfilled_requests(0),
16 num_shared_memory_requests(0),
17 current_shared_memory_handle_index(0) {}
18
19 BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {}
20
21 BlobAsyncBuilderHost::BlobAsyncBuilderHost() {}
22
23 BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {}
24
25 void BlobAsyncBuilderHost::StartBuildingBlob(
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<uint64_t>&)> request_memory,
33 base::Callback<void(BlobDataBuilder*)> done,
34 base::Callback<void(IPCBlobCreationCancelCode)> cancel) {
35 if (BlobAsyncTransportStrategy::ShouldBeShortcut(descriptions,
36 memory_available)) {
37 // We have enough memory, and all the data is here, so we use the shortcut
38 // method and populate the old way.
39 BlobDataBuilder builder(uuid);
40 builder.set_content_type(type);
41 for (const DataElement& element : descriptions) {
42 builder.AppendIPCDataElement(element);
43 }
44 done.Run(&builder);
45 return;
46 }
47
48 DCHECK(async_blob_map_.find(uuid) == async_blob_map_.end());
49 BlobBuildingState* state_ptr = new BlobBuildingState();
kinuko 2015/11/20 15:19:42 nit: I would make this scoped_ptr<BlobBuildingStat
dmurph 2015/11/23 20:07:02 Done.
50 async_blob_map_.insert(uuid, make_scoped_ptr(state_ptr).Pass());
51 state_ptr->type = type;
52 state_ptr->request_memory_callback = request_memory;
53 state_ptr->done_callback = done;
54 state_ptr->cancel_callback = cancel;
55
56 // We are currently only operating in 'no disk' mode. This will change in
57 // future patches to enable disk storage.
58 // Since we don't have a disk yet, we put 0 for disk_space_left.
59 state_ptr->transport_strategy.Initialize(
60 max_ipc_memory_size_, max_shared_memory_size_, max_file_size_,
61 /* disk_space_left */ 0, memory_available, uuid, descriptions);
62
63 switch (state_ptr->transport_strategy.error()) {
64 case BlobAsyncTransportStrategy::ERROR_NONE:
65 ContinueBlobMemoryRequests(uuid);
66 return;
67 case BlobAsyncTransportStrategy::ERROR_TOO_LARGE:
68 // Cancel cleanly, we're out of memory.
69 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
70 return;
71 case BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS:
72 // Bad IPC, so we ignore and clean up.
73 async_blob_map_.erase(async_blob_map_.find(uuid));
74 NOTREACHED() << "Error initializing transport strategy: "
75 << state_ptr->transport_strategy.error();
76 return;
77 }
78 }
79
80 void BlobAsyncBuilderHost::OnMemoryResponses(
81 const std::string& uuid,
82 const std::vector<BlobItemBytesResponse>& responses) {
83 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
84 DCHECK(state_it != async_blob_map_.end());
85 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
86 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
87 bool populate_success = false;
88 const auto& requests = strategy.requests();
89 for (const BlobItemBytesResponse& response : responses) {
90 if (response.request_number >= requests.size()) {
91 // Bad IPC, so we delete our record and ignore.
92 DVLOG(1) << "Invalid request number " << response.request_number;
93 async_blob_map_.erase(state_it);
94 return;
95 }
96 const MemoryItemRequest& request = requests[response.request_number];
97 if (request.received) {
98 // Bad IPC, so we delete our record and ignore.
99 async_blob_map_.erase(state_it);
100 NOTREACHED() << "Already received response for that request.";
101 return;
102 }
103 switch (request.message.transport_strategy) {
104 case IPCBlobItemRequestStrategy::IPC:
105 if (response.inline_data.size() < request.message.size) {
106 // Bad IPC, so we delete our record and ignore.
107 async_blob_map_.erase(state_it);
108 NOTREACHED() << "Invalid data size " << response.inline_data.size()
109 << " vs requested size of " << request.message.size;
110 return;
111 }
112 populate_success = strategy.blob_builder()->PopulateFutureData(
113 request.browser_item_index, &response.inline_data[0],
114 request.browser_item_offset, request.message.size);
115 break;
116 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
117 if (state->num_shared_memory_requests == 0) {
118 // Bad IPC, so we delete our record and ignore.
119 async_blob_map_.erase(state_it);
120 NOTREACHED() << "Received too many responses for shared memory.";
121 return;
122 }
123 state->num_shared_memory_requests--;
124 if (!state->shared_memory_block->memory()) {
125 // We just map the whole block, as we'll probably be accessing the
126 // whole thing in this group of responses. Another option is to use
127 // MapAt, remove the mapped boolean, and then exclude the
128 // handle_offset below.
129 size_t handle_size = strategy.shared_memory_handle_sizes().at(
130 state->current_shared_memory_handle_index);
131 if (!state->shared_memory_block->Map(handle_size)) {
132 DVLOG(1) << "Unable to map memory to size " << handle_size;
133 populate_success = false;
134 break;
135 }
136 }
137
138 populate_success = strategy.blob_builder()->PopulateFutureData(
139 request.browser_item_index,
140 static_cast<const char*>(state->shared_memory_block->memory()) +
141 request.message.handle_offset,
142 request.browser_item_offset, request.message.size);
143 break;
144 case IPCBlobItemRequestStrategy::FILE:
145 case IPCBlobItemRequestStrategy::UNKNOWN:
146 NOTREACHED() << "Not implemented yet.";
147 break;
148 }
149 if (!populate_success) {
150 DVLOG(1) << "Unable to populate blob data.";
151 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
152 return;
153 }
154 state->num_fulfilled_requests++;
155 }
156 ContinueBlobMemoryRequests(uuid);
157 }
158
159 void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) {
160 async_blob_map_.erase(async_blob_map_.find(uuid));
161 }
162
163 void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) {
164 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
165 DCHECK(state_it != async_blob_map_.end());
166 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second;
167
168 const std::vector<MemoryItemRequest>& requests =
169 state->transport_strategy.requests();
170 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
171 size_t num_requests = requests.size();
172 if (state->num_fulfilled_requests == num_requests) {
173 DoneAndCleanup(uuid);
174 return;
175 }
176 DCHECK_LT(state->num_fulfilled_requests, num_requests);
177 if (state->next_request == num_requests) {
178 // We are still waiting on other requests to come back.
179 return;
180 }
181
182 std::vector<BlobItemBytesRequest> byte_requests;
183 std::vector<base::SharedMemoryHandle> shared_memory;
184 std::vector<uint64_t> files;
185
186 for (; state->next_request < num_requests; ++state->next_request) {
187 const MemoryItemRequest& request = requests[state->next_request];
188
189 bool stop_accumulating = false;
190 bool using_shared_memory_handle = state->num_shared_memory_requests > 0;
191 switch (request.message.transport_strategy) {
192 case IPCBlobItemRequestStrategy::IPC:
193 byte_requests.push_back(request.message);
194 break;
195 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
196 if (using_shared_memory_handle &&
197 state->current_shared_memory_handle_index !=
198 request.message.handle_index) {
199 // We only want one shared memory per requesting blob.
200 stop_accumulating = true;
201 break;
202 }
203 using_shared_memory_handle = true;
204 state->current_shared_memory_handle_index =
205 request.message.handle_index;
206 state->num_shared_memory_requests++;
207
208 if (!state->shared_memory_block) {
209 state->shared_memory_block.reset(new base::SharedMemory());
210 size_t size =
211 strategy
212 .shared_memory_handle_sizes()[request.message.handle_index];
213 if (!state->shared_memory_block->CreateAnonymous(size)) {
214 DVLOG(1) << "Unable to allocate shared memory for blob transfer.";
215 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
216 return;
217 }
218 }
219 shared_memory.push_back(state->shared_memory_block->handle());
220 byte_requests.push_back(request.message);
221 // Since we are only using one handle at a time, transform our handle
222 // index correctly back to 0.
223 byte_requests.back().handle_index = 0;
224 break;
225 case IPCBlobItemRequestStrategy::FILE:
226 case IPCBlobItemRequestStrategy::UNKNOWN:
227 NOTREACHED() << "Not implemented yet.";
228 break;
229 }
230 if (stop_accumulating) {
231 break;
232 }
233 }
234
235 DCHECK(!requests.empty());
236
237 state->request_memory_callback.Run(byte_requests, shared_memory, files);
238 }
239
240 void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid,
241 IPCBlobCreationCancelCode code) {
242 scoped_ptr<BlobBuildingState> state = async_blob_map_.take_and_erase(uuid);
243 DCHECK(state.get());
244 state->cancel_callback.Run(code);
245 }
246
247 void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) {
248 scoped_ptr<BlobBuildingState> state = async_blob_map_.take_and_erase(uuid);
249 DCHECK(state.get());
250 BlobDataBuilder* builder = state->transport_strategy.blob_builder();
251 builder->set_content_type(state->type);
252 DCHECK(builder);
253 state->done_callback.Run(builder);
254 }
255
256 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698