Chromium Code Reviews
Help | Chromium Project | Sign in
(1009)

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: Address comments Created 1 year, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
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. 720 } else { // File exists, move it to persistent dir.
kinaba 2012/11/09 09:11:10 nit: you might want to drop else { ... }, since we
hashimoto 2012/11/09 09:16:30 Good catch. Done.
721 // Gets the current path of the file in cache.
722 FilePath source_path =
723 GetCacheFilePath(resource_id,
724 md5,
725 GetSubDirectoryType(cache_entry),
726 CACHED_FILE_FROM_SERVER);
727
754 dest_path = GetCacheFilePath(resource_id, 728 dest_path = GetCacheFilePath(resource_id,
755 md5, 729 md5,
756 CACHE_TYPE_PERSISTENT, 730 CACHE_TYPE_PERSISTENT,
757 CACHED_FILE_FROM_SERVER); 731 CACHED_FILE_FROM_SERVER);
732 if (!MoveFile(source_path, dest_path))
733 return DRIVE_FILE_ERROR_FAILED;
758 } 734 }
759 } 735 }
760 } 736 }
761 737
762 // Create symlink in pinned dir. 738 // Create symlink in pinned dir.
763 if (create_symlink) { 739 FilePath symlink_path = GetCacheFilePath(resource_id,
764 symlink_path = GetCacheFilePath(resource_id, 740 std::string(),
765 std::string(), 741 CACHE_TYPE_PINNED,
766 CACHE_TYPE_PINNED, 742 CACHED_FILE_FROM_SERVER);
767 CACHED_FILE_FROM_SERVER); 743 DCHECK(!dest_path.empty());
768 } 744 if (!CreateSymlink(dest_path, symlink_path))
745 return DRIVE_FILE_ERROR_FAILED;
769 746
770 DriveFileError error = ModifyCacheState(source_path, 747 // Now that file operations have completed, update metadata.
771 dest_path, 748 cache_entry.set_md5(md5);
772 FILE_OPERATION_MOVE, 749 cache_entry.set_is_pinned(true);
773 symlink_path, 750 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
774 create_symlink); 751 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
775 if (error == DRIVE_FILE_OK) { 752 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 } 753 }
785 754
786 DriveFileError DriveCache::UnpinOnBlockingPool(const std::string& resource_id, 755 DriveFileError DriveCache::UnpinOnBlockingPool(const std::string& resource_id,
787 const std::string& md5) { 756 const std::string& md5) {
788 AssertOnSequencedWorkerPool(); 757 AssertOnSequencedWorkerPool();
789 758
790 // Unpinning a file means its entry must exist in cache. 759 // Unpinning a file means its entry must exist in cache.
791 DriveCacheEntry cache_entry; 760 DriveCacheEntry cache_entry;
792 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) { 761 if (!GetCacheEntryOnBlockingPool(resource_id, md5, &cache_entry)) {
793 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id=" 762 LOG(WARNING) << "Can't unpin a file that wasn't pinned or cached: res_id="
794 << resource_id 763 << resource_id
795 << ", md5=" << md5; 764 << ", md5=" << md5;
796 return DRIVE_FILE_ERROR_NOT_FOUND; 765 return DRIVE_FILE_ERROR_NOT_FOUND;
797 } 766 }
798 767
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; 768 CacheSubDirectoryType sub_dir_type = CACHE_TYPE_TMP;
804 769
805 // If file is dirty or mounted, don't move it, so determine |dest_path| and 770 // 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()) { 771 if (cache_entry.is_dirty() || cache_entry.is_mounted()) {
809 sub_dir_type = CACHE_TYPE_PERSISTENT; 772 sub_dir_type = CACHE_TYPE_PERSISTENT;
810 DCHECK(cache_entry.is_persistent()); 773 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 { 774 } 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, 775 // 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 776 // don't need to move the file.
825 // ModifyCacheState only moves files if source and destination are 777 if (cache_entry.is_present()) {
826 // different. 778 // Gets the current path of the file in cache.
827 if (!cache_entry.is_present()) { 779 FilePath source_path = GetCacheFilePath(resource_id,
828 dest_path = source_path; 780 md5,
829 } else { // File exists, move it to tmp dir. 781 GetSubDirectoryType(cache_entry),
830 dest_path = GetCacheFilePath(resource_id, md5, 782 CACHED_FILE_FROM_SERVER);
831 CACHE_TYPE_TMP, 783 // File exists, move it to tmp dir.
832 CACHED_FILE_FROM_SERVER); 784 FilePath dest_path = GetCacheFilePath(resource_id,
785 md5,
786 CACHE_TYPE_TMP,
787 CACHED_FILE_FROM_SERVER);
788 if (!MoveFile(source_path, dest_path))
789 return DRIVE_FILE_ERROR_FAILED;
833 } 790 }
834 } 791 }
835 792
836 // If file was pinned, get absolute path of symlink in pinned dir so as to 793 // If file was pinned, remove the symlink in pinned dir.
837 // remove it.
838 FilePath symlink_path;
839 if (cache_entry.is_pinned()) { 794 if (cache_entry.is_pinned()) {
840 symlink_path = GetCacheFilePath(resource_id, 795 FilePath symlink_path = GetCacheFilePath(resource_id,
841 std::string(), 796 std::string(),
842 CACHE_TYPE_PINNED, 797 CACHE_TYPE_PINNED,
843 CACHED_FILE_FROM_SERVER); 798 CACHED_FILE_FROM_SERVER);
799 DeleteSymlink(symlink_path);
844 } 800 }
845 801
846 DriveFileError error = ModifyCacheState( 802 // Now that file operations have completed, update metadata.
847 source_path, 803 if (cache_entry.is_present()) {
848 dest_path, 804 cache_entry.set_md5(md5);
849 FILE_OPERATION_MOVE, 805 cache_entry.set_is_pinned(false);
850 symlink_path, // This will be deleted if it exists. 806 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
851 false /* don't create symlink*/); 807 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
852 808 } else {
853 if (error == DRIVE_FILE_OK) { 809 // Remove the existing entry if we are unpinning a non-present file.
854 // Now that file operations have completed, update cache map. 810 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 } 811 }
865 812 return DRIVE_FILE_OK;
866 return error;
867 } 813 }
868 814
869 scoped_ptr<DriveCache::GetFileResult> DriveCache::SetMountedStateOnBlockingPool( 815 scoped_ptr<DriveCache::GetFileResult> DriveCache::SetMountedStateOnBlockingPool(
870 const FilePath& file_path, 816 const FilePath& file_path,
871 bool to_mount) { 817 bool to_mount) {
872 AssertOnSequencedWorkerPool(); 818 AssertOnSequencedWorkerPool();
873 819
874 scoped_ptr<GetFileResult> result(new GetFileResult); 820 scoped_ptr<GetFileResult> result(new GetFileResult);
875 821
876 // Parse file path to obtain resource_id, md5 and extra_extension. 822 // 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; 860 dest_subdir = mounted_subdir;
915 cache_entry.set_is_mounted(true); 861 cache_entry.set_is_mounted(true);
916 } else { 862 } else {
917 source_path = mounted_path; 863 source_path = mounted_path;
918 cache_file_path = unmounted_path; 864 cache_file_path = unmounted_path;
919 dest_subdir = unmounted_subdir; 865 dest_subdir = unmounted_subdir;
920 cache_entry.set_is_mounted(false); 866 cache_entry.set_is_mounted(false);
921 } 867 }
922 868
923 // Move cache blob from source path to destination path. 869 // Move cache blob from source path to destination path.
924 DriveFileError error = ModifyCacheState( 870 bool success = MoveFile(source_path, cache_file_path);
925 source_path, cache_file_path, FILE_OPERATION_MOVE, FilePath(), false); 871
926 if (error == DRIVE_FILE_OK) { 872 if (success) {
927 // Now that cache operation is complete, update cache map 873 // Now that cache operation is complete, update metadata.
928 cache_entry.set_md5(md5); 874 cache_entry.set_md5(md5);
929 cache_entry.set_is_persistent(dest_subdir == CACHE_TYPE_PERSISTENT); 875 cache_entry.set_is_persistent(dest_subdir == CACHE_TYPE_PERSISTENT);
930 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 876 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
931 } 877 }
932 878 result->first = success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
933 result->first = error;
934 result->second = cache_file_path; 879 result->second = cache_file_path;
935 return result.Pass(); 880 return result.Pass();
936 } 881 }
937 882
938 scoped_ptr<DriveCache::GetFileResult> DriveCache::MarkDirtyOnBlockingPool( 883 scoped_ptr<DriveCache::GetFileResult> DriveCache::MarkDirtyOnBlockingPool(
939 const std::string& resource_id, 884 const std::string& resource_id,
940 const std::string& md5) { 885 const std::string& md5) {
941 AssertOnSequencedWorkerPool(); 886 AssertOnSequencedWorkerPool();
942 887
943 scoped_ptr<GetFileResult> result(new GetFileResult); 888 scoped_ptr<GetFileResult> result(new GetFileResult);
(...skipping 19 matching lines...) Expand all
963 // delete outgoing symlink if it exists. 908 // delete outgoing symlink if it exists.
964 // TODO(benchan): We should only delete outgoing symlink if file is currently 909 // 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 910 // 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 911 // file is in progress. Per zel, the upload process should be canceled before
967 // MarkDirtyInCache is called again. 912 // MarkDirtyInCache is called again.
968 if (cache_entry.is_dirty()) { 913 if (cache_entry.is_dirty()) {
969 // The file must be in persistent dir. 914 // The file must be in persistent dir.
970 DCHECK(cache_entry.is_persistent()); 915 DCHECK(cache_entry.is_persistent());
971 916
972 // Determine symlink path in outgoing dir, so as to remove it. 917 // Determine symlink path in outgoing dir, so as to remove it.
973 FilePath symlink_path = GetCacheFilePath( 918 FilePath symlink_path = GetCacheFilePath(resource_id,
974 resource_id, 919 std::string(),
975 std::string(), 920 CACHE_TYPE_OUTGOING,
976 CACHE_TYPE_OUTGOING, 921 CACHED_FILE_FROM_SERVER);
977 CACHED_FILE_FROM_SERVER); 922 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 923
989 // Determine current path of dirty file. 924 // Determine current path of dirty file.
990 result->first = error; 925 result->first = DRIVE_FILE_OK;
991 if (error == DRIVE_FILE_OK) { 926 result->second = GetCacheFilePath(resource_id,
992 result->second = GetCacheFilePath(resource_id, 927 md5,
993 md5, 928 CACHE_TYPE_PERSISTENT,
994 CACHE_TYPE_PERSISTENT, 929 CACHED_FILE_LOCALLY_MODIFIED);
995 CACHED_FILE_LOCALLY_MODIFIED);
996 }
997 return result.Pass(); 930 return result.Pass();
998 } 931 }
999 932
1000 // Move file to persistent dir with new .local extension. 933 // Move file to persistent dir with new .local extension.
1001 934
1002 // Get the current path of the file in cache. 935 // Get the current path of the file in cache.
1003 FilePath source_path = GetCacheFilePath( 936 FilePath source_path = GetCacheFilePath(resource_id,
1004 resource_id, 937 md5,
1005 md5, 938 GetSubDirectoryType(cache_entry),
1006 GetSubDirectoryType(cache_entry), 939 CACHED_FILE_FROM_SERVER);
1007 CACHED_FILE_FROM_SERVER);
1008
1009 // Determine destination path. 940 // Determine destination path.
1010 const CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT; 941 const CacheSubDirectoryType sub_dir_type = CACHE_TYPE_PERSISTENT;
1011 FilePath cache_file_path = GetCacheFilePath(resource_id, 942 FilePath cache_file_path = GetCacheFilePath(resource_id,
1012 md5, 943 md5,
1013 sub_dir_type, 944 sub_dir_type,
1014 CACHED_FILE_LOCALLY_MODIFIED); 945 CACHED_FILE_LOCALLY_MODIFIED);
1015 946
947 bool success = MoveFile(source_path, cache_file_path);
948
1016 // If file is pinned, update symlink in pinned dir. 949 // If file is pinned, update symlink in pinned dir.
1017 FilePath symlink_path; 950 if (success && cache_entry.is_pinned()) {
1018 if (cache_entry.is_pinned()) { 951 FilePath symlink_path = GetCacheFilePath(resource_id,
1019 symlink_path = GetCacheFilePath(resource_id, 952 std::string(),
1020 std::string(), 953 CACHE_TYPE_PINNED,
1021 CACHE_TYPE_PINNED, 954 CACHED_FILE_FROM_SERVER);
1022 CACHED_FILE_FROM_SERVER); 955 success = CreateSymlink(cache_file_path, symlink_path);
1023 } 956 }
1024 957
1025 DriveFileError error = ModifyCacheState( 958 if (success) {
1026 source_path, 959 // 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); 960 cache_entry.set_md5(md5);
1035 cache_entry.set_is_dirty(true); 961 cache_entry.set_is_dirty(true);
1036 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); 962 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
1037 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 963 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1038 } 964 }
1039 result->first = error; 965 result->first = success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
1040 result->second = cache_file_path; 966 result->second = cache_file_path;
1041 return result.Pass(); 967 return result.Pass();
1042 } 968 }
1043 969
1044 DriveFileError DriveCache::CommitDirtyOnBlockingPool( 970 DriveFileError DriveCache::CommitDirtyOnBlockingPool(
1045 const std::string& resource_id, 971 const std::string& resource_id,
1046 const std::string& md5) { 972 const std::string& md5) {
1047 AssertOnSequencedWorkerPool(); 973 AssertOnSequencedWorkerPool();
1048 974
1049 // If file has already been marked dirty in previous instance of chrome, we 975 // If file has already been marked dirty in previous instance of chrome, we
(...skipping 29 matching lines...) Expand all
1079 std::string(), 1005 std::string(),
1080 CACHE_TYPE_OUTGOING, 1006 CACHE_TYPE_OUTGOING,
1081 CACHED_FILE_FROM_SERVER); 1007 CACHED_FILE_FROM_SERVER);
1082 1008
1083 // Get target path of symlink i.e. current path of the file in cache. 1009 // Get target path of symlink i.e. current path of the file in cache.
1084 FilePath target_path = GetCacheFilePath(resource_id, 1010 FilePath target_path = GetCacheFilePath(resource_id,
1085 md5, 1011 md5,
1086 GetSubDirectoryType(cache_entry), 1012 GetSubDirectoryType(cache_entry),
1087 CACHED_FILE_LOCALLY_MODIFIED); 1013 CACHED_FILE_LOCALLY_MODIFIED);
1088 1014
1089 // Since there's no need to move files, use |target_path| for both 1015 return CreateSymlink(target_path, symlink_path) ?
1090 // |source_path| and |dest_path|, because ModifyCacheState only moves files 1016 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 } 1017 }
1098 1018
1099 DriveFileError DriveCache::ClearDirtyOnBlockingPool( 1019 DriveFileError DriveCache::ClearDirtyOnBlockingPool(
1100 const std::string& resource_id, 1020 const std::string& resource_id,
1101 const std::string& md5) { 1021 const std::string& md5) {
1102 AssertOnSequencedWorkerPool(); 1022 AssertOnSequencedWorkerPool();
1103 1023
1104 // |md5| is the new .<md5> extension to rename the file to. 1024 // |md5| is the new .<md5> extension to rename the file to.
1105 // So, search for entry in cache without comparing md5. 1025 // So, search for entry in cache without comparing md5.
1106 DriveCacheEntry cache_entry; 1026 DriveCacheEntry cache_entry;
(...skipping 29 matching lines...) Expand all
1136 // Determine destination path. 1056 // Determine destination path.
1137 // If file is pinned, move it to persistent dir with .md5 extension; 1057 // If file is pinned, move it to persistent dir with .md5 extension;
1138 // otherwise, move it to tmp dir with .md5 extension. 1058 // otherwise, move it to tmp dir with .md5 extension.
1139 const CacheSubDirectoryType sub_dir_type = 1059 const CacheSubDirectoryType sub_dir_type =
1140 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; 1060 cache_entry.is_pinned() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1141 FilePath dest_path = GetCacheFilePath(resource_id, 1061 FilePath dest_path = GetCacheFilePath(resource_id,
1142 md5, 1062 md5,
1143 sub_dir_type, 1063 sub_dir_type,
1144 CACHED_FILE_FROM_SERVER); 1064 CACHED_FILE_FROM_SERVER);
1145 1065
1146 // Delete symlink in outgoing dir. 1066 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 1067
1152 DriveFileError error = ModifyCacheState(source_path, 1068 if (success) {
1153 dest_path, 1069 // Delete symlink in outgoing dir.
1154 FILE_OPERATION_MOVE, 1070 FilePath symlink_path = GetCacheFilePath(resource_id,
1155 symlink_path, 1071 std::string(),
1156 false /* don't create symlink */); 1072 CACHE_TYPE_OUTGOING,
1073 CACHED_FILE_FROM_SERVER);
1074 DeleteSymlink(symlink_path);
1075 }
1157 1076
1158 // If file is pinned, update symlink in pinned dir. 1077 // If file is pinned, update symlink in pinned dir.
1159 if (error == DRIVE_FILE_OK && cache_entry.is_pinned()) { 1078 if (success && cache_entry.is_pinned()) {
1160 symlink_path = GetCacheFilePath(resource_id, 1079 FilePath symlink_path = GetCacheFilePath(resource_id,
1161 std::string(), 1080 std::string(),
1162 CACHE_TYPE_PINNED, 1081 CACHE_TYPE_PINNED,
1163 CACHED_FILE_FROM_SERVER); 1082 CACHED_FILE_FROM_SERVER);
1164 1083
1165 // Since there's no moving of files here, use |dest_path| for both 1084 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 } 1085 }
1174 1086
1175 if (error == DRIVE_FILE_OK) { 1087 if (success) {
1176 // Now that file operations have completed, update cache map. 1088 // Now that file operations have completed, update metadata.
1177 cache_entry.set_md5(md5); 1089 cache_entry.set_md5(md5);
1178 cache_entry.set_is_dirty(false); 1090 cache_entry.set_is_dirty(false);
1179 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT); 1091 cache_entry.set_is_persistent(sub_dir_type == CACHE_TYPE_PERSISTENT);
1180 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 1092 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry);
1181 } 1093 }
1182 1094
1183 return error; 1095 return success ? DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED;
1184 } 1096 }
1185 1097
1186 DriveFileError DriveCache::RemoveOnBlockingPool( 1098 DriveFileError DriveCache::RemoveOnBlockingPool(
1187 const std::string& resource_id) { 1099 const std::string& resource_id) {
1188 AssertOnSequencedWorkerPool(); 1100 AssertOnSequencedWorkerPool();
1189 1101
1190 // MD5 is not passed into RemoveCacheEntry because we would delete all 1102 // MD5 is not passed into RemoveCacheEntry because we would delete all
1191 // cache files corresponding to <resource_id> regardless of the md5. 1103 // cache files corresponding to <resource_id> regardless of the md5.
1192 // So, search for entry in cache without taking md5 into account. 1104 // So, search for entry in cache without taking md5 into account.
1193 DriveCacheEntry cache_entry; 1105 DriveCacheEntry cache_entry;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 // outgoing path to |paths_to_delete|. 1143 // outgoing path to |paths_to_delete|.
1232 FilePath path_to_keep = GetCacheFilePath(resource_id, 1144 FilePath path_to_keep = GetCacheFilePath(resource_id,
1233 std::string(), 1145 std::string(),
1234 CACHE_TYPE_PERSISTENT, 1146 CACHE_TYPE_PERSISTENT,
1235 CACHED_FILE_LOCALLY_MODIFIED); 1147 CACHED_FILE_LOCALLY_MODIFIED);
1236 1148
1237 for (size_t i = 0; i < paths_to_delete.size(); ++i) { 1149 for (size_t i = 0; i < paths_to_delete.size(); ++i) {
1238 DeleteFilesSelectively(paths_to_delete[i], path_to_keep); 1150 DeleteFilesSelectively(paths_to_delete[i], path_to_keep);
1239 } 1151 }
1240 1152
1241 // Now that all file operations have completed, remove from cache map. 1153 // Now that all file operations have completed, remove from metadata.
1242 metadata_->RemoveCacheEntry(resource_id); 1154 metadata_->RemoveCacheEntry(resource_id);
1243 1155
1244 return DRIVE_FILE_OK; 1156 return DRIVE_FILE_OK;
1245 } 1157 }
1246 1158
1247 bool DriveCache::ClearAllOnBlockingPool() { 1159 bool DriveCache::ClearAllOnBlockingPool() {
1248 AssertOnSequencedWorkerPool(); 1160 AssertOnSequencedWorkerPool();
1249 1161
1250 if (!file_util::Delete(cache_root_path_, true)) { 1162 if (!file_util::Delete(cache_root_path_, true)) {
1251 LOG(WARNING) << "Failed to delete the cache directory"; 1163 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) { 1274 const DriveCacheEntry& cache_entry) {
1363 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP; 1275 return cache_entry.is_persistent() ? CACHE_TYPE_PERSISTENT : CACHE_TYPE_TMP;
1364 } 1276 }
1365 1277
1366 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { 1278 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) {
1367 delete global_free_disk_getter_for_testing; // Safe to delete NULL; 1279 delete global_free_disk_getter_for_testing; // Safe to delete NULL;
1368 global_free_disk_getter_for_testing = getter; 1280 global_free_disk_getter_for_testing = getter;
1369 } 1281 }
1370 1282
1371 } // namespace drive 1283 } // namespace drive
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1275:d14800f88434