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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/gdata/gdata_file_system.cc
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc
index c08061475799f53f66dce5bf03940036066de51a..8c998c009ffa1b86898ecbfb12bc76d93af62437 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc
@@ -58,6 +58,7 @@ const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata");
const char kFeedField[] = "feed";
const char kWildCard[] = "*";
const char kLocallyModifiedFileExtension[] = "local";
+const char kMountedArchiveFileExtension[] = "mounted";
const FilePath::CharType kGDataCacheVersionDir[] = FILE_PATH_LITERAL("v1");
const FilePath::CharType kGDataCacheMetaDir[] = FILE_PATH_LITERAL("meta");
@@ -509,6 +510,18 @@ void RunGetFromCacheCallbackHelper(
callback.Run(*error, resource_id, md5, gdata_file_path, *cache_file_path);
}
+// Ditto for SetMountedStateCallback
+void RunSetMountedStateCallbackHelper(
+ const SetMountedStateCallback& callback,
+ base::PlatformFileError* error,
+ FilePath* cache_file_path) {
+ DCHECK(error);
+ DCHECK(cache_file_path);
+
+ if (!callback.is_null())
+ callback.Run(*error, *cache_file_path);
+}
+
void RunGetCacheStateCallbackHelper(
const GetCacheStateCallback& callback,
base::PlatformFileError* error,
@@ -1939,6 +1952,10 @@ bool GDataFileSystem::GetFileInfoFromPath(
return true;
}
+bool GDataFileSystem::IsUnderGDataCacheDirectory(const FilePath& path) const {
+ return gdata_cache_path_ == path || gdata_cache_path_.IsParent(path);
+}
+
FilePath GDataFileSystem::GetGDataCacheTmpDirectory() const {
return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP];
}
@@ -2087,6 +2104,111 @@ void GDataFileSystem::SetPinState(const FilePath& file_path, bool to_pin,
Unpin(resource_id, md5, cache_callback);
}
+void GDataFileSystem::SetMountedState(const FilePath& file_path, bool to_mount,
+ const SetMountedStateCallback& callback) {
+ InitializeCacheIfNecessary();
+
+ base::PlatformFileError* error =
+ new base::PlatformFileError(base::PLATFORM_FILE_OK);
+ FilePath* cache_file_path = new FilePath;
+ PostBlockingPoolSequencedTaskAndReply(
+ kGDataFileSystemToken,
+ FROM_HERE,
+ base::Bind(&GDataFileSystem::SetMountedStateOnIOThreadPool,
+ base::Unretained(this),
+ file_path,
+ to_mount,
+ error,
+ cache_file_path),
+ base::Bind(&RunSetMountedStateCallbackHelper,
+ callback,
+ base::Owned(error),
+ base::Owned(cache_file_path)));
+}
+
+void GDataFileSystem::SetMountedStateOnIOThreadPool(
+ const FilePath& file_path,
+ bool to_mount,
+ base::PlatformFileError *error,
+ FilePath* cache_file_path) {
+ DCHECK(error);
+ DCHECK(cache_file_path);
+
+ // Lock to access cache map.
+ base::AutoLock lock(lock_);
+
+ FilePath base_name = file_path.BaseName();
+ FilePath::StringType resource_id = base_name.RemoveExtension().value();
+ FilePath::StringType extension = base_name.Extension();
+ FilePath::StringType md5 = FilePath::StringType();
satorux1 2012/04/20 20:11:25 nit: the following is sufficient FilePath::String
+ if (!extension.empty()) {
+ // FilePath::Extension returns ".", so strip it.
+ md5 = GDataEntry::UnescapeUtf8FileName(extension.substr(1));
+ if (md5 == kMountedArchiveFileExtension) {
+ DCHECK(!to_mount);
+ // Files that are already mounted have filenames in format of
+ // resource_id.md5.mounted, i.e. ".mounted" is the extension, so
+ // strip it and get the actual resource_id and md5.
+ base_name = base_name.RemoveExtension();
+ resource_id = GDataEntry::UnescapeUtf8FileName(
+ base_name.RemoveExtension().value());
+ extension = base_name.Extension();
+ md5 = !extension.empty() ?
+ GDataEntry::UnescapeUtf8FileName(extension.substr(1)) :
+ FilePath::StringType();
+ }
+ }
satorux1 2012/04/20 20:11:25 This function is already large. can you factor out
+ GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id,
+ md5);
+ if (!entry) {
+ *error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+ return;
+ }
+ if (to_mount == entry->IsMounted()) {
+ *error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ return;
+ }
+
+ md5 = entry->md5;
+ // Get subdir types for the unmounted and mounted state.
+ GDataRootDirectory::CacheSubDirectoryType unmounted_subdir =
+ entry->IsPinned() ? GDataRootDirectory::CACHE_TYPE_PERSISTENT :
+ GDataRootDirectory::CACHE_TYPE_TMP;
+ GDataRootDirectory::CacheSubDirectoryType mounted_subdir =
+ GDataRootDirectory::CACHE_TYPE_PERSISTENT;
+ // Gets path of the file if it were to be unmounted.
+ FilePath unmounted_path = GetCacheFilePath(resource_id, md5, unmounted_subdir,
+ CACHED_FILE_FROM_SERVER);
+ // Gets path of the file if it were to be mounted.
+ FilePath mounted_path = GetCacheFilePath(resource_id, md5, mounted_subdir,
+ CACHED_FILE_MOUNTED);
+
+ // Determine the source and destination paths for moving the cache blob.
+ FilePath source_path;
+ GDataRootDirectory::CacheSubDirectoryType dest_subdir;
+ int cache_state = entry->cache_state;
+ if (to_mount) {
+ source_path = unmounted_path;
+ *cache_file_path = mounted_path;
+ dest_subdir = mounted_subdir;
+ cache_state = GDataFile::SetCacheMounted(cache_state);
+ } else {
+ source_path = mounted_path;
+ *cache_file_path = unmounted_path;
+ dest_subdir = unmounted_subdir;
+ cache_state = GDataFile::ClearCacheMounted(cache_state);
+ }
+
+ // Move cache blob from source path to destination path.
+ *error = ModifyCacheState(source_path, *cache_file_path,
+ GDataFileSystem::FILE_OPERATION_MOVE,
+ FilePath(), false);
+ if (*error == base::PLATFORM_FILE_OK) {
+ // Now that cache operation is complete, update cache map
+ root_->UpdateCacheMap(resource_id, md5, dest_subdir, cache_state);
+ }
+}
+
void GDataFileSystem::OnSetPinStateCompleted(
const FileOperationCallback& callback,
base::PlatformFileError error,
@@ -3268,6 +3390,13 @@ FilePath GDataFileSystem::GetCacheFilePath(
base_name += FilePath::kExtensionSeparator;
base_name += GDataEntry::EscapeUtf8FileName(md5);
}
+ // For mounted archives the filename is formatted as resource_id.md5.mounted,
+ // i.e. resource_id.md5 is the base name and ".mounted" is the extension
+ if (file_origin == CACHED_FILE_MOUNTED) {
+ DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT);
+ base_name += FilePath::kExtensionSeparator;
+ base_name += kMountedArchiveFileExtension;
+ }
return cache_paths_[sub_dir_type].Append(base_name);
}
@@ -3506,12 +3635,19 @@ void GDataFileSystem::GetFromCacheOnIOThreadPool(
GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id,
md5);
if (entry && entry->IsPresent()) {
+ CachedFileOrigin file_origin;
+ if (entry->IsMounted()) {
+ file_origin = CACHED_FILE_MOUNTED;
+ } else if (entry->IsDirty()) {
+ file_origin = CACHED_FILE_LOCALLY_MODIFIED;
+ } else {
+ file_origin = CACHED_FILE_FROM_SERVER;
+ }
*cache_file_path = GetCacheFilePath(
resource_id,
md5,
entry->sub_dir_type,
- entry->IsDirty() ? CACHED_FILE_LOCALLY_MODIFIED :
- CACHED_FILE_FROM_SERVER);
+ file_origin);
*error = base::PLATFORM_FILE_OK;
} else {
*error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
@@ -3568,10 +3704,11 @@ void GDataFileSystem::StoreToCacheOnIOThreadPool(
// If file was previously pinned, store it in persistent dir and create
// symlink in pinned dir.
if (entry) { // File exists in cache.
- // If file is dirty, return error.
- if (entry->IsDirty()) {
- LOG(WARNING) << "Can't store a file to replace a dirty file: res_id="
- << resource_id
+ // If file is dirty or mounted, return error.
+ if (entry->IsDirty() || entry->IsMounted()) {
+ LOG(WARNING) << "Can't store a file to replace a "
+ << (entry->IsDirty() ? "dirty" : "mounted")
+ << " file: res_id=" << resource_id
<< ", md5=" << md5;
*error = base::PLATFORM_FILE_ERROR_IN_USE;
return;
@@ -3670,10 +3807,10 @@ void GDataFileSystem::PinOnIOThreadPool(const std::string& resource_id,
// Determine source and destination paths.
- // If file is dirty, don't move it, so determine |dest_path| and set
- // |source_path| the same, because ModifyCacheState only moves files if
+ // If file is dirty or mounted, don't move it, so determine |dest_path| and
+ // set |source_path| the same, because ModifyCacheState only moves files if
// source and destination are different.
- if (entry->IsDirty()) {
+ if (entry->IsDirty() || entry->IsMounted()) {
DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type);
dest_path = GetCacheFilePath(resource_id,
md5,
@@ -3753,10 +3890,10 @@ void GDataFileSystem::UnpinOnIOThreadPool(const std::string& resource_id,
GDataRootDirectory::CacheSubDirectoryType sub_dir_type =
GDataRootDirectory::CACHE_TYPE_TMP;
- // If file is dirty, don't move it, so determine |dest_path| and set
- // |source_path| the same, because ModifyCacheState moves files if source
+ // If file is dirty or mounted, don't move it, so determine |dest_path| and
+ // set |source_path| the same, because ModifyCacheState moves files if source
// and destination are different.
- if (entry->IsDirty()) {
+ if (entry->IsDirty() || entry->IsMounted()) {
sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT;
DCHECK_EQ(sub_dir_type, entry->sub_dir_type);
dest_path = GetCacheFilePath(resource_id,
@@ -4088,9 +4225,11 @@ void GDataFileSystem::RemoveFromCacheOnIOThreadPool(
GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(
resource_id, std::string());
- // If entry doesn't exist or is dirty in cache, nothing to do.
- if (!entry || entry->IsDirty()) {
- DVLOG(1) << "Entry " << (entry ? "is dirty" : "doesn't exist")
+ // If entry doesn't exist or is dirty or mounted in cache, nothing to do.
+ if (!entry || entry->IsDirty() || entry->IsMounted()) {
+ DVLOG(1) << "Entry is "
+ << (entry ? (entry->IsDirty() ? "dirty" : "mounted") :
+ "non-existent")
<< " in cache, not removing";
*error = base::PLATFORM_FILE_OK;
return;
@@ -4240,6 +4379,22 @@ void GDataFileSystem::ScanCacheDirectory(
if (iter != cache_map->end()) { // Entry exists, update pinned state.
GDataRootDirectory::CacheEntry* entry = iter->second;
entry->cache_state = GDataFile::SetCachePinned(entry->cache_state);
+ // Check that the file exists in the persistent directory
+ FilePath expected_path = GetCacheFilePath(
+ resource_id, entry->md5,
+ GDataRootDirectory::CACHE_TYPE_PERSISTENT,
+ CACHED_FILE_FROM_SERVER);
+ if (!file_util::PathExists(expected_path))
+ {
satorux1 2012/04/20 20:11:25 nit: move { to the previous line.
+ // If the pinned file is a mounted archive, it may be stripped of the
+ // 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..
+ FilePath tmp_path = GetCacheFilePath(
+ resource_id, entry->md5,
+ GDataRootDirectory::CACHE_TYPE_TMP,
+ CACHED_FILE_FROM_SERVER);
+ DCHECK(file_util::PathExists(tmp_path));
+ file_util::Move(tmp_path, expected_path);
+ }
continue;
}
// Entry doesn't exist, this is a special symlink that refers to
@@ -4265,6 +4420,25 @@ void GDataFileSystem::ScanCacheDirectory(
cache_state = GDataFile::SetCachePresent(cache_state);
}
+ // Mounted archives in cache should be unmounted upon logout/shutdown.
+ // But if we encounter a mounted file at start, move it back to tmp.
+ if (md5 == kMountedArchiveFileExtension) {
+ DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT);
+ sub_dir_type = GDataRootDirectory::CACHE_TYPE_TMP;
+ // Files that are already mounted have filenames in format of
+ // resource_id.md5.mounted, i.e. ".mounted" is the extension, so strip
+ // it and get the actual resource_id and md5
+ base_name = base_name.RemoveExtension();
+ resource_id = GDataEntry::UnescapeUtf8FileName(
+ base_name.RemoveExtension().value());
+ FilePath::StringType extension = base_name.Extension();
+ md5 = !extension.empty() ?
+ GDataEntry::UnescapeUtf8FileName(extension.substr(1)) :
+ std::string();
+ file_util::Move(current, GetCacheFilePath(resource_id, md5, sub_dir_type,
+ CACHED_FILE_FROM_SERVER));
+ }
+
// Create and insert new entry into cache map.
GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry(
md5, sub_dir_type, cache_state);
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_file_system.h ('k') | chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698