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.
5 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/task_runner_util.h"
20 #include "base/values.h"
21 #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
22 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
23 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util.h"
24 #include "chrome/browser/sync_file_system/logger.h"
25 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
26 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
27 #include "third_party/leveldatabase/src/include/leveldb/db.h"
28 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
30 #include "webkit/browser/fileapi/file_system_url.h"
31 #include "webkit/common/fileapi/file_system_util.h"
33 using fileapi::FileSystemURL;
35 namespace sync_file_system {
37 typedef DriveMetadataStore::MetadataMap MetadataMap;
38 typedef DriveMetadataStore::OriginByResourceId OriginByResourceId;
39 typedef DriveMetadataStore::PathToMetadata PathToMetadata;
40 typedef DriveMetadataStore::ResourceIdByOrigin ResourceIdByOrigin;
42 const base::FilePath::CharType DriveMetadataStore::kDatabaseName[] =
43 FILE_PATH_LITERAL("DriveMetadata");
46 SyncStatusCode status;
47 scoped_ptr<leveldb::DB> db;
50 int64 largest_changestamp;
51 DriveMetadataStore::MetadataMap metadata_map;
52 std::string sync_root_directory_resource_id;
53 ResourceIdByOrigin incremental_sync_origins;
54 ResourceIdByOrigin disabled_origins;
57 : status(SYNC_STATUS_UNKNOWN),
59 largest_changestamp(0) {
65 const char kDatabaseVersionKey[] = "VERSION";
66 const int64 kCurrentDatabaseVersion = 2;
67 const char kChangeStampKey[] = "CHANGE_STAMP";
68 const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
69 const char kDriveMetadataKeyPrefix[] = "METADATA: ";
70 const char kMetadataKeySeparator = ' ';
71 const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
72 const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
75 INCREMENTAL_SYNC_ORIGIN,
79 std::string RemovePrefix(const std::string& str, const std::string& prefix) {
80 if (StartsWithASCII(str, prefix, true))
81 return str.substr(prefix.size());
85 std::string OriginAndPathToMetadataKey(const GURL& origin,
86 const base::FilePath& path) {
87 return kDriveMetadataKeyPrefix + origin.spec() +
88 kMetadataKeySeparator + path.AsUTF8Unsafe();
91 std::string FileSystemURLToMetadataKey(const FileSystemURL& url) {
92 return OriginAndPathToMetadataKey(url.origin(), url.path());
95 void MetadataKeyToOriginAndPath(const std::string& metadata_key,
97 base::FilePath* path) {
98 std::string key_body(RemovePrefix(metadata_key, kDriveMetadataKeyPrefix));
99 size_t separator_position = key_body.find(kMetadataKeySeparator);
100 *origin = GURL(key_body.substr(0, separator_position));
101 *path = base::FilePath::FromUTF8Unsafe(
102 key_body.substr(separator_position + 1));
105 bool UpdateResourceIdMap(ResourceIdByOrigin* map,
106 OriginByResourceId* reverse_map,
108 const std::string& resource_id) {
109 ResourceIdByOrigin::iterator found = map->find(origin);
110 if (found == map->end())
112 reverse_map->erase(found->second);
113 reverse_map->insert(std::make_pair(resource_id, origin));
115 found->second = resource_id;
119 ////////////////////////////////////////////////////////////////////////////////
121 bool IsDBEmpty(leveldb::DB* db) {
123 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
125 return !itr->Valid();
128 scoped_ptr<leveldb::DB> OpenDatabase(const base::FilePath& path,
129 SyncStatusCode* status,
134 leveldb::Options options;
135 options.max_open_files = 0; // Use minimum.
136 options.create_if_missing = true;
137 leveldb::DB* db = NULL;
138 leveldb::Status db_status = leveldb::DB::Open(
139 options, path.AsUTF8Unsafe(), &db);
140 if (db_status.ok()) {
141 *created = IsDBEmpty(db);
146 *status = LevelDBStatusToSyncStatusCode(db_status);
148 return make_scoped_ptr(db);
151 SyncStatusCode WriteInitialData(leveldb::DB* db) {
153 return LevelDBStatusToSyncStatusCode(db->Put(
154 leveldb::WriteOptions(),
156 base::Int64ToString(kCurrentDatabaseVersion)));
159 SyncStatusCode MigrateDatabaseIfNeeded(leveldb::DB* db) {
162 leveldb::Status status = db->Get(leveldb::ReadOptions(),
163 kDatabaseVersionKey, &value);
166 if (!base::StringToInt64(value, &version))
167 return SYNC_DATABASE_ERROR_FAILED;
169 if (!status.IsNotFound())
170 return SYNC_DATABASE_ERROR_FAILED;
175 drive_backend::MigrateDatabaseFromV0ToV1(db);
178 drive_backend::MigrateDatabaseFromV1ToV2(db);
181 DCHECK_EQ(2, kCurrentDatabaseVersion);
182 return SYNC_STATUS_OK;
184 return SYNC_DATABASE_ERROR_FAILED;
188 SyncStatusCode ReadContents(DBContents* contents) {
190 DCHECK(contents->db);
192 contents->largest_changestamp = 0;
193 contents->metadata_map.clear();
194 contents->incremental_sync_origins.clear();
196 scoped_ptr<leveldb::Iterator> itr(
197 contents->db->NewIterator(leveldb::ReadOptions()));
198 for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
199 std::string key = itr->key().ToString();
200 if (key == kChangeStampKey) {
201 bool success = base::StringToInt64(itr->value().ToString(),
202 &contents->largest_changestamp);
207 if (key == kSyncRootDirectoryKey) {
208 std::string resource_id = itr->value().ToString();
209 if (IsDriveAPIDisabled())
210 resource_id = drive_backend::AddWapiFolderPrefix(resource_id);
211 contents->sync_root_directory_resource_id = resource_id;
215 if (StartsWithASCII(key, kDriveMetadataKeyPrefix, true)) {
218 MetadataKeyToOriginAndPath(key, &origin, &path);
220 DriveMetadata metadata;
221 bool success = metadata.ParseFromString(itr->value().ToString());
224 if (IsDriveAPIDisabled()) {
225 metadata.set_resource_id(drive_backend::AddWapiIdPrefix(
226 metadata.resource_id(), metadata.type()));
229 success = contents->metadata_map[origin].insert(
230 std::make_pair(path, metadata)).second;
235 if (StartsWithASCII(key, kDriveIncrementalSyncOriginKeyPrefix, true)) {
236 GURL origin(RemovePrefix(key, kDriveIncrementalSyncOriginKeyPrefix));
237 DCHECK(origin.is_valid());
239 std::string origin_resource_id = IsDriveAPIDisabled()
240 ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
241 : itr->value().ToString();
243 DCHECK(!ContainsKey(contents->incremental_sync_origins, origin));
244 contents->incremental_sync_origins[origin] = origin_resource_id;
248 if (StartsWithASCII(key, kDriveDisabledOriginKeyPrefix, true)) {
249 GURL origin(RemovePrefix(key, kDriveDisabledOriginKeyPrefix));
250 DCHECK(origin.is_valid());
252 std::string origin_resource_id = IsDriveAPIDisabled()
253 ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
254 : itr->value().ToString();
256 DCHECK(!ContainsKey(contents->disabled_origins, origin));
257 contents->disabled_origins[origin] = origin_resource_id;
262 return SYNC_STATUS_OK;
265 scoped_ptr<DBContents> LoadDBContents(const base::FilePath& db_path) {
266 scoped_ptr<DBContents> contents(new DBContents);
267 contents->db = OpenDatabase(db_path,
270 if (contents->status != SYNC_STATUS_OK)
271 return contents.Pass();
273 if (contents->created) {
274 contents->status = WriteInitialData(contents->db.get());
275 if (contents->status != SYNC_STATUS_OK)
276 return contents.Pass();
278 contents->status = MigrateDatabaseIfNeeded(contents->db.get());
279 if (contents->status != SYNC_STATUS_OK)
280 return contents.Pass();
283 contents->status = ReadContents(contents.get());
284 return contents.Pass();
287 ////////////////////////////////////////////////////////////////////////////////
289 // Returns a key string for the given origin.
290 // For example, when |origin| is "http://www.example.com" and |sync_type| is
291 // BATCH_SYNC_ORIGIN, returns "BSYNC_ORIGIN: http://www.example.com".
292 std::string CreateKeyForOriginRoot(const GURL& origin,
293 OriginSyncType sync_type) {
294 DCHECK(origin.is_valid());
296 case INCREMENTAL_SYNC_ORIGIN:
297 return kDriveIncrementalSyncOriginKeyPrefix + origin.spec();
298 case DISABLED_ORIGIN:
299 return kDriveDisabledOriginKeyPrefix + origin.spec();
302 return std::string();
305 void AddOriginsToVector(std::vector<GURL>* all_origins,
306 const ResourceIdByOrigin& resource_map) {
307 for (ResourceIdByOrigin::const_iterator itr = resource_map.begin();
308 itr != resource_map.end();
310 all_origins->push_back(itr->first);
314 void InsertReverseMap(const ResourceIdByOrigin& forward_map,
315 OriginByResourceId* backward_map) {
316 for (ResourceIdByOrigin::const_iterator itr = forward_map.begin();
317 itr != forward_map.end(); ++itr)
318 backward_map->insert(std::make_pair(itr->second, itr->first));
321 bool EraseIfExists(ResourceIdByOrigin* map,
323 std::string* resource_id) {
324 ResourceIdByOrigin::iterator found = map->find(origin);
325 if (found == map->end())
327 *resource_id = found->second;
332 void AppendMetadataDeletionToBatch(const MetadataMap& metadata_map,
334 leveldb::WriteBatch* batch) {
335 MetadataMap::const_iterator found = metadata_map.find(origin);
336 if (found == metadata_map.end())
339 for (PathToMetadata::const_iterator itr = found->second.begin();
340 itr != found->second.end(); ++itr)
341 batch->Delete(OriginAndPathToMetadataKey(origin, itr->first));
344 std::string DriveTypeToString(DriveMetadata_ResourceType drive_type) {
345 switch (drive_type) {
346 case DriveMetadata_ResourceType_RESOURCE_TYPE_FILE:
348 case DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER:
358 DriveMetadataStore::DriveMetadataStore(
359 const base::FilePath& base_dir,
360 base::SequencedTaskRunner* file_task_runner)
361 : file_task_runner_(file_task_runner),
363 db_status_(SYNC_STATUS_UNKNOWN),
364 largest_changestamp_(0) {
365 DCHECK(file_task_runner);
368 DriveMetadataStore::~DriveMetadataStore() {
369 DCHECK(CalledOnValidThread());
370 file_task_runner_->DeleteSoon(FROM_HERE, db_.release());
373 void DriveMetadataStore::Initialize(const InitializationCallback& callback) {
374 DCHECK(CalledOnValidThread());
375 base::PostTaskAndReplyWithResult(
376 file_task_runner_.get(), FROM_HERE,
377 base::Bind(&LoadDBContents, base_dir_.Append(kDatabaseName)),
378 base::Bind(&DriveMetadataStore::DidInitialize, AsWeakPtr(), callback));
381 void DriveMetadataStore::DidInitialize(const InitializationCallback& callback,
382 scoped_ptr<DBContents> contents) {
383 DCHECK(CalledOnValidThread());
386 db_status_ = contents->status;
387 if (db_status_ != SYNC_STATUS_OK) {
388 callback.Run(db_status_, false);
389 file_task_runner_->DeleteSoon(FROM_HERE, contents.release());
393 db_ = contents->db.Pass();
394 largest_changestamp_ = contents->largest_changestamp;
395 metadata_map_.swap(contents->metadata_map);
396 sync_root_directory_resource_id_ = contents->sync_root_directory_resource_id;
397 incremental_sync_origins_.swap(contents->incremental_sync_origins);
398 disabled_origins_.swap(contents->disabled_origins);
400 origin_by_resource_id_.clear();
401 InsertReverseMap(incremental_sync_origins_, &origin_by_resource_id_);
402 InsertReverseMap(disabled_origins_, &origin_by_resource_id_);
404 callback.Run(db_status_, contents->created);
407 void DriveMetadataStore::SetLargestChangeStamp(
408 int64 largest_changestamp,
409 const SyncStatusCallback& callback) {
410 DCHECK(CalledOnValidThread());
411 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
412 largest_changestamp_ = largest_changestamp;
414 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
415 batch->Put(kChangeStampKey, base::Int64ToString(largest_changestamp));
416 return WriteToDB(batch.Pass(), callback);
419 int64 DriveMetadataStore::GetLargestChangeStamp() const {
420 DCHECK(CalledOnValidThread());
421 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
422 return largest_changestamp_;
425 void DriveMetadataStore::UpdateEntry(
426 const FileSystemURL& url,
427 const DriveMetadata& metadata,
428 const SyncStatusCallback& callback) {
429 DCHECK(CalledOnValidThread());
430 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
431 DCHECK(!metadata.conflicted() || !metadata.to_be_fetched());
433 std::pair<PathToMetadata::iterator, bool> result =
434 metadata_map_[url.origin()].insert(std::make_pair(url.path(), metadata));
436 result.first->second = metadata;
439 if (IsDriveAPIDisabled()) {
440 DriveMetadata metadata_in_db(metadata);
441 metadata_in_db.set_resource_id(
442 drive_backend::RemoveWapiIdPrefix(metadata.resource_id()));
443 bool success = metadata_in_db.SerializeToString(&value);
446 bool success = metadata.SerializeToString(&value);
450 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
451 batch->Put(FileSystemURLToMetadataKey(url), value);
452 WriteToDB(batch.Pass(), callback);
455 void DriveMetadataStore::DeleteEntry(
456 const FileSystemURL& url,
457 const SyncStatusCallback& callback) {
458 DCHECK(CalledOnValidThread());
459 MetadataMap::iterator found = metadata_map_.find(url.origin());
460 if (found == metadata_map_.end()) {
461 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
465 if (found->second.erase(url.path()) == 1) {
466 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
467 batch->Delete(FileSystemURLToMetadataKey(url));
468 WriteToDB(batch.Pass(), callback);
472 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
475 SyncStatusCode DriveMetadataStore::ReadEntry(const FileSystemURL& url,
476 DriveMetadata* metadata) const {
477 DCHECK(CalledOnValidThread());
480 MetadataMap::const_iterator found_origin = metadata_map_.find(url.origin());
481 if (found_origin == metadata_map_.end())
482 return SYNC_DATABASE_ERROR_NOT_FOUND;
484 PathToMetadata::const_iterator found = found_origin->second.find(url.path());
485 if (found == found_origin->second.end())
486 return SYNC_DATABASE_ERROR_NOT_FOUND;
488 *metadata = found->second;
489 return SYNC_STATUS_OK;
492 void DriveMetadataStore::AddIncrementalSyncOrigin(
494 const std::string& resource_id) {
495 DCHECK(CalledOnValidThread());
496 DCHECK(!IsIncrementalSyncOrigin(origin));
497 DCHECK(!IsOriginDisabled(origin));
498 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
500 incremental_sync_origins_.insert(std::make_pair(origin, resource_id));
501 origin_by_resource_id_.insert(std::make_pair(resource_id, origin));
503 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
504 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
505 batch->Put(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN),
506 drive_backend::RemoveWapiIdPrefix(resource_id));
507 WriteToDB(batch.Pass(),
508 base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
511 void DriveMetadataStore::SetSyncRootDirectory(const std::string& resource_id) {
512 DCHECK(CalledOnValidThread());
514 sync_root_directory_resource_id_ = resource_id;
516 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
517 batch->Put(kSyncRootDirectoryKey,
518 drive_backend::RemoveWapiIdPrefix(resource_id));
519 return WriteToDB(batch.Pass(),
520 base::Bind(&DriveMetadataStore::UpdateDBStatus,
524 void DriveMetadataStore::SetOriginRootDirectory(
526 const std::string& resource_id) {
527 DCHECK(CalledOnValidThread());
528 DCHECK(IsKnownOrigin(origin));
530 OriginSyncType sync_type;
531 if (UpdateResourceIdMap(
532 &incremental_sync_origins_, &origin_by_resource_id_,
533 origin, resource_id)) {
534 sync_type = INCREMENTAL_SYNC_ORIGIN;
535 } else if (UpdateResourceIdMap(&disabled_origins_, &origin_by_resource_id_,
536 origin, resource_id)) {
537 sync_type = DISABLED_ORIGIN;
542 std::string key = CreateKeyForOriginRoot(origin, sync_type);
543 DCHECK(!key.empty());
545 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
546 batch->Put(key, drive_backend::RemoveWapiIdPrefix(resource_id));
547 WriteToDB(batch.Pass(),
548 base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
551 bool DriveMetadataStore::IsKnownOrigin(const GURL& origin) const {
552 DCHECK(CalledOnValidThread());
553 return IsIncrementalSyncOrigin(origin) || IsOriginDisabled(origin);
556 bool DriveMetadataStore::IsIncrementalSyncOrigin(const GURL& origin) const {
557 DCHECK(CalledOnValidThread());
558 return ContainsKey(incremental_sync_origins_, origin);
561 bool DriveMetadataStore::IsOriginDisabled(const GURL& origin) const {
562 DCHECK(CalledOnValidThread());
563 return ContainsKey(disabled_origins_, origin);
566 void DriveMetadataStore::EnableOrigin(
568 const SyncStatusCallback& callback) {
569 DCHECK(CalledOnValidThread());
571 std::map<GURL, std::string>::iterator found = disabled_origins_.find(origin);
572 if (found == disabled_origins_.end()) {
573 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
574 // |origin| has not been registered yet.
577 disabled_origins_.erase(found);
579 // |origin| goes back to DriveFileSyncService::pending_batch_sync_origins_
580 // only and is not stored in drive_metadata_store.
581 found = incremental_sync_origins_.find(origin);
582 if (found != incremental_sync_origins_.end())
583 incremental_sync_origins_.erase(found);
585 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
586 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
587 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
588 WriteToDB(batch.Pass(), callback);
591 void DriveMetadataStore::DisableOrigin(
593 const SyncStatusCallback& callback) {
594 DCHECK(CalledOnValidThread());
596 std::string resource_id;
597 if (!EraseIfExists(&incremental_sync_origins_, origin, &resource_id)) {
598 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
601 disabled_origins_[origin] = resource_id;
603 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
604 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
605 batch->Put(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN),
606 drive_backend::RemoveWapiIdPrefix(resource_id));
607 AppendMetadataDeletionToBatch(metadata_map_, origin, batch.get());
608 metadata_map_.erase(origin);
610 WriteToDB(batch.Pass(), callback);
613 void DriveMetadataStore::RemoveOrigin(
615 const SyncStatusCallback& callback) {
616 DCHECK(CalledOnValidThread());
618 std::string resource_id;
619 if (!EraseIfExists(&incremental_sync_origins_, origin, &resource_id) &&
620 !EraseIfExists(&disabled_origins_, origin, &resource_id)) {
621 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
624 origin_by_resource_id_.erase(resource_id);
626 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
627 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
628 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
629 AppendMetadataDeletionToBatch(metadata_map_, origin, batch.get());
630 metadata_map_.erase(origin);
632 WriteToDB(batch.Pass(), callback);
635 void DriveMetadataStore::WriteToDB(scoped_ptr<leveldb::WriteBatch> batch,
636 const SyncStatusCallback& callback) {
637 DCHECK(CalledOnValidThread());
638 if (db_status_ != SYNC_STATUS_OK &&
639 db_status_ != SYNC_DATABASE_ERROR_NOT_FOUND) {
640 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_FAILED));
645 base::PostTaskAndReplyWithResult(
646 file_task_runner_.get(),
648 base::Bind(&leveldb::DB::Write,
649 base::Unretained(db_.get()),
650 leveldb::WriteOptions(),
651 base::Owned(batch.release())),
652 base::Bind(&DriveMetadataStore::UpdateDBStatusAndInvokeCallback,
657 void DriveMetadataStore::UpdateDBStatus(SyncStatusCode status) {
658 DCHECK(CalledOnValidThread());
659 if (db_status_ != SYNC_STATUS_OK &&
660 db_status_ != SYNC_DATABASE_ERROR_NOT_FOUND) {
661 // TODO(tzik): Handle database corruption. http://crbug.com/153709
663 util::Log(logging::LOG_WARNING,
665 "DriveMetadataStore turned to wrong state: %s",
666 SyncStatusCodeToString(status));
669 db_status_ = SYNC_STATUS_OK;
672 void DriveMetadataStore::UpdateDBStatusAndInvokeCallback(
673 const SyncStatusCallback& callback,
674 const leveldb::Status& leveldb_status) {
675 SyncStatusCode status = LevelDBStatusToSyncStatusCode(leveldb_status);
676 UpdateDBStatus(status);
677 callback.Run(status);
680 SyncStatusCode DriveMetadataStore::GetConflictURLs(
681 fileapi::FileSystemURLSet* urls) const {
682 DCHECK(CalledOnValidThread());
683 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
686 for (MetadataMap::const_iterator origin_itr = metadata_map_.begin();
687 origin_itr != metadata_map_.end();
689 for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
690 itr != origin_itr->second.end();
692 if (itr->second.conflicted()) {
693 urls->insert(CreateSyncableFileSystemURL(
694 origin_itr->first, itr->first));
698 return SYNC_STATUS_OK;
701 SyncStatusCode DriveMetadataStore::GetToBeFetchedFiles(
702 URLAndDriveMetadataList* list) const {
703 DCHECK(CalledOnValidThread());
704 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
707 for (MetadataMap::const_iterator origin_itr = metadata_map_.begin();
708 origin_itr != metadata_map_.end();
710 for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
711 itr != origin_itr->second.end();
713 if (itr->second.to_be_fetched()) {
714 FileSystemURL url = CreateSyncableFileSystemURL(
715 origin_itr->first, itr->first);
716 list->push_back(std::make_pair(url, itr->second));
720 return SYNC_STATUS_OK;
723 std::string DriveMetadataStore::GetResourceIdForOrigin(
724 const GURL& origin) const {
725 DCHECK(CalledOnValidThread());
727 // If we don't have valid root directory (this could be reset even after
728 // initialized) just return empty string, as the origin directories
729 // in the root directory must have become invalid now too.
730 if (sync_root_directory().empty())
731 return std::string();
733 ResourceIdByOrigin::const_iterator found =
734 incremental_sync_origins_.find(origin);
735 if (found != incremental_sync_origins_.end())
736 return found->second;
738 found = disabled_origins_.find(origin);
739 if (found != disabled_origins_.end())
740 return found->second;
742 return std::string();
745 void DriveMetadataStore::GetAllOrigins(std::vector<GURL>* origins) {
746 DCHECK(CalledOnValidThread());
749 origins->reserve(incremental_sync_origins_.size() +
750 disabled_origins_.size());
751 AddOriginsToVector(origins, incremental_sync_origins_);
752 AddOriginsToVector(origins, disabled_origins_);
755 bool DriveMetadataStore::GetOriginByOriginRootDirectoryId(
756 const std::string& resource_id,
758 DCHECK(CalledOnValidThread());
761 OriginByResourceId::iterator found = origin_by_resource_id_.find(resource_id);
762 if (found == origin_by_resource_id_.end())
764 *origin = found->second;
768 scoped_ptr<base::ListValue> DriveMetadataStore::DumpFiles(const GURL& origin) {
769 DCHECK(CalledOnValidThread());
771 scoped_ptr<base::ListValue> files(new base::ListValue);
773 MetadataMap::const_iterator found = metadata_map_.find(origin);
774 if (found == metadata_map_.end())
775 return make_scoped_ptr(new base::ListValue);
777 for (PathToMetadata::const_iterator itr = found->second.begin();
778 itr != found->second.end();
780 // Convert Drive specific metadata to Common File metadata object.
781 const DriveMetadata& metadata = itr->second;
783 base::DictionaryValue* file = new base::DictionaryValue;
784 file->SetString("path", itr->first.AsUTF8Unsafe());
785 file->SetString("title", itr->first.BaseName().AsUTF8Unsafe());
786 file->SetString("type", DriveTypeToString(metadata.type()));
788 base::DictionaryValue* details = new base::DictionaryValue;
789 details->SetString("resource_id", metadata.resource_id());
790 details->SetString("md5", metadata.md5_checksum());
791 details->SetString("dirty", metadata.to_be_fetched() ? "true" : "false");
793 file->Set("details", details);
800 } // namespace sync_file_system