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 FilePath base_name = file_path.BaseName(); | |
2141 FilePath::StringType resource_id = base_name.RemoveExtension().value(); | |
2142 FilePath::StringType extension = base_name.Extension(); | |
2143 FilePath::StringType md5 = FilePath::StringType(); | |
satorux1
2012/04/20 20:11:25
nit: the following is sufficient
FilePath::String
| |
2144 if (!extension.empty()) { | |
2145 // FilePath::Extension returns ".", so strip it. | |
2146 md5 = GDataEntry::UnescapeUtf8FileName(extension.substr(1)); | |
2147 if (md5 == kMountedArchiveFileExtension) { | |
2148 DCHECK(!to_mount); | |
2149 // Files that are already mounted have filenames in format of | |
2150 // resource_id.md5.mounted, i.e. ".mounted" is the extension, so | |
2151 // strip it and get the actual resource_id and md5. | |
2152 base_name = base_name.RemoveExtension(); | |
2153 resource_id = GDataEntry::UnescapeUtf8FileName( | |
2154 base_name.RemoveExtension().value()); | |
2155 extension = base_name.Extension(); | |
2156 md5 = !extension.empty() ? | |
2157 GDataEntry::UnescapeUtf8FileName(extension.substr(1)) : | |
2158 FilePath::StringType(); | |
2159 } | |
2160 } | |
satorux1
2012/04/20 20:11:25
This function is already large. can you factor out
| |
2161 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, | |
2162 md5); | |
2163 if (!entry) { | |
2164 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
2165 return; | |
2166 } | |
2167 if (to_mount == entry->IsMounted()) { | |
2168 *error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
2169 return; | |
2170 } | |
2171 | |
2172 md5 = entry->md5; | |
2173 // Get subdir types for the unmounted and mounted state. | |
2174 GDataRootDirectory::CacheSubDirectoryType unmounted_subdir = | |
2175 entry->IsPinned() ? GDataRootDirectory::CACHE_TYPE_PERSISTENT : | |
2176 GDataRootDirectory::CACHE_TYPE_TMP; | |
2177 GDataRootDirectory::CacheSubDirectoryType mounted_subdir = | |
2178 GDataRootDirectory::CACHE_TYPE_PERSISTENT; | |
2179 // Gets path of the file if it were to be unmounted. | |
2180 FilePath unmounted_path = GetCacheFilePath(resource_id, md5, unmounted_subdir, | |
2181 CACHED_FILE_FROM_SERVER); | |
2182 // Gets path of the file if it were to be mounted. | |
2183 FilePath mounted_path = GetCacheFilePath(resource_id, md5, mounted_subdir, | |
2184 CACHED_FILE_MOUNTED); | |
2185 | |
2186 // Determine the source and destination paths for moving the cache blob. | |
2187 FilePath source_path; | |
2188 GDataRootDirectory::CacheSubDirectoryType dest_subdir; | |
2189 int cache_state = entry->cache_state; | |
2190 if (to_mount) { | |
2191 source_path = unmounted_path; | |
2192 *cache_file_path = mounted_path; | |
2193 dest_subdir = mounted_subdir; | |
2194 cache_state = GDataFile::SetCacheMounted(cache_state); | |
2195 } else { | |
2196 source_path = mounted_path; | |
2197 *cache_file_path = unmounted_path; | |
2198 dest_subdir = unmounted_subdir; | |
2199 cache_state = GDataFile::ClearCacheMounted(cache_state); | |
2200 } | |
2201 | |
2202 // Move cache blob from source path to destination path. | |
2203 *error = ModifyCacheState(source_path, *cache_file_path, | |
2204 GDataFileSystem::FILE_OPERATION_MOVE, | |
2205 FilePath(), false); | |
2206 if (*error == base::PLATFORM_FILE_OK) { | |
2207 // Now that cache operation is complete, update cache map | |
2208 root_->UpdateCacheMap(resource_id, md5, dest_subdir, cache_state); | |
2209 } | |
2210 } | |
2211 | |
2090 void GDataFileSystem::OnSetPinStateCompleted( | 2212 void GDataFileSystem::OnSetPinStateCompleted( |
2091 const FileOperationCallback& callback, | 2213 const FileOperationCallback& callback, |
2092 base::PlatformFileError error, | 2214 base::PlatformFileError error, |
2093 const std::string& resource_id, | 2215 const std::string& resource_id, |
2094 const std::string& md5) { | 2216 const std::string& md5) { |
2095 callback.Run(error); | 2217 callback.Run(error); |
2096 } | 2218 } |
2097 | 2219 |
2098 void GDataFileSystem::OnGetAvailableSpace( | 2220 void GDataFileSystem::OnGetAvailableSpace( |
2099 const GetAvailableSpaceCallback& callback, | 2221 const GetAvailableSpaceCallback& callback, |
(...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3261 // name and md5 is the extension. | 3383 // name and md5 is the extension. |
3262 std::string base_name = GDataEntry::EscapeUtf8FileName(resource_id); | 3384 std::string base_name = GDataEntry::EscapeUtf8FileName(resource_id); |
3263 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { | 3385 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { |
3264 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | 3386 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); |
3265 base_name += FilePath::kExtensionSeparator; | 3387 base_name += FilePath::kExtensionSeparator; |
3266 base_name += kLocallyModifiedFileExtension; | 3388 base_name += kLocallyModifiedFileExtension; |
3267 } else if (!md5.empty()) { | 3389 } else if (!md5.empty()) { |
3268 base_name += FilePath::kExtensionSeparator; | 3390 base_name += FilePath::kExtensionSeparator; |
3269 base_name += GDataEntry::EscapeUtf8FileName(md5); | 3391 base_name += GDataEntry::EscapeUtf8FileName(md5); |
3270 } | 3392 } |
3393 // For mounted archives the filename is formatted as resource_id.md5.mounted, | |
3394 // i.e. resource_id.md5 is the base name and ".mounted" is the extension | |
3395 if (file_origin == CACHED_FILE_MOUNTED) { | |
3396 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | |
3397 base_name += FilePath::kExtensionSeparator; | |
3398 base_name += kMountedArchiveFileExtension; | |
3399 } | |
3271 return cache_paths_[sub_dir_type].Append(base_name); | 3400 return cache_paths_[sub_dir_type].Append(base_name); |
3272 } | 3401 } |
3273 | 3402 |
3274 void GDataFileSystem::GetFromCache(const std::string& resource_id, | 3403 void GDataFileSystem::GetFromCache(const std::string& resource_id, |
3275 const std::string& md5, | 3404 const std::string& md5, |
3276 const GetFromCacheCallback& callback) { | 3405 const GetFromCacheCallback& callback) { |
3277 GetFromCacheInternal(resource_id, md5, FilePath(), callback); | 3406 GetFromCacheInternal(resource_id, md5, FilePath(), callback); |
3278 } | 3407 } |
3279 | 3408 |
3280 void GDataFileSystem::StoreToCache(const std::string& resource_id, | 3409 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) { | 3628 FilePath* cache_file_path) { |
3500 DCHECK(error); | 3629 DCHECK(error); |
3501 DCHECK(cache_file_path); | 3630 DCHECK(cache_file_path); |
3502 | 3631 |
3503 // Lock to access cache map. | 3632 // Lock to access cache map. |
3504 base::AutoLock lock(lock_); | 3633 base::AutoLock lock(lock_); |
3505 | 3634 |
3506 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, | 3635 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, |
3507 md5); | 3636 md5); |
3508 if (entry && entry->IsPresent()) { | 3637 if (entry && entry->IsPresent()) { |
3638 CachedFileOrigin file_origin; | |
3639 if (entry->IsMounted()) { | |
3640 file_origin = CACHED_FILE_MOUNTED; | |
3641 } else if (entry->IsDirty()) { | |
3642 file_origin = CACHED_FILE_LOCALLY_MODIFIED; | |
3643 } else { | |
3644 file_origin = CACHED_FILE_FROM_SERVER; | |
3645 } | |
3509 *cache_file_path = GetCacheFilePath( | 3646 *cache_file_path = GetCacheFilePath( |
3510 resource_id, | 3647 resource_id, |
3511 md5, | 3648 md5, |
3512 entry->sub_dir_type, | 3649 entry->sub_dir_type, |
3513 entry->IsDirty() ? CACHED_FILE_LOCALLY_MODIFIED : | 3650 file_origin); |
3514 CACHED_FILE_FROM_SERVER); | |
3515 *error = base::PLATFORM_FILE_OK; | 3651 *error = base::PLATFORM_FILE_OK; |
3516 } else { | 3652 } else { |
3517 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | 3653 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
3518 } | 3654 } |
3519 } | 3655 } |
3520 | 3656 |
3521 void GDataFileSystem::GetCacheStateOnIOThreadPool( | 3657 void GDataFileSystem::GetCacheStateOnIOThreadPool( |
3522 const std::string& resource_id, | 3658 const std::string& resource_id, |
3523 const std::string& md5, | 3659 const std::string& md5, |
3524 base::PlatformFileError* error, | 3660 base::PlatformFileError* error, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3561 int cache_state = GDataFile::CACHE_STATE_PRESENT; | 3697 int cache_state = GDataFile::CACHE_STATE_PRESENT; |
3562 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3698 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
3563 GDataRootDirectory::CACHE_TYPE_TMP; | 3699 GDataRootDirectory::CACHE_TYPE_TMP; |
3564 | 3700 |
3565 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 3701 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
3566 resource_id, md5); | 3702 resource_id, md5); |
3567 | 3703 |
3568 // If file was previously pinned, store it in persistent dir and create | 3704 // If file was previously pinned, store it in persistent dir and create |
3569 // symlink in pinned dir. | 3705 // symlink in pinned dir. |
3570 if (entry) { // File exists in cache. | 3706 if (entry) { // File exists in cache. |
3571 // If file is dirty, return error. | 3707 // If file is dirty or mounted, return error. |
3572 if (entry->IsDirty()) { | 3708 if (entry->IsDirty() || entry->IsMounted()) { |
3573 LOG(WARNING) << "Can't store a file to replace a dirty file: res_id=" | 3709 LOG(WARNING) << "Can't store a file to replace a " |
3574 << resource_id | 3710 << (entry->IsDirty() ? "dirty" : "mounted") |
3711 << " file: res_id=" << resource_id | |
3575 << ", md5=" << md5; | 3712 << ", md5=" << md5; |
3576 *error = base::PLATFORM_FILE_ERROR_IN_USE; | 3713 *error = base::PLATFORM_FILE_ERROR_IN_USE; |
3577 return; | 3714 return; |
3578 } | 3715 } |
3579 | 3716 |
3580 cache_state |= entry->cache_state; | 3717 cache_state |= entry->cache_state; |
3581 | 3718 |
3582 // If file is pinned, determines destination path. | 3719 // If file is pinned, determines destination path. |
3583 if (entry->IsPinned()) { | 3720 if (entry->IsPinned()) { |
3584 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3721 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3663 | 3800 |
3664 // Set sub_dir_type to PINNED to indicate that the file doesn't exist. | 3801 // 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 | 3802 // When the file is finally downloaded and StoreToCache called, it will be |
3666 // moved to persistent directory. | 3803 // moved to persistent directory. |
3667 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; | 3804 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; |
3668 } else { // File exists in cache, determines destination path. | 3805 } else { // File exists in cache, determines destination path. |
3669 cache_state |= entry->cache_state; | 3806 cache_state |= entry->cache_state; |
3670 | 3807 |
3671 // Determine source and destination paths. | 3808 // Determine source and destination paths. |
3672 | 3809 |
3673 // If file is dirty, don't move it, so determine |dest_path| and set | 3810 // 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 | 3811 // set |source_path| the same, because ModifyCacheState only moves files if |
3675 // source and destination are different. | 3812 // source and destination are different. |
3676 if (entry->IsDirty()) { | 3813 if (entry->IsDirty() || entry->IsMounted()) { |
3677 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); | 3814 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); |
3678 dest_path = GetCacheFilePath(resource_id, | 3815 dest_path = GetCacheFilePath(resource_id, |
3679 md5, | 3816 md5, |
3680 entry->sub_dir_type, | 3817 entry->sub_dir_type, |
3681 CACHED_FILE_LOCALLY_MODIFIED); | 3818 CACHED_FILE_LOCALLY_MODIFIED); |
3682 source_path = dest_path; | 3819 source_path = dest_path; |
3683 } else { | 3820 } else { |
3684 // Gets the current path of the file in cache. | 3821 // Gets the current path of the file in cache. |
3685 source_path = GetCacheFilePath(resource_id, | 3822 source_path = GetCacheFilePath(resource_id, |
3686 md5, | 3823 md5, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3746 return; | 3883 return; |
3747 } | 3884 } |
3748 | 3885 |
3749 // Entry exists in cache, determines source and destination paths. | 3886 // Entry exists in cache, determines source and destination paths. |
3750 | 3887 |
3751 FilePath source_path; | 3888 FilePath source_path; |
3752 FilePath dest_path; | 3889 FilePath dest_path; |
3753 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3890 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
3754 GDataRootDirectory::CACHE_TYPE_TMP; | 3891 GDataRootDirectory::CACHE_TYPE_TMP; |
3755 | 3892 |
3756 // If file is dirty, don't move it, so determine |dest_path| and set | 3893 // 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 | 3894 // set |source_path| the same, because ModifyCacheState moves files if source |
3758 // and destination are different. | 3895 // and destination are different. |
3759 if (entry->IsDirty()) { | 3896 if (entry->IsDirty() || entry->IsMounted()) { |
3760 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3897 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
3761 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); | 3898 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); |
3762 dest_path = GetCacheFilePath(resource_id, | 3899 dest_path = GetCacheFilePath(resource_id, |
3763 md5, | 3900 md5, |
3764 entry->sub_dir_type, | 3901 entry->sub_dir_type, |
3765 CACHED_FILE_LOCALLY_MODIFIED); | 3902 CACHED_FILE_LOCALLY_MODIFIED); |
3766 source_path = dest_path; | 3903 source_path = dest_path; |
3767 } else { | 3904 } else { |
3768 // Gets the current path of the file in cache. | 3905 // Gets the current path of the file in cache. |
3769 source_path = GetCacheFilePath(resource_id, | 3906 source_path = GetCacheFilePath(resource_id, |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4081 // Lock to access cache map. | 4218 // Lock to access cache map. |
4082 base::AutoLock lock(lock_); | 4219 base::AutoLock lock(lock_); |
4083 | 4220 |
4084 // MD5 is not passed into RemoveFromCache and hence | 4221 // MD5 is not passed into RemoveFromCache and hence |
4085 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files | 4222 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files |
4086 // corresponding to <resource_id> regardless of the md5. | 4223 // corresponding to <resource_id> regardless of the md5. |
4087 // So, search for entry in cache without taking md5 into account. | 4224 // So, search for entry in cache without taking md5 into account. |
4088 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 4225 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
4089 resource_id, std::string()); | 4226 resource_id, std::string()); |
4090 | 4227 |
4091 // If entry doesn't exist or is dirty in cache, nothing to do. | 4228 // If entry doesn't exist or is dirty or mounted in cache, nothing to do. |
4092 if (!entry || entry->IsDirty()) { | 4229 if (!entry || entry->IsDirty() || entry->IsMounted()) { |
4093 DVLOG(1) << "Entry " << (entry ? "is dirty" : "doesn't exist") | 4230 DVLOG(1) << "Entry is " |
4231 << (entry ? (entry->IsDirty() ? "dirty" : "mounted") : | |
4232 "non-existent") | |
4094 << " in cache, not removing"; | 4233 << " in cache, not removing"; |
4095 *error = base::PLATFORM_FILE_OK; | 4234 *error = base::PLATFORM_FILE_OK; |
4096 return; | 4235 return; |
4097 } | 4236 } |
4098 | 4237 |
4099 // Determine paths to delete all cache versions of |resource_id| in | 4238 // Determine paths to delete all cache versions of |resource_id| in |
4100 // persistent, tmp and pinned directories. | 4239 // persistent, tmp and pinned directories. |
4101 std::vector<FilePath> paths_to_delete; | 4240 std::vector<FilePath> paths_to_delete; |
4102 | 4241 |
4103 // For files in persistent and tmp dirs, delete files that match | 4242 // For files in persistent and tmp dirs, delete files that match |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4233 // Determine cache state. | 4372 // Determine cache state. |
4234 int cache_state = GDataFile::CACHE_STATE_NONE; | 4373 int cache_state = GDataFile::CACHE_STATE_NONE; |
4235 // If we're scanning pinned directory and if entry already exists, just | 4374 // If we're scanning pinned directory and if entry already exists, just |
4236 // update its pinned state. | 4375 // update its pinned state. |
4237 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { | 4376 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { |
4238 GDataRootDirectory::CacheMap::iterator iter = | 4377 GDataRootDirectory::CacheMap::iterator iter = |
4239 cache_map->find(resource_id); | 4378 cache_map->find(resource_id); |
4240 if (iter != cache_map->end()) { // Entry exists, update pinned state. | 4379 if (iter != cache_map->end()) { // Entry exists, update pinned state. |
4241 GDataRootDirectory::CacheEntry* entry = iter->second; | 4380 GDataRootDirectory::CacheEntry* entry = iter->second; |
4242 entry->cache_state = GDataFile::SetCachePinned(entry->cache_state); | 4381 entry->cache_state = GDataFile::SetCachePinned(entry->cache_state); |
4382 // Check that the file exists in the persistent directory | |
4383 FilePath expected_path = GetCacheFilePath( | |
4384 resource_id, entry->md5, | |
4385 GDataRootDirectory::CACHE_TYPE_PERSISTENT, | |
4386 CACHED_FILE_FROM_SERVER); | |
4387 if (!file_util::PathExists(expected_path)) | |
4388 { | |
satorux1
2012/04/20 20:11:25
nit: move { to the previous line.
| |
4389 // If the pinned file is a mounted archive, it may be stripped of the | |
4390 // suffix ".mounted" and moved to tmp. Move it again to persistent. | |
satorux1
2012/04/20 20:11:25
I'm confused. when can it happen?
hshi
2012/04/20 20:20:30
This happens when a zip file is pinned and also mo
satorux1
2012/04/20 21:46:10
Oh I see. This is fairly tricky and hard to test..
| |
4391 FilePath tmp_path = GetCacheFilePath( | |
4392 resource_id, entry->md5, | |
4393 GDataRootDirectory::CACHE_TYPE_TMP, | |
4394 CACHED_FILE_FROM_SERVER); | |
4395 DCHECK(file_util::PathExists(tmp_path)); | |
4396 file_util::Move(tmp_path, expected_path); | |
4397 } | |
4243 continue; | 4398 continue; |
4244 } | 4399 } |
4245 // Entry doesn't exist, this is a special symlink that refers to | 4400 // 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 | 4401 // /dev/null; follow through to create an entry with the PINNED but not |
4247 // PRESENT state. | 4402 // PRESENT state. |
4248 cache_state = GDataFile::SetCachePinned(cache_state); | 4403 cache_state = GDataFile::SetCachePinned(cache_state); |
4249 } else if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { | 4404 } else if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { |
4250 // If we're scanning outgoing directory, entry must exist, update its | 4405 // If we're scanning outgoing directory, entry must exist, update its |
4251 // dirty state. | 4406 // dirty state. |
4252 // If entry doesn't exist, it's a logic error from previous execution, | 4407 // If entry doesn't exist, it's a logic error from previous execution, |
4253 // ignore this outgoing symlink and move on. | 4408 // ignore this outgoing symlink and move on. |
4254 GDataRootDirectory::CacheMap::iterator iter = | 4409 GDataRootDirectory::CacheMap::iterator iter = |
4255 cache_map->find(resource_id); | 4410 cache_map->find(resource_id); |
4256 if (iter != cache_map->end()) { // Entry exists, update dirty state. | 4411 if (iter != cache_map->end()) { // Entry exists, update dirty state. |
4257 GDataRootDirectory::CacheEntry* entry = iter->second; | 4412 GDataRootDirectory::CacheEntry* entry = iter->second; |
4258 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); | 4413 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); |
4259 } else { | 4414 } else { |
4260 NOTREACHED() << "Dirty cache file MUST have actual file blob"; | 4415 NOTREACHED() << "Dirty cache file MUST have actual file blob"; |
4261 } | 4416 } |
4262 continue; | 4417 continue; |
4263 } else { | 4418 } else { |
4264 // Scanning other directories means that cache file is actually present. | 4419 // Scanning other directories means that cache file is actually present. |
4265 cache_state = GDataFile::SetCachePresent(cache_state); | 4420 cache_state = GDataFile::SetCachePresent(cache_state); |
4266 } | 4421 } |
4267 | 4422 |
4423 // Mounted archives in cache should be unmounted upon logout/shutdown. | |
4424 // But if we encounter a mounted file at start, move it back to tmp. | |
4425 if (md5 == kMountedArchiveFileExtension) { | |
4426 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | |
4427 sub_dir_type = GDataRootDirectory::CACHE_TYPE_TMP; | |
4428 // Files that are already mounted have filenames in format of | |
4429 // resource_id.md5.mounted, i.e. ".mounted" is the extension, so strip | |
4430 // it and get the actual resource_id and md5 | |
4431 base_name = base_name.RemoveExtension(); | |
4432 resource_id = GDataEntry::UnescapeUtf8FileName( | |
4433 base_name.RemoveExtension().value()); | |
4434 FilePath::StringType extension = base_name.Extension(); | |
4435 md5 = !extension.empty() ? | |
4436 GDataEntry::UnescapeUtf8FileName(extension.substr(1)) : | |
4437 std::string(); | |
4438 file_util::Move(current, GetCacheFilePath(resource_id, md5, sub_dir_type, | |
4439 CACHED_FILE_FROM_SERVER)); | |
4440 } | |
4441 | |
4268 // Create and insert new entry into cache map. | 4442 // Create and insert new entry into cache map. |
4269 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( | 4443 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( |
4270 md5, sub_dir_type, cache_state); | 4444 md5, sub_dir_type, cache_state); |
4271 cache_map->insert(std::make_pair(resource_id, entry)); | 4445 cache_map->insert(std::make_pair(resource_id, entry)); |
4272 } | 4446 } |
4273 } | 4447 } |
4274 | 4448 |
4275 void GDataFileSystem::GetFromCacheInternal( | 4449 void GDataFileSystem::GetFromCacheInternal( |
4276 const std::string& resource_id, | 4450 const std::string& resource_id, |
4277 const std::string& md5, | 4451 const std::string& md5, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4362 pref_registrar_->Init(profile_->GetPrefs()); | 4536 pref_registrar_->Init(profile_->GetPrefs()); |
4363 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); | 4537 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); |
4364 } | 4538 } |
4365 | 4539 |
4366 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { | 4540 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { |
4367 delete global_free_disk_getter_for_testing; // Safe to delete NULL; | 4541 delete global_free_disk_getter_for_testing; // Safe to delete NULL; |
4368 global_free_disk_getter_for_testing = getter; | 4542 global_free_disk_getter_for_testing = getter; |
4369 } | 4543 } |
4370 | 4544 |
4371 } // namespace gdata | 4545 } // namespace gdata |
OLD | NEW |