local_file_change_tracker.h revision 116680a4aac90f2aa7413d9095a592090648e557
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
23namespace base {
24class SequencedTaskRunner;
25}
26
27namespace fileapi {
28class FileSystemContext;
29class FileSystemURL;
30}
31
32namespace leveldb {
33class Env;
34}
35
36namespace 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.
41class 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;
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 demoted changes for |url| to the normal queue.
101  void PromoteDemotedChangesForURL(const fileapi::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(fileapi::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, fileapi::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<fileapi::FileSystemURL, ChangeInfo,
138      fileapi::FileSystemURL::Comparator>
139          FileChangeMap;
140  typedef std::map<int64, fileapi::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(fileapi::FileSystemURLSet* urls);
148
149  // Used only in testings.
150  void DropAllChanges();
151
152  // Database related methods.
153  SyncStatusCode MarkDirtyOnDatabase(const fileapi::FileSystemURL& url);
154  SyncStatusCode ClearDirtyOnDatabase(const fileapi::FileSystemURL& url);
155
156  SyncStatusCode CollectLastDirtyChanges(
157      fileapi::FileSystemContext* file_system_context);
158  void RecordChange(const fileapi::FileSystemURL& url,
159                    const FileChange& change);
160
161  static void RecordChangeToChangeMaps(const fileapi::FileSystemURL& url,
162                                       const FileChange& change,
163                                       int change_seq,
164                                       FileChangeMap* changes,
165                                       ChangeSeqMap* change_seqs);
166
167  bool initialized_;
168
169  scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
170
171  FileChangeMap changes_;
172  ChangeSeqMap change_seqs_;
173
174  FileChangeMap mirror_changes_;  // For mirrors.
175  FileChangeMap demoted_changes_;  // For demoted changes.
176
177  scoped_ptr<TrackerDB> tracker_db_;
178
179  // Change sequence number. Briefly gives a hint about the order of changes,
180  // but they are updated when a new change comes on the same file (as
181  // well as Drive's changestamps).
182  int64 current_change_seq_;
183
184  // This can be accessed on any threads (with num_changes_lock_).
185  int64 num_changes_;
186  mutable base::Lock num_changes_lock_;
187
188  DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTracker);
189};
190
191}  // namespace sync_file_system
192
193#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_
194