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 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 |