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

Side by Side Diff: content/child/blob_storage/blob_transport_controller.cc

Issue 1292523002: [BlobAsync] Patch 3: Renderer Classes & Logic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@async2
Patch Set: comments 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 "content/child/blob_storage/blob_transport_controller.h"
6
7 #include <vector>
8
9 #include "base/containers/scoped_ptr_hash_map.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/shared_memory.h"
12 #include "base/stl_util.h"
13 #include "content/child/blob_storage/blob_consolidation.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "ipc/ipc_sender.h"
16 #include "storage/common/blob_storage/blob_item_bytes_request.h"
17 #include "storage/common/blob_storage/blob_item_bytes_response.h"
18 #include "storage/common/data_element.h"
19
20 using base::SharedMemory;
21 using base::SharedMemoryHandle;
22 using storage::BlobItemBytesRequest;
23 using storage::BlobItemBytesResponse;
24 using storage::IPCBlobItemRequestStrategy;
25 using storage::DataElement;
26
27 namespace content {
28
29 using storage::IPCBlobCreationCancelCode;
30
31 using ConsolidatedItem = BlobConsolidation::ConsolidatedItem;
32 using ReadStatus = BlobConsolidation::ReadStatus;
33
34 namespace {
35 const size_t kLargeThresholdBytes = 250 * 1024;
36 static base::LazyInstance<BlobTransportController> controller_ =
kinuko 2015/10/26 06:44:22 nit: prefer prefixing with g_ without trailing _,
dmurph 2015/10/28 01:00:51 Done.
37 LAZY_INSTANCE_INITIALIZER;
38 }
39
40 BlobTransportController* BlobTransportController::GetInstance() {
41 return controller_.Pointer();
42 }
43
44 BlobTransportController::~BlobTransportController() {
45 STLDeleteValues(&blob_storage_);
46 }
47
48 void BlobTransportController::InitiateBlobTransfer(
49 const std::string& uuid,
50 const std::string& type,
51 scoped_ptr<BlobConsolidation> consolidation,
52 IPC::Sender* sender) {
53 bool success = HoldBlobConsolidation(uuid, consolidation.Pass());
54 CHECK(success);
55
56 std::vector<storage::DataElement> descriptions;
57 GetDescriptions(uuid, kLargeThresholdBytes, &descriptions);
58 // TODO(dmurph): Uncomment when IPC messages are added.
59 // sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, type,
60 // descriptions));
61 }
62
63 void BlobTransportController::OnMemoryRequest(
64 const std::string& uuid,
65 const std::vector<storage::BlobItemBytesRequest>& requests,
66 std::vector<base::SharedMemoryHandle>* memory_handles,
67 const std::vector<IPC::PlatformFileForTransit>& file_handles,
68 IPC::Sender* sender) {
69 std::vector<storage::BlobItemBytesResponse> responses;
70 ResponsesStatus status =
71 GetResponses(uuid, requests, memory_handles, file_handles, &responses);
72
73 bool success = false;
74 switch (status) {
kinuko 2015/10/26 06:44:22 For some of those errors I'm not fully sure how th
dmurph 2015/10/28 01:00:52 They *shouldn't*, but someone can screw up the blo
michaeln 2015/10/29 01:24:53 Are BLOB_NOT_FOUND and SHARED_MEMORY_MAP_FAILED th
dmurph 2015/10/29 20:42:27 Done.
75 case ResponsesStatus::BLOB_NOT_FOUND:
76 DVLOG(1) << "Unable to find blob " << uuid << ".";
77 return;
michaeln 2015/10/29 01:24:53 should this be a break so we send the BlobStorageM
dmurph 2015/10/29 20:42:27 Done now.
78 case ResponsesStatus::INVALID_ITEM_INDEX:
79 DVLOG(1) << "Index out of bounds for blob item in blob " << uuid << ".";
80 break;
81 case ResponsesStatus::INVALID_DATA_RANGE:
82 DVLOG(1) << "Data range out of bounds for blob item in blob " << uuid
83 << ".";
84 break;
85 case ResponsesStatus::INVALID_ITEM:
86 DVLOG(1) << "Requesting data from non-memory item in blob " << uuid
87 << ".";
88 break;
89 case ResponsesStatus::INVALID_HANDLE_INDEX:
90 DVLOG(1) << "Invalid handle index for transferring in blob " << uuid
91 << ".";
92 break;
93 case ResponsesStatus::SHARED_MEMORY_MAP_FAILED:
94 // This would happen if the renderer process doesn't have enough memory
95 // to map the shared memory, which is possible if we don't have much
96 // memory. If this scenario happens often, we could delay the response
97 // until we have enough memory. For now we just fail.
98 DVLOG(1) << "Unable to map shared memory to send blob " << uuid << ".";
99 break;
100 case ResponsesStatus::SUCCESS:
101 success = true;
102 break;
103 }
104
105 if (success) {
106 // TODO(dmurph): Uncomment when IPC messages are added.
107 // sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
108 } else {
109 DVLOG(1) << "Canceling blob transfer for blob " << uuid;
110 CancelBlobTransfer(uuid, IPCBlobCreationCancelCode::UNKNOWN, sender);
111 }
112 }
113
114 void BlobTransportController::OnCancel(
115 const std::string& uuid,
116 storage::IPCBlobCreationCancelCode code) {
117 DVLOG(1) << "Received blob cancel for blob " << uuid << " with reason:";
118 switch (code) {
119 case IPCBlobCreationCancelCode::UNKNOWN:
120 DVLOG(1) << "Unknown.";
121 break;
122 case IPCBlobCreationCancelCode::OUT_OF_MEMORY:
123 DVLOG(1) << "Out of Memory.";
124 break;
125 case IPCBlobCreationCancelCode::FILE_WRITE_FAILED:
126 DVLOG(1) << "File Write Failed (Invalid cancel reason!).";
127 break;
128 }
129 ReleaseBlobConsolidation(uuid);
130 }
131
132 void BlobTransportController::OnDone(const std::string& uuid) {
133 ReleaseBlobConsolidation(uuid);
134 }
135
136 void BlobTransportController::Clear() {
137 STLDeleteValues(&blob_storage_);
138 blob_storage_.clear();
139 }
140
141 BlobTransportController::BlobTransportController() {}
142
143 void BlobTransportController::CancelBlobTransfer(
144 const std::string& uuid,
145 storage::IPCBlobCreationCancelCode code,
146 IPC::Sender* sender) {
147 // TODO(dmurph): Uncomment when IPC messages are added.
148 // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, code));
149 ReleaseBlobConsolidation(uuid);
150 }
151
152 bool BlobTransportController::HoldBlobConsolidation(
153 const std::string& uuid,
154 scoped_ptr<BlobConsolidation> consolidation) {
155 if (blob_storage_.find(uuid) != blob_storage_.end()) {
michaeln 2015/10/23 23:52:12 nit: there's code here that doesn't need to be. si
dmurph 2015/10/28 01:00:51 Done.
156 return false;
157 }
158 blob_storage_.insert(std::make_pair(uuid, consolidation.release()));
159 return true;
160 }
161
162 void BlobTransportController::GetDescriptions(
163 const std::string& uuid,
164 size_t max_data_population,
165 std::vector<storage::DataElement>* out) {
166 DCHECK(out->empty());
167 BlobConsolidation* consolidation = GetConsolidation(uuid);
168 if (!consolidation) {
169 return;
170 }
kinuko 2015/10/26 06:44:22 nit: should this be just DCHECK(consolidation) ?
dmurph 2015/10/28 01:00:51 Done.
171 const auto& consolidated_items = consolidation->consolidated_items();
172
173 size_t current_memory_population = 0;
174 size_t current_item = 0;
175 out->reserve(consolidated_items.size());
176 for (const ConsolidatedItem& item : consolidated_items) {
177 out->push_back(DataElement());
178 auto& element = out->back();
179
180 switch (item.type) {
181 case DataElement::TYPE_BYTES: {
182 size_t bytes_length = static_cast<size_t>(item.length);
183 if (current_memory_population + bytes_length <= max_data_population) {
184 element.SetToAllocatedBytes(bytes_length);
185 consolidation->ReadMemory(current_item, 0, bytes_length,
186 element.mutable_bytes());
187 current_memory_population += bytes_length;
188 } else {
189 element.SetToBytesDescription(bytes_length);
190 }
191 break;
192 }
193 case DataElement::TYPE_FILE: {
194 element.SetToFilePathRange(
195 item.path, item.offset, item.length,
196 base::Time::FromDoubleT(item.expected_modification_time));
197 break;
198 }
199 case DataElement::TYPE_BLOB: {
200 element.SetToBlobRange(item.blob_uuid, item.offset, item.length);
201 break;
202 }
203 case DataElement::TYPE_FILE_FILESYSTEM: {
204 element.SetToFileSystemUrlRange(
205 item.filesystem_url, item.offset, item.length,
206 base::Time::FromDoubleT(item.expected_modification_time));
207 break;
208 }
209 case DataElement::TYPE_DISK_CACHE_ENTRY:
210 case DataElement::TYPE_BYTES_DESCRIPTION:
211 case DataElement::TYPE_UNKNOWN:
212 NOTREACHED();
213 }
214 ++current_item;
215 }
216 }
217
218 BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
219 const std::string& uuid,
220 const std::vector<BlobItemBytesRequest>& requests,
221 std::vector<SharedMemoryHandle>* memory_handles,
222 const std::vector<IPC::PlatformFileForTransit>& file_handles,
223 std::vector<BlobItemBytesResponse>* out) {
224 DCHECK(out->empty());
225 BlobConsolidation* consolidation = GetConsolidation(uuid);
226 if (!consolidation)
227 return ResponsesStatus::BLOB_NOT_FOUND;
228 const auto& consolidated_items = consolidation->consolidated_items();
229
230 base::ScopedPtrHashMap<size_t, scoped_ptr<SharedMemory>> opened_memory;
kinuko 2015/10/26 06:44:22 Sorry, I'm probably missing something obvious... s
dmurph 2015/10/28 01:00:51 So we need to handle the case where multiple items
kinuko (google) 2015/10/28 03:53:36 Ah I see thanks, that makes it clearer why we have
dmurph 2015/10/29 20:42:27 Done. I changed it into a scoped vector as that's
231 for (const BlobItemBytesRequest& request : requests) {
232 if (request.renderer_item_index >= consolidated_items.size())
233 return ResponsesStatus::INVALID_ITEM_INDEX;
234
235 const ConsolidatedItem& item =
236 consolidated_items[request.renderer_item_index];
237 if (request.renderer_item_offset + request.size > item.length)
238 return ResponsesStatus::INVALID_DATA_RANGE;
239 if (item.type != DataElement::TYPE_BYTES)
240 return ResponsesStatus::INVALID_ITEM;
241
242 out->push_back(BlobItemBytesResponse(request.request_number));
243 switch (request.transport_strategy) {
244 case IPCBlobItemRequestStrategy::IPC: {
245 BlobItemBytesResponse& response = out->back();
246 ReadStatus status = consolidation->ReadMemory(
247 request.renderer_item_index, request.renderer_item_offset,
248 request.size, response.allocate_mutable_data(request.size));
249 CHECK(status == ReadStatus::OK)
250 << "Error reading from consolidated blob: "
251 << static_cast<int>(status);
kinuko (google) 2015/10/28 03:53:36 Does this need to be CHECK?
dmurph 2015/10/29 20:42:27 no, changed.
252 break;
253 }
254 case IPCBlobItemRequestStrategy::SHARED_MEMORY: {
255 if (request.handle_index >= memory_handles->size()) {
256 DCHECK_LT(request.handle_index, memory_handles->size());
kinuko 2015/10/26 06:44:22 Is this handling DCHECK failure pattern?
dmurph 2015/10/28 01:00:51 Question: How do I test for a failure case, but h
kinuko (google) 2015/10/28 03:53:36 Could this error happen without any coding error?
michaeln 2015/10/29 01:24:53 When it comes to CHECKs and DCHECKs and LOG'ing, o
dmurph 2015/10/29 20:42:27 Done. I cleaned this up a lot and only have a coup
257 return ResponsesStatus::INVALID_HANDLE_INDEX;
258 }
259 SharedMemory* memory = nullptr;
260 auto memory_it = opened_memory.find(request.handle_index);
261 if (memory_it == opened_memory.end()) {
262 SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
263 DCHECK(SharedMemory::IsHandleValid(handle));
264 scoped_ptr<SharedMemory> shared_memory(
265 new SharedMemory(handle, false));
266 if (!shared_memory->Map(request.size))
267 return ResponsesStatus::SHARED_MEMORY_MAP_FAILED;
268 memory = shared_memory.get();
269 opened_memory.add(request.handle_index, shared_memory.Pass());
270 } else {
271 memory = memory_it->second;
272 }
273 CHECK(memory->memory()) << "Couldn't map memory for blob transfer.";
274 ReadStatus status = consolidation->ReadMemory(
275 request.renderer_item_index, request.renderer_item_offset,
276 request.size,
277 static_cast<char*>(memory->memory()) + request.handle_offset);
278 CHECK(status == ReadStatus::OK)
279 << "Error reading from consolidated blob: "
280 << static_cast<int>(status);
281 break;
282 }
283 case IPCBlobItemRequestStrategy::FILE:
284 NOTREACHED() << "TODO(dmurph): Not implemented.";
285 break;
286 case IPCBlobItemRequestStrategy::UNKNOWN:
287 NOTREACHED();
288 break;
289 }
290 }
291 return ResponsesStatus::SUCCESS;
292 }
293
294 void BlobTransportController::ReleaseBlobConsolidation(
295 const std::string& uuid) {
296 auto iter = blob_storage_.find(uuid);
297 if (iter != blob_storage_.end()) {
298 BlobConsolidation* consolidation = iter->second;
299 delete consolidation;
300 blob_storage_.erase(iter);
301 }
302 }
303
304 BlobConsolidation* BlobTransportController::GetConsolidation(
305 const std::string& uuid) {
306 auto iter = blob_storage_.find(uuid);
307 if (iter == blob_storage_.end())
308 return nullptr;
309 return iter->second;
310 }
311
312 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698