| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "components/drive/file_cache.h" | 5 #include "components/drive/file_cache.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/files/file_enumerator.h" | 13 #include "base/files/file_enumerator.h" |
| 14 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "base/sys_info.h" | 20 #include "base/sys_info.h" |
| 21 #include "build/build_config.h" |
| 21 #include "components/drive/drive.pb.h" | 22 #include "components/drive/drive.pb.h" |
| 22 #include "components/drive/drive_api_util.h" | 23 #include "components/drive/drive_api_util.h" |
| 23 #include "components/drive/file_system_core_util.h" | 24 #include "components/drive/file_system_core_util.h" |
| 24 #include "components/drive/resource_metadata_storage.h" | 25 #include "components/drive/resource_metadata_storage.h" |
| 25 #include "google_apis/drive/task_util.h" | 26 #include "google_apis/drive/task_util.h" |
| 26 #include "net/base/filename_util.h" | 27 #include "net/base/filename_util.h" |
| 27 #include "net/base/mime_sniffer.h" | 28 #include "net/base/mime_sniffer.h" |
| 28 #include "net/base/mime_util.h" | 29 #include "net/base/mime_util.h" |
| 29 | 30 |
| 30 namespace drive { | 31 namespace drive { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 } | 80 } |
| 80 | 81 |
| 81 void FileCache::AssertOnSequencedWorkerPool() { | 82 void FileCache::AssertOnSequencedWorkerPool() { |
| 82 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 83 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 83 } | 84 } |
| 84 | 85 |
| 85 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { | 86 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { |
| 86 return cache_file_directory_.IsParent(path); | 87 return cache_file_directory_.IsParent(path); |
| 87 } | 88 } |
| 88 | 89 |
| 89 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { | 90 bool FileCache::FreeDiskSpaceIfNeededFor(int64_t num_bytes) { |
| 90 AssertOnSequencedWorkerPool(); | 91 AssertOnSequencedWorkerPool(); |
| 91 | 92 |
| 92 // Do nothing and return if we have enough space. | 93 // Do nothing and return if we have enough space. |
| 93 if (GetAvailableSpace() >= num_bytes) | 94 if (GetAvailableSpace() >= num_bytes) |
| 94 return true; | 95 return true; |
| 95 | 96 |
| 96 // Otherwise, try to free up the disk space. | 97 // Otherwise, try to free up the disk space. |
| 97 DVLOG(1) << "Freeing up disk space for " << num_bytes; | 98 DVLOG(1) << "Freeing up disk space for " << num_bytes; |
| 98 | 99 |
| 99 // Remove all files which have no corresponding cache entries. | 100 // Remove all files which have no corresponding cache entries. |
| 100 base::FileEnumerator enumerator(cache_file_directory_, | 101 base::FileEnumerator enumerator(cache_file_directory_, |
| 101 false, // not recursive | 102 false, // not recursive |
| 102 base::FileEnumerator::FILES); | 103 base::FileEnumerator::FILES); |
| 103 ResourceEntry entry; | 104 ResourceEntry entry; |
| 104 for (base::FilePath current = enumerator.Next(); !current.empty(); | 105 for (base::FilePath current = enumerator.Next(); !current.empty(); |
| 105 current = enumerator.Next()) { | 106 current = enumerator.Next()) { |
| 106 const std::string id = GetIdFromPath(current); | 107 const std::string id = GetIdFromPath(current); |
| 107 const FileError error = storage_->GetEntry(id, &entry); | 108 const FileError error = storage_->GetEntry(id, &entry); |
| 108 | 109 |
| 109 if (error == FILE_ERROR_NOT_FOUND) | 110 if (error == FILE_ERROR_NOT_FOUND) |
| 110 base::DeleteFile(current, false /* recursive */); | 111 base::DeleteFile(current, false /* recursive */); |
| 111 else if (error != FILE_ERROR_OK) | 112 else if (error != FILE_ERROR_OK) |
| 112 return false; | 113 return false; |
| 113 } | 114 } |
| 114 | 115 |
| 115 // Check available space again. If we have enough space here, do nothing. | 116 // Check available space again. If we have enough space here, do nothing. |
| 116 const int64 available_space = GetAvailableSpace(); | 117 const int64_t available_space = GetAvailableSpace(); |
| 117 if (available_space >= num_bytes) | 118 if (available_space >= num_bytes) |
| 118 return true; | 119 return true; |
| 119 | 120 |
| 120 const int64 requested_space = num_bytes - available_space; | 121 const int64_t requested_space = num_bytes - available_space; |
| 121 | 122 |
| 122 // Put all entries in priority queue where latest entry becomes top. | 123 // Put all entries in priority queue where latest entry becomes top. |
| 123 std::priority_queue<CacheInfo, std::vector<CacheInfo>, CacheInfoLatestCompare> | 124 std::priority_queue<CacheInfo, std::vector<CacheInfo>, CacheInfoLatestCompare> |
| 124 cache_info_queue; | 125 cache_info_queue; |
| 125 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); | 126 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); |
| 126 for (; !it->IsAtEnd(); it->Advance()) { | 127 for (; !it->IsAtEnd(); it->Advance()) { |
| 127 if (IsEvictable(it->GetID(), it->GetValue())) { | 128 if (IsEvictable(it->GetID(), it->GetValue())) { |
| 128 const ResourceEntry& entry = it->GetValue(); | 129 const ResourceEntry& entry = it->GetValue(); |
| 129 | 130 |
| 130 const base::FilePath& cache_path = GetCacheFilePath(entry.local_id()); | 131 const base::FilePath& cache_path = GetCacheFilePath(entry.local_id()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 151 return false; | 152 return false; |
| 152 | 153 |
| 153 // Copy entries to the vector. This becomes last-accessed desc order. | 154 // Copy entries to the vector. This becomes last-accessed desc order. |
| 154 std::vector<CacheInfo> cache_info_list; | 155 std::vector<CacheInfo> cache_info_list; |
| 155 while (!cache_info_queue.empty()) { | 156 while (!cache_info_queue.empty()) { |
| 156 cache_info_list.push_back(cache_info_queue.top()); | 157 cache_info_list.push_back(cache_info_queue.top()); |
| 157 cache_info_queue.pop(); | 158 cache_info_queue.pop(); |
| 158 } | 159 } |
| 159 | 160 |
| 160 // Update DB and delete files with accessing to the vector in ascending order. | 161 // Update DB and delete files with accessing to the vector in ascending order. |
| 161 int64 evicted_cache_size = 0; | 162 int64_t evicted_cache_size = 0; |
| 162 auto iter = cache_info_list.rbegin(); | 163 auto iter = cache_info_list.rbegin(); |
| 163 while (evicted_cache_size < requested_space && | 164 while (evicted_cache_size < requested_space && |
| 164 iter != cache_info_list.rend()) { | 165 iter != cache_info_list.rend()) { |
| 165 const CacheInfo& cache_info = *iter; | 166 const CacheInfo& cache_info = *iter; |
| 166 | 167 |
| 167 // Update DB. | 168 // Update DB. |
| 168 ResourceEntry entry = cache_info.second; | 169 ResourceEntry entry = cache_info.second; |
| 169 entry.mutable_file_specific_info()->clear_cache_state(); | 170 entry.mutable_file_specific_info()->clear_cache_state(); |
| 170 storage_->PutEntry(entry); | 171 storage_->PutEntry(entry); |
| 171 | 172 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 const std::string& md5, | 224 const std::string& md5, |
| 224 const base::FilePath& source_path, | 225 const base::FilePath& source_path, |
| 225 FileOperationType file_operation_type) { | 226 FileOperationType file_operation_type) { |
| 226 AssertOnSequencedWorkerPool(); | 227 AssertOnSequencedWorkerPool(); |
| 227 | 228 |
| 228 ResourceEntry entry; | 229 ResourceEntry entry; |
| 229 FileError error = storage_->GetEntry(id, &entry); | 230 FileError error = storage_->GetEntry(id, &entry); |
| 230 if (error != FILE_ERROR_OK) | 231 if (error != FILE_ERROR_OK) |
| 231 return error; | 232 return error; |
| 232 | 233 |
| 233 int64 file_size = 0; | 234 int64_t file_size = 0; |
| 234 if (file_operation_type == FILE_OPERATION_COPY) { | 235 if (file_operation_type == FILE_OPERATION_COPY) { |
| 235 if (!base::GetFileSize(source_path, &file_size)) { | 236 if (!base::GetFileSize(source_path, &file_size)) { |
| 236 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); | 237 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); |
| 237 return FILE_ERROR_FAILED; | 238 return FILE_ERROR_FAILED; |
| 238 } | 239 } |
| 239 } | 240 } |
| 240 if (!FreeDiskSpaceIfNeededFor(file_size)) | 241 if (!FreeDiskSpaceIfNeededFor(file_size)) |
| 241 return FILE_ERROR_NO_LOCAL_SPACE; | 242 return FILE_ERROR_NO_LOCAL_SPACE; |
| 242 | 243 |
| 243 // If file is mounted, return error. | 244 // If file is mounted, return error. |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 return error; | 634 return error; |
| 634 | 635 |
| 635 std::set<std::string>::iterator it = mounted_files_.find(id); | 636 std::set<std::string>::iterator it = mounted_files_.find(id); |
| 636 if (it == mounted_files_.end()) | 637 if (it == mounted_files_.end()) |
| 637 return FILE_ERROR_INVALID_OPERATION; | 638 return FILE_ERROR_INVALID_OPERATION; |
| 638 | 639 |
| 639 mounted_files_.erase(it); | 640 mounted_files_.erase(it); |
| 640 return FILE_ERROR_OK; | 641 return FILE_ERROR_OK; |
| 641 } | 642 } |
| 642 | 643 |
| 643 int64 FileCache::GetAvailableSpace() { | 644 int64_t FileCache::GetAvailableSpace() { |
| 644 int64 free_space = 0; | 645 int64_t free_space = 0; |
| 645 if (free_disk_space_getter_) | 646 if (free_disk_space_getter_) |
| 646 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); | 647 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); |
| 647 else | 648 else |
| 648 free_space = base::SysInfo::AmountOfFreeDiskSpace(cache_file_directory_); | 649 free_space = base::SysInfo::AmountOfFreeDiskSpace(cache_file_directory_); |
| 649 | 650 |
| 650 // Subtract this as if this portion does not exist. | 651 // Subtract this as if this portion does not exist. |
| 651 free_space -= drive::internal::kMinFreeSpaceInBytes; | 652 free_space -= drive::internal::kMinFreeSpaceInBytes; |
| 652 return free_space; | 653 return free_space; |
| 653 } | 654 } |
| 654 | 655 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 | 705 |
| 705 bool FileCache::IsEvictable(const std::string& id, const ResourceEntry& entry) { | 706 bool FileCache::IsEvictable(const std::string& id, const ResourceEntry& entry) { |
| 706 return entry.file_specific_info().has_cache_state() && | 707 return entry.file_specific_info().has_cache_state() && |
| 707 !entry.file_specific_info().cache_state().is_pinned() && | 708 !entry.file_specific_info().cache_state().is_pinned() && |
| 708 !entry.file_specific_info().cache_state().is_dirty() && | 709 !entry.file_specific_info().cache_state().is_dirty() && |
| 709 !mounted_files_.count(id); | 710 !mounted_files_.count(id); |
| 710 } | 711 } |
| 711 | 712 |
| 712 } // namespace internal | 713 } // namespace internal |
| 713 } // namespace drive | 714 } // namespace drive |
| OLD | NEW |