metadata_database.h revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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_DRIVE_BACKEND_METADATA_DATABASE_H_
6#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
7
8#include <map>
9#include <set>
10#include <string>
11
12#include "base/callback_forward.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/scoped_vector.h"
15#include "base/memory/weak_ptr.h"
16#include "chrome/browser/sync_file_system/drive_backend/tracker_set.h"
17#include "chrome/browser/sync_file_system/sync_callbacks.h"
18#include "chrome/browser/sync_file_system/sync_status_code.h"
19
20namespace base {
21class FilePath;
22class SequencedTaskRunner;
23class SingleThreadTaskRunner;
24}
25
26namespace leveldb {
27class DB;
28class WriteBatch;
29}
30
31namespace google_apis {
32class ChangeResource;
33class FileResource;
34class ResourceEntry;
35}
36
37namespace sync_file_system {
38namespace drive_backend {
39
40class FileMetadata;
41class FileTracker;
42class ServiceMetadata;
43struct DatabaseContents;
44
45// MetadataDatabase instance holds and maintains database and its indexes.  The
46// database holds metadata of the server-side files/folders as
47// DriveFileMetadata instances.
48// The term "file" includes files, folders and other resources on Drive.
49//
50// Files have following state:
51//   - Unknown file
52//     - Is initial state of the files, only file_id and parent_folder_id field
53//       are known.
54//     - Has empty synced_details, must be active and dirty.
55//   - Folder
56//     - Is either one of sync-root folder, app-root folder or a regular folder.
57//     - Sync-root folder holds app-root folders as its direct children, and
58//       holds entire SyncFileSystem files as its descentants.  Its file_id is
59//       stored in ServiceMetadata.
60//     - App-root folder holds all files for an application as its descendants.
61//   - File
62//   - Unsupported file
63//     - Represents unsupported files such as hosted documents. Must be
64//       inactive.
65//
66// Invariants:
67//   - Any file in the database must either:
68//     - be sync-root,
69//     - have an app-root as its parent folder, or
70//     - have an active folder as its parent.
71//   That is, all files must be reachable from sync-root via app-root folders
72//   and active folders.
73//
74//   - Any active folder must either:
75//     - have needs_folder_listing flag and dirty flag, or
76//     - have all children at the stored largest change id.
77//
78class MetadataDatabase {
79 public:
80  typedef std::map<std::string, FileMetadata*> FileByID;
81  typedef std::map<int64, FileTracker*> TrackerByID;
82  typedef std::map<std::string, TrackerSet> TrackersByFileID;
83  typedef std::map<std::string, TrackerSet> TrackersByTitle;
84  typedef std::map<int64, TrackersByTitle> TrackersByParentAndTitle;
85  typedef std::map<std::string, FileTracker*> TrackerByAppID;
86
87  typedef base::Callback<
88      void(SyncStatusCode status, scoped_ptr<MetadataDatabase> instance)>
89      CreateCallback;
90
91  static void Create(base::SequencedTaskRunner* task_runner,
92                     const base::FilePath& database_path,
93                     const CreateCallback& callback);
94  ~MetadataDatabase();
95
96  int64 GetLargestChangeID() const;
97
98  // Registers existing folder as the app-root for |app_id|.  The folder
99  // must be an inactive folder that does not yet associated to any App.
100  // This method associates the folder with |app_id| and activates it.
101  void RegisterApp(const std::string& app_id,
102                   const std::string& folder_id,
103                   const SyncStatusCallback& callback);
104
105  // Inactivates the folder associated to the app to disable |app_id|.
106  // Does nothing if |app_id| is already disabled.
107  void DisableApp(const std::string& app_id,
108                  const SyncStatusCallback& callback);
109
110  // Activates the folder associated to |app_id| to enable |app_id|.
111  // Does nothing if |app_id| is already enabled.
112  void EnableApp(const std::string& app_id,
113                 const SyncStatusCallback& callback);
114
115  // Unregisters the folder as the app-root for |app_id|.  If |app_id| does not
116  // exist, does nothing.  The folder is left as an inactive normal folder.
117  void UnregisterApp(const std::string& app_id,
118                     const SyncStatusCallback& callback);
119
120  // Updates database by |changes|.
121  // Marks dirty for each changed file if the file has the metadata in the
122  // database.  Adds new metadata to track the file if the file doesn't have
123  // the metadata and its parent folder has the active metadata.
124  void UpdateByChangeList(ScopedVector<google_apis::ChangeResource> changes,
125                          const SyncStatusCallback& callback);
126
127 private:
128  struct DirtyTrackerComparator {
129    bool operator()(const FileTracker* left,
130                    const FileTracker* right) const;
131  };
132
133  typedef std::set<FileTracker*, DirtyTrackerComparator> DirtyTrackers;
134
135  friend class MetadataDatabaseTest;
136
137  explicit MetadataDatabase(base::SequencedTaskRunner* task_runner);
138  static void CreateOnTaskRunner(base::SingleThreadTaskRunner* callback_runner,
139                                 base::SequencedTaskRunner* task_runner,
140                                 const base::FilePath& database_path,
141                                 const CreateCallback& callback);
142  static SyncStatusCode CreateForTesting(
143      scoped_ptr<leveldb::DB> db,
144      scoped_ptr<MetadataDatabase>* metadata_database_out);
145  SyncStatusCode InitializeOnTaskRunner(const base::FilePath& database_path);
146  void BuildIndexes(DatabaseContents* contents);
147
148  void WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
149                       const SyncStatusCallback& callback);
150
151  scoped_refptr<base::SequencedTaskRunner> task_runner_;
152  scoped_ptr<leveldb::DB> db_;
153
154  scoped_ptr<ServiceMetadata> service_metadata_;
155
156  FileByID file_by_id_;  // Owned.
157  TrackerByID tracker_by_id_;  // Owned.
158
159  // Maps FileID to trackers.  The active tracker must be unique per FileID.
160  // This must be updated when updating |active| field of a tracker.
161  TrackersByFileID trackers_by_file_id_;  // Not owned.
162
163  // Maps AppID to the app-root tracker.
164  // This must be updated when a tracker is registered/unregistered as an
165  // app-root.
166  TrackerByAppID app_root_by_app_id_;  // Not owned.
167
168  // Maps |tracker_id| to its children grouped by their |title|.
169  // If the title is unknown for a tracker, treats its title as empty. Empty
170  // titled file must not be active.
171  // The active tracker must be unique per its parent_tracker and its title.
172  // This must be updated when updating |title|, |active| or
173  // |parent_tracker_id|.
174  TrackersByParentAndTitle trackers_by_parent_and_title_;
175
176  // Holds all trackers which marked as dirty.
177  // This must be updated when updating |dirty| field of a tracker.
178  DirtyTrackers dirty_trackers_;  // Not owned.
179
180  base::WeakPtrFactory<MetadataDatabase> weak_ptr_factory_;
181
182  DISALLOW_COPY_AND_ASSIGN(MetadataDatabase);
183};
184
185}  // namespace drive_backend
186}  // namespace sync_file_system
187
188#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
189