| 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 "chrome/browser/chromeos/drive/file_cache.h" | 5 #include "chrome/browser/chromeos/drive/file_cache.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 base::Unretained(this), | 478 base::Unretained(this), |
| 479 resource_id, md5, source_path, file_operation_type), | 479 resource_id, md5, source_path, file_operation_type), |
| 480 callback); | 480 callback); |
| 481 } | 481 } |
| 482 | 482 |
| 483 FileError FileCache::Store(const std::string& resource_id, | 483 FileError FileCache::Store(const std::string& resource_id, |
| 484 const std::string& md5, | 484 const std::string& md5, |
| 485 const base::FilePath& source_path, | 485 const base::FilePath& source_path, |
| 486 FileOperationType file_operation_type) { | 486 FileOperationType file_operation_type) { |
| 487 AssertOnSequencedWorkerPool(); | 487 AssertOnSequencedWorkerPool(); |
| 488 return StoreInternal(resource_id, md5, source_path, file_operation_type, | 488 return StoreInternal(resource_id, md5, source_path, file_operation_type); |
| 489 CACHED_FILE_FROM_SERVER); | |
| 490 } | |
| 491 | |
| 492 void FileCache::StoreLocallyModifiedOnUIThread( | |
| 493 const std::string& resource_id, | |
| 494 const std::string& md5, | |
| 495 const base::FilePath& source_path, | |
| 496 FileOperationType file_operation_type, | |
| 497 const FileOperationCallback& callback) { | |
| 498 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 499 DCHECK(!callback.is_null()); | |
| 500 | |
| 501 base::PostTaskAndReplyWithResult( | |
| 502 blocking_task_runner_, | |
| 503 FROM_HERE, | |
| 504 base::Bind(&FileCache::StoreInternal, | |
| 505 base::Unretained(this), | |
| 506 resource_id, md5, source_path, file_operation_type, | |
| 507 CACHED_FILE_LOCALLY_MODIFIED), | |
| 508 base::Bind(&FileCache::OnCommitDirty, | |
| 509 weak_ptr_factory_.GetWeakPtr(), resource_id, callback)); | |
| 510 } | 489 } |
| 511 | 490 |
| 512 void FileCache::PinOnUIThread(const std::string& resource_id, | 491 void FileCache::PinOnUIThread(const std::string& resource_id, |
| 513 const std::string& md5, | 492 const std::string& md5, |
| 514 const FileOperationCallback& callback) { | 493 const FileOperationCallback& callback) { |
| 515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 494 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 516 DCHECK(!callback.is_null()); | 495 DCHECK(!callback.is_null()); |
| 517 | 496 |
| 518 base::PostTaskAndReplyWithResult( | 497 base::PostTaskAndReplyWithResult( |
| 519 blocking_task_runner_, | 498 blocking_task_runner_, |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 return FILE_ERROR_FAILED; | 705 return FILE_ERROR_FAILED; |
| 727 | 706 |
| 728 // Now that file operations have completed, update metadata. | 707 // Now that file operations have completed, update metadata. |
| 729 cache_entry.set_md5(md5); | 708 cache_entry.set_md5(md5); |
| 730 cache_entry.set_is_dirty(true); | 709 cache_entry.set_is_dirty(true); |
| 731 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); | 710 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); |
| 732 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); | 711 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); |
| 733 return FILE_ERROR_OK; | 712 return FILE_ERROR_OK; |
| 734 } | 713 } |
| 735 | 714 |
| 736 void FileCache::CommitDirtyOnUIThread(const std::string& resource_id, | |
| 737 const std::string& md5, | |
| 738 const FileOperationCallback& callback) { | |
| 739 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 740 DCHECK(!callback.is_null()); | |
| 741 | |
| 742 // TODO(hashimoto): Move logic around OnCommitDirty to FileSystem and remove | |
| 743 // this method. | |
| 744 base::MessageLoopProxy::current()->PostTask( | |
| 745 FROM_HERE, | |
| 746 base::Bind(&FileCache::OnCommitDirty, | |
| 747 weak_ptr_factory_.GetWeakPtr(), resource_id, callback, | |
| 748 FILE_ERROR_OK)); | |
| 749 } | |
| 750 | |
| 751 FileError FileCache::ClearDirty(const std::string& resource_id, | 715 FileError FileCache::ClearDirty(const std::string& resource_id, |
| 752 const std::string& md5) { | 716 const std::string& md5) { |
| 753 AssertOnSequencedWorkerPool(); | 717 AssertOnSequencedWorkerPool(); |
| 754 | 718 |
| 755 // |md5| is the new .<md5> extension to rename the file to. | 719 // |md5| is the new .<md5> extension to rename the file to. |
| 756 // So, search for entry in cache without comparing md5. | 720 // So, search for entry in cache without comparing md5. |
| 757 FileCacheEntry cache_entry; | 721 FileCacheEntry cache_entry; |
| 758 | 722 |
| 759 // Clearing a dirty file means its entry and actual file blob must exist in | 723 // Clearing a dirty file means its entry and actual file blob must exist in |
| 760 // cache. | 724 // cache. |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 } | 899 } |
| 936 | 900 |
| 937 void FileCache::DestroyOnBlockingPool() { | 901 void FileCache::DestroyOnBlockingPool() { |
| 938 AssertOnSequencedWorkerPool(); | 902 AssertOnSequencedWorkerPool(); |
| 939 delete this; | 903 delete this; |
| 940 } | 904 } |
| 941 | 905 |
| 942 FileError FileCache::StoreInternal(const std::string& resource_id, | 906 FileError FileCache::StoreInternal(const std::string& resource_id, |
| 943 const std::string& md5, | 907 const std::string& md5, |
| 944 const base::FilePath& source_path, | 908 const base::FilePath& source_path, |
| 945 FileOperationType file_operation_type, | 909 FileOperationType file_operation_type) { |
| 946 CachedFileOrigin origin) { | |
| 947 AssertOnSequencedWorkerPool(); | 910 AssertOnSequencedWorkerPool(); |
| 948 | 911 |
| 949 int64 file_size = 0; | 912 int64 file_size = 0; |
| 950 if (file_operation_type == FILE_OPERATION_COPY) { | 913 if (file_operation_type == FILE_OPERATION_COPY) { |
| 951 if (!file_util::GetFileSize(source_path, &file_size)) { | 914 if (!file_util::GetFileSize(source_path, &file_size)) { |
| 952 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); | 915 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); |
| 953 return FILE_ERROR_FAILED; | 916 return FILE_ERROR_FAILED; |
| 954 } | 917 } |
| 955 } | 918 } |
| 956 if (!FreeDiskSpaceIfNeededFor(file_size)) | 919 if (!FreeDiskSpaceIfNeededFor(file_size)) |
| 957 return FILE_ERROR_NO_SPACE; | 920 return FILE_ERROR_NO_SPACE; |
| 958 | 921 |
| 959 FileCacheEntry cache_entry; | 922 FileCacheEntry cache_entry; |
| 960 GetCacheEntry(resource_id, std::string(), &cache_entry); | 923 GetCacheEntry(resource_id, std::string(), &cache_entry); |
| 961 | 924 |
| 962 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; | 925 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; |
| 963 if (origin == CACHED_FILE_FROM_SERVER) { | 926 // If file is dirty or mounted, return error. |
| 964 // If file is dirty or mounted, return error. | 927 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { |
| 965 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { | 928 LOG(WARNING) << "Can't store a file to replace a " |
| 966 LOG(WARNING) << "Can't store a file to replace a " | 929 << (cache_entry.is_dirty() ? "dirty" : "mounted") |
| 967 << (cache_entry.is_dirty() ? "dirty" : "mounted") | 930 << " file: res_id=" << resource_id |
| 968 << " file: res_id=" << resource_id | 931 << ", md5=" << md5; |
| 969 << ", md5=" << md5; | 932 return FILE_ERROR_IN_USE; |
| 970 return FILE_ERROR_IN_USE; | |
| 971 } | |
| 972 | |
| 973 // If file was previously pinned, store it in persistent dir. | |
| 974 if (cache_entry.is_pinned()) | |
| 975 sub_dir_type = CACHE_TYPE_PERSISTENT; | |
| 976 } else { | |
| 977 sub_dir_type = CACHE_TYPE_PERSISTENT; | |
| 978 } | 933 } |
| 979 | 934 |
| 935 // If file was previously pinned, store it in persistent dir. |
| 936 if (cache_entry.is_pinned()) |
| 937 sub_dir_type = CACHE_TYPE_PERSISTENT; |
| 938 |
| 980 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type, | 939 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type, |
| 981 origin); | 940 CACHED_FILE_FROM_SERVER); |
| 982 bool success = false; | 941 bool success = false; |
| 983 switch (file_operation_type) { | 942 switch (file_operation_type) { |
| 984 case FILE_OPERATION_MOVE: | 943 case FILE_OPERATION_MOVE: |
| 985 success = MoveFile(source_path, dest_path); | 944 success = MoveFile(source_path, dest_path); |
| 986 break; | 945 break; |
| 987 case FILE_OPERATION_COPY: | 946 case FILE_OPERATION_COPY: |
| 988 success = CopyFile(source_path, dest_path); | 947 success = CopyFile(source_path, dest_path); |
| 989 break; | 948 break; |
| 990 default: | 949 default: |
| 991 NOTREACHED(); | 950 NOTREACHED(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1011 } | 970 } |
| 1012 | 971 |
| 1013 // Delete files that match |stale_filenames_pattern| except for |dest_path|. | 972 // Delete files that match |stale_filenames_pattern| except for |dest_path|. |
| 1014 DeleteFilesSelectively(stale_filenames_pattern, dest_path); | 973 DeleteFilesSelectively(stale_filenames_pattern, dest_path); |
| 1015 | 974 |
| 1016 if (success) { | 975 if (success) { |
| 1017 // Now that file operations have completed, update metadata. | 976 // Now that file operations have completed, update metadata. |
| 1018 cache_entry.set_md5(md5); | 977 cache_entry.set_md5(md5); |
| 1019 cache_entry.set_is_present(true); | 978 cache_entry.set_is_present(true); |
| 1020 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); | 979 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); |
| 1021 cache_entry.set_is_dirty(origin == CACHED_FILE_LOCALLY_MODIFIED); | 980 cache_entry.set_is_dirty(false); |
| 1022 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); | 981 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); |
| 1023 } | 982 } |
| 1024 | 983 |
| 1025 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED; | 984 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED; |
| 1026 } | 985 } |
| 1027 | 986 |
| 1028 FileError FileCache::MarkAsMounted(const std::string& resource_id, | 987 FileError FileCache::MarkAsMounted(const std::string& resource_id, |
| 1029 base::FilePath* cache_file_path) { | 988 base::FilePath* cache_file_path) { |
| 1030 AssertOnSequencedWorkerPool(); | 989 AssertOnSequencedWorkerPool(); |
| 1031 DCHECK(cache_file_path); | 990 DCHECK(cache_file_path); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 | 1119 |
| 1161 // Now the file is moved from "persistent" to "tmp" directory. | 1120 // Now the file is moved from "persistent" to "tmp" directory. |
| 1162 // It's a chance to free up space if needed. | 1121 // It's a chance to free up space if needed. |
| 1163 blocking_task_runner_->PostTask( | 1122 blocking_task_runner_->PostTask( |
| 1164 FROM_HERE, | 1123 FROM_HERE, |
| 1165 base::Bind( | 1124 base::Bind( |
| 1166 base::IgnoreResult(&FileCache::FreeDiskSpaceIfNeededFor), | 1125 base::IgnoreResult(&FileCache::FreeDiskSpaceIfNeededFor), |
| 1167 base::Unretained(this), 0)); | 1126 base::Unretained(this), 0)); |
| 1168 } | 1127 } |
| 1169 | 1128 |
| 1170 void FileCache::OnCommitDirty(const std::string& resource_id, | |
| 1171 const FileOperationCallback& callback, | |
| 1172 FileError error) { | |
| 1173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1174 DCHECK(!callback.is_null()); | |
| 1175 | |
| 1176 callback.Run(error); | |
| 1177 | |
| 1178 if (error == FILE_ERROR_OK) | |
| 1179 FOR_EACH_OBSERVER(FileCacheObserver, | |
| 1180 observers_, | |
| 1181 OnCacheCommitted(resource_id)); | |
| 1182 } | |
| 1183 | |
| 1184 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, | 1129 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, |
| 1185 const base::FilePath& path) { | 1130 const base::FilePath& path) { |
| 1186 int64 free_space = 0; | 1131 int64 free_space = 0; |
| 1187 if (free_disk_space_getter_) | 1132 if (free_disk_space_getter_) |
| 1188 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); | 1133 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); |
| 1189 else | 1134 else |
| 1190 free_space = base::SysInfo::AmountOfFreeDiskSpace(path); | 1135 free_space = base::SysInfo::AmountOfFreeDiskSpace(path); |
| 1191 | 1136 |
| 1192 // Subtract this as if this portion does not exist. | 1137 // Subtract this as if this portion does not exist. |
| 1193 free_space -= kMinFreeSpace; | 1138 free_space -= kMinFreeSpace; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 } | 1173 } |
| 1229 | 1174 |
| 1230 // static | 1175 // static |
| 1231 FileCache::CacheSubDirectoryType FileCache::GetSubDirectoryType( | 1176 FileCache::CacheSubDirectoryType FileCache::GetSubDirectoryType( |
| 1232 const FileCacheEntry& cache_entry) { | 1177 const FileCacheEntry& cache_entry) { |
| 1233 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; | 1178 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; |
| 1234 } | 1179 } |
| 1235 | 1180 |
| 1236 } // namespace internal | 1181 } // namespace internal |
| 1237 } // namespace drive | 1182 } // namespace drive |
| OLD | NEW |