Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/browser/sync_file_system/drive_backend/metadata_database.h

Issue 1545223002: Switch to standard integer types in chrome/browser/, part 4 of 4. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_ 5 #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_ 6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
7 7
8 #include <stddef.h>
9 #include <stdint.h>
10
8 #include <map> 11 #include <map>
9 #include <set> 12 #include <set>
10 #include <string> 13 #include <string>
11 #include <vector> 14 #include <vector>
12 15
13 #include "base/containers/hash_tables.h" 16 #include "base/containers/hash_tables.h"
14 #include "base/containers/scoped_ptr_hash_map.h" 17 #include "base/containers/scoped_ptr_hash_map.h"
15 #include "base/files/file_path.h" 18 #include "base/files/file_path.h"
19 #include "base/macros.h"
16 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/scoped_vector.h" 21 #include "base/memory/scoped_vector.h"
18 #include "base/memory/weak_ptr.h" 22 #include "base/memory/weak_ptr.h"
19 #include "base/sequence_checker.h" 23 #include "base/sequence_checker.h"
20 #include "base/values.h" 24 #include "base/values.h"
21 #include "chrome/browser/sync_file_system/drive_backend/tracker_id_set.h" 25 #include "chrome/browser/sync_file_system/drive_backend/tracker_id_set.h"
22 #include "chrome/browser/sync_file_system/sync_status_code.h" 26 #include "chrome/browser/sync_file_system/sync_status_code.h"
23 27
24 namespace leveldb { 28 namespace leveldb {
25 class Env; 29 class Env;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 SyncStatusCode* status); 135 SyncStatusCode* status);
132 static SyncStatusCode CreateForTesting( 136 static SyncStatusCode CreateForTesting(
133 scoped_ptr<LevelDBWrapper> db, 137 scoped_ptr<LevelDBWrapper> db,
134 bool enable_on_disk_index, 138 bool enable_on_disk_index,
135 scoped_ptr<MetadataDatabase>* metadata_database_out); 139 scoped_ptr<MetadataDatabase>* metadata_database_out);
136 140
137 ~MetadataDatabase(); 141 ~MetadataDatabase();
138 142
139 static void ClearDatabase(scoped_ptr<MetadataDatabase> metadata_database); 143 static void ClearDatabase(scoped_ptr<MetadataDatabase> metadata_database);
140 144
141 int64 GetLargestFetchedChangeID() const; 145 int64_t GetLargestFetchedChangeID() const;
142 int64 GetSyncRootTrackerID() const; 146 int64_t GetSyncRootTrackerID() const;
143 147
144 // Returns true if the client should check if the sync root is still valid. 148 // Returns true if the client should check if the sync root is still valid.
145 bool NeedsSyncRootRevalidation() const; 149 bool NeedsSyncRootRevalidation() const;
146 150
147 bool HasSyncRoot() const; 151 bool HasSyncRoot() const;
148 152
149 // Returns all file metadata for the given |app_id|. 153 // Returns all file metadata for the given |app_id|.
150 scoped_ptr<base::ListValue> DumpFiles(const std::string& app_id); 154 scoped_ptr<base::ListValue> DumpFiles(const std::string& app_id);
151 155
152 // Returns all database data. 156 // Returns all database data.
153 scoped_ptr<base::ListValue> DumpDatabase(); 157 scoped_ptr<base::ListValue> DumpDatabase();
154 158
155 // TODO(tzik): Move GetLargestKnownChangeID() to private section, and hide its 159 // TODO(tzik): Move GetLargestKnownChangeID() to private section, and hide its
156 // handling in the class, instead of letting user do. 160 // handling in the class, instead of letting user do.
157 // 161 //
158 // Gets / updates the largest known change ID. 162 // Gets / updates the largest known change ID.
159 // The largest known change ID is on-memory and not persist over restart. 163 // The largest known change ID is on-memory and not persist over restart.
160 // This is supposed to use when a task fetches ChangeList in parallel to other 164 // This is supposed to use when a task fetches ChangeList in parallel to other
161 // operation. When a task starts fetching paged ChangeList one by one, it 165 // operation. When a task starts fetching paged ChangeList one by one, it
162 // should update the largest known change ID on the first round and background 166 // should update the largest known change ID on the first round and background
163 // remaining fetch job. 167 // remaining fetch job.
164 // Then, when other tasks that update FileMetadata by UpdateByFileResource, 168 // Then, when other tasks that update FileMetadata by UpdateByFileResource,
165 // it should use largest known change ID as the |change_id| that prevents 169 // it should use largest known change ID as the |change_id| that prevents
166 // FileMetadata from overwritten by ChangeList. 170 // FileMetadata from overwritten by ChangeList.
167 // Also if other tasks try to update a remote resource whose change is not yet 171 // Also if other tasks try to update a remote resource whose change is not yet
168 // retrieved the task should fail due to etag check, so we should be fine. 172 // retrieved the task should fail due to etag check, so we should be fine.
169 int64 GetLargestKnownChangeID() const; 173 int64_t GetLargestKnownChangeID() const;
170 void UpdateLargestKnownChangeID(int64 change_id); 174 void UpdateLargestKnownChangeID(int64_t change_id);
171 175
172 // Populates empty database with initial data. 176 // Populates empty database with initial data.
173 // Adds a file metadata and a file tracker for |sync_root_folder|, and adds 177 // Adds a file metadata and a file tracker for |sync_root_folder|, and adds
174 // file metadata and file trackers for each |app_root_folders|. 178 // file metadata and file trackers for each |app_root_folders|.
175 // Newly added tracker for |sync_root_folder| is active and non-dirty. 179 // Newly added tracker for |sync_root_folder| is active and non-dirty.
176 // Newly added trackers for |app_root_folders| are inactive and non-dirty. 180 // Newly added trackers for |app_root_folders| are inactive and non-dirty.
177 // Trackers for |app_root_folders| are not yet registered as app-roots, but 181 // Trackers for |app_root_folders| are not yet registered as app-roots, but
178 // are ready to register. 182 // are ready to register.
179 SyncStatusCode PopulateInitialData( 183 SyncStatusCode PopulateInitialData(
180 int64 largest_change_id, 184 int64_t largest_change_id,
181 const google_apis::FileResource& sync_root_folder, 185 const google_apis::FileResource& sync_root_folder,
182 const ScopedVector<google_apis::FileResource>& app_root_folders); 186 const ScopedVector<google_apis::FileResource>& app_root_folders);
183 187
184 // Returns true if the folder associated to |app_id| is enabled. 188 // Returns true if the folder associated to |app_id| is enabled.
185 bool IsAppEnabled(const std::string& app_id) const; 189 bool IsAppEnabled(const std::string& app_id) const;
186 190
187 // Registers existing folder as the app-root for |app_id|. The folder 191 // Registers existing folder as the app-root for |app_id|. The folder
188 // must be an inactive folder that does not yet associated to any App. 192 // must be an inactive folder that does not yet associated to any App.
189 // This method associates the folder with |app_id| and activates it. 193 // This method associates the folder with |app_id| and activates it.
190 SyncStatusCode RegisterApp(const std::string& app_id, 194 SyncStatusCode RegisterApp(const std::string& app_id,
(...skipping 20 matching lines...) Expand all
211 215
212 // Finds the file identified by |file_id|. Returns true if the file is found. 216 // Finds the file identified by |file_id|. Returns true if the file is found.
213 // Copies the metadata identified by |file_id| into |file| if exists and 217 // Copies the metadata identified by |file_id| into |file| if exists and
214 // |file| is non-NULL. 218 // |file| is non-NULL.
215 bool FindFileByFileID(const std::string& file_id, FileMetadata* file) const; 219 bool FindFileByFileID(const std::string& file_id, FileMetadata* file) const;
216 220
217 // Finds the tracker identified by |tracker_id|. Returns true if the tracker 221 // Finds the tracker identified by |tracker_id|. Returns true if the tracker
218 // is found. 222 // is found.
219 // Copies the tracker identified by |tracker_id| into |tracker| if exists and 223 // Copies the tracker identified by |tracker_id| into |tracker| if exists and
220 // |tracker| is non-NULL. 224 // |tracker| is non-NULL.
221 bool FindTrackerByTrackerID(int64 tracker_id, FileTracker* tracker) const; 225 bool FindTrackerByTrackerID(int64_t tracker_id, FileTracker* tracker) const;
222 226
223 // Finds the trackers tracking |file_id|. Returns true if the trackers are 227 // Finds the trackers tracking |file_id|. Returns true if the trackers are
224 // found. 228 // found.
225 bool FindTrackersByFileID(const std::string& file_id, 229 bool FindTrackersByFileID(const std::string& file_id,
226 TrackerIDSet* trackers) const; 230 TrackerIDSet* trackers) const;
227 231
228 // Finds the set of trackers whose parent's tracker ID is |parent_tracker_id|, 232 // Finds the set of trackers whose parent's tracker ID is |parent_tracker_id|,
229 // and who has |title| as its title in the synced_details. 233 // and who has |title| as its title in the synced_details.
230 // Copies the tracker set to |trackers| if it is non-NULL. 234 // Copies the tracker set to |trackers| if it is non-NULL.
231 // Returns true if the trackers are found. 235 // Returns true if the trackers are found.
232 bool FindTrackersByParentAndTitle( 236 bool FindTrackersByParentAndTitle(int64_t parent_tracker_id,
233 int64 parent_tracker_id, 237 const std::string& title,
234 const std::string& title, 238 TrackerIDSet* trackers) const;
235 TrackerIDSet* trackers) const;
236 239
237 // Builds the file path for the given tracker. Returns true on success. 240 // Builds the file path for the given tracker. Returns true on success.
238 // |path| can be NULL. 241 // |path| can be NULL.
239 // The file path is relative to app-root and have a leading path separator. 242 // The file path is relative to app-root and have a leading path separator.
240 bool BuildPathForTracker(int64 tracker_id, base::FilePath* path) const; 243 bool BuildPathForTracker(int64_t tracker_id, base::FilePath* path) const;
241 244
242 // Builds the file path for the given tracker for display purpose. 245 // Builds the file path for the given tracker for display purpose.
243 // This may return a path ending with '<unknown>' if the given tracker does 246 // This may return a path ending with '<unknown>' if the given tracker does
244 // not have title information (yet). This may return an empty path. 247 // not have title information (yet). This may return an empty path.
245 base::FilePath BuildDisplayPathForTracker(const FileTracker& tracker) const; 248 base::FilePath BuildDisplayPathForTracker(const FileTracker& tracker) const;
246 249
247 // Returns false if no registered app exists associated to |app_id|. 250 // Returns false if no registered app exists associated to |app_id|.
248 // If |full_path| is active, assigns the tracker of |full_path| to |tracker|. 251 // If |full_path| is active, assigns the tracker of |full_path| to |tracker|.
249 // Otherwise, assigns the nearest active ancestor to |full_path| to |tracker|. 252 // Otherwise, assigns the nearest active ancestor to |full_path| to |tracker|.
250 // Also, assigns the full path of |tracker| to |path|. 253 // Also, assigns the full path of |tracker| to |path|.
251 bool FindNearestActiveAncestor(const std::string& app_id, 254 bool FindNearestActiveAncestor(const std::string& app_id,
252 const base::FilePath& full_path, 255 const base::FilePath& full_path,
253 FileTracker* tracker, 256 FileTracker* tracker,
254 base::FilePath* path) const; 257 base::FilePath* path) const;
255 258
256 // Updates database by |changes|. 259 // Updates database by |changes|.
257 // Marks each tracker for modified file as dirty and adds new trackers if 260 // Marks each tracker for modified file as dirty and adds new trackers if
258 // needed. 261 // needed.
259 SyncStatusCode UpdateByChangeList( 262 SyncStatusCode UpdateByChangeList(
260 int64 largest_change_id, 263 int64_t largest_change_id,
261 ScopedVector<google_apis::ChangeResource> changes); 264 ScopedVector<google_apis::ChangeResource> changes);
262 265
263 // Updates database by |resource|. 266 // Updates database by |resource|.
264 // Marks each tracker for modified file as dirty and adds new trackers if 267 // Marks each tracker for modified file as dirty and adds new trackers if
265 // needed. 268 // needed.
266 SyncStatusCode UpdateByFileResource( 269 SyncStatusCode UpdateByFileResource(
267 const google_apis::FileResource& resource); 270 const google_apis::FileResource& resource);
268 SyncStatusCode UpdateByFileResourceList( 271 SyncStatusCode UpdateByFileResourceList(
269 ScopedVector<google_apis::FileResource> resources); 272 ScopedVector<google_apis::FileResource> resources);
270 273
271 SyncStatusCode UpdateByDeletedRemoteFile(const std::string& file_id); 274 SyncStatusCode UpdateByDeletedRemoteFile(const std::string& file_id);
272 SyncStatusCode UpdateByDeletedRemoteFileList(const FileIDList& file_ids); 275 SyncStatusCode UpdateByDeletedRemoteFileList(const FileIDList& file_ids);
273 276
274 // Adds new FileTracker and FileMetadata. The database must not have 277 // Adds new FileTracker and FileMetadata. The database must not have
275 // |resource| beforehand. 278 // |resource| beforehand.
276 // The newly added tracker under |parent_tracker_id| is active and non-dirty. 279 // The newly added tracker under |parent_tracker_id| is active and non-dirty.
277 // Deactivates existing active tracker if exists that has the same title and 280 // Deactivates existing active tracker if exists that has the same title and
278 // parent_tracker to the newly added tracker. 281 // parent_tracker to the newly added tracker.
279 SyncStatusCode ReplaceActiveTrackerWithNewResource( 282 SyncStatusCode ReplaceActiveTrackerWithNewResource(
280 int64 parent_tracker_id, 283 int64_t parent_tracker_id,
281 const google_apis::FileResource& resource); 284 const google_apis::FileResource& resource);
282 285
283 // Adds |child_file_ids| to |folder_id| as its children. 286 // Adds |child_file_ids| to |folder_id| as its children.
284 // This method affects the active tracker only. 287 // This method affects the active tracker only.
285 // If the tracker has no further change to sync, unmarks its dirty flag. 288 // If the tracker has no further change to sync, unmarks its dirty flag.
286 SyncStatusCode PopulateFolderByChildList(const std::string& folder_id, 289 SyncStatusCode PopulateFolderByChildList(const std::string& folder_id,
287 const FileIDList& child_file_ids); 290 const FileIDList& child_file_ids);
288 291
289 // Updates |synced_details| of the tracker with |updated_details|. 292 // Updates |synced_details| of the tracker with |updated_details|.
290 SyncStatusCode UpdateTracker(int64 tracker_id, 293 SyncStatusCode UpdateTracker(int64_t tracker_id,
291 const FileDetails& updated_details); 294 const FileDetails& updated_details);
292 295
293 // Activates a tracker identified by |parent_tracker_id| and |file_id| if the 296 // Activates a tracker identified by |parent_tracker_id| and |file_id| if the
294 // tracker can be activated without inactivating other trackers that have the 297 // tracker can be activated without inactivating other trackers that have the
295 // same |file_id| but different paths. 298 // same |file_id| but different paths.
296 // If |file_id| has another active tracker, the function returns 299 // If |file_id| has another active tracker, the function returns
297 // ACTIVATION_FAILED_ANOTHER_ACTIVE_TRACKER and does not invoke |callback|. 300 // ACTIVATION_FAILED_ANOTHER_ACTIVE_TRACKER and does not invoke |callback|.
298 // If there is another active tracker that has the same path but different 301 // If there is another active tracker that has the same path but different
299 // |file_id|, inactivates the tracker. 302 // |file_id|, inactivates the tracker.
300 // In success case, returns ACTIVATION_PENDING and invokes |callback| upon 303 // In success case, returns ACTIVATION_PENDING and invokes |callback| upon
301 // completion. 304 // completion.
302 // 305 //
303 // The tracker to be activated must: 306 // The tracker to be activated must:
304 // - have a tracked metadata in the database, 307 // - have a tracked metadata in the database,
305 // - have |synced_details| with valid |title|. 308 // - have |synced_details| with valid |title|.
306 ActivationStatus TryActivateTracker(int64 parent_tracker_id, 309 ActivationStatus TryActivateTracker(int64_t parent_tracker_id,
307 const std::string& file_id, 310 const std::string& file_id,
308 SyncStatusCode* status); 311 SyncStatusCode* status);
309 312
310 // Changes the priority of the tracker to low. 313 // Changes the priority of the tracker to low.
311 void DemoteTracker(int64 tracker_id); 314 void DemoteTracker(int64_t tracker_id);
312 bool PromoteDemotedTrackers(); 315 bool PromoteDemotedTrackers();
313 void PromoteDemotedTracker(int64 tracker_id); 316 void PromoteDemotedTracker(int64_t tracker_id);
314 317
315 // Returns true if there is a normal priority dirty tracker. 318 // Returns true if there is a normal priority dirty tracker.
316 // Assigns the dirty tracker if exists and |tracker| is non-NULL. 319 // Assigns the dirty tracker if exists and |tracker| is non-NULL.
317 bool GetDirtyTracker(FileTracker* tracker) const; 320 bool GetDirtyTracker(FileTracker* tracker) const;
318 321
319 // Returns true if there is a low priority dirty tracker. 322 // Returns true if there is a low priority dirty tracker.
320 bool HasDemotedDirtyTracker() const; 323 bool HasDemotedDirtyTracker() const;
321 324
322 bool HasDirtyTracker() const; 325 bool HasDirtyTracker() const;
323 size_t CountDirtyTracker() const; 326 size_t CountDirtyTracker() const;
(...skipping 13 matching lines...) Expand all
337 340
338 private: 341 private:
339 friend class MetadataDatabaseTest; 342 friend class MetadataDatabaseTest;
340 343
341 MetadataDatabase(const base::FilePath& database_path, 344 MetadataDatabase(const base::FilePath& database_path,
342 bool enable_on_disk_index, 345 bool enable_on_disk_index,
343 leveldb::Env* env_override); 346 leveldb::Env* env_override);
344 SyncStatusCode Initialize(); 347 SyncStatusCode Initialize();
345 348
346 // Database manipulation methods. 349 // Database manipulation methods.
347 void RegisterTrackerAsAppRoot(const std::string& app_id, 350 void RegisterTrackerAsAppRoot(const std::string& app_id, int64_t tracker_id);
348 int64 tracker_id);
349 351
350 void CreateTrackerForParentAndFileID(const FileTracker& parent_tracker, 352 void CreateTrackerForParentAndFileID(const FileTracker& parent_tracker,
351 const std::string& file_id); 353 const std::string& file_id);
352 void CreateTrackerForParentAndFileMetadata(const FileTracker& parent_tracker, 354 void CreateTrackerForParentAndFileMetadata(const FileTracker& parent_tracker,
353 const FileMetadata& file_metadata, 355 const FileMetadata& file_metadata,
354 UpdateOption option); 356 UpdateOption option);
355 void CreateTrackerInternal(const FileTracker& parent_tracker, 357 void CreateTrackerInternal(const FileTracker& parent_tracker,
356 const std::string& file_id, 358 const std::string& file_id,
357 const FileDetails* details, 359 const FileDetails* details,
358 UpdateOption option); 360 UpdateOption option);
359 361
360 void MaybeAddTrackersForNewFile(const FileMetadata& file, 362 void MaybeAddTrackersForNewFile(const FileMetadata& file,
361 UpdateOption option); 363 UpdateOption option);
362 364
363 int64 IncrementTrackerID(); 365 int64_t IncrementTrackerID();
364 366
365 bool CanActivateTracker(const FileTracker& tracker); 367 bool CanActivateTracker(const FileTracker& tracker);
366 bool ShouldKeepDirty(const FileTracker& tracker) const; 368 bool ShouldKeepDirty(const FileTracker& tracker) const;
367 369
368 bool HasDisabledAppRoot(const FileTracker& tracker) const; 370 bool HasDisabledAppRoot(const FileTracker& tracker) const;
369 bool HasActiveTrackerForFileID(const std::string& file_id) const; 371 bool HasActiveTrackerForFileID(const std::string& file_id) const;
370 bool HasActiveTrackerForPath(int64 parent_tracker, 372 bool HasActiveTrackerForPath(int64_t parent_tracker,
371 const std::string& title) const; 373 const std::string& title) const;
372 374
373 void RemoveUnneededTrackersForMissingFile(const std::string& file_id); 375 void RemoveUnneededTrackersForMissingFile(const std::string& file_id);
374 void UpdateByFileMetadata(const tracked_objects::Location& from_where, 376 void UpdateByFileMetadata(const tracked_objects::Location& from_where,
375 scoped_ptr<FileMetadata> file, 377 scoped_ptr<FileMetadata> file,
376 UpdateOption option); 378 UpdateOption option);
377 379
378 SyncStatusCode WriteToDatabase(); 380 SyncStatusCode WriteToDatabase();
379 381
380 bool HasNewerFileMetadata(const std::string& file_id, int64 change_id); 382 bool HasNewerFileMetadata(const std::string& file_id, int64_t change_id);
381 383
382 scoped_ptr<base::ListValue> DumpTrackers(); 384 scoped_ptr<base::ListValue> DumpTrackers();
383 scoped_ptr<base::ListValue> DumpMetadata(); 385 scoped_ptr<base::ListValue> DumpMetadata();
384 386
385 void AttachSyncRoot(const google_apis::FileResource& sync_root_folder); 387 void AttachSyncRoot(const google_apis::FileResource& sync_root_folder);
386 void AttachInitialAppRoot(const google_apis::FileResource& app_root_folder); 388 void AttachInitialAppRoot(const google_apis::FileResource& app_root_folder);
387 389
388 void ForceActivateTrackerByPath(int64 parent_tracker_id, 390 void ForceActivateTrackerByPath(int64_t parent_tracker_id,
389 const std::string& title, 391 const std::string& title,
390 const std::string& file_id); 392 const std::string& file_id);
391 393
392 bool CanClearDirty(const FileTracker& tracker); 394 bool CanClearDirty(const FileTracker& tracker);
393 395
394 base::FilePath database_path_; 396 base::FilePath database_path_;
395 leveldb::Env* env_override_; 397 leveldb::Env* env_override_;
396 scoped_ptr<LevelDBWrapper> db_; 398 scoped_ptr<LevelDBWrapper> db_;
397 399
398 bool enable_on_disk_index_; 400 bool enable_on_disk_index_;
399 401
400 int64 largest_known_change_id_; 402 int64_t largest_known_change_id_;
401 403
402 scoped_ptr<MetadataDatabaseIndexInterface> index_; 404 scoped_ptr<MetadataDatabaseIndexInterface> index_;
403 405
404 base::WeakPtrFactory<MetadataDatabase> weak_ptr_factory_; 406 base::WeakPtrFactory<MetadataDatabase> weak_ptr_factory_;
405 407
406 DISALLOW_COPY_AND_ASSIGN(MetadataDatabase); 408 DISALLOW_COPY_AND_ASSIGN(MetadataDatabase);
407 }; 409 };
408 410
409 } // namespace drive_backend 411 } // namespace drive_backend
410 } // namespace sync_file_system 412 } // namespace sync_file_system
411 413
412 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_ 414 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_METADATA_DATABASE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698