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

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

Issue 22341005: [SyncFS] Delete old MetadataDatabase code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
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 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 5 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
6 6
7 #include <stack> 7 #include <stack>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 13 matching lines...) Expand all
24 #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_ut il.h" 24 #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_ut il.h"
25 #include "chrome/browser/sync_file_system/logger.h" 25 #include "chrome/browser/sync_file_system/logger.h"
26 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" 26 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
27 #include "third_party/leveldatabase/src/include/leveldb/db.h" 27 #include "third_party/leveldatabase/src/include/leveldb/db.h"
28 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 28 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
29 #include "webkit/common/fileapi/file_system_util.h" 29 #include "webkit/common/fileapi/file_system_util.h"
30 30
31 namespace sync_file_system { 31 namespace sync_file_system {
32 namespace drive_backend { 32 namespace drive_backend {
33 33
34 typedef MetadataDatabase::FileByAppID FileByAppID;
35 typedef MetadataDatabase::FileByFileID FileByFileID;
36 typedef MetadataDatabase::FileByParentAndTitle FileByParentAndTitle;
37 typedef MetadataDatabase::FileSet FileSet;
38 typedef MetadataDatabase::FilesByParent FilesByParent;
39
40 const char kDatabaseVersionKey[] = "VERSION"; 34 const char kDatabaseVersionKey[] = "VERSION";
41 const int64 kCurrentDatabaseVersion = 3; 35 const int64 kCurrentDatabaseVersion = 3;
42 const char kServiceMetadataKey[] = "SERVICE"; 36 const char kServiceMetadataKey[] = "SERVICE";
43 const char kFileMetadataKeyPrefix[] = "FILE: "; 37 const char kFileMetadataKeyPrefix[] = "FILE: ";
44 38
45 struct DatabaseContents { 39 struct DatabaseContents {
46 scoped_ptr<ServiceMetadata> service_metadata; 40 scoped_ptr<ServiceMetadata> service_metadata;
47 ScopedVector<DriveFileMetadata> file_metadata;
48 }; 41 };
49 42
50 namespace { 43 namespace {
51 44
52 std::string RemovePrefix(const std::string& str, const std::string& prefix) { 45 std::string RemovePrefix(const std::string& str, const std::string& prefix) {
53 if (StartsWithASCII(str, prefix, true)) 46 if (StartsWithASCII(str, prefix, true))
54 return str.substr(prefix.size()); 47 return str.substr(prefix.size());
55 return str; 48 return str;
56 } 49 }
57 50
(...skipping 12 matching lines...) Expand all
70 result.reserve(total_size); 63 result.reserve(total_size);
71 for (PathComponents::const_reverse_iterator itr = components.rbegin(); 64 for (PathComponents::const_reverse_iterator itr = components.rbegin();
72 itr != components.rend(); ++itr) { 65 itr != components.rend(); ++itr) {
73 result.append(1, base::FilePath::kSeparators[0]); 66 result.append(1, base::FilePath::kSeparators[0]);
74 result.append(itr->value()); 67 result.append(itr->value());
75 } 68 }
76 69
77 return base::FilePath(result).NormalizePathSeparators(); 70 return base::FilePath(result).NormalizePathSeparators();
78 } 71 }
79 72
80 void PopulateFileDetailsFromFileResource(
81 int64 change_id,
82 const google_apis::FileResource& file_resource,
83 DriveFileMetadata::Details* details) {
84 details->set_change_id(change_id);
85 for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
86 file_resource.parents().begin();
87 itr != file_resource.parents().end();
88 ++itr) {
89 details->add_parent_folder_id((*itr)->file_id());
90 }
91 details->set_title(file_resource.title());
92
93 google_apis::DriveEntryKind kind = file_resource.GetKind();
94 if (kind == google_apis::ENTRY_KIND_FILE)
95 details->set_kind(KIND_FILE);
96 else if (kind == google_apis::ENTRY_KIND_FOLDER)
97 details->set_kind(KIND_FOLDER);
98 else
99 details->set_kind(KIND_UNSUPPORTED);
100
101 details->set_md5(file_resource.md5_checksum());
102 details->set_etag(file_resource.etag());
103 details->set_creation_time(file_resource.created_date().ToInternalValue());
104 details->set_modification_time(
105 file_resource.modified_date().ToInternalValue());
106 details->set_deleted(false);
107 }
108
109 void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback, 73 void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback,
110 const leveldb::Status& status) { 74 const leveldb::Status& status) {
111 callback.Run(LevelDBStatusToSyncStatusCode(status)); 75 callback.Run(LevelDBStatusToSyncStatusCode(status));
112 } 76 }
113 77
114 void PutFileToBatch(const DriveFileMetadata& file, leveldb::WriteBatch* batch) {
115 std::string value;
116 bool success = file.SerializeToString(&value);
117 DCHECK(success);
118 batch->Put(kFileMetadataKeyPrefix + file.file_id(), value);
119 }
120
121 void PushChildrenToStack(const FilesByParent& files_by_parent,
122 const std::string& folder_id,
123 std::stack<std::string>* stack) {
124 FilesByParent::const_iterator found = files_by_parent.find(folder_id);
125 if (found == files_by_parent.end())
126 return;
127 const FileSet& children = found->second;
128 for (FileSet::const_iterator itr = children.begin();
129 itr != children.end(); ++itr)
130 stack->push((*itr)->file_id());
131 }
132
133 // Returns true if |db| has no content. 78 // Returns true if |db| has no content.
134 bool IsDatabaseEmpty(leveldb::DB* db) { 79 bool IsDatabaseEmpty(leveldb::DB* db) {
135 DCHECK(db); 80 DCHECK(db);
136 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions())); 81 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
137 itr->SeekToFirst(); 82 itr->SeekToFirst();
138 return !itr->Valid(); 83 return !itr->Valid();
139 } 84 }
140 85
141 SyncStatusCode OpenDatabase(const base::FilePath& path, 86 SyncStatusCode OpenDatabase(const base::FilePath& path,
142 scoped_ptr<leveldb::DB>* db_out, 87 scoped_ptr<leveldb::DB>* db_out,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 if (!service_metadata->ParseFromString(value)) { 174 if (!service_metadata->ParseFromString(value)) {
230 util::Log(logging::LOG_WARNING, FROM_HERE, 175 util::Log(logging::LOG_WARNING, FROM_HERE,
231 "Failed to parse SyncServiceMetadata"); 176 "Failed to parse SyncServiceMetadata");
232 continue; 177 continue;
233 } 178 }
234 179
235 contents->service_metadata = service_metadata.Pass(); 180 contents->service_metadata = service_metadata.Pass();
236 continue; 181 continue;
237 } 182 }
238 183
239 if (StartsWithASCII(key, kFileMetadataKeyPrefix, true)) { 184 NOTIMPLEMENTED();
240 std::string file_id = RemovePrefix(key, kFileMetadataKeyPrefix); 185 continue;
241
242 scoped_ptr<DriveFileMetadata> metadata(new DriveFileMetadata);
243 if (!metadata->ParseFromString(itr->value().ToString())) {
244 util::Log(logging::LOG_WARNING, FROM_HERE,
245 "Failed to parse a Metadata");
246 continue;
247 }
248
249 contents->file_metadata.push_back(metadata.release());
250 continue;
251 }
252 } 186 }
253 187
254 return SYNC_STATUS_OK; 188 return SYNC_STATUS_OK;
255 } 189 }
256 190
257 SyncStatusCode InitializeServiceMetadata(DatabaseContents* contents, 191 SyncStatusCode InitializeServiceMetadata(DatabaseContents* contents,
258 leveldb::WriteBatch* batch) { 192 leveldb::WriteBatch* batch) {
259 193
260 if (!contents->service_metadata) { 194 if (!contents->service_metadata) {
261 contents->service_metadata.reset(new ServiceMetadata); 195 contents->service_metadata.reset(new ServiceMetadata);
262 196
263 std::string value; 197 std::string value;
264 contents->service_metadata->SerializeToString(&value); 198 contents->service_metadata->SerializeToString(&value);
265 batch->Put(kServiceMetadataKey, value); 199 batch->Put(kServiceMetadataKey, value);
266 } 200 }
267 return SYNC_STATUS_OK; 201 return SYNC_STATUS_OK;
268 } 202 }
269 203
270 SyncStatusCode RemoveUnreachableFiles(DatabaseContents* contents, 204 SyncStatusCode RemoveUnreachableFiles(DatabaseContents* contents,
271 leveldb::WriteBatch* batch) { 205 leveldb::WriteBatch* batch) {
272 FileByFileID unvisited_files; 206 NOTIMPLEMENTED();
273 FilesByParent files_by_parent;
274
275 for (ScopedVector<DriveFileMetadata>::iterator itr =
276 contents->file_metadata.begin();
277 itr != contents->file_metadata.end();
278 ++itr) {
279 DriveFileMetadata* metadata = *itr;
280 DCHECK(!ContainsKey(unvisited_files, metadata->file_id()));
281 unvisited_files[metadata->file_id()] = metadata;
282 files_by_parent[metadata->parent_folder_id()].insert(metadata);
283 }
284
285 // Traverse synced metadata tree. Take only active items and their children.
286 // Drop unreachable items.
287 ScopedVector<DriveFileMetadata> reachable_files;
288 std::stack<std::string> pending;
289 if (!contents->service_metadata->sync_root_folder_id().empty())
290 pending.push(contents->service_metadata->sync_root_folder_id());
291
292 while (!pending.empty()) {
293 std::string file_id = pending.top();
294 pending.pop();
295
296 {
297 FileByFileID::iterator found = unvisited_files.find(file_id);
298 if (found == unvisited_files.end())
299 continue;
300
301 DriveFileMetadata* metadata = found->second;
302 unvisited_files.erase(found);
303 reachable_files.push_back(metadata);
304
305 if (!metadata->active() && !metadata->is_app_root())
306 continue;
307 }
308
309 FilesByParent::iterator found = files_by_parent.find(file_id);
310 if (found == files_by_parent.end())
311 continue;
312
313 for (FileSet::const_iterator itr = found->second.begin();
314 itr != found->second.end();
315 ++itr)
316 pending.push((*itr)->file_id());
317 }
318
319 for (FileByFileID::iterator itr = unvisited_files.begin();
320 itr != unvisited_files.end();
321 ++itr) {
322 DriveFileMetadata* metadata = itr->second;
323 batch->Delete(metadata->file_id());
324 delete metadata;
325 }
326 unvisited_files.clear();
327
328 // |reachable_files| contains all files/folders reachable from sync-root
329 // folder via active folders.
330 contents->file_metadata.weak_clear();
331 contents->file_metadata.swap(reachable_files);
332
333 return SYNC_STATUS_OK; 207 return SYNC_STATUS_OK;
334 } 208 }
335 209
336 template <typename Container, typename Key, typename Value> 210 template <typename Container, typename Key, typename Value>
337 bool FindItem(const Container& container, const Key& key, Value* value) { 211 bool FindItem(const Container& container, const Key& key, Value* value) {
338 typename Container::const_iterator found = container.find(key); 212 typename Container::const_iterator found = container.find(key);
339 if (found == container.end()) 213 if (found == container.end())
340 return false; 214 return false;
341 if (value) 215 if (value)
342 *value = *found->second; 216 *value = *found->second;
343 return true; 217 return true;
344 } 218 }
345 219
346 void RunSoon(const tracked_objects::Location& from_here, 220 void RunSoon(const tracked_objects::Location& from_here,
347 const base::Closure& closure) { 221 const base::Closure& closure) {
348 base::MessageLoopProxy::current()->PostTask(from_here, closure); 222 base::MessageLoopProxy::current()->PostTask(from_here, closure);
349 } 223 }
350 224
351 } // namespace 225 } // namespace
352 226
353 bool MetadataDatabase::FileIDComparator::operator()(
354 DriveFileMetadata* left,
355 DriveFileMetadata* right) const {
356 return left->file_id() < right->file_id();
357 }
358
359 // static 227 // static
360 void MetadataDatabase::Create(base::SequencedTaskRunner* task_runner, 228 void MetadataDatabase::Create(base::SequencedTaskRunner* task_runner,
361 const base::FilePath& database_path, 229 const base::FilePath& database_path,
362 const CreateCallback& callback) { 230 const CreateCallback& callback) {
363 task_runner->PostTask(FROM_HERE, base::Bind( 231 task_runner->PostTask(FROM_HERE, base::Bind(
364 &CreateOnTaskRunner, 232 &CreateOnTaskRunner,
365 base::MessageLoopProxy::current(), 233 base::MessageLoopProxy::current(),
366 make_scoped_refptr(task_runner), 234 make_scoped_refptr(task_runner),
367 database_path, callback)); 235 database_path, callback));
368 } 236 }
369 237
370 MetadataDatabase::~MetadataDatabase() { 238 MetadataDatabase::~MetadataDatabase() {
371 task_runner_->DeleteSoon(FROM_HERE, db_.release()); 239 task_runner_->DeleteSoon(FROM_HERE, db_.release());
372 STLDeleteContainerPairSecondPointers(
373 file_by_file_id_.begin(), file_by_file_id_.end());
374 } 240 }
375 241
376 int64 MetadataDatabase::GetLargestChangeID() const { 242 int64 MetadataDatabase::GetLargestChangeID() const {
377 return service_metadata_->largest_change_id(); 243 return service_metadata_->largest_change_id();
378 } 244 }
379 245
380 void MetadataDatabase::RegisterApp(const std::string& app_id, 246 void MetadataDatabase::RegisterApp(const std::string& app_id,
381 const std::string& folder_id, 247 const std::string& folder_id,
382 const SyncStatusCallback& callback) { 248 const SyncStatusCallback& callback) {
383 if (FindAppRootFolder(app_id, NULL)) { 249 NOTIMPLEMENTED();
384 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
385 return;
386 }
387
388 DriveFileMetadata folder;
389 if (!FindFileByFileID(folder_id, &folder)) {
390 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
391 return;
392 }
393
394 DCHECK(!folder.active());
395 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
396 RegisterFolderAsAppRoot(app_id, folder.file_id(), batch.get());
397 WriteToDatabase(batch.Pass(), callback);
398 } 250 }
399 251
400 void MetadataDatabase::DisableApp(const std::string& app_id, 252 void MetadataDatabase::DisableApp(const std::string& app_id,
401 const SyncStatusCallback& callback) { 253 const SyncStatusCallback& callback) {
402 DriveFileMetadata folder; 254 NOTIMPLEMENTED();
403 if (!FindAppRootFolder(app_id, &folder)) {
404 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
405 return;
406 }
407
408 if (!folder.active()) {
409 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
410 return;
411 }
412
413 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
414 MakeFileInactive(folder.file_id(), batch.get());
415 WriteToDatabase(batch.Pass(), callback);
416 } 255 }
417 256
418 void MetadataDatabase::EnableApp(const std::string& app_id, 257 void MetadataDatabase::EnableApp(const std::string& app_id,
419 const SyncStatusCallback& callback) { 258 const SyncStatusCallback& callback) {
420 DriveFileMetadata folder; 259 NOTIMPLEMENTED();
421 if (!FindAppRootFolder(app_id, &folder)) {
422 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
423 return;
424 }
425
426 if (folder.active()) {
427 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
428 return;
429 }
430
431 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
432 MakeFileActive(folder.file_id(), batch.get());
433 WriteToDatabase(batch.Pass(), callback);
434 } 260 }
435 261
436 void MetadataDatabase::UnregisterApp(const std::string& app_id, 262 void MetadataDatabase::UnregisterApp(const std::string& app_id,
437 const SyncStatusCallback& callback) { 263 const SyncStatusCallback& callback) {
438 DriveFileMetadata folder;
439 if (!FindAppRootFolder(app_id, &folder)) {
440 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
441 return;
442 }
443
444 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
445 UnregisterFolderAsAppRoot(app_id, batch.get());
446 WriteToDatabase(batch.Pass(), callback);
447 }
448
449 bool MetadataDatabase::FindAppRootFolder(const std::string& app_id,
450 DriveFileMetadata* folder) const {
451 return FindItem(app_root_by_app_id_, app_id, folder);
452 }
453
454 bool MetadataDatabase::FindFileByFileID(const std::string& file_id,
455 DriveFileMetadata* metadata) const {
456 return FindItem(file_by_file_id_, file_id, metadata);
457 }
458
459 size_t MetadataDatabase::FindFilesByParentAndTitle(
460 const std::string& file_id,
461 const std::string& title,
462 ScopedVector<DriveFileMetadata>* files) const {
463 NOTIMPLEMENTED(); 264 NOTIMPLEMENTED();
464 return 0;
465 }
466
467 bool MetadataDatabase::FindActiveFileByParentAndTitle(
468 const std::string& folder_id,
469 const std::string& title,
470 DriveFileMetadata* file) const {
471 return FindItem(active_file_by_parent_and_title_,
472 std::make_pair(folder_id, title),
473 file);
474 }
475
476 bool MetadataDatabase::FindActiveFileByPath(const std::string& app_id,
477 const base::FilePath& path,
478 DriveFileMetadata* file) const {
479 DriveFileMetadata current;
480 if (!FindAppRootFolder(app_id, &current))
481 return false;
482
483 std::vector<base::FilePath::StringType> components;
484 path.GetComponents(&components);
485
486 std::string parent_folder_id = current.file_id();
487 for (std::vector<base::FilePath::StringType>::iterator itr =
488 components.begin();
489 itr != components.end();
490 ++itr) {
491 std::string current_folder_id = current.file_id();
492 if (!FindActiveFileByParentAndTitle(
493 current_folder_id, base::FilePath(*itr).AsUTF8Unsafe(), &current))
494 return false;
495 }
496 if (file)
497 *file = current;
498 return true;
499 }
500
501 bool MetadataDatabase::BuildPathForFile(const std::string& file_id,
502 base::FilePath* path) const {
503 DriveFileMetadata current;
504 if (!FindFileByFileID(file_id, &current) || !current.active())
505 return false;
506
507 std::vector<base::FilePath> components;
508 while (!current.is_app_root()) {
509 components.push_back(base::FilePath::FromUTF8Unsafe(
510 current.synced_details().title()));
511 if (!FindFileByFileID(current.parent_folder_id(), &current) ||
512 !current.active())
513 return false;
514 }
515
516 if (path)
517 *path = ReverseConcatPathComponents(components);
518
519 return true;
520 } 265 }
521 266
522 void MetadataDatabase::UpdateByChangeList( 267 void MetadataDatabase::UpdateByChangeList(
523 ScopedVector<google_apis::ChangeResource> changes, 268 ScopedVector<google_apis::ChangeResource> changes,
524 const SyncStatusCallback& callback) { 269 const SyncStatusCallback& callback) {
525 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
526
527 for (ScopedVector<google_apis::ChangeResource>::iterator itr =
528 changes.begin();
529 itr != changes.end();
530 ++itr) {
531 const google_apis::ChangeResource& change = **itr;
532 DriveFileMetadata file;
533
534 // If the remote file already has an entry in the database, update its
535 // |remote_detais| and mark it dirty.
536 if (FindFileByFileID(change.file_id(), NULL)) {
537 const google_apis::FileResource* file_resource = NULL;
538 if (!change.is_deleted())
539 file_resource = change.file();
540 UpdateRemoteDetails(change.change_id(), change.file_id(), file_resource,
541 batch.get());
542 continue;
543 }
544
545 // Deletion of an unknown file can be safely ignorable.
546 if (change.is_deleted())
547 continue;
548
549 // Find first active parent.
550 std::string parent_folder_id;
551 DriveFileMetadata parent;
552 for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
553 change.file()->parents().begin();
554 itr != change.file()->parents().end();
555 ++itr) {
556 if (FindFileByFileID((*itr)->file_id(), &parent) &&
557 (parent.active() || parent.is_app_root())) {
558 parent_folder_id = parent.file_id();
559 break;
560 }
561 }
562
563 // If the remote file doesn't have active parent, ignore the file.
564 if (parent_folder_id.empty())
565 continue;
566
567 RegisterNewFile(change.change_id(), parent, *change.file(),
568 batch.get());
569 }
570
571 WriteToDatabase(batch.Pass(), callback);
572 }
573
574 void MetadataDatabase::PopulateFolder(
575 const std::string& folder_id,
576 ScopedVector<google_apis::ResourceEntry> children,
577 const SyncStatusCallback& callback) {
578 NOTIMPLEMENTED(); 270 NOTIMPLEMENTED();
579 } 271 }
580 272
581 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner) 273 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner)
582 : task_runner_(task_runner), weak_ptr_factory_(this) { 274 : task_runner_(task_runner), weak_ptr_factory_(this) {
583 DCHECK(task_runner); 275 DCHECK(task_runner);
584 } 276 }
585 277
586 // static 278 // static
587 void MetadataDatabase::CreateOnTaskRunner( 279 void MetadataDatabase::CreateOnTaskRunner(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 status = LevelDBStatusToSyncStatusCode( 347 status = LevelDBStatusToSyncStatusCode(
656 db_->Write(leveldb::WriteOptions(), &batch)); 348 db_->Write(leveldb::WriteOptions(), &batch));
657 if (status != SYNC_STATUS_OK) 349 if (status != SYNC_STATUS_OK)
658 return status; 350 return status;
659 351
660 BuildIndexes(&contents); 352 BuildIndexes(&contents);
661 return status; 353 return status;
662 } 354 }
663 355
664 void MetadataDatabase::BuildIndexes(DatabaseContents* contents) { 356 void MetadataDatabase::BuildIndexes(DatabaseContents* contents) {
665 for (ScopedVector<DriveFileMetadata>::iterator itr = 357 NOTIMPLEMENTED();
666 contents->file_metadata.begin();
667 itr != contents->file_metadata.end();
668 ++itr) {
669 DriveFileMetadata* file = *itr;
670 file_by_file_id_[file->file_id()] = file;
671
672 if (file->is_app_root())
673 app_root_by_app_id_[file->app_id()] = file;
674
675 if (file->active() && file->has_synced_details()) {
676 FileByParentAndTitle::key_type key(
677 file->parent_folder_id(), file->synced_details().title());
678 active_file_by_parent_and_title_[key] = file;
679 }
680
681 if (!file->parent_folder_id().empty())
682 files_by_parent_[file->parent_folder_id()].insert(file);
683
684 if (file->dirty())
685 dirty_files_.insert(file);
686 }
687
688 contents->file_metadata.weak_clear();
689 }
690
691 void MetadataDatabase::RegisterFolderAsAppRoot(
692 const std::string& app_id,
693 const std::string& folder_id,
694 leveldb::WriteBatch* batch) {
695 DriveFileMetadata* folder = file_by_file_id_[folder_id];
696 if (!folder || folder->active() || folder->is_app_root() ||
697 !folder->app_id().empty()) {
698 NOTREACHED();
699 return;
700 }
701
702 folder->set_is_app_root(true);
703 folder->set_app_id(app_id);
704 folder->set_active(true);
705 folder->set_dirty(true);
706 folder->set_needs_folder_listing(true);
707 PutFileToBatch(*folder, batch);
708
709 app_root_by_app_id_[app_id] = folder;
710 if (folder->has_synced_details()) {
711 FileByParentAndTitle::key_type key(
712 folder->parent_folder_id(), folder->synced_details().title());
713 DCHECK(!ContainsKey(active_file_by_parent_and_title_, key));
714 active_file_by_parent_and_title_[key] = folder;
715 }
716 dirty_files_.insert(folder);
717 }
718
719 void MetadataDatabase::UnregisterFolderAsAppRoot(
720 const std::string& app_id,
721 leveldb::WriteBatch* batch) {
722 DriveFileMetadata* folder = app_root_by_app_id_[app_id];
723 if (!folder || !folder->active() ||
724 folder->app_id() != app_id || !folder->is_app_root()) {
725 NOTREACHED();
726 return;
727 }
728
729 folder->set_active(false);
730 folder->set_is_app_root(false);
731 folder->set_app_id(std::string());
732 PutFileToBatch(*folder, batch);
733
734 // Remove child entries recursively.
735 std::stack<std::string> pending_files;
736 PushChildrenToStack(files_by_parent_, folder->file_id(), &pending_files);
737 while (!pending_files.empty()) {
738 std::string file_id = pending_files.top();
739 pending_files.pop();
740 PushChildrenToStack(files_by_parent_, file_id, &pending_files);
741 RemoveFile(file_id, batch);
742 }
743
744 app_root_by_app_id_.erase(app_id);
745 if (folder->has_synced_details()) {
746 FileByParentAndTitle::key_type key(
747 folder->parent_folder_id(), folder->synced_details().title());
748 active_file_by_parent_and_title_.erase(key);
749 }
750 }
751
752 void MetadataDatabase::MakeFileActive(const std::string& file_id,
753 leveldb::WriteBatch* batch) {
754 DriveFileMetadata* file = file_by_file_id_[file_id];
755 if (!file || file->active()) {
756 NOTREACHED();
757 return;
758 }
759
760 file->set_active(true);
761 if (file->has_synced_details() &&
762 file->synced_details().kind() == KIND_FOLDER)
763 file->set_needs_folder_listing(true);
764 PutFileToBatch(*file, batch);
765
766 if (file->has_synced_details()) {
767 FileByParentAndTitle::key_type key(
768 file->parent_folder_id(), file->synced_details().title());
769 DCHECK(!ContainsKey(active_file_by_parent_and_title_, key));
770 active_file_by_parent_and_title_[key] = file;
771 }
772 }
773
774 void MetadataDatabase::MakeFileInactive(const std::string& file_id,
775 leveldb::WriteBatch* batch) {
776 DriveFileMetadata* file = file_by_file_id_[file_id];
777 if (!file || !file->active()) {
778 NOTREACHED();
779 return;
780 }
781
782 file->set_active(false);
783 PutFileToBatch(*file, batch);
784
785 if (file->has_synced_details()) {
786 FileByParentAndTitle::key_type key(
787 file->parent_folder_id(), file->synced_details().title());
788 DCHECK(ContainsKey(active_file_by_parent_and_title_, key));
789 active_file_by_parent_and_title_.erase(key);
790 }
791 }
792
793 void MetadataDatabase::RemoveFile(const std::string& file_id,
794 leveldb::WriteBatch* batch) {
795 scoped_ptr<DriveFileMetadata> file(file_by_file_id_[file_id]);
796 file_by_file_id_.erase(file_id);
797
798 batch->Delete(file->file_id());
799
800 files_by_parent_[file->parent_folder_id()].erase(file.get());
801 if (file->is_app_root())
802 app_root_by_app_id_.erase(file->app_id());
803 if (file->active() && file->has_synced_details()) {
804 FileByParentAndTitle::key_type key(
805 file->parent_folder_id(), file->synced_details().title());
806 active_file_by_parent_and_title_.erase(key);
807 }
808 dirty_files_.erase(file.get());
809 }
810
811 void MetadataDatabase::UpdateRemoteDetails(
812 int64 change_id,
813 const std::string& file_id,
814 const google_apis::FileResource* file_resource,
815 leveldb::WriteBatch* batch) {
816 DriveFileMetadata* file = file_by_file_id_[file_id];
817
818 file->clear_remote_details();
819 DriveFileMetadata::Details* details = file->mutable_remote_details();
820 if (file_resource) {
821 PopulateFileDetailsFromFileResource(change_id, *file_resource, details);
822 } else {
823 details->set_deleted(true);
824 details->set_change_id(change_id);
825 }
826
827 file->set_dirty(true);
828 PutFileToBatch(*file, batch);
829
830 dirty_files_.insert(file);
831 }
832
833 void MetadataDatabase::RegisterNewFile(
834 int64 change_id,
835 const DriveFileMetadata& parent_folder,
836 const google_apis::FileResource& new_file_resource,
837 leveldb::WriteBatch* batch) {
838 scoped_ptr<DriveFileMetadata> file(new DriveFileMetadata);
839 std::string file_id = new_file_resource.file_id();
840 file->set_file_id(file_id);
841 file->set_parent_folder_id(parent_folder.file_id());
842 file->set_app_id(parent_folder.app_id());
843 file->set_is_app_root(false);
844
845 PopulateFileDetailsFromFileResource(
846 change_id, new_file_resource, file->mutable_remote_details());
847
848 file->set_dirty(true);
849 file->set_active(false);
850 file->set_needs_folder_listing(
851 new_file_resource.GetKind() == google_apis::ENTRY_KIND_FOLDER);
852
853 PutFileToBatch(*file, batch);
854
855 files_by_parent_[parent_folder.file_id()].insert(file.get());
856 dirty_files_.insert(file.get());
857
858 file_by_file_id_[file_id] = file.release();
859 } 358 }
860 359
861 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch, 360 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
862 const SyncStatusCallback& callback) { 361 const SyncStatusCallback& callback) {
863 base::PostTaskAndReplyWithResult( 362 base::PostTaskAndReplyWithResult(
864 task_runner_.get(), 363 task_runner_.get(),
865 FROM_HERE, 364 FROM_HERE,
866 base::Bind(&leveldb::DB::Write, 365 base::Bind(&leveldb::DB::Write,
867 base::Unretained(db_.get()), 366 base::Unretained(db_.get()),
868 leveldb::WriteOptions(), 367 leveldb::WriteOptions(),
869 base::Owned(batch.release())), 368 base::Owned(batch.release())),
870 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback)); 369 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback));
871 } 370 }
872 371
873 } // namespace drive_backend 372 } // namespace drive_backend
874 } // namespace sync_file_system 373 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698