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

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

Issue 17249004: drive: Use ResourceMetadataStorage from FileCache (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More precise old DB handling 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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/sys_info.h" 14 #include "base/sys_info.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "chrome/browser/chromeos/drive/drive.pb.h" 16 #include "chrome/browser/chromeos/drive/drive.pb.h"
17 #include "chrome/browser/chromeos/drive/file_cache_metadata.h" 17 #include "chrome/browser/chromeos/drive/file_cache_metadata.h"
18 #include "chrome/browser/chromeos/drive/file_system_util.h" 18 #include "chrome/browser/chromeos/drive/file_system_util.h"
19 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
19 #include "chrome/browser/google_apis/task_util.h" 20 #include "chrome/browser/google_apis/task_util.h"
20 #include "chromeos/chromeos_constants.h" 21 #include "chromeos/chromeos_constants.h"
21 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
22 23
23 using content::BrowserThread; 24 using content::BrowserThread;
24 25
25 namespace drive { 26 namespace drive {
26 namespace internal { 27 namespace internal {
27 namespace { 28 namespace {
28 29
29 // Name of the cache metadata DB.
30 const base::FilePath::CharType* kCacheMetadataDBName =
31 FILE_PATH_LITERAL("cache_metadata.db");
32
33 typedef std::map<std::string, FileCacheEntry> CacheMap; 30 typedef std::map<std::string, FileCacheEntry> CacheMap;
34 31
35 // Returns true if |md5| matches the one in |cache_entry| with some 32 // Returns true if |md5| matches the one in |cache_entry| with some
36 // exceptions. See the function definition for details. 33 // exceptions. See the function definition for details.
37 bool CheckIfMd5Matches(const std::string& md5, 34 bool CheckIfMd5Matches(const std::string& md5,
38 const FileCacheEntry& cache_entry) { 35 const FileCacheEntry& cache_entry) {
39 if (cache_entry.is_dirty()) { 36 if (cache_entry.is_dirty()) {
40 // If the entry is dirty, its MD5 may have been replaced by "local" 37 // If the entry is dirty, its MD5 may have been replaced by "local"
41 // during cache initialization, so we don't compare MD5. 38 // during cache initialization, so we don't compare MD5.
42 return true; 39 return true;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback, 149 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback,
153 FileCacheEntry* cache_entry, 150 FileCacheEntry* cache_entry,
154 bool success) { 151 bool success) {
155 DCHECK(cache_entry); 152 DCHECK(cache_entry);
156 DCHECK(!callback.is_null()); 153 DCHECK(!callback.is_null());
157 callback.Run(success, *cache_entry); 154 callback.Run(success, *cache_entry);
158 } 155 }
159 156
160 } // namespace 157 } // namespace
161 158
162 FileCache::FileCache(const base::FilePath& metadata_directory, 159 const base::FilePath::CharType FileCache::kOldCacheMetadataDBName[] =
160 FILE_PATH_LITERAL("cache_metadata.db");
161
162 FileCache::FileCache(ResourceMetadataStorage* storage,
163 const base::FilePath& cache_file_directory, 163 const base::FilePath& cache_file_directory,
164 base::SequencedTaskRunner* blocking_task_runner, 164 base::SequencedTaskRunner* blocking_task_runner,
165 FreeDiskSpaceGetterInterface* free_disk_space_getter) 165 FreeDiskSpaceGetterInterface* free_disk_space_getter)
166 : metadata_directory_(metadata_directory), 166 : cache_file_directory_(cache_file_directory),
167 cache_file_directory_(cache_file_directory),
168 blocking_task_runner_(blocking_task_runner), 167 blocking_task_runner_(blocking_task_runner),
168 storage_(storage),
169 free_disk_space_getter_(free_disk_space_getter), 169 free_disk_space_getter_(free_disk_space_getter),
170 weak_ptr_factory_(this) { 170 weak_ptr_factory_(this) {
171 DCHECK(blocking_task_runner_.get()); 171 DCHECK(blocking_task_runner_.get());
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
173 } 173 }
174 174
175 FileCache::~FileCache() { 175 FileCache::~FileCache() {
176 // Must be on the sequenced worker pool, as |metadata_| must be deleted on 176 // Must be on the sequenced worker pool, as |metadata_| must be deleted on
177 // the sequenced worker pool. 177 // the sequenced worker pool.
178 AssertOnSequencedWorkerPool(); 178 AssertOnSequencedWorkerPool();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 cache_entry), 222 cache_entry),
223 base::Bind( 223 base::Bind(
224 &RunGetCacheEntryCallback, callback, base::Owned(cache_entry))); 224 &RunGetCacheEntryCallback, callback, base::Owned(cache_entry)));
225 } 225 }
226 226
227 bool FileCache::GetCacheEntry(const std::string& resource_id, 227 bool FileCache::GetCacheEntry(const std::string& resource_id,
228 const std::string& md5, 228 const std::string& md5,
229 FileCacheEntry* entry) { 229 FileCacheEntry* entry) {
230 DCHECK(entry); 230 DCHECK(entry);
231 AssertOnSequencedWorkerPool(); 231 AssertOnSequencedWorkerPool();
232 return metadata_->GetCacheEntry(resource_id, entry) && 232 return storage_->GetCacheEntry(resource_id, entry) &&
233 CheckIfMd5Matches(md5, *entry); 233 CheckIfMd5Matches(md5, *entry);
234 } 234 }
235 235
236 void FileCache::IterateOnUIThread( 236 void FileCache::IterateOnUIThread(
237 const CacheIterateCallback& iteration_callback, 237 const CacheIterateCallback& iteration_callback,
238 const base::Closure& completion_callback) { 238 const base::Closure& completion_callback) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 DCHECK(!iteration_callback.is_null()); 240 DCHECK(!iteration_callback.is_null());
241 DCHECK(!completion_callback.is_null()); 241 DCHECK(!completion_callback.is_null());
242 242
243 blocking_task_runner_->PostTaskAndReply( 243 blocking_task_runner_->PostTaskAndReply(
244 FROM_HERE, 244 FROM_HERE,
245 base::Bind(&FileCache::Iterate, 245 base::Bind(&FileCache::Iterate,
246 base::Unretained(this), 246 base::Unretained(this),
247 google_apis::CreateRelayCallback(iteration_callback)), 247 google_apis::CreateRelayCallback(iteration_callback)),
248 completion_callback); 248 completion_callback);
249 } 249 }
250 250
251 void FileCache::Iterate(const CacheIterateCallback& iteration_callback) { 251 void FileCache::Iterate(const CacheIterateCallback& iteration_callback) {
252 AssertOnSequencedWorkerPool(); 252 AssertOnSequencedWorkerPool();
253 DCHECK(!iteration_callback.is_null()); 253 DCHECK(!iteration_callback.is_null());
254 254
255 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 255 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
256 storage_->GetCacheEntryIterator();
256 for (; !it->IsAtEnd(); it->Advance()) 257 for (; !it->IsAtEnd(); it->Advance())
257 iteration_callback.Run(it->GetKey(), it->GetValue()); 258 iteration_callback.Run(it->GetID(), it->GetValue());
258 DCHECK(!it->HasError()); 259 DCHECK(!it->HasError());
259 } 260 }
260 261
261 void FileCache::FreeDiskSpaceIfNeededForOnUIThread( 262 void FileCache::FreeDiskSpaceIfNeededForOnUIThread(
262 int64 num_bytes, 263 int64 num_bytes,
263 const InitializeCacheCallback& callback) { 264 const InitializeCacheCallback& callback) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 DCHECK(!callback.is_null()); 266 DCHECK(!callback.is_null());
266 267
267 base::PostTaskAndReplyWithResult( 268 base::PostTaskAndReplyWithResult(
268 blocking_task_runner_.get(), 269 blocking_task_runner_.get(),
269 FROM_HERE, 270 FROM_HERE,
270 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor, 271 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor,
271 base::Unretained(this), 272 base::Unretained(this),
272 num_bytes), 273 num_bytes),
273 callback); 274 callback);
274 } 275 }
275 276
276 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { 277 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) {
277 AssertOnSequencedWorkerPool(); 278 AssertOnSequencedWorkerPool();
278 279
279 // Do nothing and return if we have enough space. 280 // Do nothing and return if we have enough space.
280 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) 281 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_))
281 return true; 282 return true;
282 283
283 // Otherwise, try to free up the disk space. 284 // Otherwise, try to free up the disk space.
284 DVLOG(1) << "Freeing up disk space for " << num_bytes; 285 DVLOG(1) << "Freeing up disk space for " << num_bytes;
285 286
286 // Remove all entries unless specially marked. 287 // Remove all entries unless specially marked.
287 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 288 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
289 storage_->GetCacheEntryIterator();
288 for (; !it->IsAtEnd(); it->Advance()) { 290 for (; !it->IsAtEnd(); it->Advance()) {
289 const FileCacheEntry& entry = it->GetValue(); 291 const FileCacheEntry& entry = it->GetValue();
290 if (!entry.is_pinned() && 292 if (!entry.is_pinned() &&
291 !entry.is_dirty() && 293 !entry.is_dirty() &&
292 !mounted_files_.count(it->GetKey())) 294 !mounted_files_.count(it->GetID()))
293 metadata_->RemoveCacheEntry(it->GetKey()); 295 storage_->RemoveCacheEntry(it->GetID());
294 } 296 }
295 DCHECK(!it->HasError()); 297 DCHECK(!it->HasError());
296 298
297 // Remove all files which have no corresponding cache entries. 299 // Remove all files which have no corresponding cache entries.
298 base::FileEnumerator enumerator(cache_file_directory_, 300 base::FileEnumerator enumerator(cache_file_directory_,
299 false, // not recursive 301 false, // not recursive
300 base::FileEnumerator::FILES); 302 base::FileEnumerator::FILES);
301 std::string resource_id; 303 std::string resource_id;
302 std::string md5; 304 std::string md5;
303 FileCacheEntry entry; 305 FileCacheEntry entry;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 blocking_task_runner_.get(), 387 blocking_task_runner_.get(),
386 FROM_HERE, 388 FROM_HERE,
387 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id), 389 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id),
388 callback); 390 callback);
389 } 391 }
390 392
391 FileError FileCache::Pin(const std::string& resource_id) { 393 FileError FileCache::Pin(const std::string& resource_id) {
392 AssertOnSequencedWorkerPool(); 394 AssertOnSequencedWorkerPool();
393 395
394 FileCacheEntry cache_entry; 396 FileCacheEntry cache_entry;
395 metadata_->GetCacheEntry(resource_id, &cache_entry); 397 storage_->GetCacheEntry(resource_id, &cache_entry);
396 cache_entry.set_is_pinned(true); 398 cache_entry.set_is_pinned(true);
397 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 399 storage_->PutCacheEntry(resource_id, cache_entry);
398 return FILE_ERROR_OK; 400 return FILE_ERROR_OK;
399 } 401 }
400 402
401 void FileCache::UnpinOnUIThread(const std::string& resource_id, 403 void FileCache::UnpinOnUIThread(const std::string& resource_id,
402 const FileOperationCallback& callback) { 404 const FileOperationCallback& callback) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 DCHECK(!callback.is_null()); 406 DCHECK(!callback.is_null());
405 407
406 base::PostTaskAndReplyWithResult( 408 base::PostTaskAndReplyWithResult(
407 blocking_task_runner_.get(), 409 blocking_task_runner_.get(),
408 FROM_HERE, 410 FROM_HERE,
409 base::Bind(&FileCache::Unpin, base::Unretained(this), resource_id), 411 base::Bind(&FileCache::Unpin, base::Unretained(this), resource_id),
410 callback); 412 callback);
411 } 413 }
412 414
413 FileError FileCache::Unpin(const std::string& resource_id) { 415 FileError FileCache::Unpin(const std::string& resource_id) {
414 AssertOnSequencedWorkerPool(); 416 AssertOnSequencedWorkerPool();
415 417
416 // Unpinning a file means its entry must exist in cache. 418 // Unpinning a file means its entry must exist in cache.
417 FileCacheEntry cache_entry; 419 FileCacheEntry cache_entry;
418 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 420 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
419 return FILE_ERROR_NOT_FOUND; 421 return FILE_ERROR_NOT_FOUND;
420 422
421 // Now that file operations have completed, update metadata. 423 // Now that file operations have completed, update metadata.
422 if (cache_entry.is_present()) { 424 if (cache_entry.is_present()) {
423 cache_entry.set_is_pinned(false); 425 cache_entry.set_is_pinned(false);
424 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 426 storage_->PutCacheEntry(resource_id, cache_entry);
425 } else { 427 } else {
426 // Remove the existing entry if we are unpinning a non-present file. 428 // Remove the existing entry if we are unpinning a non-present file.
427 metadata_->RemoveCacheEntry(resource_id); 429 storage_->RemoveCacheEntry(resource_id);
428 } 430 }
429 431
430 // Now it's a chance to free up space if needed. 432 // Now it's a chance to free up space if needed.
431 FreeDiskSpaceIfNeededFor(0); 433 FreeDiskSpaceIfNeededFor(0);
432 434
433 return FILE_ERROR_OK; 435 return FILE_ERROR_OK;
434 } 436 }
435 437
436 void FileCache::MarkAsMountedOnUIThread( 438 void FileCache::MarkAsMountedOnUIThread(
437 const std::string& resource_id, 439 const std::string& resource_id,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 AssertOnSequencedWorkerPool(); 486 AssertOnSequencedWorkerPool();
485 487
486 // If file has already been marked dirty in previous instance of chrome, we 488 // If file has already been marked dirty in previous instance of chrome, we
487 // would have lost the md5 info during cache initialization, because the file 489 // would have lost the md5 info during cache initialization, because the file
488 // would have been renamed to .local extension. 490 // would have been renamed to .local extension.
489 // So, search for entry in cache without comparing md5. 491 // So, search for entry in cache without comparing md5.
490 492
491 // Marking a file dirty means its entry and actual file blob must exist in 493 // Marking a file dirty means its entry and actual file blob must exist in
492 // cache. 494 // cache.
493 FileCacheEntry cache_entry; 495 FileCacheEntry cache_entry;
494 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) || 496 if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
495 !cache_entry.is_present()) { 497 !cache_entry.is_present()) {
496 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id=" 498 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id="
497 << resource_id 499 << resource_id
498 << ", md5=" << md5; 500 << ", md5=" << md5;
499 return FILE_ERROR_NOT_FOUND; 501 return FILE_ERROR_NOT_FOUND;
500 } 502 }
501 503
502 if (cache_entry.is_dirty()) 504 if (cache_entry.is_dirty())
503 return FILE_ERROR_OK; 505 return FILE_ERROR_OK;
504 506
505 // Get the current path of the file in cache. 507 // Get the current path of the file in cache.
506 base::FilePath source_path = GetCacheFilePath(resource_id, md5, 508 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
507 CACHED_FILE_FROM_SERVER); 509 CACHED_FILE_FROM_SERVER);
508 // Determine destination path. 510 // Determine destination path.
509 base::FilePath cache_file_path = GetCacheFilePath( 511 base::FilePath cache_file_path = GetCacheFilePath(
510 resource_id, md5, CACHED_FILE_LOCALLY_MODIFIED); 512 resource_id, md5, CACHED_FILE_LOCALLY_MODIFIED);
511 513
512 if (!MoveFile(source_path, cache_file_path)) 514 if (!MoveFile(source_path, cache_file_path))
513 return FILE_ERROR_FAILED; 515 return FILE_ERROR_FAILED;
514 516
515 // Now that file operations have completed, update metadata. 517 // Now that file operations have completed, update metadata.
516 cache_entry.set_md5(md5); 518 cache_entry.set_md5(md5);
517 cache_entry.set_is_dirty(true); 519 cache_entry.set_is_dirty(true);
518 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 520 storage_->PutCacheEntry(resource_id, cache_entry);
519 return FILE_ERROR_OK; 521 return FILE_ERROR_OK;
520 } 522 }
521 523
522 FileError FileCache::ClearDirty(const std::string& resource_id, 524 FileError FileCache::ClearDirty(const std::string& resource_id,
523 const std::string& md5) { 525 const std::string& md5) {
524 AssertOnSequencedWorkerPool(); 526 AssertOnSequencedWorkerPool();
525 527
526 // |md5| is the new .<md5> extension to rename the file to. 528 // |md5| is the new .<md5> extension to rename the file to.
527 // So, search for entry in cache without comparing md5. 529 // So, search for entry in cache without comparing md5.
528 FileCacheEntry cache_entry; 530 FileCacheEntry cache_entry;
529 531
530 // Clearing a dirty file means its entry and actual file blob must exist in 532 // Clearing a dirty file means its entry and actual file blob must exist in
531 // cache. 533 // cache.
532 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) || 534 if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
533 !cache_entry.is_present()) { 535 !cache_entry.is_present()) {
534 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " 536 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
535 << "res_id=" << resource_id 537 << "res_id=" << resource_id
536 << ", md5=" << md5; 538 << ", md5=" << md5;
537 return FILE_ERROR_NOT_FOUND; 539 return FILE_ERROR_NOT_FOUND;
538 } 540 }
539 541
540 // If a file is not dirty (it should have been marked dirty via 542 // If a file is not dirty (it should have been marked dirty via
541 // MarkDirtyInCache), clearing its dirty state is an invalid operation. 543 // MarkDirtyInCache), clearing its dirty state is an invalid operation.
542 if (!cache_entry.is_dirty()) { 544 if (!cache_entry.is_dirty()) {
543 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id=" 545 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id="
544 << resource_id 546 << resource_id
545 << ", md5=" << md5; 547 << ", md5=" << md5;
546 return FILE_ERROR_INVALID_OPERATION; 548 return FILE_ERROR_INVALID_OPERATION;
547 } 549 }
548 550
549 base::FilePath source_path = GetCacheFilePath(resource_id, md5, 551 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
550 CACHED_FILE_LOCALLY_MODIFIED); 552 CACHED_FILE_LOCALLY_MODIFIED);
551 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, 553 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
552 CACHED_FILE_FROM_SERVER); 554 CACHED_FILE_FROM_SERVER);
553 if (!MoveFile(source_path, dest_path)) 555 if (!MoveFile(source_path, dest_path))
554 return FILE_ERROR_FAILED; 556 return FILE_ERROR_FAILED;
555 557
556 // Now that file operations have completed, update metadata. 558 // Now that file operations have completed, update metadata.
557 cache_entry.set_md5(md5); 559 cache_entry.set_md5(md5);
558 cache_entry.set_is_dirty(false); 560 cache_entry.set_is_dirty(false);
559 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 561 storage_->PutCacheEntry(resource_id, cache_entry);
560 return FILE_ERROR_OK; 562 return FILE_ERROR_OK;
561 } 563 }
562 564
563 void FileCache::RemoveOnUIThread(const std::string& resource_id, 565 void FileCache::RemoveOnUIThread(const std::string& resource_id,
564 const FileOperationCallback& callback) { 566 const FileOperationCallback& callback) {
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
566 DCHECK(!callback.is_null()); 568 DCHECK(!callback.is_null());
567 569
568 base::PostTaskAndReplyWithResult( 570 base::PostTaskAndReplyWithResult(
569 blocking_task_runner_.get(), 571 blocking_task_runner_.get(),
570 FROM_HERE, 572 FROM_HERE,
571 base::Bind(&FileCache::Remove, base::Unretained(this), resource_id), 573 base::Bind(&FileCache::Remove, base::Unretained(this), resource_id),
572 callback); 574 callback);
573 } 575 }
574 576
575 FileError FileCache::Remove(const std::string& resource_id) { 577 FileError FileCache::Remove(const std::string& resource_id) {
576 AssertOnSequencedWorkerPool(); 578 AssertOnSequencedWorkerPool();
577 579
578 // MD5 is not passed into RemoveCacheEntry because we would delete all 580 // MD5 is not passed into RemoveCacheEntry because we would delete all
579 // cache files corresponding to <resource_id> regardless of the md5. 581 // cache files corresponding to <resource_id> regardless of the md5.
580 // So, search for entry in cache without taking md5 into account. 582 // So, search for entry in cache without taking md5 into account.
581 FileCacheEntry cache_entry; 583 FileCacheEntry cache_entry;
582 584
583 // If entry doesn't exist, nothing to do. 585 // If entry doesn't exist, nothing to do.
584 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 586 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
585 return FILE_ERROR_OK; 587 return FILE_ERROR_OK;
586 588
587 // Cannot delete a dirty or mounted file. 589 // Cannot delete a dirty or mounted file.
588 if (cache_entry.is_dirty() || mounted_files_.count(resource_id)) 590 if (cache_entry.is_dirty() || mounted_files_.count(resource_id))
589 return FILE_ERROR_IN_USE; 591 return FILE_ERROR_IN_USE;
590 592
591 // Delete files that match "<resource_id>.*" unless modified locally. 593 // Delete files that match "<resource_id>.*" unless modified locally.
592 base::FilePath path_to_delete = GetCacheFilePath(resource_id, util::kWildCard, 594 base::FilePath path_to_delete = GetCacheFilePath(resource_id, util::kWildCard,
593 CACHED_FILE_FROM_SERVER); 595 CACHED_FILE_FROM_SERVER);
594 base::FilePath path_to_keep = GetCacheFilePath(resource_id, std::string(), 596 base::FilePath path_to_keep = GetCacheFilePath(resource_id, std::string(),
595 CACHED_FILE_LOCALLY_MODIFIED); 597 CACHED_FILE_LOCALLY_MODIFIED);
596 DeleteFilesSelectively(path_to_delete, path_to_keep); 598 DeleteFilesSelectively(path_to_delete, path_to_keep);
597 599
598 // Now that all file operations have completed, remove from metadata. 600 // Now that all file operations have completed, remove from metadata.
599 metadata_->RemoveCacheEntry(resource_id); 601 storage_->RemoveCacheEntry(resource_id);
600 602
601 return FILE_ERROR_OK; 603 return FILE_ERROR_OK;
602 } 604 }
603 605
604 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) { 606 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) {
605 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
606 DCHECK(!callback.is_null()); 608 DCHECK(!callback.is_null());
607 609
608 base::PostTaskAndReplyWithResult( 610 base::PostTaskAndReplyWithResult(
609 blocking_task_runner_.get(), 611 blocking_task_runner_.get(),
610 FROM_HERE, 612 FROM_HERE,
611 base::Bind(&FileCache::ClearAll, base::Unretained(this)), 613 base::Bind(&FileCache::ClearAll, base::Unretained(this)),
612 callback); 614 callback);
613 } 615 }
614 616
615 bool FileCache::Initialize() { 617 bool FileCache::Initialize() {
616 AssertOnSequencedWorkerPool(); 618 AssertOnSequencedWorkerPool();
617 619
618 metadata_.reset(new FileCacheMetadata(blocking_task_runner_.get())); 620 if (!ImportOldDB(storage_->directory_path().Append(
619 621 kOldCacheMetadataDBName)) &&
620 const base::FilePath db_path = 622 !storage_->opened_existing_db()) {
621 metadata_directory_.Append(kCacheMetadataDBName); 623 CacheMap cache_map;
622 switch (metadata_->Initialize(db_path)) { 624 ScanCacheDirectory(cache_file_directory_, &cache_map);
623 case FileCacheMetadata::INITIALIZE_FAILED: 625 for (CacheMap::const_iterator it = cache_map.begin();
624 return false; 626 it != cache_map.end(); ++it) {
625 627 storage_->PutCacheEntry(it->first, it->second);
626 case FileCacheMetadata::INITIALIZE_OPENED: // Do nothing.
627 break;
628
629 case FileCacheMetadata::INITIALIZE_CREATED: {
630 CacheMap cache_map;
631 ScanCacheDirectory(cache_file_directory_, &cache_map);
632 for (CacheMap::const_iterator it = cache_map.begin();
633 it != cache_map.end(); ++it) {
634 metadata_->AddOrUpdateCacheEntry(it->first, it->second);
635 }
636 break;
637 } 628 }
638 } 629 }
639 return true; 630 return true;
640 } 631 }
641 632
642 void FileCache::Destroy() { 633 void FileCache::Destroy() {
643 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 634 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
644 635
645 // Invalidate the weak pointer. 636 // Invalidate the weak pointer.
646 weak_ptr_factory_.InvalidateWeakPtrs(); 637 weak_ptr_factory_.InvalidateWeakPtrs();
(...skipping 21 matching lines...) Expand all
668 if (file_operation_type == FILE_OPERATION_COPY) { 659 if (file_operation_type == FILE_OPERATION_COPY) {
669 if (!file_util::GetFileSize(source_path, &file_size)) { 660 if (!file_util::GetFileSize(source_path, &file_size)) {
670 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); 661 LOG(WARNING) << "Couldn't get file size for: " << source_path.value();
671 return FILE_ERROR_FAILED; 662 return FILE_ERROR_FAILED;
672 } 663 }
673 } 664 }
674 if (!FreeDiskSpaceIfNeededFor(file_size)) 665 if (!FreeDiskSpaceIfNeededFor(file_size))
675 return FILE_ERROR_NO_SPACE; 666 return FILE_ERROR_NO_SPACE;
676 667
677 FileCacheEntry cache_entry; 668 FileCacheEntry cache_entry;
678 metadata_->GetCacheEntry(resource_id, &cache_entry); 669 storage_->GetCacheEntry(resource_id, &cache_entry);
679 670
680 // If file is dirty or mounted, return error. 671 // If file is dirty or mounted, return error.
681 if (cache_entry.is_dirty() || mounted_files_.count(resource_id)) 672 if (cache_entry.is_dirty() || mounted_files_.count(resource_id))
682 return FILE_ERROR_IN_USE; 673 return FILE_ERROR_IN_USE;
683 674
684 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, 675 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
685 CACHED_FILE_FROM_SERVER); 676 CACHED_FILE_FROM_SERVER);
686 bool success = false; 677 bool success = false;
687 switch (file_operation_type) { 678 switch (file_operation_type) {
688 case FILE_OPERATION_MOVE: 679 case FILE_OPERATION_MOVE:
(...skipping 26 matching lines...) Expand all
715 } 706 }
716 707
717 // Delete files that match |stale_filenames_pattern| except for |dest_path|. 708 // Delete files that match |stale_filenames_pattern| except for |dest_path|.
718 DeleteFilesSelectively(stale_filenames_pattern, dest_path); 709 DeleteFilesSelectively(stale_filenames_pattern, dest_path);
719 710
720 if (success) { 711 if (success) {
721 // Now that file operations have completed, update metadata. 712 // Now that file operations have completed, update metadata.
722 cache_entry.set_md5(md5); 713 cache_entry.set_md5(md5);
723 cache_entry.set_is_present(true); 714 cache_entry.set_is_present(true);
724 cache_entry.set_is_dirty(false); 715 cache_entry.set_is_dirty(false);
725 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 716 storage_->PutCacheEntry(resource_id, cache_entry);
726 } 717 }
727 718
728 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED; 719 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED;
729 } 720 }
730 721
731 FileError FileCache::MarkAsMounted(const std::string& resource_id, 722 FileError FileCache::MarkAsMounted(const std::string& resource_id,
732 base::FilePath* cache_file_path) { 723 base::FilePath* cache_file_path) {
733 AssertOnSequencedWorkerPool(); 724 AssertOnSequencedWorkerPool();
734 DCHECK(cache_file_path); 725 DCHECK(cache_file_path);
735 726
736 // Get cache entry associated with the resource_id and md5 727 // Get cache entry associated with the resource_id and md5
737 FileCacheEntry cache_entry; 728 FileCacheEntry cache_entry;
738 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 729 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
739 return FILE_ERROR_NOT_FOUND; 730 return FILE_ERROR_NOT_FOUND;
740 731
741 if (mounted_files_.count(resource_id)) 732 if (mounted_files_.count(resource_id))
742 return FILE_ERROR_INVALID_OPERATION; 733 return FILE_ERROR_INVALID_OPERATION;
743 734
744 // Ensure the file is readable to cros_disks. See crbug.com/236994. 735 // Ensure the file is readable to cros_disks. See crbug.com/236994.
745 base::FilePath path = GetCacheFilePath( 736 base::FilePath path = GetCacheFilePath(
746 resource_id, cache_entry.md5(), CACHED_FILE_FROM_SERVER); 737 resource_id, cache_entry.md5(), CACHED_FILE_FROM_SERVER);
747 file_util::SetPosixFilePermissions( 738 file_util::SetPosixFilePermissions(
748 path, 739 path,
(...skipping 27 matching lines...) Expand all
776 return FILE_ERROR_INVALID_OPERATION; 767 return FILE_ERROR_INVALID_OPERATION;
777 768
778 mounted_files_.erase(it); 769 mounted_files_.erase(it);
779 return FILE_ERROR_OK; 770 return FILE_ERROR_OK;
780 } 771 }
781 772
782 bool FileCache::ClearAll() { 773 bool FileCache::ClearAll() {
783 AssertOnSequencedWorkerPool(); 774 AssertOnSequencedWorkerPool();
784 775
785 // Remove entries on the metadata. 776 // Remove entries on the metadata.
786 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 777 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
778 storage_->GetCacheEntryIterator();
787 for (; !it->IsAtEnd(); it->Advance()) 779 for (; !it->IsAtEnd(); it->Advance())
788 metadata_->RemoveCacheEntry(it->GetKey()); 780 storage_->RemoveCacheEntry(it->GetID());
789 781
790 if (it->HasError()) 782 if (it->HasError())
791 return false; 783 return false;
792 784
793 // Remove files. 785 // Remove files.
794 base::FileEnumerator enumerator(cache_file_directory_, 786 base::FileEnumerator enumerator(cache_file_directory_,
795 false, // not recursive 787 false, // not recursive
796 base::FileEnumerator::FILES); 788 base::FileEnumerator::FILES);
797 for (base::FilePath file = enumerator.Next(); !file.empty(); 789 for (base::FilePath file = enumerator.Next(); !file.empty();
798 file = enumerator.Next()) 790 file = enumerator.Next())
799 file_util::Delete(file, false /* recursive */); 791 file_util::Delete(file, false /* recursive */);
800 792
801 return true; 793 return true;
802 } 794 }
803 795
804 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, 796 bool FileCache::HasEnoughSpaceFor(int64 num_bytes,
805 const base::FilePath& path) { 797 const base::FilePath& path) {
806 int64 free_space = 0; 798 int64 free_space = 0;
807 if (free_disk_space_getter_) 799 if (free_disk_space_getter_)
808 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); 800 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace();
809 else 801 else
810 free_space = base::SysInfo::AmountOfFreeDiskSpace(path); 802 free_space = base::SysInfo::AmountOfFreeDiskSpace(path);
811 803
812 // Subtract this as if this portion does not exist. 804 // Subtract this as if this portion does not exist.
813 free_space -= kMinFreeSpace; 805 free_space -= kMinFreeSpace;
814 return (free_space >= num_bytes); 806 return (free_space >= num_bytes);
815 } 807 }
816 808
817 void FileCache::ImportOldDB(const base::FilePath& old_db_path) { 809 bool FileCache::ImportOldDB(const base::FilePath& old_db_path) {
818 if (!file_util::PathExists(old_db_path)) // Old DB is not there, do nothing. 810 if (!file_util::PathExists(old_db_path)) // Old DB is not there, do nothing.
819 return; 811 return false;
820 812
821 // Copy all entries stored in the old DB. 813 // Copy all entries stored in the old DB.
822 FileCacheMetadata old_data(blocking_task_runner_); 814 bool imported = false;
823 if (old_data.Initialize(old_db_path)) { 815 {
824 scoped_ptr<FileCacheMetadata::Iterator> it = old_data.GetIterator(); 816 FileCacheMetadata old_data(blocking_task_runner_);
825 for (; !it->IsAtEnd(); it->Advance()) { 817 if (old_data.Initialize(old_db_path) ==
826 FileCacheEntry entry; 818 FileCacheMetadata::INITIALIZE_OPENED) {
827 if (metadata_->GetCacheEntry(it->GetKey(), &entry)) 819 scoped_ptr<FileCacheMetadata::Iterator> it = old_data.GetIterator();
828 continue; // Do not overwrite. 820 for (; !it->IsAtEnd(); it->Advance()) {
821 FileCacheEntry entry;
822 if (storage_->GetCacheEntry(it->GetKey(), &entry))
823 continue; // Do not overwrite.
829 824
830 metadata_->AddOrUpdateCacheEntry(it->GetKey(), it->GetValue()); 825 storage_->PutCacheEntry(it->GetKey(), it->GetValue());
826 }
827 imported = true;
831 } 828 }
832 } 829 }
833 830
834 // Delete old DB. 831 // Delete old DB.
835 file_util::Delete(old_db_path, true /* recursive */ ); 832 file_util::Delete(old_db_path, true /* recursive */ );
833 return imported;
836 } 834 }
837 835
838 } // namespace internal 836 } // namespace internal
839 } // namespace drive 837 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/file_cache.h ('k') | chrome/browser/chromeos/drive/file_cache_metadata.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698