| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/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/logging.h" | 10 #include "base/logging.h" |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 | 280 |
| 281 base::PostTaskAndReplyWithResult( | 281 base::PostTaskAndReplyWithResult( |
| 282 blocking_task_runner_, | 282 blocking_task_runner_, |
| 283 FROM_HERE, | 283 FROM_HERE, |
| 284 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor, | 284 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor, |
| 285 base::Unretained(this), | 285 base::Unretained(this), |
| 286 num_bytes), | 286 num_bytes), |
| 287 callback); | 287 callback); |
| 288 } | 288 } |
| 289 | 289 |
| 290 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { |
| 291 AssertOnSequencedWorkerPool(); |
| 292 |
| 293 // Do nothing and return if we have enough space. |
| 294 if (HasEnoughSpaceFor(num_bytes, cache_root_path_)) |
| 295 return true; |
| 296 |
| 297 // Otherwise, try to free up the disk space. |
| 298 DVLOG(1) << "Freeing up disk space for " << num_bytes; |
| 299 // First remove temporary files from the metadata. |
| 300 metadata_->RemoveTemporaryFiles(); |
| 301 // Then remove all files under "tmp" directory. |
| 302 RemoveAllFiles(GetCacheDirectoryPath(CACHE_TYPE_TMP)); |
| 303 |
| 304 // Check the disk space again. |
| 305 return HasEnoughSpaceFor(num_bytes, cache_root_path_); |
| 306 } |
| 307 |
| 290 void FileCache::GetFileOnUIThread(const std::string& resource_id, | 308 void FileCache::GetFileOnUIThread(const std::string& resource_id, |
| 291 const std::string& md5, | 309 const std::string& md5, |
| 292 const GetFileFromCacheCallback& callback) { | 310 const GetFileFromCacheCallback& callback) { |
| 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 294 DCHECK(!callback.is_null()); | 312 DCHECK(!callback.is_null()); |
| 295 | 313 |
| 296 base::FilePath* cache_file_path = new base::FilePath; | 314 base::FilePath* cache_file_path = new base::FilePath; |
| 297 base::PostTaskAndReplyWithResult( | 315 base::PostTaskAndReplyWithResult( |
| 298 blocking_task_runner_, | 316 blocking_task_runner_, |
| 299 FROM_HERE, | 317 FROM_HERE, |
| 300 base::Bind(&FileCache::GetFile, | 318 base::Bind(&FileCache::GetFile, |
| 301 base::Unretained(this), resource_id, md5, cache_file_path), | 319 base::Unretained(this), resource_id, md5, cache_file_path), |
| 302 base::Bind(&RunGetFileFromCacheCallback, | 320 base::Bind(&RunGetFileFromCacheCallback, |
| 303 callback, base::Owned(cache_file_path))); | 321 callback, base::Owned(cache_file_path))); |
| 304 } | 322 } |
| 305 | 323 |
| 324 FileError FileCache::GetFile(const std::string& resource_id, |
| 325 const std::string& md5, |
| 326 base::FilePath* cache_file_path) { |
| 327 AssertOnSequencedWorkerPool(); |
| 328 DCHECK(cache_file_path); |
| 329 |
| 330 FileCacheEntry cache_entry; |
| 331 if (!GetCacheEntry(resource_id, md5, &cache_entry) || |
| 332 !cache_entry.is_present()) |
| 333 return FILE_ERROR_NOT_FOUND; |
| 334 |
| 335 CachedFileOrigin file_origin; |
| 336 if (cache_entry.is_mounted()) { |
| 337 file_origin = CACHED_FILE_MOUNTED; |
| 338 } else if (cache_entry.is_dirty()) { |
| 339 file_origin = CACHED_FILE_LOCALLY_MODIFIED; |
| 340 } else { |
| 341 file_origin = CACHED_FILE_FROM_SERVER; |
| 342 } |
| 343 |
| 344 *cache_file_path = GetCacheFilePath(resource_id, |
| 345 md5, |
| 346 GetSubDirectoryType(cache_entry), |
| 347 file_origin); |
| 348 return FILE_ERROR_OK; |
| 349 } |
| 350 |
| 306 void FileCache::StoreOnUIThread(const std::string& resource_id, | 351 void FileCache::StoreOnUIThread(const std::string& resource_id, |
| 307 const std::string& md5, | 352 const std::string& md5, |
| 308 const base::FilePath& source_path, | 353 const base::FilePath& source_path, |
| 309 FileOperationType file_operation_type, | 354 FileOperationType file_operation_type, |
| 310 const FileOperationCallback& callback) { | 355 const FileOperationCallback& callback) { |
| 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 312 DCHECK(!callback.is_null()); | 357 DCHECK(!callback.is_null()); |
| 313 | 358 |
| 314 base::PostTaskAndReplyWithResult( | 359 base::PostTaskAndReplyWithResult( |
| 315 blocking_task_runner_, | 360 blocking_task_runner_, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 | 417 |
| 373 base::PostTaskAndReplyWithResult( | 418 base::PostTaskAndReplyWithResult( |
| 374 blocking_task_runner_, | 419 blocking_task_runner_, |
| 375 FROM_HERE, | 420 FROM_HERE, |
| 376 base::Bind(&FileCache::Unpin, | 421 base::Bind(&FileCache::Unpin, |
| 377 base::Unretained(this), resource_id, md5), | 422 base::Unretained(this), resource_id, md5), |
| 378 base::Bind(&FileCache::OnUnpinned, | 423 base::Bind(&FileCache::OnUnpinned, |
| 379 weak_ptr_factory_.GetWeakPtr(), resource_id, md5, callback)); | 424 weak_ptr_factory_.GetWeakPtr(), resource_id, md5, callback)); |
| 380 } | 425 } |
| 381 | 426 |
| 427 FileError FileCache::Unpin(const std::string& resource_id, |
| 428 const std::string& md5) { |
| 429 AssertOnSequencedWorkerPool(); |
| 430 |
| 431 // Unpinning a file means its entry must exist in cache. |
| 432 FileCacheEntry cache_entry; |
| 433 if (!GetCacheEntry(resource_id, md5, &cache_entry)) { |
| 434 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id=" |
| 435 << resource_id |
| 436 << ", md5=" << md5; |
| 437 return FILE_ERROR_NOT_FOUND; |
| 438 } |
| 439 |
| 440 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; |
| 441 |
| 442 // If file is dirty or mounted, don't move it. |
| 443 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { |
| 444 sub_dir_type = CACHE_TYPE_PERSISTENT; |
| 445 DCHECK(cache_entry.is_persistent()); |
| 446 } else { |
| 447 // If file was pinned but actual file blob still doesn't exist in cache, |
| 448 // don't need to move the file. |
| 449 if (cache_entry.is_present()) { |
| 450 // Gets the current path of the file in cache. |
| 451 base::FilePath source_path = GetCacheFilePath( |
| 452 resource_id, |
| 453 md5, |
| 454 GetSubDirectoryType(cache_entry), |
| 455 CACHED_FILE_FROM_SERVER); |
| 456 // File exists, move it to tmp dir. |
| 457 base::FilePath dest_path = GetCacheFilePath( |
| 458 resource_id, |
| 459 md5, |
| 460 CACHE_TYPE_TMP, |
| 461 CACHED_FILE_FROM_SERVER); |
| 462 if (!MoveFile(source_path, dest_path)) |
| 463 return FILE_ERROR_FAILED; |
| 464 } |
| 465 } |
| 466 |
| 467 // Now that file operations have completed, update metadata. |
| 468 if (cache_entry.is_present()) { |
| 469 cache_entry.set_md5(md5); |
| 470 cache_entry.set_is_pinned(false); |
| 471 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); |
| 472 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); |
| 473 } else { |
| 474 // Remove the existing entry if we are unpinning a non-present file. |
| 475 metadata_->RemoveCacheEntry(resource_id); |
| 476 } |
| 477 return FILE_ERROR_OK; |
| 478 } |
| 479 |
| 382 void FileCache::MarkAsMountedOnUIThread( | 480 void FileCache::MarkAsMountedOnUIThread( |
| 383 const std::string& resource_id, | 481 const std::string& resource_id, |
| 384 const std::string& md5, | 482 const std::string& md5, |
| 385 const GetFileFromCacheCallback& callback) { | 483 const GetFileFromCacheCallback& callback) { |
| 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 387 DCHECK(!callback.is_null()); | 485 DCHECK(!callback.is_null()); |
| 388 | 486 |
| 389 base::FilePath* cache_file_path = new base::FilePath; | 487 base::FilePath* cache_file_path = new base::FilePath; |
| 390 base::PostTaskAndReplyWithResult( | 488 base::PostTaskAndReplyWithResult( |
| 391 blocking_task_runner_, | 489 blocking_task_runner_, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 metadata_ = FileCacheMetadata::CreateCacheMetadataForTesting( | 678 metadata_ = FileCacheMetadata::CreateCacheMetadataForTesting( |
| 581 blocking_task_runner_); | 679 blocking_task_runner_); |
| 582 metadata_->Initialize(cache_paths_); | 680 metadata_->Initialize(cache_paths_); |
| 583 } | 681 } |
| 584 | 682 |
| 585 void FileCache::DestroyOnBlockingPool() { | 683 void FileCache::DestroyOnBlockingPool() { |
| 586 AssertOnSequencedWorkerPool(); | 684 AssertOnSequencedWorkerPool(); |
| 587 delete this; | 685 delete this; |
| 588 } | 686 } |
| 589 | 687 |
| 590 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { | |
| 591 AssertOnSequencedWorkerPool(); | |
| 592 | |
| 593 // Do nothing and return if we have enough space. | |
| 594 if (HasEnoughSpaceFor(num_bytes, cache_root_path_)) | |
| 595 return true; | |
| 596 | |
| 597 // Otherwise, try to free up the disk space. | |
| 598 DVLOG(1) << "Freeing up disk space for " << num_bytes; | |
| 599 // First remove temporary files from the metadata. | |
| 600 metadata_->RemoveTemporaryFiles(); | |
| 601 // Then remove all files under "tmp" directory. | |
| 602 RemoveAllFiles(GetCacheDirectoryPath(CACHE_TYPE_TMP)); | |
| 603 | |
| 604 // Check the disk space again. | |
| 605 return HasEnoughSpaceFor(num_bytes, cache_root_path_); | |
| 606 } | |
| 607 | |
| 608 FileError FileCache::GetFile(const std::string& resource_id, | |
| 609 const std::string& md5, | |
| 610 base::FilePath* cache_file_path) { | |
| 611 AssertOnSequencedWorkerPool(); | |
| 612 DCHECK(cache_file_path); | |
| 613 | |
| 614 FileCacheEntry cache_entry; | |
| 615 if (!GetCacheEntry(resource_id, md5, &cache_entry) || | |
| 616 !cache_entry.is_present()) | |
| 617 return FILE_ERROR_NOT_FOUND; | |
| 618 | |
| 619 CachedFileOrigin file_origin; | |
| 620 if (cache_entry.is_mounted()) { | |
| 621 file_origin = CACHED_FILE_MOUNTED; | |
| 622 } else if (cache_entry.is_dirty()) { | |
| 623 file_origin = CACHED_FILE_LOCALLY_MODIFIED; | |
| 624 } else { | |
| 625 file_origin = CACHED_FILE_FROM_SERVER; | |
| 626 } | |
| 627 | |
| 628 *cache_file_path = GetCacheFilePath(resource_id, | |
| 629 md5, | |
| 630 GetSubDirectoryType(cache_entry), | |
| 631 file_origin); | |
| 632 return FILE_ERROR_OK; | |
| 633 } | |
| 634 | |
| 635 FileError FileCache::StoreInternal(const std::string& resource_id, | 688 FileError FileCache::StoreInternal(const std::string& resource_id, |
| 636 const std::string& md5, | 689 const std::string& md5, |
| 637 const base::FilePath& source_path, | 690 const base::FilePath& source_path, |
| 638 FileOperationType file_operation_type, | 691 FileOperationType file_operation_type, |
| 639 CachedFileOrigin origin) { | 692 CachedFileOrigin origin) { |
| 640 AssertOnSequencedWorkerPool(); | 693 AssertOnSequencedWorkerPool(); |
| 641 | 694 |
| 642 int64 file_size = 0; | 695 int64 file_size = 0; |
| 643 if (file_operation_type == FILE_OPERATION_COPY) { | 696 if (file_operation_type == FILE_OPERATION_COPY) { |
| 644 if (!file_util::GetFileSize(source_path, &file_size)) { | 697 if (!file_util::GetFileSize(source_path, &file_size)) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 } | 808 } |
| 756 | 809 |
| 757 // Now that file operations have completed, update metadata. | 810 // Now that file operations have completed, update metadata. |
| 758 cache_entry.set_md5(md5); | 811 cache_entry.set_md5(md5); |
| 759 cache_entry.set_is_pinned(true); | 812 cache_entry.set_is_pinned(true); |
| 760 cache_entry.set_is_persistent(is_persistent); | 813 cache_entry.set_is_persistent(is_persistent); |
| 761 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); | 814 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); |
| 762 return FILE_ERROR_OK; | 815 return FILE_ERROR_OK; |
| 763 } | 816 } |
| 764 | 817 |
| 765 FileError FileCache::Unpin(const std::string& resource_id, | |
| 766 const std::string& md5) { | |
| 767 AssertOnSequencedWorkerPool(); | |
| 768 | |
| 769 // Unpinning a file means its entry must exist in cache. | |
| 770 FileCacheEntry cache_entry; | |
| 771 if (!GetCacheEntry(resource_id, md5, &cache_entry)) { | |
| 772 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id=" | |
| 773 << resource_id | |
| 774 << ", md5=" << md5; | |
| 775 return FILE_ERROR_NOT_FOUND; | |
| 776 } | |
| 777 | |
| 778 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; | |
| 779 | |
| 780 // If file is dirty or mounted, don't move it. | |
| 781 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { | |
| 782 sub_dir_type = CACHE_TYPE_PERSISTENT; | |
| 783 DCHECK(cache_entry.is_persistent()); | |
| 784 } else { | |
| 785 // If file was pinned but actual file blob still doesn't exist in cache, | |
| 786 // don't need to move the file. | |
| 787 if (cache_entry.is_present()) { | |
| 788 // Gets the current path of the file in cache. | |
| 789 base::FilePath source_path = GetCacheFilePath( | |
| 790 resource_id, | |
| 791 md5, | |
| 792 GetSubDirectoryType(cache_entry), | |
| 793 CACHED_FILE_FROM_SERVER); | |
| 794 // File exists, move it to tmp dir. | |
| 795 base::FilePath dest_path = GetCacheFilePath( | |
| 796 resource_id, | |
| 797 md5, | |
| 798 CACHE_TYPE_TMP, | |
| 799 CACHED_FILE_FROM_SERVER); | |
| 800 if (!MoveFile(source_path, dest_path)) | |
| 801 return FILE_ERROR_FAILED; | |
| 802 } | |
| 803 } | |
| 804 | |
| 805 // Now that file operations have completed, update metadata. | |
| 806 if (cache_entry.is_present()) { | |
| 807 cache_entry.set_md5(md5); | |
| 808 cache_entry.set_is_pinned(false); | |
| 809 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); | |
| 810 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); | |
| 811 } else { | |
| 812 // Remove the existing entry if we are unpinning a non-present file. | |
| 813 metadata_->RemoveCacheEntry(resource_id); | |
| 814 } | |
| 815 return FILE_ERROR_OK; | |
| 816 } | |
| 817 | 818 |
| 818 FileError FileCache::MarkAsMounted(const std::string& resource_id, | 819 FileError FileCache::MarkAsMounted(const std::string& resource_id, |
| 819 const std::string& md5, | 820 const std::string& md5, |
| 820 base::FilePath* cache_file_path) { | 821 base::FilePath* cache_file_path) { |
| 821 AssertOnSequencedWorkerPool(); | 822 AssertOnSequencedWorkerPool(); |
| 822 DCHECK(cache_file_path); | 823 DCHECK(cache_file_path); |
| 823 | 824 |
| 824 // Get cache entry associated with the resource_id and md5 | 825 // Get cache entry associated with the resource_id and md5 |
| 825 FileCacheEntry cache_entry; | 826 FileCacheEntry cache_entry; |
| 826 if (!GetCacheEntry(resource_id, md5, &cache_entry)) | 827 if (!GetCacheEntry(resource_id, md5, &cache_entry)) |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1130 } | 1131 } |
| 1131 | 1132 |
| 1132 // static | 1133 // static |
| 1133 FileCache::CacheSubDirectoryType FileCache::GetSubDirectoryType( | 1134 FileCache::CacheSubDirectoryType FileCache::GetSubDirectoryType( |
| 1134 const FileCacheEntry& cache_entry) { | 1135 const FileCacheEntry& cache_entry) { |
| 1135 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; | 1136 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; |
| 1136 } | 1137 } |
| 1137 | 1138 |
| 1138 } // namespace internal | 1139 } // namespace internal |
| 1139 } // namespace drive | 1140 } // namespace drive |
| OLD | NEW |