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

Side by Side Diff: storage/browser/blob/blob_storage_context.cc

Issue 1528233004: [Blob] Blob paging to disk patch. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-disk1
Patch Set: Created 5 years 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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_storage_context.h" 5 #include "storage/browser/blob/blob_storage_context.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/thread_task_runner_handle.h" 17 #include "base/thread_task_runner_handle.h"
18 #include "base/trace_event/trace_event.h" 18 #include "base/trace_event/trace_event.h"
19 #include "storage/browser/blob/blob_data_builder.h" 19 #include "storage/browser/blob/blob_data_builder.h"
20 #include "storage/browser/blob/blob_data_handle.h" 20 #include "storage/browser/blob/blob_data_handle.h"
21 #include "storage/browser/blob/blob_data_item.h" 21 #include "storage/browser/blob/blob_data_item.h"
22 #include "storage/browser/blob/blob_data_snapshot.h" 22 #include "storage/browser/blob/blob_data_snapshot.h"
23 #include "storage/browser/blob/shareable_blob_data_item.h" 23 #include "storage/browser/blob/shareable_blob_data_item.h"
24 #include "url/gurl.h" 24 #include "url/gurl.h"
25 25
26 namespace storage { 26 namespace storage {
27 using BlobRegistryEntry = BlobStorageRegistry::Entry; 27 using BlobRegistryEntry = BlobStorageRegistry::Entry;
28 using BlobState = BlobStorageRegistry::BlobState; 28 using BlobState = BlobStorageRegistry::BlobState;
29 29
30 BlobStorageContext::BlobStorageContext() : memory_usage_(0) {} 30 BlobStorageContext::BlobStorageContext() {}
31
32 BlobStorageContext::BlobStorageContext(
33 bool enable_disk,
34 const base::FilePath& blob_storage_dir,
35 scoped_refptr<base::TaskRunner> file_runner)
36 : memory_controller_(enable_disk, blob_storage_dir, file_runner) {}
31 37
32 BlobStorageContext::~BlobStorageContext() { 38 BlobStorageContext::~BlobStorageContext() {
33 } 39 }
34 40
35 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID( 41 scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
36 const std::string& uuid) { 42 const std::string& uuid) {
37 scoped_ptr<BlobDataHandle> result; 43 scoped_ptr<BlobDataHandle> result;
38 BlobRegistryEntry* entry = registry_.GetEntry(uuid); 44 BlobRegistryEntry* entry = registry_.GetEntry(uuid);
39 if (!entry || entry->state != BlobState::ACTIVE || entry->exceeded_memory) { 45 if (!entry || entry->state != BlobState::ACTIVE || entry->exceeded_memory) {
40 LOG(ERROR) << "Could not find blob " << uuid; 46 LOG(ERROR) << "Could not find blob " << uuid;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 case BlobState::CONSTRUCTION: 220 case BlobState::CONSTRUCTION:
215 memory_freeing = entry->data_builder->GetNonsharedMemoryUsage(); 221 memory_freeing = entry->data_builder->GetNonsharedMemoryUsage();
216 entry->data_builder->RemoveBlobFromShareableItems(uuid); 222 entry->data_builder->RemoveBlobFromShareableItems(uuid);
217 break; 223 break;
218 case BlobState::ASYNC_TRANSPORTATION: 224 case BlobState::ASYNC_TRANSPORTATION:
219 case BlobState::RESERVED: 225 case BlobState::RESERVED:
220 break; 226 break;
221 } 227 }
222 DCHECK_LE(memory_freeing, memory_usage_); 228 DCHECK_LE(memory_freeing, memory_usage_);
223 memory_usage_ -= memory_freeing; 229 memory_usage_ -= memory_freeing;
230 for (const auto& item_refptr : entry->data->items_) {
231 if (item_refptr->num_referencing_blob() == 0) {
232 memory_controller_.RemoveBlobItemInRecents(item_refptr->item_id());
233 }
234 }
224 registry_.DeleteEntry(uuid); 235 registry_.DeleteEntry(uuid);
225 } 236 }
226 } 237 }
227 238
228 void BlobStorageContext::BlobEntryExceededMemory(BlobRegistryEntry* entry) { 239 void BlobStorageContext::BlobEntryExceededMemory(BlobRegistryEntry* entry) {
229 // If we're using too much memory, drop this blob's data. 240 // If we're using too much memory, drop this blob's data.
230 // TODO(michaeln): Blob memory storage does not yet spill over to disk, 241 // TODO(michaeln): Blob memory storage does not yet spill over to disk,
231 // as a stop gap, we'll prevent memory usage over a max amount. 242 // as a stop gap, we'll prevent memory usage over a max amount.
232 memory_usage_ -= entry->data_builder->GetNonsharedMemoryUsage(); 243 memory_usage_ -= entry->data_builder->GetNonsharedMemoryUsage();
233 entry->exceeded_memory = true; 244 entry->exceeded_memory = true;
(...skipping 27 matching lines...) Expand all
261 memory_usage_ / 1024); 272 memory_usage_ / 1024);
262 switch (data_element.type()) { 273 switch (data_element.type()) {
263 case DataElement::TYPE_BYTES: 274 case DataElement::TYPE_BYTES:
264 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Bytes", length / 1024); 275 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Bytes", length / 1024);
265 DCHECK(!offset); 276 DCHECK(!offset);
266 if (memory_usage_ + length > kBlobStorageMaxMemoryUsage) { 277 if (memory_usage_ + length > kBlobStorageMaxMemoryUsage) {
267 exceeded_memory = true; 278 exceeded_memory = true;
268 break; 279 break;
269 } 280 }
270 memory_usage_ += length; 281 memory_usage_ += length;
271 target_blob_builder->AppendSharedBlobItem( 282 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
272 new ShareableBlobDataItem(target_blob_uuid, blob_item)); 283 target_blob_uuid, GetAndIncrementItemId(), blob_item));
273 break; 284 break;
274 case DataElement::TYPE_FILE: { 285 case DataElement::TYPE_FILE: {
275 bool full_file = (length == std::numeric_limits<uint64>::max()); 286 bool full_file = (length == std::numeric_limits<uint64>::max());
276 UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", full_file); 287 UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", full_file);
277 if (!full_file) { 288 if (!full_file) {
278 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File", 289 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File",
279 (length - offset) / 1024); 290 (length - offset) / 1024);
280 } 291 }
281 target_blob_builder->AppendSharedBlobItem( 292 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
282 new ShareableBlobDataItem(target_blob_uuid, blob_item)); 293 target_blob_uuid, GetAndIncrementItemId(), blob_item));
283 break; 294 break;
284 } 295 }
285 case DataElement::TYPE_FILE_FILESYSTEM: { 296 case DataElement::TYPE_FILE_FILESYSTEM: {
286 bool full_file = (length == std::numeric_limits<uint64>::max()); 297 bool full_file = (length == std::numeric_limits<uint64>::max());
287 UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown", 298 UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown",
288 full_file); 299 full_file);
289 if (!full_file) { 300 if (!full_file) {
290 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.FileSystem", 301 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.FileSystem",
291 (length - offset) / 1024); 302 (length - offset) / 1024);
292 } 303 }
293 target_blob_builder->AppendSharedBlobItem( 304 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
294 new ShareableBlobDataItem(target_blob_uuid, blob_item)); 305 target_blob_uuid, GetAndIncrementItemId(), blob_item));
295 break; 306 break;
296 } 307 }
297 case DataElement::TYPE_BLOB: { 308 case DataElement::TYPE_BLOB: {
298 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Blob", 309 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Blob",
299 (length - offset) / 1024); 310 (length - offset) / 1024);
300 // We grab the handle to ensure it stays around while we copy it. 311 // We grab the handle to ensure it stays around while we copy it.
301 scoped_ptr<BlobDataHandle> src = 312 scoped_ptr<BlobDataHandle> src =
302 GetBlobDataFromUUID(data_element.blob_uuid()); 313 GetBlobDataFromUUID(data_element.blob_uuid());
303 if (src) { 314 if (src) {
304 BlobRegistryEntry* other_entry = 315 BlobRegistryEntry* other_entry =
305 registry_.GetEntry(data_element.blob_uuid()); 316 registry_.GetEntry(data_element.blob_uuid());
306 DCHECK(other_entry->data); 317 DCHECK(other_entry->data);
307 exceeded_memory = !AppendBlob(target_blob_uuid, *other_entry->data, 318 exceeded_memory = !AppendBlob(target_blob_uuid, *other_entry->data,
308 offset, length, target_blob_builder); 319 offset, length, target_blob_builder);
309 } 320 }
310 break; 321 break;
311 } 322 }
312 case DataElement::TYPE_DISK_CACHE_ENTRY: { 323 case DataElement::TYPE_DISK_CACHE_ENTRY: {
313 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.CacheEntry", 324 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.CacheEntry",
314 (length - offset) / 1024); 325 (length - offset) / 1024);
315 target_blob_builder->AppendSharedBlobItem( 326 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
316 new ShareableBlobDataItem(target_blob_uuid, blob_item)); 327 target_blob_uuid, GetAndIncrementItemId(), blob_item));
317 break; 328 break;
318 } 329 }
319 case DataElement::TYPE_BYTES_DESCRIPTION: 330 case DataElement::TYPE_BYTES_DESCRIPTION:
320 case DataElement::TYPE_UNKNOWN: 331 case DataElement::TYPE_UNKNOWN:
321 NOTREACHED(); 332 NOTREACHED();
322 break; 333 break;
323 } 334 }
324 UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeAfterAppend", 335 UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeAfterAppend",
325 memory_usage_ / 1024); 336 memory_usage_ / 1024);
326 337
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.Bytes", 382 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.Bytes",
372 new_length / 1024); 383 new_length / 1024);
373 if (memory_usage_ + new_length > kBlobStorageMaxMemoryUsage) { 384 if (memory_usage_ + new_length > kBlobStorageMaxMemoryUsage) {
374 return false; 385 return false;
375 } 386 }
376 DCHECK(!item.offset()); 387 DCHECK(!item.offset());
377 scoped_ptr<DataElement> element(new DataElement()); 388 scoped_ptr<DataElement> element(new DataElement());
378 element->SetToBytes(item.bytes() + offset, 389 element->SetToBytes(item.bytes() + offset,
379 static_cast<int64>(new_length)); 390 static_cast<int64>(new_length));
380 memory_usage_ += new_length; 391 memory_usage_ += new_length;
381 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem( 392 target_blob_builder->AppendSharedBlobItem(
382 target_blob_uuid, new BlobDataItem(element.Pass()))); 393 new ShareableBlobDataItem(target_blob_uuid, GetAndIncrementItemId(),
394 new BlobDataItem(element.Pass())));
383 } break; 395 } break;
384 case DataElement::TYPE_FILE: { 396 case DataElement::TYPE_FILE: {
385 DCHECK_NE(item.length(), std::numeric_limits<uint64>::max()) 397 DCHECK_NE(item.length(), std::numeric_limits<uint64>::max())
386 << "We cannot use a section of a file with an unknown length"; 398 << "We cannot use a section of a file with an unknown length";
387 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File", 399 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File",
388 new_length / 1024); 400 new_length / 1024);
389 scoped_ptr<DataElement> element(new DataElement()); 401 scoped_ptr<DataElement> element(new DataElement());
390 element->SetToFilePathRange(item.path(), item.offset() + offset, 402 element->SetToFilePathRange(item.path(), item.offset() + offset,
391 new_length, 403 new_length,
392 item.expected_modification_time()); 404 item.expected_modification_time());
393 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem( 405 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
394 target_blob_uuid, 406 target_blob_uuid, GetAndIncrementItemId(),
395 new BlobDataItem(element.Pass(), item.data_handle_))); 407 new BlobDataItem(element.Pass(), item.data_handle_)));
396 } break; 408 } break;
397 case DataElement::TYPE_FILE_FILESYSTEM: { 409 case DataElement::TYPE_FILE_FILESYSTEM: {
398 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem", 410 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem",
399 new_length / 1024); 411 new_length / 1024);
400 scoped_ptr<DataElement> element(new DataElement()); 412 scoped_ptr<DataElement> element(new DataElement());
401 element->SetToFileSystemUrlRange(item.filesystem_url(), 413 element->SetToFileSystemUrlRange(item.filesystem_url(),
402 item.offset() + offset, new_length, 414 item.offset() + offset, new_length,
403 item.expected_modification_time()); 415 item.expected_modification_time());
404 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem( 416 target_blob_builder->AppendSharedBlobItem(
405 target_blob_uuid, new BlobDataItem(element.Pass()))); 417 new ShareableBlobDataItem(target_blob_uuid, GetAndIncrementItemId(),
418 new BlobDataItem(element.Pass())));
406 } break; 419 } break;
407 case DataElement::TYPE_DISK_CACHE_ENTRY: { 420 case DataElement::TYPE_DISK_CACHE_ENTRY: {
408 scoped_ptr<DataElement> element(new DataElement()); 421 scoped_ptr<DataElement> element(new DataElement());
409 element->SetToDiskCacheEntryRange(item.offset() + offset, 422 element->SetToDiskCacheEntryRange(item.offset() + offset,
410 new_length); 423 new_length);
411 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem( 424 target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
412 target_blob_uuid, 425 target_blob_uuid, GetAndIncrementItemId(),
413 new BlobDataItem(element.Pass(), item.data_handle_, 426 new BlobDataItem(element.Pass(), item.data_handle_,
414 item.disk_cache_entry(), 427 item.disk_cache_entry(),
415 item.disk_cache_stream_index()))); 428 item.disk_cache_stream_index())));
416 } break; 429 } break;
417 case DataElement::TYPE_BYTES_DESCRIPTION: 430 case DataElement::TYPE_BYTES_DESCRIPTION:
418 case DataElement::TYPE_BLOB: 431 case DataElement::TYPE_BLOB:
419 case DataElement::TYPE_UNKNOWN: 432 case DataElement::TYPE_UNKNOWN:
420 CHECK(false) << "Illegal blob item type: " << item.type(); 433 CHECK(false) << "Illegal blob item type: " << item.type();
421 } 434 }
422 length -= new_length; 435 length -= new_length;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return false; 482 return false;
470 } 483 }
471 for (const auto& callback : entry->construction_complete_callbacks) { 484 for (const auto& callback : entry->construction_complete_callbacks) {
472 base::MessageLoop::current()->PostTask(FROM_HERE, 485 base::MessageLoop::current()->PostTask(FROM_HERE,
473 base::Bind(callback, false)); 486 base::Bind(callback, false));
474 } 487 }
475 registry_.DeleteEntry(uuid); 488 registry_.DeleteEntry(uuid);
476 return true; 489 return true;
477 } 490 }
478 491
492 uint64_t BlobStorageContext::GetAndIncrementItemId() {
493 return next_item_id_++;
494 }
495
496 void BlobStorageContext::UpdateItemsInRecents(BlobRegistryEntry* entry) {
497 for (const auto& item_refptr : entry->data->items_) {
498 memory_controller_.UpdateBlobItemInRecents(item_refptr.get());
499 }
500 }
501
479 } // namespace storage 502 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/blob/blob_storage_context.h ('k') | storage/browser/blob/shareable_blob_data_item.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698