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

Side by Side Diff: chrome/browser/chromeos/drive/file_cache.cc

Issue 15663006: drive: Merge 'persistent' and 'tmp' directories to 'files' (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
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/drive/file_cache.h" 5 #include "chrome/browser/chromeos/drive/file_cache.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
(...skipping 10 matching lines...) Expand all
21 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
22 22
23 using content::BrowserThread; 23 using content::BrowserThread;
24 24
25 namespace drive { 25 namespace drive {
26 namespace internal { 26 namespace internal {
27 namespace { 27 namespace {
28 28
29 typedef std::map<std::string, FileCacheEntry> CacheMap; 29 typedef std::map<std::string, FileCacheEntry> CacheMap;
30 30
31 typedef std::map<std::string, base::FilePath> ResourceIdToFilePathMap;
32
33 const base::FilePath::CharType kFileCacheMetaDir[] = FILE_PATH_LITERAL("meta"); 31 const base::FilePath::CharType kFileCacheMetaDir[] = FILE_PATH_LITERAL("meta");
34 const base::FilePath::CharType kFileCachePersistentDir[] = 32 const base::FilePath::CharType kFileCacheFilesDir[] =
35 FILE_PATH_LITERAL("persistent"); 33 FILE_PATH_LITERAL("files");
36 const base::FilePath::CharType kFileCacheTmpDir[] = FILE_PATH_LITERAL("tmp");
37 const base::FilePath::CharType kFileCacheTmpDownloadsDir[] = 34 const base::FilePath::CharType kFileCacheTmpDownloadsDir[] =
38 FILE_PATH_LITERAL("tmp/downloads"); 35 FILE_PATH_LITERAL("tmp/downloads");
39 const base::FilePath::CharType kFileCacheTmpDocumentsDir[] = 36 const base::FilePath::CharType kFileCacheTmpDocumentsDir[] =
40 FILE_PATH_LITERAL("tmp/documents"); 37 FILE_PATH_LITERAL("tmp/documents");
41 38
42 // Returns true if |md5| matches the one in |cache_entry| with some 39 // Returns true if |md5| matches the one in |cache_entry| with some
43 // exceptions. See the function definition for details. 40 // exceptions. See the function definition for details.
44 bool CheckIfMd5Matches(const std::string& md5, 41 bool CheckIfMd5Matches(const std::string& md5,
45 const FileCacheEntry& cache_entry) { 42 const FileCacheEntry& cache_entry) {
46 if (cache_entry.is_dirty()) { 43 if (cache_entry.is_dirty()) {
47 // If the entry is dirty, its MD5 may have been replaced by "local" 44 // If the entry is dirty, its MD5 may have been replaced by "local"
48 // during cache initialization, so we don't compare MD5. 45 // during cache initialization, so we don't compare MD5.
49 return true; 46 return true;
50 } else if (cache_entry.is_pinned() && cache_entry.md5().empty()) { 47 } else if (cache_entry.is_pinned() && cache_entry.md5().empty()) {
51 // If the entry is pinned, it's ok for the entry to have an empty 48 // If the entry is pinned, it's ok for the entry to have an empty
52 // MD5. This can happen if the pinned file is not fetched. MD5 for pinned 49 // MD5. This can happen if the pinned file is not fetched.
53 // files are collected from files in "persistent" directory, but the
54 // persistent files do not exist if these are not fetched yet.
55 return true; 50 return true;
56 } else if (md5.empty()) { 51 } else if (md5.empty()) {
57 // If the MD5 matching is not requested, don't check MD5. 52 // If the MD5 matching is not requested, don't check MD5.
58 return true; 53 return true;
59 } else if (md5 == cache_entry.md5()) { 54 } else if (md5 == cache_entry.md5()) {
60 // Otherwise, compare the MD5. 55 // Otherwise, compare the MD5.
61 return true; 56 return true;
62 } 57 }
63 return false; 58 return false;
64 } 59 }
65 60
66 // Scans cache subdirectory and build or update |cache_map| with found files. 61 // Scans cache subdirectory and insert found files to |cache_map|.
67 // 62 void ScanCacheDirectory(const base::FilePath& directory_path,
68 // The resource IDs and file paths of discovered files are collected as a 63 CacheMap* cache_map) {
69 // ResourceIdToFilePathMap, if these are processed properly. 64 base::FileEnumerator enumerator(directory_path,
70 void ScanCacheDirectory(const std::vector<base::FilePath>& cache_paths,
71 FileCache::CacheSubDirectoryType sub_dir_type,
72 CacheMap* cache_map,
73 ResourceIdToFilePathMap* processed_file_map) {
74 DCHECK(cache_map);
75 DCHECK(processed_file_map);
76
77 base::FileEnumerator enumerator(cache_paths[sub_dir_type],
78 false, // not recursive 65 false, // not recursive
79 base::FileEnumerator::FILES, 66 base::FileEnumerator::FILES);
80 util::kWildCard);
81 for (base::FilePath current = enumerator.Next(); !current.empty(); 67 for (base::FilePath current = enumerator.Next(); !current.empty();
82 current = enumerator.Next()) { 68 current = enumerator.Next()) {
83 // Extract resource_id and md5 from filename. 69 // Extract resource_id and md5 from filename.
84 std::string resource_id; 70 std::string resource_id;
85 std::string md5; 71 std::string md5;
86 std::string extra_extension; 72 std::string extra_extension;
87 util::ParseCacheFilePath(current, &resource_id, &md5, &extra_extension); 73 util::ParseCacheFilePath(current, &resource_id, &md5, &extra_extension);
88 74
75 if (extra_extension == util::kMountedArchiveFileExtension) {
76 // Mounted archives in cache should be unmounted upon logout/shutdown.
77 // But if we encounter a mounted file at start, delete it.
78 file_util::Delete(current, false);
79 continue;
80 }
81
89 // Determine cache state. 82 // Determine cache state.
90 FileCacheEntry cache_entry; 83 FileCacheEntry cache_entry;
91 cache_entry.set_md5(md5); 84 cache_entry.set_md5(md5);
92 if (sub_dir_type == FileCache::CACHE_TYPE_PERSISTENT) 85 cache_entry.set_is_present(true);
93 cache_entry.set_is_persistent(true);
94 86
95 if (extra_extension == util::kMountedArchiveFileExtension) { 87 // Add the dirty bit if |md5| indicates that the file is dirty.
96 // Mounted archives in cache should be unmounted upon logout/shutdown. 88 if (md5 == util::kLocallyModifiedFileExtension)
97 // But if we encounter a mounted file at start, delete it and create an 89 cache_entry.set_is_dirty(true);
98 // entry with not PRESENT state.
99 DCHECK(sub_dir_type == FileCache::CACHE_TYPE_PERSISTENT);
100 file_util::Delete(current, false);
101 } else {
102 // The cache file is present.
103 cache_entry.set_is_present(true);
104
105 // Adds the dirty bit if |md5| indicates that the file is dirty, and
106 // the file is in the persistent directory.
107 if (md5 == util::kLocallyModifiedFileExtension) {
108 if (sub_dir_type == FileCache::CACHE_TYPE_PERSISTENT) {
109 cache_entry.set_is_dirty(true);
110 } else {
111 LOG(WARNING) << "Removing a dirty file in tmp directory: "
112 << current.value();
113 file_util::Delete(current, false);
114 continue;
115 }
116 }
117 }
118 90
119 // Create and insert new entry into cache map. 91 // Create and insert new entry into cache map.
120 cache_map->insert(std::make_pair(resource_id, cache_entry)); 92 cache_map->insert(std::make_pair(resource_id, cache_entry));
121 processed_file_map->insert(std::make_pair(resource_id, current));
122 } 93 }
123 } 94 }
124 95
125 void ScanCachePaths(const std::vector<base::FilePath>& cache_paths,
126 CacheMap* cache_map) {
127 DVLOG(1) << "Scanning directories";
128
129 // Scan cache persistent and tmp directories to enumerate all files and create
130 // corresponding entries for cache map.
131 ResourceIdToFilePathMap persistent_file_map;
132 ScanCacheDirectory(cache_paths,
133 FileCache::CACHE_TYPE_PERSISTENT,
134 cache_map,
135 &persistent_file_map);
136 ResourceIdToFilePathMap tmp_file_map;
137 ScanCacheDirectory(cache_paths,
138 FileCache::CACHE_TYPE_TMP,
139 cache_map,
140 &tmp_file_map);
141
142 // On DB corruption, keep only dirty-and-committed files in persistent
143 // directory. Other files are deleted or moved to temporary directory.
144 for (ResourceIdToFilePathMap::const_iterator iter =
145 persistent_file_map.begin();
146 iter != persistent_file_map.end(); ++iter) {
147 const std::string& resource_id = iter->first;
148 const base::FilePath& file_path = iter->second;
149
150 CacheMap::iterator cache_map_iter = cache_map->find(resource_id);
151 if (cache_map_iter != cache_map->end()) {
152 FileCacheEntry* cache_entry = &cache_map_iter->second;
153 const bool is_dirty = cache_entry->is_dirty();
154 if (!is_dirty) {
155 // If the file is not dirty, move to temporary directory.
156 base::FilePath new_file_path =
157 cache_paths[FileCache::CACHE_TYPE_TMP].Append(
158 file_path.BaseName());
159 DLOG(WARNING) << "Moving: " << file_path.value()
160 << " to: " << new_file_path.value();
161 file_util::Move(file_path, new_file_path);
162 cache_entry->set_is_persistent(false);
163 }
164 }
165 }
166 DVLOG(1) << "Directory scan finished";
167 }
168
169 // Create cache directory paths and set permissions. 96 // Create cache directory paths and set permissions.
170 bool InitCachePaths(const std::vector<base::FilePath>& cache_paths) { 97 bool InitCachePaths(const std::vector<base::FilePath>& cache_paths) {
171 if (cache_paths.size() < FileCache::NUM_CACHE_TYPES) { 98 if (cache_paths.size() < FileCache::NUM_CACHE_TYPES) {
172 NOTREACHED(); 99 NOTREACHED();
173 LOG(ERROR) << "Size of cache_paths is invalid."; 100 LOG(ERROR) << "Size of cache_paths is invalid.";
174 return false; 101 return false;
175 } 102 }
176 103
177 if (!FileCache::CreateCacheDirectories(cache_paths)) 104 if (!FileCache::CreateCacheDirectories(cache_paths))
178 return false; 105 return false;
179 106
180 // Change permissions of cache persistent directory to u+rwx,og+x (711) in 107 // Change permissions of cache file directory to u+rwx,og+x (711) in order to
181 // order to allow archive files in that directory to be mounted by cros-disks. 108 // allow archive files in that directory to be mounted by cros-disks.
182 file_util::SetPosixFilePermissions( 109 file_util::SetPosixFilePermissions(
183 cache_paths[FileCache::CACHE_TYPE_PERSISTENT], 110 cache_paths[FileCache::CACHE_TYPE_FILES],
184 file_util::FILE_PERMISSION_USER_MASK | 111 file_util::FILE_PERMISSION_USER_MASK |
185 file_util::FILE_PERMISSION_EXECUTE_BY_GROUP | 112 file_util::FILE_PERMISSION_EXECUTE_BY_GROUP |
186 file_util::FILE_PERMISSION_EXECUTE_BY_OTHERS); 113 file_util::FILE_PERMISSION_EXECUTE_BY_OTHERS);
187 114
188 return true; 115 return true;
189 } 116 }
190 117
191 // Remove all files under the given directory, non-recursively.
192 // Do not remove recursively as we don't want to touch <gcache>/tmp/downloads,
193 // which is used for user initiated downloads like "Save As"
194 void RemoveAllFiles(const base::FilePath& directory) {
195 base::FileEnumerator enumerator(directory, false /* recursive */,
196 base::FileEnumerator::FILES);
197 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
198 file_path = enumerator.Next()) {
199 DVLOG(1) << "Removing " << file_path.value();
200 if (!file_util::Delete(file_path, false /* recursive */))
201 LOG(WARNING) << "Failed to delete " << file_path.value();
202 }
203 }
204
205 // Moves the file. 118 // Moves the file.
206 bool MoveFile(const base::FilePath& source_path, 119 bool MoveFile(const base::FilePath& source_path,
207 const base::FilePath& dest_path) { 120 const base::FilePath& dest_path) {
208 if (!file_util::Move(source_path, dest_path)) { 121 if (!file_util::Move(source_path, dest_path)) {
209 LOG(ERROR) << "Failed to move " << source_path.value() 122 LOG(ERROR) << "Failed to move " << source_path.value()
210 << " to " << dest_path.value(); 123 << " to " << dest_path.value();
211 return false; 124 return false;
212 } 125 }
213 DVLOG(1) << "Moved " << source_path.value() << " to " << dest_path.value(); 126 DVLOG(1) << "Moved " << source_path.value() << " to " << dest_path.value();
214 return true; 127 return true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 continue; 161 continue;
249 162
250 success = file_util::Delete(current, false); 163 success = file_util::Delete(current, false);
251 if (!success) 164 if (!success)
252 DVLOG(1) << "Error deleting " << current.value(); 165 DVLOG(1) << "Error deleting " << current.value();
253 else 166 else
254 DVLOG(1) << "Deleted " << current.value(); 167 DVLOG(1) << "Deleted " << current.value();
255 } 168 }
256 } 169 }
257 170
171 // Moves all files under |directory_from| to |directory_to|.
172 void MoveAllFilesFromDirectory(const base::FilePath& directory_from,
173 const base::FilePath& directory_to) {
174 base::FileEnumerator enumerator(directory_from, false, // not recursive
175 base::FileEnumerator::FILES);
176 for (base::FilePath file_from = enumerator.Next(); !file_from.empty();
177 file_from = enumerator.Next()) {
178 const base::FilePath file_to = directory_to.Append(file_from.BaseName());
179 if (!file_util::PathExists(file_to)) // Do not overwrite existing files.
180 file_util::Move(file_from, file_to);
181 }
182 }
183
258 // Runs callback with pointers dereferenced. 184 // Runs callback with pointers dereferenced.
259 // Used to implement GetFile, MarkAsMounted. 185 // Used to implement GetFile, MarkAsMounted.
260 void RunGetFileFromCacheCallback( 186 void RunGetFileFromCacheCallback(
261 const GetFileFromCacheCallback& callback, 187 const GetFileFromCacheCallback& callback,
262 base::FilePath* file_path, 188 base::FilePath* file_path,
263 FileError error) { 189 FileError error) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 DCHECK(!callback.is_null()); 191 DCHECK(!callback.is_null());
266 DCHECK(file_path); 192 DCHECK(file_path);
267 193
(...skipping 30 matching lines...) Expand all
298 AssertOnSequencedWorkerPool(); 224 AssertOnSequencedWorkerPool();
299 } 225 }
300 226
301 base::FilePath FileCache::GetCacheDirectoryPath( 227 base::FilePath FileCache::GetCacheDirectoryPath(
302 CacheSubDirectoryType sub_dir_type) const { 228 CacheSubDirectoryType sub_dir_type) const {
303 DCHECK_LE(0, sub_dir_type); 229 DCHECK_LE(0, sub_dir_type);
304 DCHECK_GT(NUM_CACHE_TYPES, sub_dir_type); 230 DCHECK_GT(NUM_CACHE_TYPES, sub_dir_type);
305 return cache_paths_[sub_dir_type]; 231 return cache_paths_[sub_dir_type];
306 } 232 }
307 233
308 base::FilePath FileCache::GetCacheFilePath( 234 base::FilePath FileCache::GetCacheFilePath(const std::string& resource_id,
309 const std::string& resource_id, 235 const std::string& md5,
310 const std::string& md5, 236 CachedFileOrigin file_origin) const {
311 CacheSubDirectoryType sub_dir_type,
312 CachedFileOrigin file_origin) const {
313 DCHECK(sub_dir_type != CACHE_TYPE_META);
314
315 // Runs on any thread. 237 // Runs on any thread.
316 // Filename is formatted as resource_id.md5, i.e. resource_id is the base 238 // Filename is formatted as resource_id.md5, i.e. resource_id is the base
317 // name and md5 is the extension. 239 // name and md5 is the extension.
318 std::string base_name = util::EscapeCacheFileName(resource_id); 240 std::string base_name = util::EscapeCacheFileName(resource_id);
319 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { 241 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) {
320 DCHECK(sub_dir_type == CACHE_TYPE_PERSISTENT);
321 base_name += base::FilePath::kExtensionSeparator; 242 base_name += base::FilePath::kExtensionSeparator;
322 base_name += util::kLocallyModifiedFileExtension; 243 base_name += util::kLocallyModifiedFileExtension;
323 } else if (!md5.empty()) { 244 } else if (!md5.empty()) {
324 base_name += base::FilePath::kExtensionSeparator; 245 base_name += base::FilePath::kExtensionSeparator;
325 base_name += util::EscapeCacheFileName(md5); 246 base_name += util::EscapeCacheFileName(md5);
326 } 247 }
327 // For mounted archives the filename is formatted as resource_id.md5.mounted, 248 // For mounted archives the filename is formatted as resource_id.md5.mounted,
328 // i.e. resource_id.md5 is the base name and ".mounted" is the extension 249 // i.e. resource_id.md5 is the base name and ".mounted" is the extension
329 if (file_origin == CACHED_FILE_MOUNTED) { 250 if (file_origin == CACHED_FILE_MOUNTED) {
330 DCHECK(sub_dir_type == CACHE_TYPE_PERSISTENT);
331 base_name += base::FilePath::kExtensionSeparator; 251 base_name += base::FilePath::kExtensionSeparator;
332 base_name += util::kMountedArchiveFileExtension; 252 base_name += util::kMountedArchiveFileExtension;
333 } 253 }
334 return GetCacheDirectoryPath(sub_dir_type).Append( 254 return GetCacheDirectoryPath(CACHE_TYPE_FILES).Append(
335 base::FilePath::FromUTF8Unsafe(base_name)); 255 base::FilePath::FromUTF8Unsafe(base_name));
336 } 256 }
337 257
338 void FileCache::AssertOnSequencedWorkerPool() { 258 void FileCache::AssertOnSequencedWorkerPool() {
339 DCHECK(!blocking_task_runner_ || 259 DCHECK(!blocking_task_runner_ ||
340 blocking_task_runner_->RunsTasksOnCurrentThread()); 260 blocking_task_runner_->RunsTasksOnCurrentThread());
341 } 261 }
342 262
343 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { 263 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const {
344 return cache_root_path_ == path || cache_root_path_.IsParent(path); 264 return cache_root_path_ == path || cache_root_path_.IsParent(path);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { 332 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) {
413 AssertOnSequencedWorkerPool(); 333 AssertOnSequencedWorkerPool();
414 334
415 // Do nothing and return if we have enough space. 335 // Do nothing and return if we have enough space.
416 if (HasEnoughSpaceFor(num_bytes, cache_root_path_)) 336 if (HasEnoughSpaceFor(num_bytes, cache_root_path_))
417 return true; 337 return true;
418 338
419 // Otherwise, try to free up the disk space. 339 // Otherwise, try to free up the disk space.
420 DVLOG(1) << "Freeing up disk space for " << num_bytes; 340 DVLOG(1) << "Freeing up disk space for " << num_bytes;
421 341
422 // First remove temporary files from the metadata. 342 // Remove all entries unless specially marked.
423 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 343 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator();
424 for (; !it->IsAtEnd(); it->Advance()) { 344 for (; !it->IsAtEnd(); it->Advance()) {
425 if (!it->GetValue().is_persistent()) 345 const FileCacheEntry& entry = it->GetValue();
346 if (!entry.is_pinned() && !entry.is_dirty() && !entry.is_mounted())
426 metadata_->RemoveCacheEntry(it->GetKey()); 347 metadata_->RemoveCacheEntry(it->GetKey());
427 } 348 }
428 DCHECK(!it->HasError()); 349 DCHECK(!it->HasError());
429 350
430 // Then remove all files under "tmp" directory. 351 // Remove all files which have no corresponding cache entries.
431 RemoveAllFiles(GetCacheDirectoryPath(CACHE_TYPE_TMP)); 352 base::FileEnumerator enumerator(cache_paths_[CACHE_TYPE_FILES],
353 false, // not recursive
354 base::FileEnumerator::FILES);
355 std::string resource_id;
356 std::string md5;
357 std::string extra_extension;
358 FileCacheEntry entry;
359 for (base::FilePath current = enumerator.Next(); !current.empty();
360 current = enumerator.Next()) {
361 util::ParseCacheFilePath(current, &resource_id, &md5, &extra_extension);
362 if (!GetCacheEntry(resource_id, md5, &entry))
363 file_util::Delete(current, false /* recursive */);
364 }
432 365
433 // Check the disk space again. 366 // Check the disk space again.
434 return HasEnoughSpaceFor(num_bytes, cache_root_path_); 367 return HasEnoughSpaceFor(num_bytes, cache_root_path_);
435 } 368 }
436 369
437 void FileCache::GetFileOnUIThread(const std::string& resource_id, 370 void FileCache::GetFileOnUIThread(const std::string& resource_id,
438 const std::string& md5, 371 const std::string& md5,
439 const GetFileFromCacheCallback& callback) { 372 const GetFileFromCacheCallback& callback) {
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
441 DCHECK(!callback.is_null()); 374 DCHECK(!callback.is_null());
(...skipping 21 matching lines...) Expand all
463 396
464 CachedFileOrigin file_origin; 397 CachedFileOrigin file_origin;
465 if (cache_entry.is_mounted()) { 398 if (cache_entry.is_mounted()) {
466 file_origin = CACHED_FILE_MOUNTED; 399 file_origin = CACHED_FILE_MOUNTED;
467 } else if (cache_entry.is_dirty()) { 400 } else if (cache_entry.is_dirty()) {
468 file_origin = CACHED_FILE_LOCALLY_MODIFIED; 401 file_origin = CACHED_FILE_LOCALLY_MODIFIED;
469 } else { 402 } else {
470 file_origin = CACHED_FILE_FROM_SERVER; 403 file_origin = CACHED_FILE_FROM_SERVER;
471 } 404 }
472 405
473 *cache_file_path = GetCacheFilePath(resource_id, 406 *cache_file_path = GetCacheFilePath(resource_id, cache_entry.md5(),
474 cache_entry.md5(),
475 GetSubDirectoryType(cache_entry),
476 file_origin); 407 file_origin);
477 return FILE_ERROR_OK; 408 return FILE_ERROR_OK;
478 } 409 }
479 410
480 void FileCache::StoreOnUIThread(const std::string& resource_id, 411 void FileCache::StoreOnUIThread(const std::string& resource_id,
481 const std::string& md5, 412 const std::string& md5,
482 const base::FilePath& source_path, 413 const base::FilePath& source_path,
483 FileOperationType file_operation_type, 414 FileOperationType file_operation_type,
484 const FileOperationCallback& callback) { 415 const FileOperationCallback& callback) {
485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 26 matching lines...) Expand all
512 blocking_task_runner_, 443 blocking_task_runner_,
513 FROM_HERE, 444 FROM_HERE,
514 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id, md5), 445 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id, md5),
515 callback); 446 callback);
516 } 447 }
517 448
518 FileError FileCache::Pin(const std::string& resource_id, 449 FileError FileCache::Pin(const std::string& resource_id,
519 const std::string& md5) { 450 const std::string& md5) {
520 AssertOnSequencedWorkerPool(); 451 AssertOnSequencedWorkerPool();
521 452
522 bool is_persistent = true;
523 FileCacheEntry cache_entry; 453 FileCacheEntry cache_entry;
524 if (!GetCacheEntry(resource_id, md5, &cache_entry)) { 454 if (!GetCacheEntry(resource_id, md5, &cache_entry))
525 // The file will be first downloaded in 'tmp', then moved to 'persistent'. 455 cache_entry.set_md5(md5);
526 is_persistent = false;
527 } else { // File exists in cache, determines destination path.
528 // Determine source and destination paths.
529
530 // If file is dirty or mounted, don't move it.
531 if (!cache_entry.is_dirty() && !cache_entry.is_mounted()) {
532 // If file was pinned before but actual file blob doesn't exist in cache:
533 // - don't need to move the file.
534 if (!cache_entry.is_present()) {
535 DCHECK(cache_entry.is_pinned());
536 return FILE_ERROR_OK;
537 }
538 // File exists, move it to persistent dir.
539 // Gets the current path of the file in cache.
540 base::FilePath source_path = GetCacheFilePath(
541 resource_id,
542 md5,
543 GetSubDirectoryType(cache_entry),
544 CACHED_FILE_FROM_SERVER);
545 base::FilePath dest_path = GetCacheFilePath(resource_id,
546 md5,
547 CACHE_TYPE_PERSISTENT,
548 CACHED_FILE_FROM_SERVER);
549 if (!MoveFile(source_path, dest_path))
550 return FILE_ERROR_FAILED;
551 }
552 }
553
554 // Now that file operations have completed, update metadata.
555 cache_entry.set_md5(md5);
556 cache_entry.set_is_pinned(true); 456 cache_entry.set_is_pinned(true);
557 cache_entry.set_is_persistent(is_persistent);
558 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 457 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
559 return FILE_ERROR_OK; 458 return FILE_ERROR_OK;
560 } 459 }
561 460
562 void FileCache::UnpinOnUIThread(const std::string& resource_id, 461 void FileCache::UnpinOnUIThread(const std::string& resource_id,
563 const std::string& md5, 462 const std::string& md5,
564 const FileOperationCallback& callback) { 463 const FileOperationCallback& callback) {
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
566 DCHECK(!callback.is_null()); 465 DCHECK(!callback.is_null());
567 466
(...skipping 10 matching lines...) Expand all
578 477
579 // Unpinning a file means its entry must exist in cache. 478 // Unpinning a file means its entry must exist in cache.
580 FileCacheEntry cache_entry; 479 FileCacheEntry cache_entry;
581 if (!GetCacheEntry(resource_id, md5, &cache_entry)) { 480 if (!GetCacheEntry(resource_id, md5, &cache_entry)) {
582 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id=" 481 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id="
583 << resource_id 482 << resource_id
584 << ", md5=" << md5; 483 << ", md5=" << md5;
585 return FILE_ERROR_NOT_FOUND; 484 return FILE_ERROR_NOT_FOUND;
586 } 485 }
587 486
588 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP;
589
590 // If file is dirty or mounted, don't move it.
591 if (cache_entry.is_dirty() || cache_entry.is_mounted()) {
592 sub_dir_type = CACHE_TYPE_PERSISTENT;
593 DCHECK(cache_entry.is_persistent());
594 } else {
595 // If file was pinned but actual file blob still doesn't exist in cache,
596 // don't need to move the file.
597 if (cache_entry.is_present()) {
598 // Gets the current path of the file in cache.
599 base::FilePath source_path = GetCacheFilePath(
600 resource_id,
601 md5,
602 GetSubDirectoryType(cache_entry),
603 CACHED_FILE_FROM_SERVER);
604 // File exists, move it to tmp dir.
605 base::FilePath dest_path = GetCacheFilePath(
606 resource_id,
607 md5,
608 CACHE_TYPE_TMP,
609 CACHED_FILE_FROM_SERVER);
610 if (!MoveFile(source_path, dest_path))
611 return FILE_ERROR_FAILED;
612 }
613 }
614
615 // Now that file operations have completed, update metadata. 487 // Now that file operations have completed, update metadata.
616 if (cache_entry.is_present()) { 488 if (cache_entry.is_present()) {
617 cache_entry.set_md5(md5); 489 cache_entry.set_md5(md5);
618 cache_entry.set_is_pinned(false); 490 cache_entry.set_is_pinned(false);
619 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
620 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 491 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
621 } else { 492 } else {
622 // Remove the existing entry if we are unpinning a non-present file. 493 // Remove the existing entry if we are unpinning a non-present file.
623 metadata_->RemoveCacheEntry(resource_id); 494 metadata_->RemoveCacheEntry(resource_id);
624 } 495 }
625 496
626 // Now the file is moved from "persistent" to "tmp" directory. 497 // Now it's a chance to free up space if needed.
627 // It's a chance to free up space if needed.
628 FreeDiskSpaceIfNeededFor(0); 498 FreeDiskSpaceIfNeededFor(0);
629 499
630 return FILE_ERROR_OK; 500 return FILE_ERROR_OK;
631 } 501 }
632 502
633 void FileCache::MarkAsMountedOnUIThread( 503 void FileCache::MarkAsMountedOnUIThread(
634 const std::string& resource_id, 504 const std::string& resource_id,
635 const GetFileFromCacheCallback& callback) { 505 const GetFileFromCacheCallback& callback) {
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637 DCHECK(!callback.is_null()); 507 DCHECK(!callback.is_null());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // cache. 557 // cache.
688 FileCacheEntry cache_entry; 558 FileCacheEntry cache_entry;
689 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) || 559 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) ||
690 !cache_entry.is_present()) { 560 !cache_entry.is_present()) {
691 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id=" 561 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id="
692 << resource_id 562 << resource_id
693 << ", md5=" << md5; 563 << ", md5=" << md5;
694 return FILE_ERROR_NOT_FOUND; 564 return FILE_ERROR_NOT_FOUND;
695 } 565 }
696 566
697 if (cache_entry.is_dirty()) { 567 if (cache_entry.is_dirty())
698 // The file must be in persistent dir.
699 DCHECK(cache_entry.is_persistent());
700 return FILE_ERROR_OK; 568 return FILE_ERROR_OK;
701 }
702
703 // Move file to persistent dir with new .local extension.
704 569
705 // Get the current path of the file in cache. 570 // Get the current path of the file in cache.
706 base::FilePath source_path = GetCacheFilePath( 571 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
707 resource_id, 572 CACHED_FILE_FROM_SERVER);
708 md5,
709 GetSubDirectoryType(cache_entry),
710 CACHED_FILE_FROM_SERVER);
711 // Determine destination path. 573 // Determine destination path.
712 const CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT;
713 base::FilePath cache_file_path = GetCacheFilePath( 574 base::FilePath cache_file_path = GetCacheFilePath(
714 resource_id, 575 resource_id, md5, CACHED_FILE_LOCALLY_MODIFIED);
715 md5,
716 sub_dir_type,
717 CACHED_FILE_LOCALLY_MODIFIED);
718 576
719 if (!MoveFile(source_path, cache_file_path)) 577 if (!MoveFile(source_path, cache_file_path))
720 return FILE_ERROR_FAILED; 578 return FILE_ERROR_FAILED;
721 579
722 // Now that file operations have completed, update metadata. 580 // Now that file operations have completed, update metadata.
723 cache_entry.set_md5(md5); 581 cache_entry.set_md5(md5);
724 cache_entry.set_is_dirty(true); 582 cache_entry.set_is_dirty(true);
725 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
726 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 583 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
727 return FILE_ERROR_OK; 584 return FILE_ERROR_OK;
728 } 585 }
729 586
730 FileError FileCache::ClearDirty(const std::string& resource_id, 587 FileError FileCache::ClearDirty(const std::string& resource_id,
731 const std::string& md5) { 588 const std::string& md5) {
732 AssertOnSequencedWorkerPool(); 589 AssertOnSequencedWorkerPool();
733 590
734 // |md5| is the new .<md5> extension to rename the file to. 591 // |md5| is the new .<md5> extension to rename the file to.
735 // So, search for entry in cache without comparing md5. 592 // So, search for entry in cache without comparing md5.
(...skipping 11 matching lines...) Expand all
747 604
748 // If a file is not dirty (it should have been marked dirty via 605 // If a file is not dirty (it should have been marked dirty via
749 // MarkDirtyInCache), clearing its dirty state is an invalid operation. 606 // MarkDirtyInCache), clearing its dirty state is an invalid operation.
750 if (!cache_entry.is_dirty()) { 607 if (!cache_entry.is_dirty()) {
751 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id=" 608 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id="
752 << resource_id 609 << resource_id
753 << ", md5=" << md5; 610 << ", md5=" << md5;
754 return FILE_ERROR_INVALID_OPERATION; 611 return FILE_ERROR_INVALID_OPERATION;
755 } 612 }
756 613
757 // File must be dirty and hence in persistent dir. 614 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
758 DCHECK(cache_entry.is_persistent()); 615 CACHED_FILE_LOCALLY_MODIFIED);
759 616 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
760 // Get the current path of the file in cache.
761 base::FilePath source_path =
762 GetCacheFilePath(resource_id,
763 md5,
764 GetSubDirectoryType(cache_entry),
765 CACHED_FILE_LOCALLY_MODIFIED);
766
767 // Determine destination path.
768 // If file is pinned, move it to persistent dir with .md5 extension;
769 // otherwise, move it to tmp dir with .md5 extension.
770 const CacheSubDirectoryType sub_dir_type =
771 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
772 base::FilePath dest_path = GetCacheFilePath(resource_id,
773 md5,
774 sub_dir_type,
775 CACHED_FILE_FROM_SERVER); 617 CACHED_FILE_FROM_SERVER);
776
777 if (!MoveFile(source_path, dest_path)) 618 if (!MoveFile(source_path, dest_path))
778 return FILE_ERROR_FAILED; 619 return FILE_ERROR_FAILED;
779 620
780 // Now that file operations have completed, update metadata. 621 // Now that file operations have completed, update metadata.
781 cache_entry.set_md5(md5); 622 cache_entry.set_md5(md5);
782 cache_entry.set_is_dirty(false); 623 cache_entry.set_is_dirty(false);
783 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
784 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 624 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
785 return FILE_ERROR_OK; 625 return FILE_ERROR_OK;
786 } 626 }
787 627
788 void FileCache::RemoveOnUIThread(const std::string& resource_id, 628 void FileCache::RemoveOnUIThread(const std::string& resource_id,
789 const FileOperationCallback& callback) { 629 const FileOperationCallback& callback) {
790 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 630 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
791 DCHECK(!callback.is_null()); 631 DCHECK(!callback.is_null());
792 632
793 base::PostTaskAndReplyWithResult( 633 base::PostTaskAndReplyWithResult(
794 blocking_task_runner_, 634 blocking_task_runner_,
795 FROM_HERE, 635 FROM_HERE,
796 base::Bind(&FileCache::Remove, 636 base::Bind(&FileCache::Remove,
797 base::Unretained(this), resource_id), 637 base::Unretained(this), resource_id),
798 callback); 638 callback);
799 } 639 }
800 640
801 FileError FileCache::Remove(const std::string& resource_id) { 641 FileError FileCache::Remove(const std::string& resource_id) {
802 AssertOnSequencedWorkerPool(); 642 AssertOnSequencedWorkerPool();
803 643
804 // MD5 is not passed into RemoveCacheEntry because we would delete all 644 // MD5 is not passed into RemoveCacheEntry because we would delete all
805 // cache files corresponding to <resource_id> regardless of the md5. 645 // cache files corresponding to <resource_id> regardless of the md5.
806 // So, search for entry in cache without taking md5 into account. 646 // So, search for entry in cache without taking md5 into account.
807 FileCacheEntry cache_entry; 647 FileCacheEntry cache_entry;
808 648
809 // If entry doesn't exist or is dirty or mounted in cache, nothing to do. 649 // If entry doesn't exist or is dirty or mounted in cache, nothing to do.
810 const bool entry_found = metadata_->GetCacheEntry(resource_id, &cache_entry); 650 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) ||
811 if (!entry_found || cache_entry.is_dirty() || cache_entry.is_mounted()) { 651 cache_entry.is_dirty() ||
812 DVLOG(1) << "Entry is " 652 cache_entry.is_mounted())
813 << (entry_found ?
814 (cache_entry.is_dirty() ? "dirty" : "mounted") :
815 "non-existent")
816 << " in cache, not removing";
817 return FILE_ERROR_OK; 653 return FILE_ERROR_OK;
818 }
819 654
820 // Determine paths to delete all cache versions of |resource_id| in 655 // Delete files that match "<resource_id>.*" unless modified locally.
821 // persistent, tmp and pinned directories. 656 base::FilePath path_to_delete = GetCacheFilePath(resource_id, util::kWildCard,
822 std::vector<base::FilePath> paths_to_delete; 657 CACHED_FILE_FROM_SERVER);
823 658 base::FilePath path_to_keep = GetCacheFilePath(resource_id, std::string(),
824 // For files in persistent and tmp dirs, delete files that match
825 // "<resource_id>.*".
826 paths_to_delete.push_back(GetCacheFilePath(resource_id,
827 util::kWildCard,
828 CACHE_TYPE_PERSISTENT,
829 CACHED_FILE_FROM_SERVER));
830 paths_to_delete.push_back(GetCacheFilePath(resource_id,
831 util::kWildCard,
832 CACHE_TYPE_TMP,
833 CACHED_FILE_FROM_SERVER));
834
835 // Don't delete locally modified files.
836 base::FilePath path_to_keep = GetCacheFilePath(resource_id,
837 std::string(),
838 CACHE_TYPE_PERSISTENT,
839 CACHED_FILE_LOCALLY_MODIFIED); 659 CACHED_FILE_LOCALLY_MODIFIED);
840 660 DeleteFilesSelectively(path_to_delete, path_to_keep);
841 for (size_t i = 0; i < paths_to_delete.size(); ++i) {
842 DeleteFilesSelectively(paths_to_delete[i], path_to_keep);
843 }
844 661
845 // Now that all file operations have completed, remove from metadata. 662 // Now that all file operations have completed, remove from metadata.
846 metadata_->RemoveCacheEntry(resource_id); 663 metadata_->RemoveCacheEntry(resource_id);
847 664
848 return FILE_ERROR_OK; 665 return FILE_ERROR_OK;
849 } 666 }
850 667
851 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) { 668 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) {
852 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 669 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
853 DCHECK(!callback.is_null()); 670 DCHECK(!callback.is_null());
(...skipping 26 matching lines...) Expand all
880 // Note that base::DeletePointer<> cannot be used as the destructor of this 697 // Note that base::DeletePointer<> cannot be used as the destructor of this
881 // class is private. 698 // class is private.
882 blocking_task_runner_->PostTask( 699 blocking_task_runner_->PostTask(
883 FROM_HERE, 700 FROM_HERE,
884 base::Bind(&FileCache::DestroyOnBlockingPool, base::Unretained(this))); 701 base::Bind(&FileCache::DestroyOnBlockingPool, base::Unretained(this)));
885 } 702 }
886 703
887 bool FileCache::InitializeOnBlockingPool() { 704 bool FileCache::InitializeOnBlockingPool() {
888 AssertOnSequencedWorkerPool(); 705 AssertOnSequencedWorkerPool();
889 706
707 MigrateFilesFromOldDirectories();
kinaba 2013/06/14 01:59:33 How about moving this migration after InitCachePat
hashimoto 2013/06/14 04:04:46 Done.
708
890 if (!InitCachePaths(cache_paths_)) 709 if (!InitCachePaths(cache_paths_))
891 return false; 710 return false;
892 711
893 metadata_.reset(new FileCacheMetadata(blocking_task_runner_)); 712 metadata_.reset(new FileCacheMetadata(blocking_task_runner_));
894 713
895 switch (metadata_->Initialize(cache_paths_[CACHE_TYPE_META])) { 714 switch (metadata_->Initialize(cache_paths_[CACHE_TYPE_META])) {
896 case FileCacheMetadata::INITIALIZE_FAILED: 715 case FileCacheMetadata::INITIALIZE_FAILED:
897 return false; 716 return false;
898 717
899 case FileCacheMetadata::INITIALIZE_OPENED: // Do nothing. 718 case FileCacheMetadata::INITIALIZE_OPENED: // Do nothing.
900 break; 719 break;
901 720
902 case FileCacheMetadata::INITIALIZE_CREATED: { 721 case FileCacheMetadata::INITIALIZE_CREATED: {
903 CacheMap cache_map; 722 CacheMap cache_map;
904 ScanCachePaths(cache_paths_, &cache_map); 723 ScanCacheDirectory(cache_paths_[CACHE_TYPE_FILES], &cache_map);
905 for (CacheMap::const_iterator it = cache_map.begin(); 724 for (CacheMap::const_iterator it = cache_map.begin();
906 it != cache_map.end(); ++it) { 725 it != cache_map.end(); ++it) {
907 metadata_->AddOrUpdateCacheEntry(it->first, it->second); 726 metadata_->AddOrUpdateCacheEntry(it->first, it->second);
908 } 727 }
909 break; 728 break;
910 } 729 }
911 } 730 }
912 return true; 731 return true;
913 } 732 }
914 733
915 void FileCache::DestroyOnBlockingPool() { 734 void FileCache::DestroyOnBlockingPool() {
916 AssertOnSequencedWorkerPool(); 735 AssertOnSequencedWorkerPool();
917 delete this; 736 delete this;
918 } 737 }
919 738
739 void FileCache::MigrateFilesFromOldDirectories() {
740 const base::FilePath persistent_directory =
741 cache_root_path_.AppendASCII("persistent");
742 const base::FilePath tmp_directory = cache_root_path_.AppendASCII("tmp");
743 if (!file_util::PathExists(persistent_directory))
744 return;
745
746 // Create "files".
kinaba 2013/06/14 01:59:33 ...then this creation is not needed.
747 if (!file_util::CreateDirectory(cache_paths_[CACHE_TYPE_FILES]))
748 return;
749
750 // Move all files inside "persistent" to "files".
751 MoveAllFilesFromDirectory(persistent_directory,
752 cache_paths_[CACHE_TYPE_FILES]);
753 file_util::Delete(persistent_directory, true /* recursive */);
754
755 // Move all files inside "tmp" to "files".
756 MoveAllFilesFromDirectory(tmp_directory, cache_paths_[CACHE_TYPE_FILES]);
757 file_util::Delete(tmp_directory, true /* recursive */);
758 }
759
920 FileError FileCache::StoreInternal(const std::string& resource_id, 760 FileError FileCache::StoreInternal(const std::string& resource_id,
921 const std::string& md5, 761 const std::string& md5,
922 const base::FilePath& source_path, 762 const base::FilePath& source_path,
923 FileOperationType file_operation_type) { 763 FileOperationType file_operation_type) {
924 AssertOnSequencedWorkerPool(); 764 AssertOnSequencedWorkerPool();
925 765
926 int64 file_size = 0; 766 int64 file_size = 0;
927 if (file_operation_type == FILE_OPERATION_COPY) { 767 if (file_operation_type == FILE_OPERATION_COPY) {
928 if (!file_util::GetFileSize(source_path, &file_size)) { 768 if (!file_util::GetFileSize(source_path, &file_size)) {
929 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); 769 LOG(WARNING) << "Couldn't get file size for: " << source_path.value();
930 return FILE_ERROR_FAILED; 770 return FILE_ERROR_FAILED;
931 } 771 }
932 } 772 }
933 if (!FreeDiskSpaceIfNeededFor(file_size)) 773 if (!FreeDiskSpaceIfNeededFor(file_size))
934 return FILE_ERROR_NO_SPACE; 774 return FILE_ERROR_NO_SPACE;
935 775
936 FileCacheEntry cache_entry; 776 FileCacheEntry cache_entry;
937 metadata_->GetCacheEntry(resource_id, &cache_entry); 777 metadata_->GetCacheEntry(resource_id, &cache_entry);
938 778
939 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP;
940 // If file is dirty or mounted, return error. 779 // If file is dirty or mounted, return error.
941 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { 780 if (cache_entry.is_dirty() || cache_entry.is_mounted())
942 LOG(WARNING) << "Can't store a file to replace a "
943 << (cache_entry.is_dirty() ? "dirty" : "mounted")
944 << " file: res_id=" << resource_id
945 << ", md5=" << md5;
946 return FILE_ERROR_IN_USE; 781 return FILE_ERROR_IN_USE;
947 }
948 782
949 // If file was previously pinned, store it in persistent dir. 783 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
950 if (cache_entry.is_pinned())
951 sub_dir_type = CACHE_TYPE_PERSISTENT;
952
953 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type,
954 CACHED_FILE_FROM_SERVER); 784 CACHED_FILE_FROM_SERVER);
955 bool success = false; 785 bool success = false;
956 switch (file_operation_type) { 786 switch (file_operation_type) {
957 case FILE_OPERATION_MOVE: 787 case FILE_OPERATION_MOVE:
958 success = MoveFile(source_path, dest_path); 788 success = MoveFile(source_path, dest_path);
959 break; 789 break;
960 case FILE_OPERATION_COPY: 790 case FILE_OPERATION_COPY:
961 success = CopyFile(source_path, dest_path); 791 success = CopyFile(source_path, dest_path);
962 break; 792 break;
963 default: 793 default:
(...skipping 19 matching lines...) Expand all
983 stale_filenames_pattern = dest_path.ReplaceExtension(util::kWildCard); 813 stale_filenames_pattern = dest_path.ReplaceExtension(util::kWildCard);
984 } 814 }
985 815
986 // Delete files that match |stale_filenames_pattern| except for |dest_path|. 816 // Delete files that match |stale_filenames_pattern| except for |dest_path|.
987 DeleteFilesSelectively(stale_filenames_pattern, dest_path); 817 DeleteFilesSelectively(stale_filenames_pattern, dest_path);
988 818
989 if (success) { 819 if (success) {
990 // Now that file operations have completed, update metadata. 820 // Now that file operations have completed, update metadata.
991 cache_entry.set_md5(md5); 821 cache_entry.set_md5(md5);
992 cache_entry.set_is_present(true); 822 cache_entry.set_is_present(true);
993 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
994 cache_entry.set_is_dirty(false); 823 cache_entry.set_is_dirty(false);
995 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 824 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
996 } 825 }
997 826
998 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED; 827 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED;
999 } 828 }
1000 829
1001 FileError FileCache::MarkAsMounted(const std::string& resource_id, 830 FileError FileCache::MarkAsMounted(const std::string& resource_id,
1002 base::FilePath* cache_file_path) { 831 base::FilePath* cache_file_path) {
1003 AssertOnSequencedWorkerPool(); 832 AssertOnSequencedWorkerPool();
1004 DCHECK(cache_file_path); 833 DCHECK(cache_file_path);
1005 834
1006 // Get cache entry associated with the resource_id and md5 835 // Get cache entry associated with the resource_id and md5
1007 FileCacheEntry cache_entry; 836 FileCacheEntry cache_entry;
1008 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 837 if (!metadata_->GetCacheEntry(resource_id, &cache_entry))
1009 return FILE_ERROR_NOT_FOUND; 838 return FILE_ERROR_NOT_FOUND;
1010 839
1011 if (cache_entry.is_mounted()) 840 if (cache_entry.is_mounted())
1012 return FILE_ERROR_INVALID_OPERATION; 841 return FILE_ERROR_INVALID_OPERATION;
1013 842
1014 // Get the subdir type and path for the unmounted state. 843 // Move cache file.
1015 CacheSubDirectoryType unmounted_subdir =
1016 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1017 base::FilePath unmounted_path = GetCacheFilePath( 844 base::FilePath unmounted_path = GetCacheFilePath(
1018 resource_id, cache_entry.md5(), unmounted_subdir, 845 resource_id, cache_entry.md5(), CACHED_FILE_FROM_SERVER);
1019 CACHED_FILE_FROM_SERVER);
1020
1021 // Get the subdir type and path for the mounted state.
1022 CacheSubDirectoryType mounted_subdir = CACHE_TYPE_PERSISTENT;
1023 base::FilePath mounted_path = GetCacheFilePath( 846 base::FilePath mounted_path = GetCacheFilePath(
1024 resource_id, cache_entry.md5(), mounted_subdir, CACHED_FILE_MOUNTED); 847 resource_id, cache_entry.md5(), CACHED_FILE_MOUNTED);
1025
1026 // Move cache file.
1027 if (!MoveFile(unmounted_path, mounted_path)) 848 if (!MoveFile(unmounted_path, mounted_path))
1028 return FILE_ERROR_FAILED; 849 return FILE_ERROR_FAILED;
1029 850
1030 // Ensures the file is readable to cros_disks. See crbug.com/236994. 851 // Ensures the file is readable to cros_disks. See crbug.com/236994.
1031 file_util::SetPosixFilePermissions( 852 file_util::SetPosixFilePermissions(
1032 mounted_path, 853 mounted_path,
1033 file_util::FILE_PERMISSION_READ_BY_USER | 854 file_util::FILE_PERMISSION_READ_BY_USER |
1034 file_util::FILE_PERMISSION_WRITE_BY_USER | 855 file_util::FILE_PERMISSION_WRITE_BY_USER |
1035 file_util::FILE_PERMISSION_READ_BY_GROUP | 856 file_util::FILE_PERMISSION_READ_BY_GROUP |
1036 file_util::FILE_PERMISSION_READ_BY_OTHERS); 857 file_util::FILE_PERMISSION_READ_BY_OTHERS);
1037 858
1038 // Now that cache operation is complete, update metadata. 859 // Now that cache operation is complete, update metadata.
1039 cache_entry.set_is_mounted(true); 860 cache_entry.set_is_mounted(true);
1040 cache_entry.set_is_persistent(true);
1041 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 861 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1042 862
1043 *cache_file_path = mounted_path; 863 *cache_file_path = mounted_path;
1044 return FILE_ERROR_OK; 864 return FILE_ERROR_OK;
1045 } 865 }
1046 866
1047 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { 867 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) {
1048 AssertOnSequencedWorkerPool(); 868 AssertOnSequencedWorkerPool();
1049 DCHECK(IsUnderFileCacheDirectory(file_path)); 869 DCHECK(IsUnderFileCacheDirectory(file_path));
1050 870
1051 // Parse file path to obtain resource_id, md5 and extra_extension. 871 // Parse file path to obtain resource_id, md5 and extra_extension.
1052 std::string resource_id; 872 std::string resource_id;
1053 std::string md5; 873 std::string md5;
1054 std::string extra_extension; 874 std::string extra_extension;
1055 util::ParseCacheFilePath(file_path, &resource_id, &md5, &extra_extension); 875 util::ParseCacheFilePath(file_path, &resource_id, &md5, &extra_extension);
1056 // The extra_extension shall be ".mounted" iff we're unmounting. 876 // The extra_extension shall be ".mounted" iff we're unmounting.
1057 DCHECK_EQ(util::kMountedArchiveFileExtension, extra_extension); 877 DCHECK_EQ(util::kMountedArchiveFileExtension, extra_extension);
1058 878
1059 // Get cache entry associated with the resource_id and md5 879 // Get cache entry associated with the resource_id and md5
1060 FileCacheEntry cache_entry; 880 FileCacheEntry cache_entry;
1061 if (!GetCacheEntry(resource_id, md5, &cache_entry)) 881 if (!GetCacheEntry(resource_id, md5, &cache_entry))
1062 return FILE_ERROR_NOT_FOUND; 882 return FILE_ERROR_NOT_FOUND;
1063 883
1064 if (!cache_entry.is_mounted()) 884 if (!cache_entry.is_mounted())
1065 return FILE_ERROR_INVALID_OPERATION; 885 return FILE_ERROR_INVALID_OPERATION;
1066 886
1067 // Get the subdir type and path for the unmounted state. 887 // Move cache file.
1068 CacheSubDirectoryType unmounted_subdir =
1069 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1070 base::FilePath unmounted_path = GetCacheFilePath( 888 base::FilePath unmounted_path = GetCacheFilePath(
1071 resource_id, md5, unmounted_subdir, CACHED_FILE_FROM_SERVER); 889 resource_id, md5, CACHED_FILE_FROM_SERVER);
1072
1073 // Get the subdir type and path for the mounted state.
1074 CacheSubDirectoryType mounted_subdir = CACHE_TYPE_PERSISTENT;
1075 base::FilePath mounted_path = GetCacheFilePath( 890 base::FilePath mounted_path = GetCacheFilePath(
1076 resource_id, md5, mounted_subdir, CACHED_FILE_MOUNTED); 891 resource_id, md5, CACHED_FILE_MOUNTED);
1077
1078 // Move cache file.
1079 if (!MoveFile(mounted_path, unmounted_path)) 892 if (!MoveFile(mounted_path, unmounted_path))
1080 return FILE_ERROR_FAILED; 893 return FILE_ERROR_FAILED;
1081 894
1082 // Now that cache operation is complete, update metadata. 895 // Now that cache operation is complete, update metadata.
1083 cache_entry.set_md5(md5); 896 cache_entry.set_md5(md5);
1084 cache_entry.set_is_mounted(false); 897 cache_entry.set_is_mounted(false);
1085 cache_entry.set_is_persistent(unmounted_subdir == CACHE_TYPE_PERSISTENT);
1086 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 898 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1087 return FILE_ERROR_OK; 899 return FILE_ERROR_OK;
1088 } 900 }
1089 901
1090 bool FileCache::ClearAll() { 902 bool FileCache::ClearAll() {
1091 AssertOnSequencedWorkerPool(); 903 AssertOnSequencedWorkerPool();
1092 904
1093 if (!file_util::Delete(cache_root_path_, true)) { 905 if (!file_util::Delete(cache_root_path_, true)) {
1094 LOG(WARNING) << "Failed to delete the cache directory"; 906 LOG(WARNING) << "Failed to delete the cache directory";
1095 return false; 907 return false;
(...skipping 18 matching lines...) Expand all
1114 free_space -= kMinFreeSpace; 926 free_space -= kMinFreeSpace;
1115 return (free_space >= num_bytes); 927 return (free_space >= num_bytes);
1116 } 928 }
1117 929
1118 // static 930 // static
1119 std::vector<base::FilePath> FileCache::GetCachePaths( 931 std::vector<base::FilePath> FileCache::GetCachePaths(
1120 const base::FilePath& cache_root_path) { 932 const base::FilePath& cache_root_path) {
1121 std::vector<base::FilePath> cache_paths; 933 std::vector<base::FilePath> cache_paths;
1122 // The order should match FileCache::CacheSubDirectoryType enum. 934 // The order should match FileCache::CacheSubDirectoryType enum.
1123 cache_paths.push_back(cache_root_path.Append(kFileCacheMetaDir)); 935 cache_paths.push_back(cache_root_path.Append(kFileCacheMetaDir));
1124 cache_paths.push_back(cache_root_path.Append(kFileCachePersistentDir)); 936 cache_paths.push_back(cache_root_path.Append(kFileCacheFilesDir));
1125 cache_paths.push_back(cache_root_path.Append(kFileCacheTmpDir));
1126 cache_paths.push_back(cache_root_path.Append(kFileCacheTmpDownloadsDir)); 937 cache_paths.push_back(cache_root_path.Append(kFileCacheTmpDownloadsDir));
1127 cache_paths.push_back(cache_root_path.Append(kFileCacheTmpDocumentsDir)); 938 cache_paths.push_back(cache_root_path.Append(kFileCacheTmpDocumentsDir));
1128 return cache_paths; 939 return cache_paths;
1129 } 940 }
1130 941
1131 // static 942 // static
1132 bool FileCache::CreateCacheDirectories( 943 bool FileCache::CreateCacheDirectories(
1133 const std::vector<base::FilePath>& paths_to_create) { 944 const std::vector<base::FilePath>& paths_to_create) {
1134 bool success = true; 945 bool success = true;
1135 946
1136 for (size_t i = 0; i < paths_to_create.size(); ++i) { 947 for (size_t i = 0; i < paths_to_create.size(); ++i) {
1137 if (file_util::DirectoryExists(paths_to_create[i])) 948 if (file_util::DirectoryExists(paths_to_create[i]))
1138 continue; 949 continue;
1139 950
1140 if (!file_util::CreateDirectory(paths_to_create[i])) { 951 if (!file_util::CreateDirectory(paths_to_create[i])) {
1141 // Error creating this directory, record error and proceed with next one. 952 // Error creating this directory, record error and proceed with next one.
1142 success = false; 953 success = false;
1143 PLOG(ERROR) << "Error creating directory " << paths_to_create[i].value(); 954 PLOG(ERROR) << "Error creating directory " << paths_to_create[i].value();
1144 } else { 955 } else {
1145 DVLOG(1) << "Created directory " << paths_to_create[i].value(); 956 DVLOG(1) << "Created directory " << paths_to_create[i].value();
1146 } 957 }
1147 } 958 }
1148 return success; 959 return success;
1149 } 960 }
1150 961
1151 // static
1152 FileCache::CacheSubDirectoryType FileCache::GetSubDirectoryType(
1153 const FileCacheEntry& cache_entry) {
1154 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1155 }
1156
1157 } // namespace internal 962 } // namespace internal
1158 } // namespace drive 963 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698