Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_file_system.cc

Issue 10116044: gdata: Support mounting archive files in GData cache. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: gdata: Support mounting archive files in GData cache. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698