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 |