• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkit/browser/fileapi/file_observers.h"
21 #include "webkit/browser/fileapi/file_system_url.h"
22 
23 namespace base {
24 class SequencedTaskRunner;
25 }
26 
27 namespace fileapi {
28 class FileSystemContext;
29 class FileSystemURL;
30 }
31 
32 namespace leveldb {
33 class Env;
34 }
35 
36 namespace sync_file_system {
37 
38 // Tracks local file changes for cloud-backed file systems.
39 // All methods must be called on the file_task_runner given to the constructor.
40 // Owned by FileSystemContext.
41 class LocalFileChangeTracker
42     : public fileapi::FileUpdateObserver,
43       public fileapi::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 fileapi::FileSystemURL& url) OVERRIDE;
OnUpdate(const fileapi::FileSystemURL & url,int64 delta)55   virtual void OnUpdate(
56       const fileapi::FileSystemURL& url, int64 delta) OVERRIDE {}
57   virtual void OnEndUpdate(const fileapi::FileSystemURL& url) OVERRIDE;
58 
59   // FileChangeObserver overrides.
60   virtual void OnCreateFile(const fileapi::FileSystemURL& url) OVERRIDE;
61   virtual void OnCreateFileFrom(const fileapi::FileSystemURL& url,
62                                 const fileapi::FileSystemURL& src) OVERRIDE;
63   virtual void OnRemoveFile(const fileapi::FileSystemURL& url) OVERRIDE;
64   virtual void OnModifyFile(const fileapi::FileSystemURL& url) OVERRIDE;
65   virtual void OnCreateDirectory(const fileapi::FileSystemURL& url) OVERRIDE;
66   virtual void OnRemoveDirectory(const fileapi::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<fileapi::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 fileapi::FileSystemURL& url,
79                         FileChangeList* changes);
80 
81   // Clears the pending changes recorded in this tracker for |url|.
82   void ClearChangesForURL(const fileapi::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 fileapi::FileSystemURL& url);
87 
88   // Removes a mirror for |url|, and commits the change status to database.
89   void RemoveMirrorAndCommitChangesForURL(const fileapi::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 fileapi::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 fileapi::FileSystemURL& url);
99 
100   // Promotes all demoted changes to the normal queue. Returns true if it has
101   // promoted any changes.
102   bool PromoteDemotedChanges();
103 
104   // Called by FileSyncService at the startup time to restore last dirty changes
105   // left after the last shutdown (if any).
106   SyncStatusCode Initialize(fileapi::FileSystemContext* file_system_context);
107 
108   // Resets all the changes recorded for the given |origin| and |type|.
109   // TODO(kinuko,nhiroki): Ideally this should be automatically called in
110   // DeleteFileSystem via QuotaUtil::DeleteOriginDataOnFileThread.
111   void ResetForFileSystem(const GURL& origin, fileapi::FileSystemType type);
112 
113   // This method is (exceptionally) thread-safe.
num_changes()114   int64 num_changes() const {
115     base::AutoLock lock(num_changes_lock_);
116     return num_changes_;
117   }
118 
119  private:
120   class TrackerDB;
121   friend class CannedSyncableFileSystem;
122   friend class LocalFileChangeTrackerTest;
123   friend class LocalFileSyncContext;
124   friend class LocalFileSyncContextTest;
125   friend class SyncableFileSystemTest;
126 
127   struct ChangeInfo {
128     ChangeInfo();
129     ~ChangeInfo();
130     FileChangeList change_list;
131     int64 change_seq;
132   };
133 
134   typedef std::map<fileapi::FileSystemURL, ChangeInfo,
135       fileapi::FileSystemURL::Comparator>
136           FileChangeMap;
137   typedef std::map<int64, fileapi::FileSystemURL> ChangeSeqMap;
138 
139   void UpdateNumChanges();
140 
141   // This does mostly same as calling GetNextChangedURLs with max_url=0
142   // except that it returns urls in set rather than in deque.
143   // Used only in testings.
144   void GetAllChangedURLs(fileapi::FileSystemURLSet* urls);
145 
146   // Used only in testings.
147   void DropAllChanges();
148 
149   // Database related methods.
150   SyncStatusCode MarkDirtyOnDatabase(const fileapi::FileSystemURL& url);
151   SyncStatusCode ClearDirtyOnDatabase(const fileapi::FileSystemURL& url);
152 
153   SyncStatusCode CollectLastDirtyChanges(
154       fileapi::FileSystemContext* file_system_context);
155   void RecordChange(const fileapi::FileSystemURL& url,
156                     const FileChange& change);
157 
158   static void RecordChangeToChangeMaps(const fileapi::FileSystemURL& url,
159                                        const FileChange& change,
160                                        int change_seq,
161                                        FileChangeMap* changes,
162                                        ChangeSeqMap* change_seqs);
163 
164   bool initialized_;
165 
166   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
167 
168   FileChangeMap changes_;
169   ChangeSeqMap change_seqs_;
170 
171   FileChangeMap mirror_changes_;  // For mirrors.
172   FileChangeMap demoted_changes_;  // For demoted changes.
173 
174   scoped_ptr<TrackerDB> tracker_db_;
175 
176   // Change sequence number. Briefly gives a hint about the order of changes,
177   // but they are updated when a new change comes on the same file (as
178   // well as Drive's changestamps).
179   int64 current_change_seq_;
180 
181   // This can be accessed on any threads (with num_changes_lock_).
182   int64 num_changes_;
183   mutable base::Lock num_changes_lock_;
184 
185   DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTracker);
186 };
187 
188 }  // namespace sync_file_system
189 
190 #endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_
191