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 |