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

Side by Side Diff: content/browser/cache_storage/cache_storage_cache.cc

Issue 2116783002: [CacheStorage] Don't call GetUsageAndQuota from a scheduled operation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2704
Patch Set: Created 4 years, 5 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/cache_storage/cache_storage_cache.h" 5 #include "content/browser/cache_storage/cache_storage_cache.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 response(std::move(response)), 268 response(std::move(response)),
269 blob_data_handle(std::move(blob_data_handle)), 269 blob_data_handle(std::move(blob_data_handle)),
270 callback(callback) {} 270 callback(callback) {}
271 271
272 // Input parameters to the Put function. 272 // Input parameters to the Put function.
273 scoped_ptr<ServiceWorkerFetchRequest> request; 273 scoped_ptr<ServiceWorkerFetchRequest> request;
274 scoped_ptr<ServiceWorkerResponse> response; 274 scoped_ptr<ServiceWorkerResponse> response;
275 scoped_ptr<storage::BlobDataHandle> blob_data_handle; 275 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
276 CacheStorageCache::ErrorCallback callback; 276 CacheStorageCache::ErrorCallback callback;
277 disk_cache::ScopedEntryPtr cache_entry; 277 disk_cache::ScopedEntryPtr cache_entry;
278 int64_t available_bytes = 0;
279 278
280 private: 279 private:
281 DISALLOW_COPY_AND_ASSIGN(PutContext); 280 DISALLOW_COPY_AND_ASSIGN(PutContext);
282 }; 281 };
283 282
284 // static 283 // static
285 scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache( 284 scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
286 const GURL& origin, 285 const GURL& origin,
287 const std::string& cache_name, 286 const std::string& cache_name,
288 scoped_refptr<net::URLRequestContextGetter> request_context_getter, 287 scoped_refptr<net::URLRequestContextGetter> request_context_getter,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 new MatchAllContext(std::move(request), match_params, pending_callback)); 348 new MatchAllContext(std::move(request), match_params, pending_callback));
350 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl, 349 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl,
351 weak_ptr_factory_.GetWeakPtr(), 350 weak_ptr_factory_.GetWeakPtr(),
352 base::Passed(std::move(context)))); 351 base::Passed(std::move(context))));
353 } 352 }
354 353
355 void CacheStorageCache::BatchOperation( 354 void CacheStorageCache::BatchOperation(
356 const std::vector<CacheStorageBatchOperation>& operations, 355 const std::vector<CacheStorageBatchOperation>& operations,
357 const ErrorCallback& callback) { 356 const ErrorCallback& callback) {
358 if (!LazyInitialize()) { 357 if (!LazyInitialize()) {
359 callback.Run(CACHE_STORAGE_ERROR_STORAGE); 358 base::ThreadTaskRunnerHandle::Get()->PostTask(
359 FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_STORAGE));
360 return; 360 return;
361 } 361 }
362 362
363 // Estimate the required size of the put operations. The size of the deletes
364 // is unknown and not considered.
365 int64_t space_required = 0;
366 for (const auto& operation : operations) {
367 if (operation.operation_type == CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT) {
368 space_required +=
369 operation.request.blob_size + operation.response.blob_size;
370 }
371 }
372 if (space_required > 0) {
373 // GetUsageAndQuota is called before entering a scheduled operation since it
374 // can call Size, another scheduled operation. This is racy. The decision
375 // to commit is made before the scheduled Put operation runs. By the time
376 // Put runs, the cache might already be full and the origin will be larger
377 // than it's supposed to be.
378 quota_manager_proxy_->GetUsageAndQuota(
379 base::ThreadTaskRunnerHandle::Get().get(), origin_,
380 storage::kStorageTypeTemporary,
381 base::Bind(&CacheStorageCache::BatchDidGetUsageAndQuota,
382 weak_ptr_factory_.GetWeakPtr(), operations, callback,
383 space_required));
384 return;
385 }
386
387 BatchDidGetUsageAndQuota(operations, callback, 0 /* space_required */,
388 storage::kQuotaStatusOk, 0 /* usage */,
389 0 /* quota */);
390 }
391
392 void CacheStorageCache::BatchDidGetUsageAndQuota(
393 const std::vector<CacheStorageBatchOperation>& operations,
394 const ErrorCallback& callback,
395 int64_t space_required,
396 storage::QuotaStatusCode status_code,
397 int64_t usage,
398 int64_t quota) {
399 if (status_code != storage::kQuotaStatusOk ||
400 space_required > quota - usage) {
401 base::ThreadTaskRunnerHandle::Get()->PostTask(
402 FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_QUOTA_EXCEEDED));
403 return;
404 }
405
363 scoped_ptr<ErrorCallback> callback_copy(new ErrorCallback(callback)); 406 scoped_ptr<ErrorCallback> callback_copy(new ErrorCallback(callback));
364 ErrorCallback* callback_ptr = callback_copy.get(); 407 ErrorCallback* callback_ptr = callback_copy.get();
365 base::Closure barrier_closure = base::BarrierClosure( 408 base::Closure barrier_closure = base::BarrierClosure(
366 operations.size(), 409 operations.size(),
367 base::Bind(&CacheStorageCache::BatchDidAllOperations, this, 410 base::Bind(&CacheStorageCache::BatchDidAllOperations, this,
368 base::Passed(std::move(callback_copy)))); 411 base::Passed(std::move(callback_copy))));
369 ErrorCallback completion_callback = 412 ErrorCallback completion_callback =
370 base::Bind(&CacheStorageCache::BatchDidOneOperation, this, 413 base::Bind(&CacheStorageCache::BatchDidOneOperation, this,
371 barrier_closure, callback_ptr); 414 barrier_closure, callback_ptr);
372 415
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 } 481 }
439 482
440 void CacheStorageCache::Size(const SizeCallback& callback) { 483 void CacheStorageCache::Size(const SizeCallback& callback) {
441 if (!LazyInitialize()) { 484 if (!LazyInitialize()) {
442 // TODO(jkarlin): Delete caches that can't be initialized. 485 // TODO(jkarlin): Delete caches that can't be initialized.
443 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 486 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
444 base::Bind(callback, 0)); 487 base::Bind(callback, 0));
445 return; 488 return;
446 } 489 }
447 490
448 if (initializing_) { 491 SizeCallback pending_callback =
449 // Note that Size doesn't use the scheduler, see header comments for why. 492 base::Bind(&CacheStorageCache::PendingSizeCallback,
450 pending_size_callbacks_.push_back(callback); 493 weak_ptr_factory_.GetWeakPtr(), callback);
451 return;
452 }
453 494
454 // Run immediately so that we don't deadlock on 495 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::SizeImpl,
455 // CacheStorageCache::PutDidDelete's call to 496 weak_ptr_factory_.GetWeakPtr(),
456 // quota_manager_proxy_->GetUsageAndQuota. 497 pending_callback));
457 SizeImpl(callback);
458 } 498 }
459 499
460 void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) { 500 void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) {
461 if (!LazyInitialize()) { 501 if (!LazyInitialize()) {
462 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 502 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
463 base::Bind(callback, 0)); 503 base::Bind(callback, 0));
464 return; 504 return;
465 } 505 }
466 506
467 SizeCallback pending_callback = 507 SizeCallback pending_callback =
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 weak_ptr_factory_.GetWeakPtr(), 863 weak_ptr_factory_.GetWeakPtr(),
824 base::Passed(std::move(put_context)))); 864 base::Passed(std::move(put_context))));
825 } 865 }
826 866
827 void CacheStorageCache::PutDidDelete(scoped_ptr<PutContext> put_context, 867 void CacheStorageCache::PutDidDelete(scoped_ptr<PutContext> put_context,
828 CacheStorageError delete_error) { 868 CacheStorageError delete_error) {
829 if (backend_state_ != BACKEND_OPEN) { 869 if (backend_state_ != BACKEND_OPEN) {
830 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); 870 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
831 return; 871 return;
832 } 872 }
833 873 std::unique_ptr<disk_cache::Entry*> scoped_entry_ptr(
834 quota_manager_proxy_->GetUsageAndQuota( 874 new disk_cache::Entry*());
835 base::ThreadTaskRunnerHandle::Get().get(), origin_,
836 storage::kStorageTypeTemporary,
837 base::Bind(&CacheStorageCache::PutDidGetUsageAndQuota,
838 weak_ptr_factory_.GetWeakPtr(),
839 base::Passed(std::move(put_context))));
840 }
841
842 void CacheStorageCache::PutDidGetUsageAndQuota(
843 scoped_ptr<PutContext> put_context,
844 storage::QuotaStatusCode status_code,
845 int64_t usage,
846 int64_t quota) {
847 if (backend_state_ != BACKEND_OPEN) {
848 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
849 return;
850 }
851
852 if (status_code != storage::kQuotaStatusOk) {
853 put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
854 return;
855 }
856
857 put_context->available_bytes = quota - usage;
858
859 scoped_ptr<disk_cache::Entry*> scoped_entry_ptr(new disk_cache::Entry*());
860 disk_cache::Entry** entry_ptr = scoped_entry_ptr.get(); 875 disk_cache::Entry** entry_ptr = scoped_entry_ptr.get();
861 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); 876 ServiceWorkerFetchRequest* request_ptr = put_context->request.get();
862 disk_cache::Backend* backend_ptr = backend_.get(); 877 disk_cache::Backend* backend_ptr = backend_.get();
863 878
864 net::CompletionCallback create_entry_callback = base::Bind( 879 net::CompletionCallback create_entry_callback = base::Bind(
865 &CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(), 880 &CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(),
866 base::Passed(std::move(scoped_entry_ptr)), 881 base::Passed(std::move(scoped_entry_ptr)),
867 base::Passed(std::move(put_context))); 882 base::Passed(std::move(put_context)));
868 883
869 int create_rv = backend_ptr->CreateEntry(request_ptr->url.spec(), entry_ptr, 884 int create_rv = backend_ptr->CreateEntry(request_ptr->url.spec(), entry_ptr,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 932
918 scoped_ptr<std::string> serialized(new std::string()); 933 scoped_ptr<std::string> serialized(new std::string());
919 if (!metadata.SerializeToString(serialized.get())) { 934 if (!metadata.SerializeToString(serialized.get())) {
920 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); 935 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
921 return; 936 return;
922 } 937 }
923 938
924 scoped_refptr<net::StringIOBuffer> buffer( 939 scoped_refptr<net::StringIOBuffer> buffer(
925 new net::StringIOBuffer(std::move(serialized))); 940 new net::StringIOBuffer(std::move(serialized)));
926 941
927 int64_t bytes_to_write = buffer->size() + put_context->response->blob_size;
928 if (put_context->available_bytes < bytes_to_write) {
929 put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
930 return;
931 }
932
933 // Get a temporary copy of the entry pointer before passing it in base::Bind. 942 // Get a temporary copy of the entry pointer before passing it in base::Bind.
934 disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get(); 943 disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get();
935 944
936 net::CompletionCallback write_headers_callback = base::Bind( 945 net::CompletionCallback write_headers_callback = base::Bind(
937 &CacheStorageCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(), 946 &CacheStorageCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(),
938 base::Passed(std::move(put_context)), buffer->size()); 947 base::Passed(std::move(put_context)), buffer->size());
939 948
940 rv = temp_entry_ptr->WriteData(INDEX_HEADERS, 0 /* offset */, buffer.get(), 949 rv = temp_entry_ptr->WriteData(INDEX_HEADERS, 0 /* offset */, buffer.get(),
941 buffer->size(), write_headers_callback, 950 buffer->size(), write_headers_callback,
942 true /* truncate */); 951 true /* truncate */);
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 1305
1297 void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error, 1306 void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error,
1298 int cache_size) { 1307 int cache_size) {
1299 cache_size_ = cache_size; 1308 cache_size_ = cache_size;
1300 initializing_ = false; 1309 initializing_ = false;
1301 backend_state_ = (cache_create_error == CACHE_STORAGE_OK && backend_ && 1310 backend_state_ = (cache_create_error == CACHE_STORAGE_OK && backend_ &&
1302 backend_state_ == BACKEND_UNINITIALIZED) 1311 backend_state_ == BACKEND_UNINITIALIZED)
1303 ? BACKEND_OPEN 1312 ? BACKEND_OPEN
1304 : BACKEND_CLOSED; 1313 : BACKEND_CLOSED;
1305 1314
1306 for (const SizeCallback& callback : pending_size_callbacks_)
1307 SizeImpl(callback);
1308 pending_size_callbacks_.clear();
1309
1310 UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", 1315 UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult",
1311 cache_create_error, CACHE_STORAGE_ERROR_LAST + 1); 1316 cache_create_error, CACHE_STORAGE_ERROR_LAST + 1);
1312 1317
1313 scheduler_->CompleteOperationAndRunNext(); 1318 scheduler_->CompleteOperationAndRunNext();
1314 } 1319 }
1315 1320
1316 void CacheStorageCache::PendingClosure(const base::Closure& callback) { 1321 void CacheStorageCache::PendingClosure(const base::Closure& callback) {
1317 base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr(); 1322 base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr();
1318 1323
1319 callback.Run(); 1324 callback.Run();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 storage::BlobDataBuilder blob_data(response->blob_uuid); 1410 storage::BlobDataBuilder blob_data(response->blob_uuid);
1406 1411
1407 disk_cache::Entry* temp_entry = entry.get(); 1412 disk_cache::Entry* temp_entry = entry.get();
1408 blob_data.AppendDiskCacheEntry( 1413 blob_data.AppendDiskCacheEntry(
1409 new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry, 1414 new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry,
1410 INDEX_RESPONSE_BODY); 1415 INDEX_RESPONSE_BODY);
1411 return blob_storage_context_->AddFinishedBlob(&blob_data); 1416 return blob_storage_context_->AddFinishedBlob(&blob_data);
1412 } 1417 }
1413 1418
1414 } // namespace content 1419 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/cache_storage/cache_storage_cache.h ('k') | content/browser/cache_storage/cache_storage_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698