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 |