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

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

Issue 11358157: chromeos: Replace ModifyCacheState with a number of small functions to simplify DriveCache (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unnecessary 'else' Created 8 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/drive_cache.h" 5 #include "chrome/browser/chromeos/drive/drive_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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 FileEnumerator enumerator(directory, false /* recursive */, 98 FileEnumerator enumerator(directory, false /* recursive */,
99 FileEnumerator::FILES); 99 FileEnumerator::FILES);
100 for (FilePath file_path = enumerator.Next(); !file_path.empty(); 100 for (FilePath file_path = enumerator.Next(); !file_path.empty();
101 file_path = enumerator.Next()) { 101 file_path = enumerator.Next()) {
102 DVLOG(1) << "Removing " << file_path.value(); 102 DVLOG(1) << "Removing " << file_path.value();
103 if (!file_util::Delete(file_path, false /* recursive */)) 103 if (!file_util::Delete(file_path, false /* recursive */))
104 LOG(WARNING) << "Failed to delete " << file_path.value(); 104 LOG(WARNING) << "Failed to delete " << file_path.value();
105 } 105 }
106 } 106 }
107 107
108 // Modifies cache state of file on blocking pool, which involves: 108 // Deletes the symlink.
109 // - moving or copying file (per |file_operation_type|) from |source_path| to 109 void DeleteSymlink(const FilePath& symlink_path) {
110 // |dest_path| if they're different
111 // - deleting symlink if |symlink_path| is not empty
112 // - creating symlink if |symlink_path| is not empty and |create_symlink| is
113 // true.
114 DriveFileError ModifyCacheState(
115 const FilePath& source_path,
116 const FilePath& dest_path,
117 DriveCache::FileOperationType file_operation_type,
118 const FilePath& symlink_path,
119 bool create_symlink) {
120 // Move or copy |source_path| to |dest_path| if they are different.
121 if (source_path != dest_path) {
122 bool success = false;
123 if (file_operation_type == DriveCache::FILE_OPERATION_MOVE)
124 success = file_util::Move(source_path, dest_path);
125 else if (file_operation_type == DriveCache::FILE_OPERATION_COPY)
126 success = file_util::CopyFile(source_path, dest_path);
127 if (!success) {
128 LOG(ERROR) << "Failed to "
129 << (file_operation_type == DriveCache::FILE_OPERATION_MOVE ?
130 "move " : "copy ")
131 << source_path.value()
132 << " to " << dest_path.value();
133 return DRIVE_FILE_ERROR_FAILED;
134 } else {
135 DVLOG(1) << (file_operation_type == DriveCache::FILE_OPERATION_MOVE ?
136 "Moved " : "Copied ")
137 << source_path.value()
138 << " to " << dest_path.value();
139 }
140 } else {
141 DVLOG(1) << "No need to move file: source = destination";
142 }
143
144 if (symlink_path.empty())
145 return DRIVE_FILE_OK;
146
147 // Remove symlink regardless of |create_symlink| because creating a link will
148 // not overwrite an existing one.
149 // We try to save one file operation by not checking if link exists before 110 // We try to save one file operation by not checking if link exists before
150 // deleting it, so unlink may return error if link doesn't exist, but it 111 // deleting it, so unlink may return error if link doesn't exist, but it
151 // doesn't really matter to us. 112 // doesn't really matter to us.
152 file_util::Delete(symlink_path, false); 113 file_util::Delete(symlink_path, false);
114 }
153 115
154 if (!create_symlink) 116 // Creates a symlink.
155 return DRIVE_FILE_OK; 117 bool CreateSymlink(const FilePath& cache_file_path,
118 const FilePath& symlink_path) {
119 // Remove symlink because creating a link will not overwrite an existing one.
120 DeleteSymlink(symlink_path);
156 121
157 // Create new symlink to |dest_path|. 122 // Create new symlink to |cache_file_path|.
158 if (!file_util::CreateSymbolicLink(dest_path, symlink_path)) { 123 if (!file_util::CreateSymbolicLink(cache_file_path, symlink_path)) {
159 LOG(ERROR) << "Failed to create a symlink from " << symlink_path.value() 124 LOG(ERROR) << "Failed to create a symlink from " << symlink_path.value()
125 << " to " << cache_file_path.value();
126 return false;
127 }
128 return true;
129 }
130
131 // Moves the file.
132 bool MoveFile(const FilePath& source_path, const FilePath& dest_path) {
133 if (!file_util::Move(source_path, dest_path)) {
134 LOG(ERROR) << "Failed to move " << source_path.value()
160 << " to " << dest_path.value(); 135 << " to " << dest_path.value();
161 return DRIVE_FILE_ERROR_FAILED; 136 return false;
162 } 137 }
138 DVLOG(1) << "Moved " << source_path.value() << " to " << dest_path.value();
139 return true;
140 }
163 141
164 return DRIVE_FILE_OK; 142 // Copies the file.
143 bool CopyFile(const FilePath& source_path, const FilePath& dest_path) {
144 if (!file_util::CopyFile(source_path, dest_path)) {
145 LOG(ERROR) << "Failed to copy " << source_path.value()
146 << " to " << dest_path.value();
147 return false;
148 }
149 DVLOG(1) << "Copied " << source_path.value() << " to " << dest_path.value();
150 return true;
165 } 151 }
166 152
167 // Deletes all files that match |path_to_delete_pattern| except for 153 // Deletes all files that match |path_to_delete_pattern| except for
168 // |path_to_keep| on blocking pool. 154 // |path_to_keep| on blocking pool.
169 // If |path_to_keep| is empty, all files in |path_to_delete_pattern| are 155 // If |path_to_keep| is empty, all files in |path_to_delete_pattern| are
170 // deleted. 156 // deleted.
171 void DeleteFilesSelectively(const FilePath& path_to_delete_pattern, 157 void DeleteFilesSelectively(const FilePath& path_to_delete_pattern,
172 const FilePath& path_to_keep) { 158 const FilePath& path_to_keep) {
173 // Enumerate all files in directory of |path_to_delete_pattern| that match 159 // Enumerate all files in directory of |path_to_delete_pattern| that match
174 // base name of |path_to_delete_pattern|. 160 // base name of |path_to_delete_pattern|.
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 314
329 bool DriveCache::FreeDiskSpaceOnBlockingPoolIfNeededFor(int64 num_bytes) { 315 bool DriveCache::FreeDiskSpaceOnBlockingPoolIfNeededFor(int64 num_bytes) {
330 AssertOnSequencedWorkerPool(); 316 AssertOnSequencedWorkerPool();
331 317
332 // Do nothing and return if we have enough space. 318 // Do nothing and return if we have enough space.
333 if (HasEnoughSpaceFor(num_bytes)) 319 if (HasEnoughSpaceFor(num_bytes))
334 return true; 320 return true;
335 321
336 // Otherwise, try to free up the disk space. 322 // Otherwise, try to free up the disk space.
337 DVLOG(1) << "Freeing up disk space for " << num_bytes; 323 DVLOG(1) << "Freeing up disk space for " << num_bytes;
338 // First remove temporary files from the cache map. 324 // First remove temporary files from the metadata.
339 metadata_->RemoveTemporaryFiles(); 325 metadata_->RemoveTemporaryFiles();
340 // Then remove all files under "tmp" directory. 326 // Then remove all files under "tmp" directory.
341 RemoveAllFiles(GetCacheDirectoryPath(CACHE_TYPE_TMP)); 327 RemoveAllFiles(GetCacheDirectoryPath(CACHE_TYPE_TMP));
342 328
343 // Check the disk space again. 329 // Check the disk space again.
344 return HasEnoughSpaceFor(num_bytes); 330 return HasEnoughSpaceFor(num_bytes);
345 } 331 }
346 332
347 void DriveCache::GetFile(const std::string& resource_id, 333 void DriveCache::GetFile(const std::string& resource_id,
348 const std::string& md5, 334 const std::string& md5,
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 if (!file_util::GetFileSize(source_path, &file_size)) { 602 if (!file_util::GetFileSize(source_path, &file_size)) {
617 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); 603 LOG(WARNING) << "Couldn't get file size for: " << source_path.value();
618 return DRIVE_FILE_ERROR_FAILED; 604 return DRIVE_FILE_ERROR_FAILED;
619 } 605 }
620 606
621 const bool enough_space = FreeDiskSpaceOnBlockingPoolIfNeededFor(file_size); 607 const bool enough_space = FreeDiskSpaceOnBlockingPoolIfNeededFor(file_size);
622 if (!enough_space) 608 if (!enough_space)
623 return DRIVE_FILE_ERROR_NO_SPACE; 609 return DRIVE_FILE_ERROR_NO_SPACE;
624 } 610 }
625 611
626 FilePath dest_path;
627 FilePath symlink_path; 612 FilePath symlink_path;
628 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; 613 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP;
629 614
630 // If file was previously pinned, store it in persistent dir and create 615 // If file was previously pinned, store it in persistent dir.
631 // symlink in pinned dir.
632 DriveCacheEntry cache_entry; 616 DriveCacheEntry cache_entry;
633 if (GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) { 617 if (GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) {
634 // File exists in cache. 618 // File exists in cache.
635 // If file is dirty or mounted, return error. 619 // If file is dirty or mounted, return error.
636 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { 620 if (cache_entry.is_dirty() || cache_entry.is_mounted()) {
637 LOG(WARNING) << "Can't store a file to replace a " 621 LOG(WARNING) << "Can't store a file to replace a "
638 << (cache_entry.is_dirty() ? "dirty" : "mounted") 622 << (cache_entry.is_dirty() ? "dirty" : "mounted")
639 << " file: res_id=" << resource_id 623 << " file: res_id=" << resource_id
640 << ", md5=" << md5; 624 << ", md5=" << md5;
641 return DRIVE_FILE_ERROR_IN_USE; 625 return DRIVE_FILE_ERROR_IN_USE;
642 } 626 }
643 627
644 // If file is pinned, determines destination path. 628 if (cache_entry.is_pinned())
645 if (cache_entry.is_pinned()) {
646 sub_dir_type = CACHE_TYPE_PERSISTENT; 629 sub_dir_type = CACHE_TYPE_PERSISTENT;
647 dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type,
648 CACHED_FILE_FROM_SERVER);
649 symlink_path = GetCacheFilePath(
650 resource_id, std::string(), CACHE_TYPE_PINNED,
651 CACHED_FILE_FROM_SERVER);
652 }
653 } 630 }
654 631
655 // File wasn't pinned or doesn't exist in cache, store in tmp dir. 632 FilePath dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type,
656 if (dest_path.empty()) { 633 CACHED_FILE_FROM_SERVER);
657 DCHECK_EQ(CACHE_TYPE_TMP, sub_dir_type); 634 bool success = false;
658 dest_path = GetCacheFilePath(resource_id, md5, sub_dir_type, 635 switch (file_operation_type) {
659 CACHED_FILE_FROM_SERVER); 636 case FILE_OPERATION_MOVE:
637 success = MoveFile(source_path, dest_path);
638 break;
639 case FILE_OPERATION_COPY:
640 success = CopyFile(source_path, dest_path);
641 break;
642 default:
643 NOTREACHED();
660 } 644 }
661 645
662 DriveFileError error = ModifyCacheState( 646 // Create symlink in pinned directory if the file is pinned.
663 source_path, 647 if (success && cache_entry.is_pinned()) {
664 dest_path, 648 FilePath symlink_path = GetCacheFilePath(resource_id, std::string(),
665 file_operation_type, 649 CACHE_TYPE_PINNED,
666 symlink_path, 650 CACHED_FILE_FROM_SERVER);
667 !symlink_path.empty()); // create symlink 651 success = CreateSymlink(dest_path, symlink_path);
652 }
668 653
669 // Determine search pattern for stale filenames corresponding to resource_id, 654 // Determine search pattern for stale filenames corresponding to resource_id,
670 // either "<resource_id>*" or "<resource_id>.*". 655 // either "<resource_id>*" or "<resource_id>.*".
671 FilePath stale_filenames_pattern; 656 FilePath stale_filenames_pattern;
672 if (md5.empty()) { 657 if (md5.empty()) {
673 // No md5 means no extension, append '*' after base name, i.e. 658 // No md5 means no extension, append '*' after base name, i.e.
674 // "<resource_id>*". 659 // "<resource_id>*".
675 // Cannot call |dest_path|.ReplaceExtension when there's no md5 extension: 660 // Cannot call |dest_path|.ReplaceExtension when there's no md5 extension:
676 // if base name of |dest_path| (i.e. escaped resource_id) contains the 661 // if base name of |dest_path| (i.e. escaped resource_id) contains the
677 // extension separator '.', ReplaceExtension will remove it and everything 662 // extension separator '.', ReplaceExtension will remove it and everything
678 // after it. The result will be nothing like the escaped resource_id. 663 // after it. The result will be nothing like the escaped resource_id.
679 stale_filenames_pattern = FilePath(dest_path.value() + util::kWildCard); 664 stale_filenames_pattern = FilePath(dest_path.value() + util::kWildCard);
680 } else { 665 } else {
681 // Replace md5 extension with '*' i.e. "<resource_id>.*". 666 // Replace md5 extension with '*' i.e. "<resource_id>.*".
682 // Note that ReplaceExtension automatically prefixes the extension with the 667 // Note that ReplaceExtension automatically prefixes the extension with the
683 // extension separator '.'. 668 // extension separator '.'.
684 stale_filenames_pattern = dest_path.ReplaceExtension(util::kWildCard); 669 stale_filenames_pattern = dest_path.ReplaceExtension(util::kWildCard);
685 } 670 }
686 671
687 // Delete files that match |stale_filenames_pattern| except for |dest_path|. 672 // Delete files that match |stale_filenames_pattern| except for |dest_path|.
688 DeleteFilesSelectively(stale_filenames_pattern, dest_path); 673 DeleteFilesSelectively(stale_filenames_pattern, dest_path);
689 674
690 if (error == DRIVE_FILE_OK) { 675 if (success) {
691 // Now that file operations have completed, update cache map. 676 // Now that file operations have completed, update metadata.
692 cache_entry.set_md5(md5); 677 cache_entry.set_md5(md5);
693 cache_entry.set_is_present(true); 678 cache_entry.set_is_present(true);
694 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); 679 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
695 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 680 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
696 } 681 }
697 682
698 return error; 683 return success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
699 } 684 }
700 685
701 DriveFileError DriveCache::PinOnBlockingPool(const std::string& resource_id, 686 DriveFileError DriveCache::PinOnBlockingPool(const std::string& resource_id,
702 const std::string& md5) { 687 const std::string& md5) {
703 AssertOnSequencedWorkerPool(); 688 AssertOnSequencedWorkerPool();
704 689
705 FilePath source_path;
706 FilePath dest_path; 690 FilePath dest_path;
707 FilePath symlink_path;
708 bool create_symlink = true;
709 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT; 691 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT;
710 692
711 DriveCacheEntry cache_entry; 693 DriveCacheEntry cache_entry;
712 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) { 694 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) {
713 // Entry does not exist in cache. 695 // Entry does not exist in cache. Set |dest_path| to /dev/null, so that
714 // Set both |dest_path| and |source_path| to /dev/null, so that: 696 // symlinks to /dev/null will be picked up by DriveSyncClient to download
715 // 1) ModifyCacheState won't move files when |source_path| and |dest_path| 697 // pinned files that don't exist in cache.
716 // are the same.
717 // 2) symlinks to /dev/null will be picked up by DriveSyncClient to download
718 // pinned files that don't exist in cache.
719 dest_path = FilePath::FromUTF8Unsafe(util::kSymLinkToDevNull); 698 dest_path = FilePath::FromUTF8Unsafe(util::kSymLinkToDevNull);
720 source_path = dest_path;
721 699
722 // Set sub_dir_type to TMP. The file will be first downloaded in 'tmp', 700 // Set sub_dir_type to TMP. The file will be first downloaded in 'tmp',
723 // then moved to 'persistent'. 701 // then moved to 'persistent'.
724 sub_dir_type = CACHE_TYPE_TMP; 702 sub_dir_type = CACHE_TYPE_TMP;
725 } else { // File exists in cache, determines destination path. 703 } else { // File exists in cache, determines destination path.
726 // Determine source and destination paths. 704 // Determine source and destination paths.
727 705
728 // If file is dirty or mounted, don't move it, so determine |dest_path| and 706 // If file is dirty or mounted, don't move it.
729 // set |source_path| the same, because ModifyCacheState only moves files if
730 // source and destination are different.
731 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { 707 if (cache_entry.is_dirty() || cache_entry.is_mounted()) {
732 DCHECK(cache_entry.is_persistent()); 708 DCHECK(cache_entry.is_persistent());
733 dest_path = GetCacheFilePath(resource_id, 709 dest_path = GetCacheFilePath(resource_id,
734 md5, 710 md5,
735 GetSubDirectoryType(cache_entry), 711 GetSubDirectoryType(cache_entry),
736 CACHED_FILE_LOCALLY_MODIFIED); 712 CACHED_FILE_LOCALLY_MODIFIED);
737 source_path = dest_path;
738 } else { 713 } else {
739 // Gets the current path of the file in cache.
740 source_path = GetCacheFilePath(resource_id,
741 md5,
742 GetSubDirectoryType(cache_entry),
743 CACHED_FILE_FROM_SERVER);
744
745 // If file was pinned before but actual file blob doesn't exist in cache: 714 // If file was pinned before but actual file blob doesn't exist in cache:
746 // - don't need to move the file, so set |dest_path| to |source_path|, 715 // - don't need to move the file.
747 // because ModifyCacheState only moves files if source and destination
748 // are different
749 // - don't create symlink since it already exists. 716 // - don't create symlink since it already exists.
750 if (!cache_entry.is_present()) { 717 if (!cache_entry.is_present()) {
751 dest_path = source_path; 718 DCHECK(cache_entry.is_pinned());
752 create_symlink = false; 719 return DRIVE_FILE_OK;
753 } else { // File exists, move it to persistent dir.
754 dest_path = GetCacheFilePath(resource_id,
755 md5,
756 CACHE_TYPE_PERSISTENT,
757 CACHED_FILE_FROM_SERVER);
758 } 720 }
721 // File exists, move it to persistent dir.
722 // Gets the current path of the file in cache.
723 FilePath source_path = GetCacheFilePath(resource_id,
724 md5,
725 GetSubDirectoryType(cache_entry),
726 CACHED_FILE_FROM_SERVER);
727 dest_path = GetCacheFilePath(resource_id,
728 md5,
729 CACHE_TYPE_PERSISTENT,
730 CACHED_FILE_FROM_SERVER);
731 if (!MoveFile(source_path, dest_path))
732 return DRIVE_FILE_ERROR_FAILED;
759 } 733 }
760 } 734 }
761 735
762 // Create symlink in pinned dir. 736 // Create symlink in pinned dir.
763 if (create_symlink) { 737 FilePath symlink_path = GetCacheFilePath(resource_id,
764 symlink_path = GetCacheFilePath(resource_id, 738 std::string(),
765 std::string(), 739 CACHE_TYPE_PINNED,
766 CACHE_TYPE_PINNED, 740 CACHED_FILE_FROM_SERVER);
767 CACHED_FILE_FROM_SERVER); 741 DCHECK(!dest_path.empty());
768 } 742 if (!CreateSymlink(dest_path, symlink_path))
743 return DRIVE_FILE_ERROR_FAILED;
769 744
770 DriveFileError error = ModifyCacheState(source_path, 745 // Now that file operations have completed, update metadata.
771 dest_path, 746 cache_entry.set_md5(md5);
772 FILE_OPERATION_MOVE, 747 cache_entry.set_is_pinned(true);
773 symlink_path, 748 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
774 create_symlink); 749 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
775 if (error == DRIVE_FILE_OK) { 750 return DRIVE_FILE_OK;
776 // Now that file operations have completed, update cache map.
777 cache_entry.set_md5(md5);
778 cache_entry.set_is_pinned(true);
779 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
780 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
781 }
782
783 return error;
784 } 751 }
785 752
786 DriveFileError DriveCache::UnpinOnBlockingPool(const std::string& resource_id, 753 DriveFileError DriveCache::UnpinOnBlockingPool(const std::string& resource_id,
787 const std::string& md5) { 754 const std::string& md5) {
788 AssertOnSequencedWorkerPool(); 755 AssertOnSequencedWorkerPool();
789 756
790 // Unpinning a file means its entry must exist in cache. 757 // Unpinning a file means its entry must exist in cache.
791 DriveCacheEntry cache_entry; 758 DriveCacheEntry cache_entry;
792 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) { 759 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) {
793 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id=" 760 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id="
794 << resource_id 761 << resource_id
795 << ", md5=" << md5; 762 << ", md5=" << md5;
796 return DRIVE_FILE_ERROR_NOT_FOUND; 763 return DRIVE_FILE_ERROR_NOT_FOUND;
797 } 764 }
798 765
799 // Entry exists in cache, determines source and destination paths.
800
801 FilePath source_path;
802 FilePath dest_path;
803 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP; 766 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP;
804 767
805 // If file is dirty or mounted, don't move it, so determine |dest_path| and 768 // If file is dirty or mounted, don't move it.
806 // set |source_path| the same, because ModifyCacheState moves files if source
807 // and destination are different.
808 if (cache_entry.is_dirty() || cache_entry.is_mounted()) { 769 if (cache_entry.is_dirty() || cache_entry.is_mounted()) {
809 sub_dir_type = CACHE_TYPE_PERSISTENT; 770 sub_dir_type = CACHE_TYPE_PERSISTENT;
810 DCHECK(cache_entry.is_persistent()); 771 DCHECK(cache_entry.is_persistent());
811 dest_path = GetCacheFilePath(resource_id,
812 md5,
813 GetSubDirectoryType(cache_entry),
814 CACHED_FILE_LOCALLY_MODIFIED);
815 source_path = dest_path;
816 } else { 772 } else {
817 // Gets the current path of the file in cache.
818 source_path = GetCacheFilePath(resource_id,
819 md5,
820 GetSubDirectoryType(cache_entry),
821 CACHED_FILE_FROM_SERVER);
822
823 // If file was pinned but actual file blob still doesn't exist in cache, 773 // If file was pinned but actual file blob still doesn't exist in cache,
824 // don't need to move the file, so set |dest_path| to |source_path|, because 774 // don't need to move the file.
825 // ModifyCacheState only moves files if source and destination are 775 if (cache_entry.is_present()) {
826 // different. 776 // Gets the current path of the file in cache.
827 if (!cache_entry.is_present()) { 777 FilePath source_path = GetCacheFilePath(resource_id,
828 dest_path = source_path; 778 md5,
829 } else { // File exists, move it to tmp dir. 779 GetSubDirectoryType(cache_entry),
830 dest_path = GetCacheFilePath(resource_id, md5, 780 CACHED_FILE_FROM_SERVER);
831 CACHE_TYPE_TMP, 781 // File exists, move it to tmp dir.
832 CACHED_FILE_FROM_SERVER); 782 FilePath dest_path = GetCacheFilePath(resource_id,
783 md5,
784 CACHE_TYPE_TMP,
785 CACHED_FILE_FROM_SERVER);
786 if (!MoveFile(source_path, dest_path))
787 return DRIVE_FILE_ERROR_FAILED;
833 } 788 }
834 } 789 }
835 790
836 // If file was pinned, get absolute path of symlink in pinned dir so as to 791 // If file was pinned, remove the symlink in pinned dir.
837 // remove it.
838 FilePath symlink_path;
839 if (cache_entry.is_pinned()) { 792 if (cache_entry.is_pinned()) {
840 symlink_path = GetCacheFilePath(resource_id, 793 FilePath symlink_path = GetCacheFilePath(resource_id,
841 std::string(), 794 std::string(),
842 CACHE_TYPE_PINNED, 795 CACHE_TYPE_PINNED,
843 CACHED_FILE_FROM_SERVER); 796 CACHED_FILE_FROM_SERVER);
797 DeleteSymlink(symlink_path);
844 } 798 }
845 799
846 DriveFileError error = ModifyCacheState( 800 // Now that file operations have completed, update metadata.
847 source_path, 801 if (cache_entry.is_present()) {
848 dest_path, 802 cache_entry.set_md5(md5);
849 FILE_OPERATION_MOVE, 803 cache_entry.set_is_pinned(false);
850 symlink_path, // This will be deleted if it exists. 804 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
851 false /* don't create symlink*/); 805 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
852 806 } else {
853 if (error == DRIVE_FILE_OK) { 807 // Remove the existing entry if we are unpinning a non-present file.
854 // Now that file operations have completed, update cache map. 808 metadata_->RemoveCacheEntry(resource_id);
855 if (cache_entry.is_present()) {
856 cache_entry.set_md5(md5);
857 cache_entry.set_is_pinned(false);
858 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
859 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
860 } else {
861 // Remove the existing entry if we are unpinning a non-present file.
862 metadata_->RemoveCacheEntry(resource_id);
863 }
864 } 809 }
865 810 return DRIVE_FILE_OK;
866 return error;
867 } 811 }
868 812
869 scoped_ptr<DriveCache::GetFileResult> DriveCache::SetMountedStateOnBlockingPool( 813 scoped_ptr<DriveCache::GetFileResult> DriveCache::SetMountedStateOnBlockingPool(
870 const FilePath& file_path, 814 const FilePath& file_path,
871 bool to_mount) { 815 bool to_mount) {
872 AssertOnSequencedWorkerPool(); 816 AssertOnSequencedWorkerPool();
873 817
874 scoped_ptr<GetFileResult> result(new GetFileResult); 818 scoped_ptr<GetFileResult> result(new GetFileResult);
875 819
876 // Parse file path to obtain resource_id, md5 and extra_extension. 820 // Parse file path to obtain resource_id, md5 and extra_extension.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 dest_subdir = mounted_subdir; 858 dest_subdir = mounted_subdir;
915 cache_entry.set_is_mounted(true); 859 cache_entry.set_is_mounted(true);
916 } else { 860 } else {
917 source_path = mounted_path; 861 source_path = mounted_path;
918 cache_file_path = unmounted_path; 862 cache_file_path = unmounted_path;
919 dest_subdir = unmounted_subdir; 863 dest_subdir = unmounted_subdir;
920 cache_entry.set_is_mounted(false); 864 cache_entry.set_is_mounted(false);
921 } 865 }
922 866
923 // Move cache blob from source path to destination path. 867 // Move cache blob from source path to destination path.
924 DriveFileError error = ModifyCacheState( 868 bool success = MoveFile(source_path, cache_file_path);
925 source_path, cache_file_path, FILE_OPERATION_MOVE, FilePath(), false); 869
926 if (error == DRIVE_FILE_OK) { 870 if (success) {
927 // Now that cache operation is complete, update cache map 871 // Now that cache operation is complete, update metadata.
928 cache_entry.set_md5(md5); 872 cache_entry.set_md5(md5);
929 cache_entry.set_is_persistent(dest_subdir == CACHE_TYPE_PERSISTENT); 873 cache_entry.set_is_persistent(dest_subdir == CACHE_TYPE_PERSISTENT);
930 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 874 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
931 } 875 }
932 876 result->first = success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
933 result->first = error;
934 result->second = cache_file_path; 877 result->second = cache_file_path;
935 return result.Pass(); 878 return result.Pass();
936 } 879 }
937 880
938 scoped_ptr<DriveCache::GetFileResult> DriveCache::MarkDirtyOnBlockingPool( 881 scoped_ptr<DriveCache::GetFileResult> DriveCache::MarkDirtyOnBlockingPool(
939 const std::string& resource_id, 882 const std::string& resource_id,
940 const std::string& md5) { 883 const std::string& md5) {
941 AssertOnSequencedWorkerPool(); 884 AssertOnSequencedWorkerPool();
942 885
943 scoped_ptr<GetFileResult> result(new GetFileResult); 886 scoped_ptr<GetFileResult> result(new GetFileResult);
(...skipping 19 matching lines...) Expand all
963 // delete outgoing symlink if it exists. 906 // delete outgoing symlink if it exists.
964 // TODO(benchan): We should only delete outgoing symlink if file is currently 907 // TODO(benchan): We should only delete outgoing symlink if file is currently
965 // not being uploaded. However, for now, cache doesn't know if uploading of a 908 // not being uploaded. However, for now, cache doesn't know if uploading of a
966 // file is in progress. Per zel, the upload process should be canceled before 909 // file is in progress. Per zel, the upload process should be canceled before
967 // MarkDirtyInCache is called again. 910 // MarkDirtyInCache is called again.
968 if (cache_entry.is_dirty()) { 911 if (cache_entry.is_dirty()) {
969 // The file must be in persistent dir. 912 // The file must be in persistent dir.
970 DCHECK(cache_entry.is_persistent()); 913 DCHECK(cache_entry.is_persistent());
971 914
972 // Determine symlink path in outgoing dir, so as to remove it. 915 // Determine symlink path in outgoing dir, so as to remove it.
973 FilePath symlink_path = GetCacheFilePath( 916 FilePath symlink_path = GetCacheFilePath(resource_id,
974 resource_id, 917 std::string(),
975 std::string(), 918 CACHE_TYPE_OUTGOING,
976 CACHE_TYPE_OUTGOING, 919 CACHED_FILE_FROM_SERVER);
977 CACHED_FILE_FROM_SERVER); 920 DeleteSymlink(symlink_path);
978
979 // We're not moving files here, so simply use empty FilePath for both
980 // |source_path| and |dest_path| because ModifyCacheState only move files
981 // if source and destination are different.
982 DriveFileError error = ModifyCacheState(
983 FilePath(), // non-applicable source path
984 FilePath(), // non-applicable dest path
985 FILE_OPERATION_MOVE,
986 symlink_path,
987 false /* don't create symlink */);
988 921
989 // Determine current path of dirty file. 922 // Determine current path of dirty file.
990 result->first = error; 923 result->first = DRIVE_FILE_OK;
991 if (error == DRIVE_FILE_OK) { 924 result->second = GetCacheFilePath(resource_id,
992 result->second = GetCacheFilePath(resource_id, 925 md5,
993 md5, 926 CACHE_TYPE_PERSISTENT,
994 CACHE_TYPE_PERSISTENT, 927 CACHED_FILE_LOCALLY_MODIFIED);
995 CACHED_FILE_LOCALLY_MODIFIED);
996 }
997 return result.Pass(); 928 return result.Pass();
998 } 929 }
999 930
1000 // Move file to persistent dir with new .local extension. 931 // Move file to persistent dir with new .local extension.
1001 932
1002 // Get the current path of the file in cache. 933 // Get the current path of the file in cache.
1003 FilePath source_path = GetCacheFilePath( 934 FilePath source_path = GetCacheFilePath(resource_id,
1004 resource_id, 935 md5,
1005 md5, 936 GetSubDirectoryType(cache_entry),
1006 GetSubDirectoryType(cache_entry), 937 CACHED_FILE_FROM_SERVER);
1007 CACHED_FILE_FROM_SERVER);
1008
1009 // Determine destination path. 938 // Determine destination path.
1010 const CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT; 939 const CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT;
1011 FilePath cache_file_path = GetCacheFilePath(resource_id, 940 FilePath cache_file_path = GetCacheFilePath(resource_id,
1012 md5, 941 md5,
1013 sub_dir_type, 942 sub_dir_type,
1014 CACHED_FILE_LOCALLY_MODIFIED); 943 CACHED_FILE_LOCALLY_MODIFIED);
1015 944
945 bool success = MoveFile(source_path, cache_file_path);
946
1016 // If file is pinned, update symlink in pinned dir. 947 // If file is pinned, update symlink in pinned dir.
1017 FilePath symlink_path; 948 if (success && cache_entry.is_pinned()) {
1018 if (cache_entry.is_pinned()) { 949 FilePath symlink_path = GetCacheFilePath(resource_id,
1019 symlink_path = GetCacheFilePath(resource_id, 950 std::string(),
1020 std::string(), 951 CACHE_TYPE_PINNED,
1021 CACHE_TYPE_PINNED, 952 CACHED_FILE_FROM_SERVER);
1022 CACHED_FILE_FROM_SERVER); 953 success = CreateSymlink(cache_file_path, symlink_path);
1023 } 954 }
1024 955
1025 DriveFileError error = ModifyCacheState( 956 if (success) {
1026 source_path, 957 // Now that file operations have completed, update metadata.
1027 cache_file_path,
1028 FILE_OPERATION_MOVE,
1029 symlink_path,
1030 !symlink_path.empty() /* create symlink */);
1031
1032 if (error == DRIVE_FILE_OK) {
1033 // Now that file operations have completed, update cache map.
1034 cache_entry.set_md5(md5); 958 cache_entry.set_md5(md5);
1035 cache_entry.set_is_dirty(true); 959 cache_entry.set_is_dirty(true);
1036 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); 960 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
1037 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 961 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1038 } 962 }
1039 result->first = error; 963 result->first = success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
1040 result->second = cache_file_path; 964 result->second = cache_file_path;
1041 return result.Pass(); 965 return result.Pass();
1042 } 966 }
1043 967
1044 DriveFileError DriveCache::CommitDirtyOnBlockingPool( 968 DriveFileError DriveCache::CommitDirtyOnBlockingPool(
1045 const std::string& resource_id, 969 const std::string& resource_id,
1046 const std::string& md5) { 970 const std::string& md5) {
1047 AssertOnSequencedWorkerPool(); 971 AssertOnSequencedWorkerPool();
1048 972
1049 // If file has already been marked dirty in previous instance of chrome, we 973 // If file has already been marked dirty in previous instance of chrome, we
(...skipping 29 matching lines...) Expand all
1079 std::string(), 1003 std::string(),
1080 CACHE_TYPE_OUTGOING, 1004 CACHE_TYPE_OUTGOING,
1081 CACHED_FILE_FROM_SERVER); 1005 CACHED_FILE_FROM_SERVER);
1082 1006
1083 // Get target path of symlink i.e. current path of the file in cache. 1007 // Get target path of symlink i.e. current path of the file in cache.
1084 FilePath target_path = GetCacheFilePath(resource_id, 1008 FilePath target_path = GetCacheFilePath(resource_id,
1085 md5, 1009 md5,
1086 GetSubDirectoryType(cache_entry), 1010 GetSubDirectoryType(cache_entry),
1087 CACHED_FILE_LOCALLY_MODIFIED); 1011 CACHED_FILE_LOCALLY_MODIFIED);
1088 1012
1089 // Since there's no need to move files, use |target_path| for both 1013 return CreateSymlink(target_path, symlink_path) ?
1090 // |source_path| and |dest_path|, because ModifyCacheState only moves files 1014 DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
1091 // if source and destination are different.
1092 return ModifyCacheState(target_path, // source
1093 target_path, // destination
1094 FILE_OPERATION_MOVE,
1095 symlink_path,
1096 true /* create symlink */);
1097 } 1015 }
1098 1016
1099 DriveFileError DriveCache::ClearDirtyOnBlockingPool( 1017 DriveFileError DriveCache::ClearDirtyOnBlockingPool(
1100 const std::string& resource_id, 1018 const std::string& resource_id,
1101 const std::string& md5) { 1019 const std::string& md5) {
1102 AssertOnSequencedWorkerPool(); 1020 AssertOnSequencedWorkerPool();
1103 1021
1104 // |md5| is the new .<md5> extension to rename the file to. 1022 // |md5| is the new .<md5> extension to rename the file to.
1105 // So, search for entry in cache without comparing md5. 1023 // So, search for entry in cache without comparing md5.
1106 DriveCacheEntry cache_entry; 1024 DriveCacheEntry cache_entry;
(...skipping 29 matching lines...) Expand all
1136 // Determine destination path. 1054 // Determine destination path.
1137 // If file is pinned, move it to persistent dir with .md5 extension; 1055 // If file is pinned, move it to persistent dir with .md5 extension;
1138 // otherwise, move it to tmp dir with .md5 extension. 1056 // otherwise, move it to tmp dir with .md5 extension.
1139 const CacheSubDirectoryType sub_dir_type = 1057 const CacheSubDirectoryType sub_dir_type =
1140 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; 1058 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1141 FilePath dest_path = GetCacheFilePath(resource_id, 1059 FilePath dest_path = GetCacheFilePath(resource_id,
1142 md5, 1060 md5,
1143 sub_dir_type, 1061 sub_dir_type,
1144 CACHED_FILE_FROM_SERVER); 1062 CACHED_FILE_FROM_SERVER);
1145 1063
1146 // Delete symlink in outgoing dir. 1064 bool success = MoveFile(source_path, dest_path);
1147 FilePath symlink_path = GetCacheFilePath(resource_id,
1148 std::string(),
1149 CACHE_TYPE_OUTGOING,
1150 CACHED_FILE_FROM_SERVER);
1151 1065
1152 DriveFileError error = ModifyCacheState(source_path, 1066 if (success) {
1153 dest_path, 1067 // Delete symlink in outgoing dir.
1154 FILE_OPERATION_MOVE, 1068 FilePath symlink_path = GetCacheFilePath(resource_id,
1155 symlink_path, 1069 std::string(),
1156 false /* don't create symlink */); 1070 CACHE_TYPE_OUTGOING,
1071 CACHED_FILE_FROM_SERVER);
1072 DeleteSymlink(symlink_path);
1073 }
1157 1074
1158 // If file is pinned, update symlink in pinned dir. 1075 // If file is pinned, update symlink in pinned dir.
1159 if (error == DRIVE_FILE_OK && cache_entry.is_pinned()) { 1076 if (success && cache_entry.is_pinned()) {
1160 symlink_path = GetCacheFilePath(resource_id, 1077 FilePath symlink_path = GetCacheFilePath(resource_id,
1161 std::string(), 1078 std::string(),
1162 CACHE_TYPE_PINNED, 1079 CACHE_TYPE_PINNED,
1163 CACHED_FILE_FROM_SERVER); 1080 CACHED_FILE_FROM_SERVER);
1164 1081
1165 // Since there's no moving of files here, use |dest_path| for both 1082 success = CreateSymlink(dest_path, symlink_path);
1166 // |source_path| and |dest_path|, because ModifyCacheState only moves files
1167 // if source and destination are different.
1168 error = ModifyCacheState(dest_path, // source path
1169 dest_path, // destination path
1170 FILE_OPERATION_MOVE,
1171 symlink_path,
1172 true /* create symlink */);
1173 } 1083 }
1174 1084
1175 if (error == DRIVE_FILE_OK) { 1085 if (success) {
1176 // Now that file operations have completed, update cache map. 1086 // Now that file operations have completed, update metadata.
1177 cache_entry.set_md5(md5); 1087 cache_entry.set_md5(md5);
1178 cache_entry.set_is_dirty(false); 1088 cache_entry.set_is_dirty(false);
1179 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); 1089 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
1180 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 1090 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1181 } 1091 }
1182 1092
1183 return error; 1093 return success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
1184 } 1094 }
1185 1095
1186 DriveFileError DriveCache::RemoveOnBlockingPool( 1096 DriveFileError DriveCache::RemoveOnBlockingPool(
1187 const std::string& resource_id) { 1097 const std::string& resource_id) {
1188 AssertOnSequencedWorkerPool(); 1098 AssertOnSequencedWorkerPool();
1189 1099
1190 // MD5 is not passed into RemoveCacheEntry because we would delete all 1100 // MD5 is not passed into RemoveCacheEntry because we would delete all
1191 // cache files corresponding to <resource_id> regardless of the md5. 1101 // cache files corresponding to <resource_id> regardless of the md5.
1192 // So, search for entry in cache without taking md5 into account. 1102 // So, search for entry in cache without taking md5 into account.
1193 DriveCacheEntry cache_entry; 1103 DriveCacheEntry cache_entry;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 // outgoing path to |paths_to_delete|. 1141 // outgoing path to |paths_to_delete|.
1232 FilePath path_to_keep = GetCacheFilePath(resource_id, 1142 FilePath path_to_keep = GetCacheFilePath(resource_id,
1233 std::string(), 1143 std::string(),
1234 CACHE_TYPE_PERSISTENT, 1144 CACHE_TYPE_PERSISTENT,
1235 CACHED_FILE_LOCALLY_MODIFIED); 1145 CACHED_FILE_LOCALLY_MODIFIED);
1236 1146
1237 for (size_t i = 0; i < paths_to_delete.size(); ++i) { 1147 for (size_t i = 0; i < paths_to_delete.size(); ++i) {
1238 DeleteFilesSelectively(paths_to_delete[i], path_to_keep); 1148 DeleteFilesSelectively(paths_to_delete[i], path_to_keep);
1239 } 1149 }
1240 1150
1241 // Now that all file operations have completed, remove from cache map. 1151 // Now that all file operations have completed, remove from metadata.
1242 metadata_->RemoveCacheEntry(resource_id); 1152 metadata_->RemoveCacheEntry(resource_id);
1243 1153
1244 return DRIVE_FILE_OK; 1154 return DRIVE_FILE_OK;
1245 } 1155 }
1246 1156
1247 bool DriveCache::ClearAllOnBlockingPool() { 1157 bool DriveCache::ClearAllOnBlockingPool() {
1248 AssertOnSequencedWorkerPool(); 1158 AssertOnSequencedWorkerPool();
1249 1159
1250 if (!file_util::Delete(cache_root_path_, true)) { 1160 if (!file_util::Delete(cache_root_path_, true)) {
1251 LOG(WARNING) << "Failed to delete the cache directory"; 1161 LOG(WARNING) << "Failed to delete the cache directory";
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 const DriveCacheEntry& cache_entry) { 1272 const DriveCacheEntry& cache_entry) {
1363 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; 1273 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1364 } 1274 }
1365 1275
1366 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { 1276 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) {
1367 delete global_free_disk_getter_for_testing; // Safe to delete NULL; 1277 delete global_free_disk_getter_for_testing; // Safe to delete NULL;
1368 global_free_disk_getter_for_testing = getter; 1278 global_free_disk_getter_for_testing = getter;
1369 } 1279 }
1370 1280
1371 } // namespace drive 1281 } // namespace drive
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698