190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_
62385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#define CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/file_change.h"
192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_observers.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_url.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedTaskRunner;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace fileapi {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FileSystemContext;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FileSystemURL;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tracks local file changes for cloud-backed file systems.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All methods must be called on the file_task_runner given to the constructor.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Owned by FileSystemContext.
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochclass LocalFileChangeTracker
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public fileapi::FileUpdateObserver,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public fileapi::FileChangeObserver {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |file_task_runner| must be the one where the observee file operations run.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (So that we can make sure DB operations are done before actual update
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // happens)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocalFileChangeTracker(const base::FilePath& base_path,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         base::SequencedTaskRunner* file_task_runner);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~LocalFileChangeTracker();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FileUpdateObserver overrides.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnStartUpdate(const fileapi::FileSystemURL& url) OVERRIDE;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnUpdate(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const fileapi::FileSystemURL& url, int64 delta) OVERRIDE {}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnEndUpdate(const fileapi::FileSystemURL& url) OVERRIDE;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FileChangeObserver overrides.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCreateFile(const fileapi::FileSystemURL& url) OVERRIDE;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCreateFileFrom(const fileapi::FileSystemURL& url,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const fileapi::FileSystemURL& src) OVERRIDE;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnRemoveFile(const fileapi::FileSystemURL& url) OVERRIDE;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnModifyFile(const fileapi::FileSystemURL& url) OVERRIDE;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCreateDirectory(const fileapi::FileSystemURL& url) OVERRIDE;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnRemoveDirectory(const fileapi::FileSystemURL& url) OVERRIDE;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieves an array of |url| which have more than one pending changes.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |max_urls| is non-zero (recommended in production code) this
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns URLs up to the number from the ones that have smallest
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change_seq numbers (i.e. older changes).
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetNextChangedURLs(std::deque<fileapi::FileSystemURL>* urls,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          int max_urls);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns all changes recorded for the given |url|.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should be called after writing is disabled.
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetChangesForURL(const fileapi::FileSystemURL& url,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        FileChangeList* changes);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clears the pending changes recorded in this tracker for |url|.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ClearChangesForURL(const fileapi::FileSystemURL& url);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Creates a fresh (empty) in-memory record for |url|.
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Note that new changes are recorded to the mirror too.
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void CreateFreshMirrorForURL(const fileapi::FileSystemURL& url);
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Removes a mirror for |url|, and commits the change status to database.
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void RemoveMirrorAndCommitChangesForURL(const fileapi::FileSystemURL& url);
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Resets the changes to the ones recorded in mirror for |url|, and
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // commits the updated change status to database.
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void ResetToMirrorAndCommitChangesForURL(const fileapi::FileSystemURL& url);
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
89d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Re-insert changes for the file with newer (bigger) sequence numbers,
90d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // so that they won't be fetched by GetChangesForURL() soon. This could be
91d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // useful for changes that have been failed to apply but would need to be
92d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // retried again later.
93d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  void DemoteChangesForURL(const fileapi::FileSystemURL& url);
94d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by FileSyncService at the startup time to restore last dirty changes
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left after the last shutdown (if any).
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode Initialize(fileapi::FileSystemContext* file_system_context);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Resets all the changes recorded for the given |origin| and |type|.
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(kinuko,nhiroki): Ideally this should be automatically called in
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // DeleteFileSystem via QuotaUtil::DeleteOriginDataOnFileThread.
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void ResetForFileSystem(const GURL& origin, fileapi::FileSystemType type);
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method is (exceptionally) thread-safe.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 num_changes() const {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(num_changes_lock_);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return num_changes_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class TrackerDB;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class CannedSyncableFileSystem;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class LocalFileChangeTrackerTest;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class LocalFileSyncContext;
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  friend class LocalFileSyncContextTest;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class SyncableFileSystemTest;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ChangeInfo {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeInfo();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~ChangeInfo();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileChangeList change_list;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 change_seq;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<fileapi::FileSystemURL, ChangeInfo,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fileapi::FileSystemURL::Comparator>
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FileChangeMap;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<int64, fileapi::FileSystemURL> ChangeSeqMap;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void UpdateNumChanges();
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This does mostly same as calling GetNextChangedURLs with max_url=0
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // except that it returns urls in set rather than in deque.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used only in testings.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetAllChangedURLs(fileapi::FileSystemURLSet* urls);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used only in testings.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DropAllChanges();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Database related methods.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode MarkDirtyOnDatabase(const fileapi::FileSystemURL& url);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode ClearDirtyOnDatabase(const fileapi::FileSystemURL& url);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncStatusCode CollectLastDirtyChanges(
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fileapi::FileSystemContext* file_system_context);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RecordChange(const fileapi::FileSystemURL& url,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const FileChange& change);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static void RecordChangeToChangeMaps(const fileapi::FileSystemURL& url,
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       const FileChange& change,
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       int change_seq,
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       FileChangeMap* changes,
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       ChangeSeqMap* change_seqs);
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialized_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileChangeMap changes_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeSeqMap change_seqs_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // For mirrors.
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileChangeMap mirror_changes_;
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TrackerDB> tracker_db_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change sequence number. Briefly gives a hint about the order of changes,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but they are updated when a new change comes on the same file (as
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // well as Drive's changestamps).
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 current_change_seq_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can be accessed on any threads (with num_changes_lock_).
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 num_changes_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock num_changes_lock_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTracker);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_CHANGE_TRACKER_H_
182