Chromium Code Reviews| 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/gdata/gdata_file_system.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 namespace gdata { | 51 namespace gdata { |
| 52 namespace { | 52 namespace { |
| 53 | 53 |
| 54 const char kMimeTypeJson[] = "application/json"; | 54 const char kMimeTypeJson[] = "application/json"; |
| 55 const char kMimeTypeOctetStream[] = "application/octet-stream"; | 55 const char kMimeTypeOctetStream[] = "application/octet-stream"; |
| 56 | 56 |
| 57 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); | 57 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); |
| 58 const char kFeedField[] = "feed"; | 58 const char kFeedField[] = "feed"; |
| 59 const char kWildCard[] = "*"; | 59 const char kWildCard[] = "*"; |
| 60 const char kLocallyModifiedFileExtension[] = "local"; | 60 const char kLocallyModifiedFileExtension[] = "local"; |
| 61 const char kMountedArchiveFileExtension[] = "mounted"; | |
| 61 | 62 |
| 62 const FilePath::CharType kGDataCacheVersionDir[] = FILE_PATH_LITERAL("v1"); | 63 const FilePath::CharType kGDataCacheVersionDir[] = FILE_PATH_LITERAL("v1"); |
| 63 const FilePath::CharType kGDataCacheMetaDir[] = FILE_PATH_LITERAL("meta"); | 64 const FilePath::CharType kGDataCacheMetaDir[] = FILE_PATH_LITERAL("meta"); |
| 64 const FilePath::CharType kGDataCachePinnedDir[] = FILE_PATH_LITERAL("pinned"); | 65 const FilePath::CharType kGDataCachePinnedDir[] = FILE_PATH_LITERAL("pinned"); |
| 65 const FilePath::CharType kGDataCacheOutgoingDir[] = | 66 const FilePath::CharType kGDataCacheOutgoingDir[] = |
| 66 FILE_PATH_LITERAL("outgoing"); | 67 FILE_PATH_LITERAL("outgoing"); |
| 67 const FilePath::CharType kGDataCachePersistentDir[] = | 68 const FilePath::CharType kGDataCachePersistentDir[] = |
| 68 FILE_PATH_LITERAL("persistent"); | 69 FILE_PATH_LITERAL("persistent"); |
| 69 const FilePath::CharType kGDataCacheTmpDir[] = FILE_PATH_LITERAL("tmp"); | 70 const FilePath::CharType kGDataCacheTmpDir[] = FILE_PATH_LITERAL("tmp"); |
| 70 const FilePath::CharType kGDataCacheTmpDownloadsDir[] = | 71 const FilePath::CharType kGDataCacheTmpDownloadsDir[] = |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 const std::string& md5, | 503 const std::string& md5, |
| 503 const FilePath& gdata_file_path, | 504 const FilePath& gdata_file_path, |
| 504 FilePath* cache_file_path) { | 505 FilePath* cache_file_path) { |
| 505 DCHECK(error); | 506 DCHECK(error); |
| 506 DCHECK(cache_file_path); | 507 DCHECK(cache_file_path); |
| 507 | 508 |
| 508 if (!callback.is_null()) | 509 if (!callback.is_null()) |
| 509 callback.Run(*error, resource_id, md5, gdata_file_path, *cache_file_path); | 510 callback.Run(*error, resource_id, md5, gdata_file_path, *cache_file_path); |
| 510 } | 511 } |
| 511 | 512 |
| 513 // Ditto for SetMountedStateCallback | |
| 514 void RunSetMountedStateCallbackHelper( | |
| 515 const SetMountedStateCallback& callback, | |
| 516 base::PlatformFileError* error, | |
| 517 FilePath* cache_file_path) { | |
| 518 DCHECK(error); | |
| 519 DCHECK(cache_file_path); | |
| 520 | |
| 521 if (!callback.is_null()) | |
| 522 callback.Run(*error, *cache_file_path); | |
| 523 } | |
| 524 | |
| 512 void RunGetCacheStateCallbackHelper( | 525 void RunGetCacheStateCallbackHelper( |
| 513 const GetCacheStateCallback& callback, | 526 const GetCacheStateCallback& callback, |
| 514 base::PlatformFileError* error, | 527 base::PlatformFileError* error, |
| 515 int* cache_state) { | 528 int* cache_state) { |
| 516 DCHECK(error); | 529 DCHECK(error); |
| 517 DCHECK(cache_state); | 530 DCHECK(cache_state); |
| 518 | 531 |
| 519 if (!callback.is_null()) | 532 if (!callback.is_null()) |
| 520 callback.Run(*error, *cache_state); | 533 callback.Run(*error, *cache_state); |
| 521 } | 534 } |
| (...skipping 1410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1932 if (regular_file) { | 1945 if (regular_file) { |
| 1933 properties->file_md5 = regular_file->file_md5(); | 1946 properties->file_md5 = regular_file->file_md5(); |
| 1934 properties->mime_type = regular_file->content_mime_type(); | 1947 properties->mime_type = regular_file->content_mime_type(); |
| 1935 properties->content_url = regular_file->content_url(); | 1948 properties->content_url = regular_file->content_url(); |
| 1936 properties->alternate_url = regular_file->alternate_url(); | 1949 properties->alternate_url = regular_file->alternate_url(); |
| 1937 properties->is_hosted_document = regular_file->is_hosted_document(); | 1950 properties->is_hosted_document = regular_file->is_hosted_document(); |
| 1938 } | 1951 } |
| 1939 return true; | 1952 return true; |
| 1940 } | 1953 } |
| 1941 | 1954 |
| 1955 bool GDataFileSystem::IsUnderGDataCacheDirectory(const FilePath& path) const { | |
| 1956 return gdata_cache_path_ == path || gdata_cache_path_.IsParent(path); | |
| 1957 } | |
| 1958 | |
| 1942 FilePath GDataFileSystem::GetGDataCacheTmpDirectory() const { | 1959 FilePath GDataFileSystem::GetGDataCacheTmpDirectory() const { |
| 1943 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP]; | 1960 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP]; |
| 1944 } | 1961 } |
| 1945 | 1962 |
| 1946 FilePath GDataFileSystem::GetGDataTempDownloadFolderPath() const { | 1963 FilePath GDataFileSystem::GetGDataTempDownloadFolderPath() const { |
| 1947 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS]; | 1964 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS]; |
| 1948 } | 1965 } |
| 1949 | 1966 |
| 1950 FilePath GDataFileSystem::GetGDataTempDocumentFolderPath() const { | 1967 FilePath GDataFileSystem::GetGDataTempDocumentFolderPath() const { |
| 1951 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS]; | 1968 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS]; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2080 GetWeakPtrForCurrentThread(), | 2097 GetWeakPtrForCurrentThread(), |
| 2081 callback); | 2098 callback); |
| 2082 } | 2099 } |
| 2083 | 2100 |
| 2084 if (to_pin) | 2101 if (to_pin) |
| 2085 Pin(resource_id, md5, cache_callback); | 2102 Pin(resource_id, md5, cache_callback); |
| 2086 else | 2103 else |
| 2087 Unpin(resource_id, md5, cache_callback); | 2104 Unpin(resource_id, md5, cache_callback); |
| 2088 } | 2105 } |
| 2089 | 2106 |
| 2107 void GDataFileSystem::SetMountedState(const FilePath& file_path, bool to_mount, | |
| 2108 const SetMountedStateCallback& callback) { | |
| 2109 InitializeCacheIfNecessary(); | |
| 2110 | |
| 2111 base::PlatformFileError* error = | |
| 2112 new base::PlatformFileError(base::PLATFORM_FILE_OK); | |
| 2113 FilePath* cache_file_path = new FilePath; | |
| 2114 PostBlockingPoolSequencedTaskAndReply( | |
| 2115 kGDataFileSystemToken, | |
| 2116 FROM_HERE, | |
| 2117 base::Bind(&GDataFileSystem::SetMountedStateOnIOThreadPool, | |
| 2118 base::Unretained(this), | |
| 2119 file_path, | |
| 2120 to_mount, | |
| 2121 error, | |
| 2122 cache_file_path), | |
| 2123 base::Bind(&RunSetMountedStateCallbackHelper, | |
| 2124 callback, | |
| 2125 base::Owned(error), | |
| 2126 base::Owned(cache_file_path))); | |
| 2127 } | |
| 2128 | |
| 2129 void GDataFileSystem::SetMountedStateOnIOThreadPool( | |
| 2130 const FilePath& file_path, | |
| 2131 bool to_mount, | |
| 2132 base::PlatformFileError *error, | |
| 2133 FilePath* cache_file_path) { | |
| 2134 DCHECK(error); | |
| 2135 DCHECK(cache_file_path); | |
| 2136 | |
| 2137 // Lock to access cache map. | |
| 2138 base::AutoLock lock(lock_); | |
| 2139 | |
| 2140 // Parse file path to obtain resource_id, md5 and extra_suffix. | |
| 2141 std::string resource_id; | |
| 2142 std::string md5; | |
| 2143 std::string extra_suffix; | |
| 2144 util::ParseCacheFilePath(file_path, &resource_id, &md5, &extra_suffix); | |
| 2145 // The extra_suffix can only be ".mounted" when unmounting. | |
| 2146 DCHECK(to_mount || extra_suffix == kMountedArchiveFileExtension); | |
| 2147 | |
| 2148 // Get cache entry associated with the resource_id and md5 | |
| 2149 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, | |
| 2150 md5); | |
| 2151 if (!entry) { | |
| 2152 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 2153 return; | |
| 2154 } | |
| 2155 if (to_mount == entry->IsMounted()) { | |
| 2156 *error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
| 2157 return; | |
| 2158 } | |
| 2159 | |
| 2160 // Get subdir types for the unmounted and mounted state. | |
| 2161 GDataRootDirectory::CacheSubDirectoryType unmounted_subdir = | |
| 2162 entry->IsPinned() ? GDataRootDirectory::CACHE_TYPE_PERSISTENT : | |
| 2163 GDataRootDirectory::CACHE_TYPE_TMP; | |
| 2164 GDataRootDirectory::CacheSubDirectoryType mounted_subdir = | |
| 2165 GDataRootDirectory::CACHE_TYPE_PERSISTENT; | |
| 2166 // Gets path of the file if it were to be unmounted. | |
| 2167 FilePath unmounted_path = GetCacheFilePath(resource_id, md5, unmounted_subdir, | |
| 2168 CACHED_FILE_FROM_SERVER); | |
| 2169 // Gets path of the file if it were to be mounted. | |
| 2170 FilePath mounted_path = GetCacheFilePath(resource_id, md5, mounted_subdir, | |
| 2171 CACHED_FILE_MOUNTED); | |
| 2172 | |
| 2173 // Determine the source and destination paths for moving the cache blob. | |
| 2174 FilePath source_path; | |
| 2175 GDataRootDirectory::CacheSubDirectoryType dest_subdir; | |
| 2176 int cache_state = entry->cache_state; | |
| 2177 if (to_mount) { | |
| 2178 source_path = unmounted_path; | |
| 2179 *cache_file_path = mounted_path; | |
| 2180 dest_subdir = mounted_subdir; | |
| 2181 cache_state = GDataFile::SetCacheMounted(cache_state); | |
| 2182 } else { | |
| 2183 source_path = mounted_path; | |
| 2184 *cache_file_path = unmounted_path; | |
| 2185 dest_subdir = unmounted_subdir; | |
| 2186 cache_state = GDataFile::ClearCacheMounted(cache_state); | |
| 2187 } | |
| 2188 | |
| 2189 // Move cache blob from source path to destination path. | |
| 2190 *error = ModifyCacheState(source_path, *cache_file_path, | |
| 2191 GDataFileSystem::FILE_OPERATION_MOVE, | |
| 2192 FilePath(), false); | |
| 2193 if (*error == base::PLATFORM_FILE_OK) { | |
| 2194 // Now that cache operation is complete, update cache map | |
| 2195 root_->UpdateCacheMap(resource_id, md5, dest_subdir, cache_state); | |
| 2196 } | |
| 2197 } | |
| 2198 | |
| 2090 void GDataFileSystem::OnSetPinStateCompleted( | 2199 void GDataFileSystem::OnSetPinStateCompleted( |
| 2091 const FileOperationCallback& callback, | 2200 const FileOperationCallback& callback, |
| 2092 base::PlatformFileError error, | 2201 base::PlatformFileError error, |
| 2093 const std::string& resource_id, | 2202 const std::string& resource_id, |
| 2094 const std::string& md5) { | 2203 const std::string& md5) { |
| 2095 callback.Run(error); | 2204 callback.Run(error); |
| 2096 } | 2205 } |
| 2097 | 2206 |
| 2098 void GDataFileSystem::OnGetAvailableSpace( | 2207 void GDataFileSystem::OnGetAvailableSpace( |
| 2099 const GetAvailableSpaceCallback& callback, | 2208 const GetAvailableSpaceCallback& callback, |
| (...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3261 // name and md5 is the extension. | 3370 // name and md5 is the extension. |
| 3262 std::string base_name = GDataEntry::EscapeUtf8FileName(resource_id); | 3371 std::string base_name = GDataEntry::EscapeUtf8FileName(resource_id); |
| 3263 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { | 3372 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { |
| 3264 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | 3373 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); |
| 3265 base_name += FilePath::kExtensionSeparator; | 3374 base_name += FilePath::kExtensionSeparator; |
| 3266 base_name += kLocallyModifiedFileExtension; | 3375 base_name += kLocallyModifiedFileExtension; |
| 3267 } else if (!md5.empty()) { | 3376 } else if (!md5.empty()) { |
| 3268 base_name += FilePath::kExtensionSeparator; | 3377 base_name += FilePath::kExtensionSeparator; |
| 3269 base_name += GDataEntry::EscapeUtf8FileName(md5); | 3378 base_name += GDataEntry::EscapeUtf8FileName(md5); |
| 3270 } | 3379 } |
| 3380 // For mounted archives the filename is formatted as resource_id.md5.mounted, | |
| 3381 // i.e. resource_id.md5 is the base name and ".mounted" is the extension | |
| 3382 if (file_origin == CACHED_FILE_MOUNTED) { | |
| 3383 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | |
| 3384 base_name += FilePath::kExtensionSeparator; | |
| 3385 base_name += kMountedArchiveFileExtension; | |
| 3386 } | |
| 3271 return cache_paths_[sub_dir_type].Append(base_name); | 3387 return cache_paths_[sub_dir_type].Append(base_name); |
| 3272 } | 3388 } |
| 3273 | 3389 |
| 3274 void GDataFileSystem::GetFromCache(const std::string& resource_id, | 3390 void GDataFileSystem::GetFromCache(const std::string& resource_id, |
| 3275 const std::string& md5, | 3391 const std::string& md5, |
| 3276 const GetFromCacheCallback& callback) { | 3392 const GetFromCacheCallback& callback) { |
| 3277 GetFromCacheInternal(resource_id, md5, FilePath(), callback); | 3393 GetFromCacheInternal(resource_id, md5, FilePath(), callback); |
| 3278 } | 3394 } |
| 3279 | 3395 |
| 3280 void GDataFileSystem::StoreToCache(const std::string& resource_id, | 3396 void GDataFileSystem::StoreToCache(const std::string& resource_id, |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3499 FilePath* cache_file_path) { | 3615 FilePath* cache_file_path) { |
| 3500 DCHECK(error); | 3616 DCHECK(error); |
| 3501 DCHECK(cache_file_path); | 3617 DCHECK(cache_file_path); |
| 3502 | 3618 |
| 3503 // Lock to access cache map. | 3619 // Lock to access cache map. |
| 3504 base::AutoLock lock(lock_); | 3620 base::AutoLock lock(lock_); |
| 3505 | 3621 |
| 3506 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, | 3622 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, |
| 3507 md5); | 3623 md5); |
| 3508 if (entry && entry->IsPresent()) { | 3624 if (entry && entry->IsPresent()) { |
| 3625 CachedFileOrigin file_origin; | |
| 3626 if (entry->IsMounted()) { | |
| 3627 file_origin = CACHED_FILE_MOUNTED; | |
| 3628 } else if (entry->IsDirty()) { | |
| 3629 file_origin = CACHED_FILE_LOCALLY_MODIFIED; | |
| 3630 } else { | |
| 3631 file_origin = CACHED_FILE_FROM_SERVER; | |
| 3632 } | |
| 3509 *cache_file_path = GetCacheFilePath( | 3633 *cache_file_path = GetCacheFilePath( |
| 3510 resource_id, | 3634 resource_id, |
| 3511 md5, | 3635 md5, |
| 3512 entry->sub_dir_type, | 3636 entry->sub_dir_type, |
| 3513 entry->IsDirty() ? CACHED_FILE_LOCALLY_MODIFIED : | 3637 file_origin); |
| 3514 CACHED_FILE_FROM_SERVER); | |
| 3515 *error = base::PLATFORM_FILE_OK; | 3638 *error = base::PLATFORM_FILE_OK; |
| 3516 } else { | 3639 } else { |
| 3517 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | 3640 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 3518 } | 3641 } |
| 3519 } | 3642 } |
| 3520 | 3643 |
| 3521 void GDataFileSystem::GetCacheStateOnIOThreadPool( | 3644 void GDataFileSystem::GetCacheStateOnIOThreadPool( |
| 3522 const std::string& resource_id, | 3645 const std::string& resource_id, |
| 3523 const std::string& md5, | 3646 const std::string& md5, |
| 3524 base::PlatformFileError* error, | 3647 base::PlatformFileError* error, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3561 int cache_state = GDataFile::CACHE_STATE_PRESENT; | 3684 int cache_state = GDataFile::CACHE_STATE_PRESENT; |
| 3562 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3685 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
| 3563 GDataRootDirectory::CACHE_TYPE_TMP; | 3686 GDataRootDirectory::CACHE_TYPE_TMP; |
| 3564 | 3687 |
| 3565 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 3688 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
| 3566 resource_id, md5); | 3689 resource_id, md5); |
| 3567 | 3690 |
| 3568 // If file was previously pinned, store it in persistent dir and create | 3691 // If file was previously pinned, store it in persistent dir and create |
| 3569 // symlink in pinned dir. | 3692 // symlink in pinned dir. |
| 3570 if (entry) { // File exists in cache. | 3693 if (entry) { // File exists in cache. |
| 3571 // If file is dirty, return error. | 3694 // If file is dirty or mounted, return error. |
| 3572 if (entry->IsDirty()) { | 3695 if (entry->IsDirty() || entry->IsMounted()) { |
| 3573 LOG(WARNING) << "Can't store a file to replace a dirty file: res_id=" | 3696 LOG(WARNING) << "Can't store a file to replace a " |
| 3574 << resource_id | 3697 << (entry->IsDirty() ? "dirty" : "mounted") |
| 3698 << " file: res_id=" << resource_id | |
| 3575 << ", md5=" << md5; | 3699 << ", md5=" << md5; |
| 3576 *error = base::PLATFORM_FILE_ERROR_IN_USE; | 3700 *error = base::PLATFORM_FILE_ERROR_IN_USE; |
| 3577 return; | 3701 return; |
| 3578 } | 3702 } |
| 3579 | 3703 |
| 3580 cache_state |= entry->cache_state; | 3704 cache_state |= entry->cache_state; |
| 3581 | 3705 |
| 3582 // If file is pinned, determines destination path. | 3706 // If file is pinned, determines destination path. |
| 3583 if (entry->IsPinned()) { | 3707 if (entry->IsPinned()) { |
| 3584 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3708 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3663 | 3787 |
| 3664 // Set sub_dir_type to PINNED to indicate that the file doesn't exist. | 3788 // Set sub_dir_type to PINNED to indicate that the file doesn't exist. |
| 3665 // When the file is finally downloaded and StoreToCache called, it will be | 3789 // When the file is finally downloaded and StoreToCache called, it will be |
| 3666 // moved to persistent directory. | 3790 // moved to persistent directory. |
| 3667 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; | 3791 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; |
| 3668 } else { // File exists in cache, determines destination path. | 3792 } else { // File exists in cache, determines destination path. |
| 3669 cache_state |= entry->cache_state; | 3793 cache_state |= entry->cache_state; |
| 3670 | 3794 |
| 3671 // Determine source and destination paths. | 3795 // Determine source and destination paths. |
| 3672 | 3796 |
| 3673 // If file is dirty, don't move it, so determine |dest_path| and set | 3797 // If file is dirty or mounted, don't move it, so determine |dest_path| and |
| 3674 // |source_path| the same, because ModifyCacheState only moves files if | 3798 // set |source_path| the same, because ModifyCacheState only moves files if |
| 3675 // source and destination are different. | 3799 // source and destination are different. |
| 3676 if (entry->IsDirty()) { | 3800 if (entry->IsDirty() || entry->IsMounted()) { |
| 3677 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); | 3801 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); |
| 3678 dest_path = GetCacheFilePath(resource_id, | 3802 dest_path = GetCacheFilePath(resource_id, |
| 3679 md5, | 3803 md5, |
| 3680 entry->sub_dir_type, | 3804 entry->sub_dir_type, |
| 3681 CACHED_FILE_LOCALLY_MODIFIED); | 3805 CACHED_FILE_LOCALLY_MODIFIED); |
| 3682 source_path = dest_path; | 3806 source_path = dest_path; |
| 3683 } else { | 3807 } else { |
| 3684 // Gets the current path of the file in cache. | 3808 // Gets the current path of the file in cache. |
| 3685 source_path = GetCacheFilePath(resource_id, | 3809 source_path = GetCacheFilePath(resource_id, |
| 3686 md5, | 3810 md5, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3746 return; | 3870 return; |
| 3747 } | 3871 } |
| 3748 | 3872 |
| 3749 // Entry exists in cache, determines source and destination paths. | 3873 // Entry exists in cache, determines source and destination paths. |
| 3750 | 3874 |
| 3751 FilePath source_path; | 3875 FilePath source_path; |
| 3752 FilePath dest_path; | 3876 FilePath dest_path; |
| 3753 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3877 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
| 3754 GDataRootDirectory::CACHE_TYPE_TMP; | 3878 GDataRootDirectory::CACHE_TYPE_TMP; |
| 3755 | 3879 |
| 3756 // If file is dirty, don't move it, so determine |dest_path| and set | 3880 // If file is dirty or mounted, don't move it, so determine |dest_path| and |
| 3757 // |source_path| the same, because ModifyCacheState moves files if source | 3881 // set |source_path| the same, because ModifyCacheState moves files if source |
| 3758 // and destination are different. | 3882 // and destination are different. |
| 3759 if (entry->IsDirty()) { | 3883 if (entry->IsDirty() || entry->IsMounted()) { |
| 3760 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3884 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
| 3761 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); | 3885 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); |
| 3762 dest_path = GetCacheFilePath(resource_id, | 3886 dest_path = GetCacheFilePath(resource_id, |
| 3763 md5, | 3887 md5, |
| 3764 entry->sub_dir_type, | 3888 entry->sub_dir_type, |
| 3765 CACHED_FILE_LOCALLY_MODIFIED); | 3889 CACHED_FILE_LOCALLY_MODIFIED); |
| 3766 source_path = dest_path; | 3890 source_path = dest_path; |
| 3767 } else { | 3891 } else { |
| 3768 // Gets the current path of the file in cache. | 3892 // Gets the current path of the file in cache. |
| 3769 source_path = GetCacheFilePath(resource_id, | 3893 source_path = GetCacheFilePath(resource_id, |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4081 // Lock to access cache map. | 4205 // Lock to access cache map. |
| 4082 base::AutoLock lock(lock_); | 4206 base::AutoLock lock(lock_); |
| 4083 | 4207 |
| 4084 // MD5 is not passed into RemoveFromCache and hence | 4208 // MD5 is not passed into RemoveFromCache and hence |
| 4085 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files | 4209 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files |
| 4086 // corresponding to <resource_id> regardless of the md5. | 4210 // corresponding to <resource_id> regardless of the md5. |
| 4087 // So, search for entry in cache without taking md5 into account. | 4211 // So, search for entry in cache without taking md5 into account. |
| 4088 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 4212 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
| 4089 resource_id, std::string()); | 4213 resource_id, std::string()); |
| 4090 | 4214 |
| 4091 // If entry doesn't exist or is dirty in cache, nothing to do. | 4215 // If entry doesn't exist or is dirty or mounted in cache, nothing to do. |
| 4092 if (!entry || entry->IsDirty()) { | 4216 if (!entry || entry->IsDirty() || entry->IsMounted()) { |
| 4093 DVLOG(1) << "Entry " << (entry ? "is dirty" : "doesn't exist") | 4217 DVLOG(1) << "Entry is " |
| 4218 << (entry ? (entry->IsDirty() ? "dirty" : "mounted") : | |
| 4219 "non-existent") | |
| 4094 << " in cache, not removing"; | 4220 << " in cache, not removing"; |
| 4095 *error = base::PLATFORM_FILE_OK; | 4221 *error = base::PLATFORM_FILE_OK; |
| 4096 return; | 4222 return; |
| 4097 } | 4223 } |
| 4098 | 4224 |
| 4099 // Determine paths to delete all cache versions of |resource_id| in | 4225 // Determine paths to delete all cache versions of |resource_id| in |
| 4100 // persistent, tmp and pinned directories. | 4226 // persistent, tmp and pinned directories. |
| 4101 std::vector<FilePath> paths_to_delete; | 4227 std::vector<FilePath> paths_to_delete; |
| 4102 | 4228 |
| 4103 // For files in persistent and tmp dirs, delete files that match | 4229 // For files in persistent and tmp dirs, delete files that match |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4205 file_util::FileEnumerator enumerator( | 4331 file_util::FileEnumerator enumerator( |
| 4206 cache_paths_[sub_dir_type], | 4332 cache_paths_[sub_dir_type], |
| 4207 false, // not recursive | 4333 false, // not recursive |
| 4208 static_cast<file_util::FileEnumerator::FileType>( | 4334 static_cast<file_util::FileEnumerator::FileType>( |
| 4209 file_util::FileEnumerator::FILES | | 4335 file_util::FileEnumerator::FILES | |
| 4210 file_util::FileEnumerator::SHOW_SYM_LINKS), | 4336 file_util::FileEnumerator::SHOW_SYM_LINKS), |
| 4211 kWildCard); | 4337 kWildCard); |
| 4212 for (FilePath current = enumerator.Next(); !current.empty(); | 4338 for (FilePath current = enumerator.Next(); !current.empty(); |
| 4213 current = enumerator.Next()) { | 4339 current = enumerator.Next()) { |
| 4214 // Extract resource_id and md5 from filename. | 4340 // Extract resource_id and md5 from filename. |
| 4215 FilePath base_name = current.BaseName(); | |
| 4216 std::string resource_id; | 4341 std::string resource_id; |
| 4217 std::string md5; | 4342 std::string md5; |
| 4218 | 4343 std::string extra_suffix; |
| 4219 // Pinned and outgoing symlinks have no extension. | 4344 util::ParseCacheFilePath(current, &resource_id, &md5, &extra_suffix); |
|
satorux1
2012/04/20 21:46:10
oh this turned out to be useful elsewhere. cool.
| |
| 4220 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED || | |
| 4221 sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { | |
| 4222 resource_id = GDataEntry::UnescapeUtf8FileName(base_name.value()); | |
| 4223 } else { | |
| 4224 FilePath::StringType extension = base_name.Extension(); | |
| 4225 if (!extension.empty()) { | |
| 4226 // FilePath::Extension returns ".", so strip it. | |
| 4227 md5 = GDataEntry::UnescapeUtf8FileName(extension.substr(1)); | |
| 4228 } | |
| 4229 resource_id = GDataEntry::UnescapeUtf8FileName( | |
| 4230 base_name.RemoveExtension().value()); | |
| 4231 } | |
| 4232 | 4345 |
| 4233 // Determine cache state. | 4346 // Determine cache state. |
| 4234 int cache_state = GDataFile::CACHE_STATE_NONE; | 4347 int cache_state = GDataFile::CACHE_STATE_NONE; |
| 4235 // If we're scanning pinned directory and if entry already exists, just | 4348 // If we're scanning pinned directory and if entry already exists, just |
| 4236 // update its pinned state. | 4349 // update its pinned state. |
| 4237 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { | 4350 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { |
| 4238 GDataRootDirectory::CacheMap::iterator iter = | 4351 GDataRootDirectory::CacheMap::iterator iter = |
| 4239 cache_map->find(resource_id); | 4352 cache_map->find(resource_id); |
| 4240 if (iter != cache_map->end()) { // Entry exists, update pinned state. | 4353 if (iter != cache_map->end()) { // Entry exists, update pinned state. |
| 4241 GDataRootDirectory::CacheEntry* entry = iter->second; | 4354 GDataRootDirectory::CacheEntry* entry = iter->second; |
| 4242 entry->cache_state = GDataFile::SetCachePinned(entry->cache_state); | 4355 entry->cache_state = GDataFile::SetCachePinned(entry->cache_state); |
| 4356 // Check that the file exists in the persistent directory | |
| 4357 FilePath expected_path = GetCacheFilePath( | |
| 4358 resource_id, entry->md5, | |
| 4359 GDataRootDirectory::CACHE_TYPE_PERSISTENT, | |
| 4360 CACHED_FILE_FROM_SERVER); | |
| 4361 if (!file_util::PathExists(expected_path)) { | |
| 4362 // If the pinned file is a mounted archive, it may be stripped of the | |
| 4363 // suffix ".mounted" and moved to tmp. Move it again to persistent. | |
| 4364 FilePath tmp_path = GetCacheFilePath( | |
| 4365 resource_id, entry->md5, | |
| 4366 GDataRootDirectory::CACHE_TYPE_TMP, | |
| 4367 CACHED_FILE_FROM_SERVER); | |
| 4368 DCHECK(file_util::PathExists(tmp_path)); | |
| 4369 file_util::Move(tmp_path, expected_path); | |
| 4370 } | |
| 4243 continue; | 4371 continue; |
| 4244 } | 4372 } |
| 4245 // Entry doesn't exist, this is a special symlink that refers to | 4373 // Entry doesn't exist, this is a special symlink that refers to |
| 4246 // /dev/null; follow through to create an entry with the PINNED but not | 4374 // /dev/null; follow through to create an entry with the PINNED but not |
| 4247 // PRESENT state. | 4375 // PRESENT state. |
| 4248 cache_state = GDataFile::SetCachePinned(cache_state); | 4376 cache_state = GDataFile::SetCachePinned(cache_state); |
| 4249 } else if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { | 4377 } else if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { |
| 4250 // If we're scanning outgoing directory, entry must exist, update its | 4378 // If we're scanning outgoing directory, entry must exist, update its |
| 4251 // dirty state. | 4379 // dirty state. |
| 4252 // If entry doesn't exist, it's a logic error from previous execution, | 4380 // If entry doesn't exist, it's a logic error from previous execution, |
| 4253 // ignore this outgoing symlink and move on. | 4381 // ignore this outgoing symlink and move on. |
| 4254 GDataRootDirectory::CacheMap::iterator iter = | 4382 GDataRootDirectory::CacheMap::iterator iter = |
| 4255 cache_map->find(resource_id); | 4383 cache_map->find(resource_id); |
| 4256 if (iter != cache_map->end()) { // Entry exists, update dirty state. | 4384 if (iter != cache_map->end()) { // Entry exists, update dirty state. |
| 4257 GDataRootDirectory::CacheEntry* entry = iter->second; | 4385 GDataRootDirectory::CacheEntry* entry = iter->second; |
| 4258 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); | 4386 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); |
| 4259 } else { | 4387 } else { |
| 4260 NOTREACHED() << "Dirty cache file MUST have actual file blob"; | 4388 NOTREACHED() << "Dirty cache file MUST have actual file blob"; |
| 4261 } | 4389 } |
| 4262 continue; | 4390 continue; |
| 4263 } else { | 4391 } else { |
| 4264 // Scanning other directories means that cache file is actually present. | 4392 // Scanning other directories means that cache file is actually present. |
| 4265 cache_state = GDataFile::SetCachePresent(cache_state); | 4393 cache_state = GDataFile::SetCachePresent(cache_state); |
| 4266 } | 4394 } |
| 4267 | 4395 |
| 4396 // Mounted archives in cache should be unmounted upon logout/shutdown. | |
| 4397 // But if we encounter a mounted file at start, move it back to tmp. | |
| 4398 if (extra_suffix == kMountedArchiveFileExtension) { | |
| 4399 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | |
| 4400 sub_dir_type = GDataRootDirectory::CACHE_TYPE_TMP; | |
| 4401 file_util::Move(current, GetCacheFilePath(resource_id, md5, sub_dir_type, | |
| 4402 CACHED_FILE_FROM_SERVER)); | |
| 4403 } | |
| 4404 | |
| 4268 // Create and insert new entry into cache map. | 4405 // Create and insert new entry into cache map. |
| 4269 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( | 4406 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( |
| 4270 md5, sub_dir_type, cache_state); | 4407 md5, sub_dir_type, cache_state); |
| 4271 cache_map->insert(std::make_pair(resource_id, entry)); | 4408 cache_map->insert(std::make_pair(resource_id, entry)); |
| 4272 } | 4409 } |
| 4273 } | 4410 } |
| 4274 | 4411 |
| 4275 void GDataFileSystem::GetFromCacheInternal( | 4412 void GDataFileSystem::GetFromCacheInternal( |
| 4276 const std::string& resource_id, | 4413 const std::string& resource_id, |
| 4277 const std::string& md5, | 4414 const std::string& md5, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4362 pref_registrar_->Init(profile_->GetPrefs()); | 4499 pref_registrar_->Init(profile_->GetPrefs()); |
| 4363 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); | 4500 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); |
| 4364 } | 4501 } |
| 4365 | 4502 |
| 4366 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { | 4503 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { |
| 4367 delete global_free_disk_getter_for_testing; // Safe to delete NULL; | 4504 delete global_free_disk_getter_for_testing; // Safe to delete NULL; |
| 4368 global_free_disk_getter_for_testing = getter; | 4505 global_free_disk_getter_for_testing = getter; |
| 4369 } | 4506 } |
| 4370 | 4507 |
| 4371 } // namespace gdata | 4508 } // namespace gdata |
| OLD | NEW |