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

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

Powered by Google App Engine
This is Rietveld 408576698