Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "storage/browser/blob/blob_async_builder_host.h" | 5 #include "storage/browser/blob/blob_async_builder_host.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/memory/shared_memory.h" | 15 #include "base/memory/shared_memory.h" |
| 16 #include "storage/browser/blob/blob_data_handle.h" | 16 #include "storage/browser/blob/blob_data_handle.h" |
| 17 #include "storage/browser/blob/blob_storage_context.h" | 17 #include "storage/browser/blob/blob_storage_context.h" |
| 18 | 18 |
| 19 namespace storage { | 19 namespace storage { |
| 20 namespace { | 20 namespace { |
| 21 | |
| 21 bool CalculateBlobMemorySize(const std::vector<DataElement>& elements, | 22 bool CalculateBlobMemorySize(const std::vector<DataElement>& elements, |
| 22 size_t* shortcut_bytes, | 23 size_t* shortcut_bytes, |
| 23 uint64_t* total_bytes) { | 24 uint64_t* total_bytes) { |
| 24 DCHECK(shortcut_bytes); | 25 DCHECK(shortcut_bytes); |
| 25 DCHECK(total_bytes); | 26 DCHECK(total_bytes); |
| 26 base::CheckedNumeric<uint64_t> total_size_checked = 0; | 27 base::CheckedNumeric<uint64_t> total_size_checked = 0; |
| 27 base::CheckedNumeric<size_t> shortcut_size_checked = 0; | 28 base::CheckedNumeric<size_t> shortcut_size_checked = 0; |
| 28 for (const auto& e : elements) { | 29 for (const auto& e : elements) { |
| 29 if (e.type() == DataElement::TYPE_BYTES) { | 30 if (e.type() == DataElement::TYPE_BYTES) { |
| 30 total_size_checked += e.length(); | 31 total_size_checked += e.length(); |
| 31 shortcut_size_checked += e.length(); | 32 shortcut_size_checked += e.length(); |
| 32 } else if (e.type() == DataElement::TYPE_BYTES_DESCRIPTION) { | 33 } else if (e.type() == DataElement::TYPE_BYTES_DESCRIPTION) { |
| 33 total_size_checked += e.length(); | 34 total_size_checked += e.length(); |
| 34 } else { | 35 } else { |
| 35 continue; | 36 continue; |
| 36 } | 37 } |
| 37 if (!total_size_checked.IsValid() || !shortcut_size_checked.IsValid()) { | 38 if (!total_size_checked.IsValid() || !shortcut_size_checked.IsValid()) { |
| 38 return false; | 39 return false; |
| 39 } | 40 } |
| 40 } | 41 } |
| 41 *shortcut_bytes = shortcut_size_checked.ValueOrDie(); | 42 *shortcut_bytes = shortcut_size_checked.ValueOrDie(); |
| 42 *total_bytes = total_size_checked.ValueOrDie(); | 43 *total_bytes = total_size_checked.ValueOrDie(); |
| 43 return true; | 44 return true; |
| 44 } | 45 } |
| 46 | |
| 47 IPCBlobCreationCancelCode TransformReferencedBlobErrorToConstructingError( | |
|
kinuko
2016/04/05 09:42:35
nit: I feel 'Convert' is more common than 'Transfo
dmurph
2016/04/05 18:15:23
Done.
| |
| 48 IPCBlobCreationCancelCode referenced_blob_error) { | |
| 49 switch (referenced_blob_error) { | |
| 50 // For most cases we propagate the error. | |
| 51 case IPCBlobCreationCancelCode::FILE_WRITE_FAILED: | |
| 52 case IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT: | |
| 53 case IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN: | |
| 54 case IPCBlobCreationCancelCode::OUT_OF_MEMORY: | |
| 55 return referenced_blob_error; | |
| 56 // Others we report that the referenced blob is broken, as we don't know | |
| 57 // why (the BLOB_DEREFERENCED_WHILE_BUILDING should never happen, as we hold | |
| 58 // onto the reference of the blobs we're using). | |
| 59 case IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING: | |
| 60 DCHECK(false) << "Referenced blob should never be dereferenced while we " | |
| 61 << "are depending on it, as our system holds a handle."; | |
| 62 case IPCBlobCreationCancelCode::UNKNOWN: | |
| 63 return IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN; | |
| 64 } | |
| 65 NOTREACHED(); | |
| 66 return IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN; | |
| 67 } | |
| 68 | |
| 45 } // namespace | 69 } // namespace |
| 46 | 70 |
| 47 using MemoryItemRequest = | 71 using MemoryItemRequest = |
| 48 BlobAsyncTransportRequestBuilder::RendererMemoryItemRequest; | 72 BlobAsyncTransportRequestBuilder::RendererMemoryItemRequest; |
| 49 | 73 |
| 50 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState( | 74 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState( |
| 51 const std::string& uuid, | 75 const std::string& uuid, |
| 52 std::set<std::string> referenced_blob_uuids, | 76 std::set<std::string> referenced_blob_uuids, |
| 53 std::vector<std::unique_ptr<BlobDataHandle>>* referenced_blob_handles) | 77 std::vector<std::unique_ptr<BlobDataHandle>>* referenced_blob_handles) |
| 54 : data_builder(uuid), | 78 : data_builder(uuid), |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 // 'built'. In this case, it's destructed in the context, but we still have | 302 // 'built'. In this case, it's destructed in the context, but we still have |
| 279 // it in our map. Hence we make sure the context has the entry before | 303 // it in our map. Hence we make sure the context has the entry before |
| 280 // calling cancel. | 304 // calling cancel. |
| 281 if (context->registry().HasEntry(uuid)) | 305 if (context->registry().HasEntry(uuid)) |
| 282 context->CancelPendingBlob(uuid, code); | 306 context->CancelPendingBlob(uuid, code); |
| 283 async_blob_map_.erase(state_it); | 307 async_blob_map_.erase(state_it); |
| 284 } | 308 } |
| 285 | 309 |
| 286 void BlobAsyncBuilderHost::CancelAll(BlobStorageContext* context) { | 310 void BlobAsyncBuilderHost::CancelAll(BlobStorageContext* context) { |
| 287 DCHECK(context); | 311 DCHECK(context); |
| 288 // Some of our pending blobs may still be referenced elsewhere. | 312 // If the blob still exists in the context (and is being built), then we know |
| 313 // that someone else is expecting our blob, and we need to cancel it to let | |
| 314 // the dependency know it's gone. | |
| 289 std::vector<std::unique_ptr<BlobDataHandle>> referenced_pending_blobs; | 315 std::vector<std::unique_ptr<BlobDataHandle>> referenced_pending_blobs; |
| 290 for (const auto& uuid_state_pair : async_blob_map_) { | 316 for (const auto& uuid_state_pair : async_blob_map_) { |
| 291 if (context->IsBeingBuilt(uuid_state_pair.first)) { | 317 if (context->IsBeingBuilt(uuid_state_pair.first)) { |
| 292 referenced_pending_blobs.emplace_back( | 318 referenced_pending_blobs.emplace_back( |
| 293 context->GetBlobDataFromUUID(uuid_state_pair.first)); | 319 context->GetBlobDataFromUUID(uuid_state_pair.first)); |
| 294 } | 320 } |
| 295 } | 321 } |
| 296 // We clear the map before canceling them to prevent any strange reentry into | 322 // We clear the map before canceling them to prevent any strange reentry into |
| 297 // our class (see ReferencedBlobFinished) if any blobs were waiting for others | 323 // our class (see ReferencedBlobFinished) if any blobs were waiting for others |
| 298 // to construct. | 324 // to construct. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 | 406 |
| 381 state->request_memory_callback.Run( | 407 state->request_memory_callback.Run( |
| 382 std::move(byte_requests), std::move(shared_memory), | 408 std::move(byte_requests), std::move(shared_memory), |
| 383 base::WrapUnique(new std::vector<base::File>())); | 409 base::WrapUnique(new std::vector<base::File>())); |
| 384 return BlobTransportResult::PENDING_RESPONSES; | 410 return BlobTransportResult::PENDING_RESPONSES; |
| 385 } | 411 } |
| 386 | 412 |
| 387 void BlobAsyncBuilderHost::ReferencedBlobFinished( | 413 void BlobAsyncBuilderHost::ReferencedBlobFinished( |
| 388 const std::string& owning_blob_uuid, | 414 const std::string& owning_blob_uuid, |
| 389 base::WeakPtr<BlobStorageContext> context, | 415 base::WeakPtr<BlobStorageContext> context, |
| 390 bool construction_success) { | 416 bool construction_success, |
| 417 IPCBlobCreationCancelCode reason) { | |
| 391 if (!context) { | 418 if (!context) { |
| 392 return; | 419 return; |
| 393 } | 420 } |
| 394 auto state_it = async_blob_map_.find(owning_blob_uuid); | 421 auto state_it = async_blob_map_.find(owning_blob_uuid); |
| 395 if (state_it == async_blob_map_.end()) { | 422 if (state_it == async_blob_map_.end()) { |
| 396 return; | 423 return; |
| 397 } | 424 } |
| 398 if (!construction_success) { | 425 if (!construction_success) { |
| 399 CancelBuildingBlob(owning_blob_uuid, | 426 CancelBuildingBlob(owning_blob_uuid, |
| 400 IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, | 427 TransformReferencedBlobErrorToConstructingError(reason), |
| 401 context.get()); | 428 context.get()); |
| 402 return; | 429 return; |
| 403 } | 430 } |
| 404 BlobBuildingState* state = state_it->second.get(); | 431 BlobBuildingState* state = state_it->second.get(); |
| 405 DCHECK_GT(state->num_referenced_blobs_building, 0u); | 432 DCHECK_GT(state->num_referenced_blobs_building, 0u); |
| 406 if (--state->num_referenced_blobs_building == 0) { | 433 if (--state->num_referenced_blobs_building == 0) { |
| 407 context->CompletePendingBlob(state->data_builder); | 434 context->CompletePendingBlob(state->data_builder); |
| 408 async_blob_map_.erase(state->data_builder.uuid()); | 435 async_blob_map_.erase(state->data_builder.uuid()); |
| 409 } | 436 } |
| 410 } | 437 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 431 if (state->num_referenced_blobs_building > 0) { | 458 if (state->num_referenced_blobs_building > 0) { |
| 432 // We wait until referenced blobs are done. | 459 // We wait until referenced blobs are done. |
| 433 return; | 460 return; |
| 434 } | 461 } |
| 435 } | 462 } |
| 436 context->CompletePendingBlob(state->data_builder); | 463 context->CompletePendingBlob(state->data_builder); |
| 437 async_blob_map_.erase(state->data_builder.uuid()); | 464 async_blob_map_.erase(state->data_builder.uuid()); |
| 438 } | 465 } |
| 439 | 466 |
| 440 } // namespace storage | 467 } // namespace storage |
| OLD | NEW |