OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_memory_controller.h" | 5 #include "storage/browser/blob/blob_memory_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 namespace { | 38 namespace { |
39 using FileCreationInfo = BlobMemoryController::FileCreationInfo; | 39 using FileCreationInfo = BlobMemoryController::FileCreationInfo; |
40 using MemoryAllocation = BlobMemoryController::MemoryAllocation; | 40 using MemoryAllocation = BlobMemoryController::MemoryAllocation; |
41 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask; | 41 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask; |
42 | 42 |
43 File::Error CreateBlobDirectory(const FilePath& blob_storage_dir) { | 43 File::Error CreateBlobDirectory(const FilePath& blob_storage_dir) { |
44 File::Error error = File::FILE_OK; | 44 File::Error error = File::FILE_OK; |
45 base::CreateDirectoryAndGetError(blob_storage_dir, &error); | 45 base::CreateDirectoryAndGetError(blob_storage_dir, &error); |
46 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.CreateDirectoryResult", -error, | 46 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.CreateDirectoryResult", -error, |
47 -File::FILE_ERROR_MAX); | 47 -File::FILE_ERROR_MAX); |
48 if (error != File::FILE_OK) | |
49 LOG(ERROR) << "Error creating blob storage directory: " << error; | |
michaeln
2016/12/02 20:41:07
you can use LOG_IF here
dmurph
2016/12/02 21:53:07
Done.
| |
48 return error; | 50 return error; |
49 } | 51 } |
50 | 52 |
51 void DestructFile(File infos_without_references) {} | 53 void DestructFile(File infos_without_references) {} |
52 | 54 |
53 // Used for new unpopulated file items. Caller must populate file reference in | 55 // Used for new unpopulated file items. Caller must populate file reference in |
54 // returned FileCreationInfos. | 56 // returned FileCreationInfos. |
55 std::pair<std::vector<FileCreationInfo>, File::Error> CreateEmptyFiles( | 57 std::pair<std::vector<FileCreationInfo>, File::Error> CreateEmptyFiles( |
56 const FilePath& blob_storage_dir, | 58 const FilePath& blob_storage_dir, |
57 scoped_refptr<base::TaskRunner> file_task_runner, | 59 scoped_refptr<base::TaskRunner> file_task_runner, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 for (const auto& item : unreserved_file_items) { | 154 for (const auto& item : unreserved_file_items) { |
153 const DataElement& element = item->item()->data_element(); | 155 const DataElement& element = item->item()->data_element(); |
154 uint64_t file_id = BlobDataBuilder::GetFutureFileID(element); | 156 uint64_t file_id = BlobDataBuilder::GetFutureFileID(element); |
155 auto it = file_id_to_sizes.find(file_id); | 157 auto it = file_id_to_sizes.find(file_id); |
156 if (it != file_id_to_sizes.end()) | 158 if (it != file_id_to_sizes.end()) |
157 it->second = std::max(it->second, element.offset() + element.length()); | 159 it->second = std::max(it->second, element.offset() + element.length()); |
158 else | 160 else |
159 file_id_to_sizes[file_id] = element.offset() + element.length(); | 161 file_id_to_sizes[file_id] = element.offset() + element.length(); |
160 total_size_output += element.length(); | 162 total_size_output += element.length(); |
161 } | 163 } |
164 uint64_t sizes_from_files = 0; | |
162 for (const auto& size_pair : file_id_to_sizes) { | 165 for (const auto& size_pair : file_id_to_sizes) { |
163 file_sizes_output->push_back(size_pair.second); | 166 file_sizes_output->push_back(size_pair.second); |
167 sizes_from_files += size_pair.second; | |
164 } | 168 } |
169 DCHECK_EQ(sizes_from_files, total_size_output) | |
michaeln
2016/12/02 20:41:07
can we use std::accumulate here to avoid the unuse
dmurph
2016/12/02 21:53:07
Done.
| |
170 << "Illegal builder configuration, temporary files must be totally used."; | |
165 return total_size_output; | 171 return total_size_output; |
166 } | 172 } |
167 | 173 |
168 } // namespace | 174 } // namespace |
169 | 175 |
170 FileCreationInfo::FileCreationInfo() {} | 176 FileCreationInfo::FileCreationInfo() {} |
171 FileCreationInfo::~FileCreationInfo() { | 177 FileCreationInfo::~FileCreationInfo() { |
172 if (file.IsValid()) { | 178 if (file.IsValid()) { |
173 DCHECK(file_deletion_runner); | 179 DCHECK(file_deletion_runner); |
174 file_deletion_runner->PostTask( | 180 file_deletion_runner->PostTask( |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 base::PostTaskAndReplyWithResult( | 297 base::PostTaskAndReplyWithResult( |
292 controller_->file_runner_.get(), FROM_HERE, | 298 controller_->file_runner_.get(), FROM_HERE, |
293 base::Bind(&CreateEmptyFiles, controller_->blob_storage_dir_, | 299 base::Bind(&CreateEmptyFiles, controller_->blob_storage_dir_, |
294 controller_->file_runner_, base::Passed(&file_paths)), | 300 controller_->file_runner_, base::Passed(&file_paths)), |
295 base::Bind(&FileQuotaAllocationTask::OnCreateEmptyFiles, | 301 base::Bind(&FileQuotaAllocationTask::OnCreateEmptyFiles, |
296 weak_factory_.GetWeakPtr(), base::Passed(&references))); | 302 weak_factory_.GetWeakPtr(), base::Passed(&references))); |
297 controller_->RecordTracingCounters(); | 303 controller_->RecordTracingCounters(); |
298 } | 304 } |
299 ~FileQuotaAllocationTask() override {} | 305 ~FileQuotaAllocationTask() override {} |
300 | 306 |
301 void RunDoneCallback(bool success, std::vector<FileCreationInfo> file_info) { | 307 void RunDoneCallback(std::vector<FileCreationInfo> file_info, bool success) { |
302 // Make sure we clear the weak pointers we gave to the caller beforehand. | 308 // Make sure we clear the weak pointers we gave to the caller beforehand. |
303 weak_factory_.InvalidateWeakPtrs(); | 309 weak_factory_.InvalidateWeakPtrs(); |
304 | 310 |
305 // We want to destroy this object on the exit of this method if we were | 311 // We want to destroy this object on the exit of this method if we were |
306 // successful. | 312 // successful. |
307 std::unique_ptr<FileQuotaAllocationTask> this_object; | 313 std::unique_ptr<FileQuotaAllocationTask> this_object; |
308 if (success) { | 314 if (success) { |
309 for (auto& item : pending_items_) { | 315 for (auto& item : pending_items_) { |
310 item->set_state(ShareableBlobDataItem::QUOTA_GRANTED); | 316 item->set_state(ShareableBlobDataItem::QUOTA_GRANTED); |
311 } | 317 } |
312 this_object = std::move(*my_list_position_); | 318 this_object = std::move(*my_list_position_); |
313 controller_->pending_file_quota_tasks_.erase(my_list_position_); | 319 controller_->pending_file_quota_tasks_.erase(my_list_position_); |
314 } | 320 } |
315 | 321 |
316 done_callback_.Run(success, std::move(file_info)); | 322 done_callback_.Run(std::move(file_info), success); |
317 } | 323 } |
318 | 324 |
319 base::WeakPtr<QuotaAllocationTask> GetWeakPtr() { | 325 base::WeakPtr<QuotaAllocationTask> GetWeakPtr() { |
320 return weak_factory_.GetWeakPtr(); | 326 return weak_factory_.GetWeakPtr(); |
321 } | 327 } |
322 | 328 |
323 void Cancel() override { | 329 void Cancel() override { |
324 // This call destroys this object. We rely on ShareableFileReference's | 330 // This call destroys this object. We rely on ShareableFileReference's |
325 // final release callback for disk_usage_ accounting. | 331 // final release callback for disk_usage_ accounting. |
326 controller_->pending_file_quota_tasks_.erase(my_list_position_); | 332 controller_->pending_file_quota_tasks_.erase(my_list_position_); |
327 } | 333 } |
328 | 334 |
329 void OnCreateEmptyFiles( | 335 void OnCreateEmptyFiles( |
330 std::vector<scoped_refptr<ShareableFileReference>> references, | 336 std::vector<scoped_refptr<ShareableFileReference>> references, |
331 std::pair<std::vector<FileCreationInfo>, File::Error> files_and_error) { | 337 std::pair<std::vector<FileCreationInfo>, File::Error> files_and_error) { |
332 auto& files = files_and_error.first; | 338 auto& files = files_and_error.first; |
333 if (files.empty()) { | 339 if (files.empty()) { |
334 DCHECK_GE(controller_->disk_used_, allocation_size_); | 340 DCHECK_GE(controller_->disk_used_, allocation_size_); |
335 controller_->disk_used_ -= allocation_size_; | 341 controller_->disk_used_ -= allocation_size_; |
336 // This will call our callback and delete the object correctly. | 342 // This will call our callback and delete the object correctly. |
337 controller_->DisableFilePaging(files_and_error.second); | 343 controller_->DisableFilePaging(files_and_error.second); |
338 return; | 344 return; |
339 } | 345 } |
340 DCHECK_EQ(files.size(), references.size()); | 346 DCHECK_EQ(files.size(), references.size()); |
341 for (size_t i = 0; i < files.size(); i++) { | 347 for (size_t i = 0; i < files.size(); i++) { |
342 files[i].file_reference = std::move(references[i]); | 348 files[i].file_reference = std::move(references[i]); |
343 } | 349 } |
344 RunDoneCallback(true, std::move(files)); | 350 RunDoneCallback(std::move(files), true); |
345 } | 351 } |
346 | 352 |
347 // The my_list_position_ iterator is stored so that we can remove ourself | 353 // The my_list_position_ iterator is stored so that we can remove ourself |
348 // from the task list when we are cancelled. | 354 // from the task list when we are cancelled. |
349 void set_my_list_position( | 355 void set_my_list_position( |
350 PendingFileQuotaTaskList::iterator my_list_position) { | 356 PendingFileQuotaTaskList::iterator my_list_position) { |
351 my_list_position_ = my_list_position; | 357 my_list_position_ = my_list_position; |
352 } | 358 } |
353 | 359 |
354 private: | 360 private: |
(...skipping 17 matching lines...) Expand all Loading... | |
372 file_runner_(std::move(file_runner)), | 378 file_runner_(std::move(file_runner)), |
373 populated_memory_items_( | 379 populated_memory_items_( |
374 base::MRUCache<uint64_t, ShareableBlobDataItem*>::NO_AUTO_EVICT), | 380 base::MRUCache<uint64_t, ShareableBlobDataItem*>::NO_AUTO_EVICT), |
375 weak_factory_(this) {} | 381 weak_factory_(this) {} |
376 | 382 |
377 BlobMemoryController::~BlobMemoryController() {} | 383 BlobMemoryController::~BlobMemoryController() {} |
378 | 384 |
379 void BlobMemoryController::DisableFilePaging(base::File::Error reason) { | 385 void BlobMemoryController::DisableFilePaging(base::File::Error reason) { |
380 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.PagingDisabled", -reason, | 386 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.PagingDisabled", -reason, |
381 -File::FILE_ERROR_MAX); | 387 -File::FILE_ERROR_MAX); |
388 LOG(ERROR) << "Blob storage paging disabled due to: " << reason; | |
382 file_paging_enabled_ = false; | 389 file_paging_enabled_ = false; |
383 in_flight_memory_used_ = 0; | 390 in_flight_memory_used_ = 0; |
384 items_paging_to_file_.clear(); | 391 items_paging_to_file_.clear(); |
385 pending_evictions_ = 0; | 392 pending_evictions_ = 0; |
386 pending_memory_quota_total_size_ = 0; | 393 pending_memory_quota_total_size_ = 0; |
387 populated_memory_items_.Clear(); | 394 populated_memory_items_.Clear(); |
388 populated_memory_items_bytes_ = 0; | 395 populated_memory_items_bytes_ = 0; |
389 file_runner_ = nullptr; | 396 file_runner_ = nullptr; |
390 | 397 |
391 PendingMemoryQuotaTaskList old_memory_tasks; | 398 PendingMemoryQuotaTaskList old_memory_tasks; |
392 PendingFileQuotaTaskList old_file_tasks; | 399 PendingFileQuotaTaskList old_file_tasks; |
393 std::swap(old_memory_tasks, pending_memory_quota_tasks_); | 400 std::swap(old_memory_tasks, pending_memory_quota_tasks_); |
394 std::swap(old_file_tasks, pending_file_quota_tasks_); | 401 std::swap(old_file_tasks, pending_file_quota_tasks_); |
395 | 402 |
396 // Don't call the callbacks until we have a consistent state. | 403 // Don't call the callbacks until we have a consistent state. |
397 for (auto& memory_request : old_memory_tasks) { | 404 for (auto& memory_request : old_memory_tasks) { |
398 memory_request->RunDoneCallback(false); | 405 memory_request->RunDoneCallback(false); |
399 } | 406 } |
400 for (auto& file_request : old_file_tasks) { | 407 for (auto& file_request : old_file_tasks) { |
401 file_request->RunDoneCallback(false, std::vector<FileCreationInfo>()); | 408 file_request->RunDoneCallback(std::vector<FileCreationInfo>(), false); |
402 } | 409 } |
403 } | 410 } |
404 | 411 |
405 BlobMemoryController::Strategy BlobMemoryController::DetermineStrategy( | 412 BlobMemoryController::Strategy BlobMemoryController::DetermineStrategy( |
406 size_t preemptive_transported_bytes, | 413 size_t preemptive_transported_bytes, |
407 uint64_t total_transportation_bytes) const { | 414 uint64_t total_transportation_bytes) const { |
408 if (total_transportation_bytes == 0) | 415 if (total_transportation_bytes == 0) |
409 return Strategy::NONE_NEEDED; | 416 return Strategy::NONE_NEEDED; |
410 if (!CanReserveQuota(total_transportation_bytes)) | 417 if (!CanReserveQuota(total_transportation_bytes)) |
411 return Strategy::TOO_LARGE; | 418 return Strategy::TOO_LARGE; |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 MaybeGrantPendingMemoryRequests(); | 745 MaybeGrantPendingMemoryRequests(); |
739 } | 746 } |
740 | 747 |
741 void BlobMemoryController::OnBlobFileDelete(uint64_t size, | 748 void BlobMemoryController::OnBlobFileDelete(uint64_t size, |
742 const FilePath& path) { | 749 const FilePath& path) { |
743 DCHECK_LE(size, disk_used_); | 750 DCHECK_LE(size, disk_used_); |
744 disk_used_ -= size; | 751 disk_used_ -= size; |
745 } | 752 } |
746 | 753 |
747 } // namespace storage | 754 } // namespace storage |
OLD | NEW |