1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_ 6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_ 7 8 #include <deque> 9 #include <map> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "base/compiler_specific.h" 14 #include "base/files/file_path.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/synchronization/lock.h" 18 #include "chrome/browser/sync_file_system/file_change.h" 19 #include "chrome/browser/sync_file_system/sync_status_code.h" 20 #include "storage/browser/fileapi/file_observers.h" 21 #include "storage/browser/fileapi/file_system_url.h" 22 23 namespace base { 24 class SequencedTaskRunner; 25 } 26 27 namespace storage { 28 class FileSystemContext; 29 class FileSystemURL; 30 } 31 32 namespace leveldb { 33 class Env; 34 class WriteBatch; 35 } 36 37 namespace sync_file_system { 38 39 // Tracks local file changes for cloud-backed file systems. 40 // All methods must be called on the file_task_runner given to the constructor. 41 // Owned by FileSystemContext. 42 class LocalFileChangeTracker : public storage::FileUpdateObserver, 43 public storage::FileChangeObserver { 44 public: 45 // |file_task_runner| must be the one where the observee file operations run. 46 // (So that we can make sure DB operations are done before actual update 47 // happens) 48 LocalFileChangeTracker(const base::FilePath& base_path, 49 leveldb::Env* env_override, 50 base::SequencedTaskRunner* file_task_runner); 51 virtual ~LocalFileChangeTracker(); 52 53 // FileUpdateObserver overrides. 54 virtual void OnStartUpdate(const storage::FileSystemURL& url) OVERRIDE; 55 virtual void OnUpdate(const storage::FileSystemURL& url, 56 int64 delta) OVERRIDE {} 57 virtual void OnEndUpdate(const storage::FileSystemURL& url) OVERRIDE; 58 59 // FileChangeObserver overrides. 60 virtual void OnCreateFile(const storage::FileSystemURL& url) OVERRIDE; 61 virtual void OnCreateFileFrom(const storage::FileSystemURL& url, 62 const storage::FileSystemURL& src) OVERRIDE; 63 virtual void OnRemoveFile(const storage::FileSystemURL& url) OVERRIDE; 64 virtual void OnModifyFile(const storage::FileSystemURL& url) OVERRIDE; 65 virtual void OnCreateDirectory(const storage::FileSystemURL& url) OVERRIDE; 66 virtual void OnRemoveDirectory(const storage::FileSystemURL& url) OVERRIDE; 67 68 // Retrieves an array of |url| which have more than one pending changes. 69 // If |max_urls| is non-zero (recommended in production code) this 70 // returns URLs up to the number from the ones that have smallest 71 // change_seq numbers (i.e. older changes). 72 void GetNextChangedURLs(std::deque<storage::FileSystemURL>* urls, 73 int max_urls); 74 75 // Returns all changes recorded for the given |url|. 76 // Note that this also returns demoted changes. 77 // This should be called after writing is disabled. 78 void GetChangesForURL(const storage::FileSystemURL& url, 79 FileChangeList* changes); 80 81 // Clears the pending changes recorded in this tracker for |url|. 82 void ClearChangesForURL(const storage::FileSystemURL& url); 83 84 // Creates a fresh (empty) in-memory record for |url|. 85 // Note that new changes are recorded to the mirror too. 86 void CreateFreshMirrorForURL(const storage::FileSystemURL& url); 87 88 // Removes a mirror for |url|, and commits the change status to database. 89 void RemoveMirrorAndCommitChangesForURL(const storage::FileSystemURL& url); 90 91 // Resets the changes to the ones recorded in mirror for |url|, and 92 // commits the updated change status to database. 93 void ResetToMirrorAndCommitChangesForURL(const storage::FileSystemURL& url); 94 95 // Re-inserts changes into the separate demoted_changes_ queue. They won't 96 // be fetched by GetNextChangedURLs() unless PromoteDemotedChanges() is 97 // called. 98 void DemoteChangesForURL(const storage::FileSystemURL& url); 99 100 // Promotes demoted changes for |url| to the normal queue. 101 void PromoteDemotedChangesForURL(const storage::FileSystemURL& url); 102 103 // Promotes all demoted changes to the normal queue. Returns true if it has 104 // promoted any changes. 105 bool PromoteDemotedChanges(); 106 107 // Called by FileSyncService at the startup time to restore last dirty changes 108 // left after the last shutdown (if any). 109 SyncStatusCode Initialize(storage::FileSystemContext* file_system_context); 110 111 // Resets all the changes recorded for the given |origin| and |type|. 112 // TODO(kinuko,nhiroki): Ideally this should be automatically called in 113 // DeleteFileSystem via QuotaUtil::DeleteOriginDataOnFileThread. 114 void ResetForFileSystem(const GURL& origin, storage::FileSystemType type); 115 116 // This method is (exceptionally) thread-safe. 117 int64 num_changes() const { 118 base::AutoLock lock(num_changes_lock_); 119 return num_changes_; 120 } 121 122 private: 123 class TrackerDB; 124 friend class CannedSyncableFileSystem; 125 friend class LocalFileChangeTrackerTest; 126 friend class LocalFileSyncContext; 127 friend class LocalFileSyncContextTest; 128 friend class SyncableFileSystemTest; 129 130 struct ChangeInfo { 131 ChangeInfo(); 132 ~ChangeInfo(); 133 FileChangeList change_list; 134 int64 change_seq; 135 }; 136 137 typedef std::map<storage::FileSystemURL, 138 ChangeInfo, 139 storage::FileSystemURL::Comparator> FileChangeMap; 140 typedef std::map<int64, storage::FileSystemURL> ChangeSeqMap; 141 142 void UpdateNumChanges(); 143 144 // This does mostly same as calling GetNextChangedURLs with max_url=0 145 // except that it returns urls in set rather than in deque. 146 // Used only in testings. 147 void GetAllChangedURLs(storage::FileSystemURLSet* urls); 148 149 // Used only in testings. 150 void DropAllChanges(); 151 152 // Database related methods. 153 SyncStatusCode MarkDirtyOnDatabase(const storage::FileSystemURL& url); 154 SyncStatusCode ClearDirtyOnDatabase(const storage::FileSystemURL& url); 155 156 SyncStatusCode CollectLastDirtyChanges( 157 storage::FileSystemContext* file_system_context); 158 void RecordChange(const storage::FileSystemURL& url, 159 const FileChange& change); 160 161 static void RecordChangeToChangeMaps(const storage::FileSystemURL& url, 162 const FileChange& change, 163 int change_seq, 164 FileChangeMap* changes, 165 ChangeSeqMap* change_seqs); 166 167 void ResetForURL(const storage::FileSystemURL& url, 168 int change_seq, 169 leveldb::WriteBatch* batch); 170 171 bool initialized_; 172 173 scoped_refptr<base::SequencedTaskRunner> file_task_runner_; 174 175 FileChangeMap changes_; 176 ChangeSeqMap change_seqs_; 177 178 FileChangeMap mirror_changes_; // For mirrors. 179 FileChangeMap demoted_changes_; // For demoted changes. 180 181 scoped_ptr<TrackerDB> tracker_db_; 182 183 // Change sequence number. Briefly gives a hint about the order of changes, 184 // but they are updated when a new change comes on the same file (as 185 // well as Drive's changestamps). 186 int64 current_change_seq_number_; 187 188 // This can be accessed on any threads (with num_changes_lock_). 189 int64 num_changes_; 190 mutable base::Lock num_changes_lock_; 191 192 DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTracker); 193 }; 194 195 } // namespace sync_file_system 196 197 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_ 198