metadata_database.h revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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 <string> 10 11#include "base/callback_forward.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/memory/scoped_vector.h" 14#include "base/memory/weak_ptr.h" 15#include "chrome/browser/sync_file_system/sync_callbacks.h" 16#include "chrome/browser/sync_file_system/sync_status_code.h" 17 18namespace base { 19class FilePath; 20class SequencedTaskRunner; 21class SingleThreadTaskRunner; 22} 23 24namespace leveldb { 25class DB; 26class WriteBatch; 27} 28 29namespace google_apis { 30class ChangeResource; 31class FileResource; 32class ResourceEntry; 33} 34 35namespace sync_file_system { 36namespace drive_backend { 37 38class ServiceMetadata; 39class DriveFileMetadata; 40struct DatabaseContents; 41 42// MetadataDatabase instance holds and maintains database and its indexes. The 43// database holds metadata of the server-side files/folders as 44// DriveFileMetadata instances. 45// The term "file" includes files, folders and other resources on Drive. 46// 47// Files have following state: 48// - Unknown file 49// - Is initial state of the files, only file_id and parent_folder_id field 50// are known. 51// - Has empty synced_details, must be active and dirty. 52// - Folder 53// - Is either one of sync-root folder, app-root folder or a regular folder. 54// - Sync-root folder holds app-root folders as its direct children, and 55// holds entire SyncFileSystem files as its descentants. Its file_id is 56// stored in ServiceMetadata. 57// - App-root folder holds all files for an application as its descendants. 58// - File 59// - Unsupported file 60// - Represents unsupported files such as hosted documents. Must be 61// inactive. 62// 63// Invariants: 64// - Any file in the database must either: 65// - be sync-root, 66// - have an app-root as its parent folder, or 67// - have an active folder as its parent. 68// That is, all files must be reachable from sync-root via app-root folders 69// and active folders. 70// 71// - Any active folder must either: 72// - have needs_folder_listing flag and dirty flag, or 73// - have all children at the stored largest change id. 74// 75class MetadataDatabase { 76 private: 77 struct FileIDComparator { 78 bool operator()(DriveFileMetadata* left, DriveFileMetadata* right) const; 79 }; 80 81 public: 82 typedef std::set<DriveFileMetadata*, FileIDComparator> FileSet; 83 typedef std::map<std::string, DriveFileMetadata*> FileByFileID; 84 typedef std::map<std::string, FileSet> FilesByParent; 85 typedef std::map<std::pair<std::string, std::string>, DriveFileMetadata*> 86 FileByParentAndTitle; 87 typedef std::map<std::string, DriveFileMetadata*> FileByAppID; 88 89 typedef base::Callback< 90 void(SyncStatusCode status, scoped_ptr<MetadataDatabase> instance)> 91 CreateCallback; 92 93 static void Create(base::SequencedTaskRunner* task_runner, 94 const base::FilePath& database_path, 95 const CreateCallback& callback); 96 ~MetadataDatabase(); 97 98 int64 GetLargestChangeID() const; 99 100 // Registers existing folder as the app-root for |app_id|. The folder 101 // must be an inactive folder that does not yet associated to any App. 102 // This method associates the folder with |app_id| and activates it. 103 void RegisterApp(const std::string& app_id, 104 const std::string& folder_id, 105 const SyncStatusCallback& callback); 106 107 // Inactivates the folder associated to the app to disable |app_id|. 108 // Does nothing if |app_id| is already disabled. 109 void DisableApp(const std::string& app_id, 110 const SyncStatusCallback& callback); 111 112 // Activates the folder associated to |app_id| to enable |app_id|. 113 // Does nothing if |app_id| is already enabled. 114 void EnableApp(const std::string& app_id, 115 const SyncStatusCallback& callback); 116 117 // Unregisters the folder as the app-root for |app_id|. If |app_id| does not 118 // exist, does nothing. The folder is left as an inactive normal folder. 119 void UnregisterApp(const std::string& app_id, 120 const SyncStatusCallback& callback); 121 122 // Finds the app-root folder for |app_id|. Returns true if exists. 123 // Copies the result to |folder| if it is non-NULL. 124 bool FindAppRootFolder(const std::string& app_id, 125 DriveFileMetadata* folder) const; 126 127 // Finds file by |file_id|. Returns true if the file was found. 128 // Copies the DriveFileMetadata instance identified by |file_id| into 129 // |file| if exists and |file| is non-NULL. 130 bool FindFileByFileID(const std::string& file_id, 131 DriveFileMetadata* file) const; 132 133 // Finds files by |title| under the folder identified by |folder_id|, and 134 // returns the number of the files. 135 // Copies the DriveFileMetadata instances to |files| if it is non-NULL. 136 size_t FindFilesByParentAndTitle( 137 const std::string& folder_id, 138 const std::string& title, 139 ScopedVector<DriveFileMetadata>* files) const; 140 141 // Finds active file by |title| under the folder identified by |folder_id|. 142 // Returns true if the file exists. 143 bool FindActiveFileByParentAndTitle( 144 const std::string& folder_id, 145 const std::string& title, 146 DriveFileMetadata* file) const; 147 148 // Finds the active file identified by |app_id| and |path|, which must be 149 // unique. Returns true if the file was found. 150 // Copies the DriveFileMetadata instance into |file| if the file is found and 151 // |file| is non-NULL. 152 // |path| must be an absolute path in |app_id|. (i.e. relative to the app-root 153 // folder.) 154 bool FindActiveFileByPath(const std::string& app_id, 155 const base::FilePath& path, 156 DriveFileMetadata* file) const; 157 158 // Looks up FilePath from FileID. Returns true on success. 159 // |path| must be non-NULL. 160 bool BuildPathForFile(const std::string& file_id, 161 base::FilePath* path) const; 162 163 // Updates database by |changes|. 164 // Marks dirty for each changed file if the file has the metadata in the 165 // database. Adds new metadata to track the file if the file doesn't have 166 // the metadata and its parent folder has the active metadata. 167 void UpdateByChangeList(ScopedVector<google_apis::ChangeResource> changes, 168 const SyncStatusCallback& callback); 169 170 // Populates |folder| with |children|. Each |children| initially has empty 171 // |synced_details| and |remote_details|. 172 void PopulateFolder(const std::string& folder_id, 173 ScopedVector<google_apis::ResourceEntry> children, 174 const SyncStatusCallback& callback); 175 176 private: 177 friend class MetadataDatabaseTest; 178 179 explicit MetadataDatabase(base::SequencedTaskRunner* task_runner); 180 static void CreateOnTaskRunner(base::SingleThreadTaskRunner* callback_runner, 181 base::SequencedTaskRunner* task_runner, 182 const base::FilePath& database_path, 183 const CreateCallback& callback); 184 static SyncStatusCode CreateForTesting( 185 scoped_ptr<leveldb::DB> db, 186 scoped_ptr<MetadataDatabase>* metadata_database_out); 187 SyncStatusCode InitializeOnTaskRunner(const base::FilePath& database_path); 188 void BuildIndexes(DatabaseContents* contents); 189 190 // Database manipulation methods. 191 void RegisterFolderAsAppRoot(const std::string& app_id, 192 const std::string& folder, 193 leveldb::WriteBatch* batch); 194 void MakeFileActive(const std::string& file_id, 195 leveldb::WriteBatch* batch); 196 void MakeFileInactive(const std::string& file_id, 197 leveldb::WriteBatch* batch); 198 void UnregisterFolderAsAppRoot(const std::string& app_id, 199 leveldb::WriteBatch* batch); 200 void RemoveFile(const std::string& file_id, 201 leveldb::WriteBatch* batch); 202 void UpdateRemoteDetails(int64 change_id, 203 const std::string& file_id, 204 const google_apis::FileResource* file, 205 leveldb::WriteBatch* batch); 206 void RegisterNewFile(int64 change_id, 207 const DriveFileMetadata& parent_folder, 208 const google_apis::FileResource& new_file, 209 leveldb::WriteBatch* batch); 210 211 void WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch, 212 const SyncStatusCallback& callback); 213 214 scoped_refptr<base::SequencedTaskRunner> task_runner_; 215 scoped_ptr<leveldb::DB> db_; 216 217 scoped_ptr<ServiceMetadata> service_metadata_; 218 FileByFileID file_by_file_id_; // Owned. 219 220 FilesByParent files_by_parent_; // Not owned. 221 FileByAppID app_root_by_app_id_; // Not owned. 222 FileByParentAndTitle active_file_by_parent_and_title_; // Not owned. 223 FileSet dirty_files_; // Not owned. 224 225 base::WeakPtrFactory<MetadataDatabase> weak_ptr_factory_; 226 227 DISALLOW_COPY_AND_ASSIGN(MetadataDatabase); 228}; 229 230} // namespace drive_backend 231} // namespace sync_file_system 232 233#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_ 234