Home | History | Annotate | Download | only in local
      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