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 <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/memory/shared_memory.h" | 13 #include "base/memory/shared_memory.h" |
| 14 #include "storage/browser/blob/blob_data_handle.h" | 14 #include "storage/browser/blob/blob_data_handle.h" |
| 15 #include "storage/browser/blob/blob_storage_context.h" | 15 #include "storage/browser/blob/blob_storage_context.h" |
| 16 | 16 |
| 17 namespace storage { | 17 namespace storage { |
| 18 namespace { | 18 namespace { |
| 19 | |
| 19 bool CalculateBlobMemorySize(const std::vector<DataElement>& elements, | 20 bool CalculateBlobMemorySize(const std::vector<DataElement>& elements, |
| 20 size_t* shortcut_bytes, | 21 size_t* shortcut_bytes, |
| 21 uint64_t* total_bytes) { | 22 uint64_t* total_bytes) { |
| 22 DCHECK(shortcut_bytes); | 23 DCHECK(shortcut_bytes); |
| 23 DCHECK(total_bytes); | 24 DCHECK(total_bytes); |
| 24 base::CheckedNumeric<uint64_t> total_size_checked = 0; | 25 base::CheckedNumeric<uint64_t> total_size_checked = 0; |
| 25 base::CheckedNumeric<size_t> shortcut_size_checked = 0; | 26 base::CheckedNumeric<size_t> shortcut_size_checked = 0; |
| 26 for (const auto& e : elements) { | 27 for (const auto& e : elements) { |
| 27 if (e.type() == DataElement::TYPE_BYTES) { | 28 if (e.type() == DataElement::TYPE_BYTES) { |
| 28 total_size_checked += e.length(); | 29 total_size_checked += e.length(); |
| 29 shortcut_size_checked += e.length(); | 30 shortcut_size_checked += e.length(); |
| 30 } else if (e.type() == DataElement::TYPE_BYTES_DESCRIPTION) { | 31 } else if (e.type() == DataElement::TYPE_BYTES_DESCRIPTION) { |
| 31 total_size_checked += e.length(); | 32 total_size_checked += e.length(); |
| 32 } else { | 33 } else { |
| 33 continue; | 34 continue; |
| 34 } | 35 } |
| 35 if (!total_size_checked.IsValid() || !shortcut_size_checked.IsValid()) { | 36 if (!total_size_checked.IsValid() || !shortcut_size_checked.IsValid()) { |
| 36 return false; | 37 return false; |
| 37 } | 38 } |
| 38 } | 39 } |
| 39 *shortcut_bytes = shortcut_size_checked.ValueOrDie(); | 40 *shortcut_bytes = shortcut_size_checked.ValueOrDie(); |
| 40 *total_bytes = total_size_checked.ValueOrDie(); | 41 *total_bytes = total_size_checked.ValueOrDie(); |
| 41 return true; | 42 return true; |
| 42 } | 43 } |
| 44 | |
| 45 IPCBlobCreationCancelCode TransformReferencedBlobErrorToConstructingError( | |
| 46 IPCBlobCreationCancelCode referenced_blob_error) { | |
| 47 switch (referenced_blob_error) { | |
| 48 // For most cases we propogate the error. | |
|
jsbell
2016/04/04 20:41:19
Typo: propagate
dmurph
2016/04/04 22:17:42
Done.
| |
| 49 case IPCBlobCreationCancelCode::FILE_WRITE_FAILED: | |
| 50 case IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT: | |
| 51 case IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN: | |
| 52 case IPCBlobCreationCancelCode::OUT_OF_MEMORY: | |
| 53 return referenced_blob_error; | |
| 54 // Others we report that the referenced blob is broken, as we don't know | |
| 55 // why (the BLOB_DEREFERENCED_WHILE_BUILDING should never happen, as we hold | |
|
jsbell
2016/04/04 20:41:19
Do we want to DCHECK so we'd notice this during de
dmurph
2016/04/04 22:17:42
Done.
| |
| 56 // onto the reference of the blobs we're using). | |
| 57 case IPCBlobCreationCancelCode::UNKNOWN: | |
| 58 case IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING: | |
| 59 return IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN; | |
| 60 } | |
| 61 NOTREACHED(); | |
| 62 } | |
| 63 | |
| 43 } // namespace | 64 } // namespace |
| 44 | 65 |
| 45 using MemoryItemRequest = | 66 using MemoryItemRequest = |
| 46 BlobAsyncTransportRequestBuilder::RendererMemoryItemRequest; | 67 BlobAsyncTransportRequestBuilder::RendererMemoryItemRequest; |
| 47 | 68 |
| 48 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState( | 69 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState( |
| 49 const std::string& uuid, | 70 const std::string& uuid, |
| 50 std::set<std::string> referenced_blob_uuids, | 71 std::set<std::string> referenced_blob_uuids, |
| 51 std::vector<scoped_ptr<BlobDataHandle>>* referenced_blob_handles) | 72 std::vector<scoped_ptr<BlobDataHandle>>* referenced_blob_handles) |
| 52 : data_builder(uuid), | 73 : data_builder(uuid), |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 // 'built'. In this case, it's destructed in the context, but we still have | 297 // 'built'. In this case, it's destructed in the context, but we still have |
| 277 // it in our map. Hence we make sure the context has the entry before | 298 // it in our map. Hence we make sure the context has the entry before |
| 278 // calling cancel. | 299 // calling cancel. |
| 279 if (context->registry().HasEntry(uuid)) | 300 if (context->registry().HasEntry(uuid)) |
| 280 context->CancelPendingBlob(uuid, code); | 301 context->CancelPendingBlob(uuid, code); |
| 281 async_blob_map_.erase(state_it); | 302 async_blob_map_.erase(state_it); |
| 282 } | 303 } |
| 283 | 304 |
| 284 void BlobAsyncBuilderHost::CancelAll(BlobStorageContext* context) { | 305 void BlobAsyncBuilderHost::CancelAll(BlobStorageContext* context) { |
| 285 DCHECK(context); | 306 DCHECK(context); |
| 286 // Some of our pending blobs may still be referenced elsewhere. | 307 // If the blob still exists in the context (and is being built), then we know |
| 308 // that someone else is expecting our blob, and we need to cancel it to let | |
| 309 // the dependency know it's gone. | |
| 287 std::vector<scoped_ptr<BlobDataHandle>> referenced_pending_blobs; | 310 std::vector<scoped_ptr<BlobDataHandle>> referenced_pending_blobs; |
| 288 for (const auto& uuid_state_pair : async_blob_map_) { | 311 for (const auto& uuid_state_pair : async_blob_map_) { |
| 289 if (context->IsBeingBuilt(uuid_state_pair.first)) { | 312 if (context->IsBeingBuilt(uuid_state_pair.first)) { |
| 290 referenced_pending_blobs.emplace_back( | 313 referenced_pending_blobs.emplace_back( |
| 291 context->GetBlobDataFromUUID(uuid_state_pair.first)); | 314 context->GetBlobDataFromUUID(uuid_state_pair.first)); |
| 292 } | 315 } |
| 293 } | 316 } |
| 294 // We clear the map before canceling them to prevent any strange reentry into | 317 // We clear the map before canceling them to prevent any strange reentry into |
| 295 // our class (see ReferencedBlobFinished) if any blobs were waiting for others | 318 // our class (see ReferencedBlobFinished) if any blobs were waiting for others |
| 296 // to construct. | 319 // to construct. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 | 400 |
| 378 state->request_memory_callback.Run( | 401 state->request_memory_callback.Run( |
| 379 std::move(byte_requests), std::move(shared_memory), | 402 std::move(byte_requests), std::move(shared_memory), |
| 380 make_scoped_ptr(new std::vector<base::File>())); | 403 make_scoped_ptr(new std::vector<base::File>())); |
| 381 return BlobTransportResult::PENDING_RESPONSES; | 404 return BlobTransportResult::PENDING_RESPONSES; |
| 382 } | 405 } |
| 383 | 406 |
| 384 void BlobAsyncBuilderHost::ReferencedBlobFinished( | 407 void BlobAsyncBuilderHost::ReferencedBlobFinished( |
| 385 const std::string& owning_blob_uuid, | 408 const std::string& owning_blob_uuid, |
| 386 base::WeakPtr<BlobStorageContext> context, | 409 base::WeakPtr<BlobStorageContext> context, |
| 387 bool construction_success) { | 410 bool construction_success, |
| 411 IPCBlobCreationCancelCode reason) { | |
|
jsbell
2016/04/04 20:41:19
ISTM we should combine these, e.g. ResultCode w/ O
dmurph
2016/04/04 22:17:42
YES this is definitely better. However, this would
| |
| 388 if (!context) { | 412 if (!context) { |
| 389 return; | 413 return; |
| 390 } | 414 } |
| 391 auto state_it = async_blob_map_.find(owning_blob_uuid); | 415 auto state_it = async_blob_map_.find(owning_blob_uuid); |
| 392 if (state_it == async_blob_map_.end()) { | 416 if (state_it == async_blob_map_.end()) { |
| 393 return; | 417 return; |
| 394 } | 418 } |
| 395 if (!construction_success) { | 419 if (!construction_success) { |
| 396 CancelBuildingBlob(owning_blob_uuid, | 420 CancelBuildingBlob(owning_blob_uuid, |
| 397 IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, | 421 TransformReferencedBlobErrorToConstructingError(reason), |
| 398 context.get()); | 422 context.get()); |
| 399 return; | 423 return; |
| 400 } | 424 } |
| 401 BlobBuildingState* state = state_it->second.get(); | 425 BlobBuildingState* state = state_it->second.get(); |
| 402 DCHECK_GT(state->num_referenced_blobs_building, 0u); | 426 DCHECK_GT(state->num_referenced_blobs_building, 0u); |
| 403 if (--state->num_referenced_blobs_building == 0) { | 427 if (--state->num_referenced_blobs_building == 0) { |
| 404 context->CompletePendingBlob(state->data_builder); | 428 context->CompletePendingBlob(state->data_builder); |
| 405 async_blob_map_.erase(state->data_builder.uuid()); | 429 async_blob_map_.erase(state->data_builder.uuid()); |
| 406 } | 430 } |
| 407 } | 431 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 428 if (state->num_referenced_blobs_building > 0) { | 452 if (state->num_referenced_blobs_building > 0) { |
| 429 // We wait until referenced blobs are done. | 453 // We wait until referenced blobs are done. |
| 430 return; | 454 return; |
| 431 } | 455 } |
| 432 } | 456 } |
| 433 context->CompletePendingBlob(state->data_builder); | 457 context->CompletePendingBlob(state->data_builder); |
| 434 async_blob_map_.erase(state->data_builder.uuid()); | 458 async_blob_map_.erase(state->data_builder.uuid()); |
| 435 } | 459 } |
| 436 | 460 |
| 437 } // namespace storage | 461 } // namespace storage |
| OLD | NEW |