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

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

Issue 23787003: [SyncFS] Move SyncFS V1 files from drive_backend to drive_backend_v1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move back metadata_db_migration_util* Created 7 years, 3 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
(Empty)
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 #include "chrome/browser/sync_file_system/drive_backend/drive_metadata_store.h"
6
7 #include <utility>
8 #include <vector>
9
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/message_loop/message_loop_proxy.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/task_runner_util.h"
21 #include "base/values.h"
22 #include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_service. h"
23 #include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_util.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"
26 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
27 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
28 #include "third_party/leveldatabase/src/include/leveldb/db.h"
29 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
30 #include "url/gurl.h"
31 #include "webkit/browser/fileapi/file_system_url.h"
32 #include "webkit/common/fileapi/file_system_util.h"
33
34 using fileapi::FileSystemURL;
35
36 namespace sync_file_system {
37
38 typedef DriveMetadataStore::MetadataMap MetadataMap;
39 typedef DriveMetadataStore::OriginByResourceId OriginByResourceId;
40 typedef DriveMetadataStore::PathToMetadata PathToMetadata;
41 typedef DriveMetadataStore::ResourceIdByOrigin ResourceIdByOrigin;
42
43 const base::FilePath::CharType DriveMetadataStore::kDatabaseName[] =
44 FILE_PATH_LITERAL("DriveMetadata");
45
46 struct DBContents {
47 SyncStatusCode status;
48 scoped_ptr<leveldb::DB> db;
49 bool created;
50
51 int64 largest_changestamp;
52 DriveMetadataStore::MetadataMap metadata_map;
53 std::string sync_root_directory_resource_id;
54 ResourceIdByOrigin incremental_sync_origins;
55 ResourceIdByOrigin disabled_origins;
56
57 DBContents()
58 : status(SYNC_STATUS_UNKNOWN),
59 created(false),
60 largest_changestamp(0) {
61 }
62 };
63
64 namespace {
65
66 const char kDatabaseVersionKey[] = "VERSION";
67 const int64 kCurrentDatabaseVersion = 2;
68 const char kChangeStampKey[] = "CHANGE_STAMP";
69 const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
70 const char kDriveMetadataKeyPrefix[] = "METADATA: ";
71 const char kMetadataKeySeparator = ' ';
72 const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
73 const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
74 const size_t kDriveMetadataKeyPrefixLength = arraysize(kDriveMetadataKeyPrefix);
75
76 enum OriginSyncType {
77 INCREMENTAL_SYNC_ORIGIN,
78 DISABLED_ORIGIN
79 };
80
81 std::string RemovePrefix(const std::string& str, const std::string& prefix) {
82 if (StartsWithASCII(str, prefix, true))
83 return str.substr(prefix.size());
84 return str;
85 }
86
87 std::string OriginAndPathToMetadataKey(const GURL& origin,
88 const base::FilePath& path) {
89 return kDriveMetadataKeyPrefix + origin.spec() +
90 kMetadataKeySeparator + path.AsUTF8Unsafe();
91 }
92
93 std::string FileSystemURLToMetadataKey(const FileSystemURL& url) {
94 return OriginAndPathToMetadataKey(url.origin(), url.path());
95 }
96
97 void MetadataKeyToOriginAndPath(const std::string& metadata_key,
98 GURL* origin,
99 base::FilePath* path) {
100 std::string key_body(RemovePrefix(metadata_key, kDriveMetadataKeyPrefix));
101 size_t separator_position = key_body.find(kMetadataKeySeparator);
102 *origin = GURL(key_body.substr(0, separator_position));
103 *path = base::FilePath::FromUTF8Unsafe(
104 key_body.substr(separator_position + 1));
105 }
106
107 bool UpdateResourceIdMap(ResourceIdByOrigin* map,
108 OriginByResourceId* reverse_map,
109 const GURL& origin,
110 const std::string& resource_id) {
111 ResourceIdByOrigin::iterator found = map->find(origin);
112 if (found == map->end())
113 return false;
114 reverse_map->erase(found->second);
115 reverse_map->insert(std::make_pair(resource_id, origin));
116
117 found->second = resource_id;
118 return true;
119 }
120
121 ////////////////////////////////////////////////////////////////////////////////
122
123 bool IsDBEmpty(leveldb::DB* db) {
124 DCHECK(db);
125 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
126 itr->SeekToFirst();
127 return !itr->Valid();
128 }
129
130 scoped_ptr<leveldb::DB> OpenDatabase(const base::FilePath& path,
131 SyncStatusCode* status,
132 bool* created) {
133 DCHECK(status);
134 DCHECK(created);
135
136 leveldb::Options options;
137 options.max_open_files = 0; // Use minimum.
138 options.create_if_missing = true;
139 leveldb::DB* db = NULL;
140 leveldb::Status db_status = leveldb::DB::Open(
141 options, path.AsUTF8Unsafe(), &db);
142 if (db_status.ok()) {
143 *created = IsDBEmpty(db);
144 } else {
145 delete db;
146 db = NULL;
147 }
148 *status = LevelDBStatusToSyncStatusCode(db_status);
149
150 return make_scoped_ptr(db);
151 }
152
153 SyncStatusCode WriteInitialData(leveldb::DB* db) {
154 DCHECK(db);
155 return LevelDBStatusToSyncStatusCode(db->Put(
156 leveldb::WriteOptions(),
157 kDatabaseVersionKey,
158 base::Int64ToString(kCurrentDatabaseVersion)));
159 }
160
161 SyncStatusCode MigrateDatabaseIfNeeded(leveldb::DB* db) {
162 DCHECK(db);
163 std::string value;
164 leveldb::Status status = db->Get(leveldb::ReadOptions(),
165 kDatabaseVersionKey, &value);
166 int64 version = 0;
167 if (status.ok()) {
168 if (!base::StringToInt64(value, &version))
169 return SYNC_DATABASE_ERROR_FAILED;
170 } else {
171 if (!status.IsNotFound())
172 return SYNC_DATABASE_ERROR_FAILED;
173 }
174
175 switch (version) {
176 case 0:
177 drive_backend::MigrateDatabaseFromV0ToV1(db);
178 // fall-through
179 case 1:
180 drive_backend::MigrateDatabaseFromV1ToV2(db);
181 // fall-through
182 case 2:
183 DCHECK_EQ(2, kCurrentDatabaseVersion);
184 return SYNC_STATUS_OK;
185 default:
186 return SYNC_DATABASE_ERROR_FAILED;
187 }
188 }
189
190 SyncStatusCode ReadContents(DBContents* contents) {
191 DCHECK(contents);
192 DCHECK(contents->db);
193
194 contents->largest_changestamp = 0;
195 contents->metadata_map.clear();
196 contents->incremental_sync_origins.clear();
197
198 scoped_ptr<leveldb::Iterator> itr(
199 contents->db->NewIterator(leveldb::ReadOptions()));
200 for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
201 std::string key = itr->key().ToString();
202 if (key == kChangeStampKey) {
203 bool success = base::StringToInt64(itr->value().ToString(),
204 &contents->largest_changestamp);
205 DCHECK(success);
206 continue;
207 }
208
209 if (key == kSyncRootDirectoryKey) {
210 std::string resource_id = itr->value().ToString();
211 if (IsDriveAPIDisabled())
212 resource_id = drive_backend::AddWapiFolderPrefix(resource_id);
213 contents->sync_root_directory_resource_id = resource_id;
214 continue;
215 }
216
217 if (StartsWithASCII(key, kDriveMetadataKeyPrefix, true)) {
218 GURL origin;
219 base::FilePath path;
220 MetadataKeyToOriginAndPath(key, &origin, &path);
221
222 DriveMetadata metadata;
223 bool success = metadata.ParseFromString(itr->value().ToString());
224 DCHECK(success);
225
226 if (IsDriveAPIDisabled()) {
227 metadata.set_resource_id(drive_backend::AddWapiIdPrefix(
228 metadata.resource_id(), metadata.type()));
229 }
230
231 success = contents->metadata_map[origin].insert(
232 std::make_pair(path, metadata)).second;
233 DCHECK(success);
234 continue;
235 }
236
237 if (StartsWithASCII(key, kDriveIncrementalSyncOriginKeyPrefix, true)) {
238 GURL origin(RemovePrefix(key, kDriveIncrementalSyncOriginKeyPrefix));
239 DCHECK(origin.is_valid());
240
241 std::string origin_resource_id = IsDriveAPIDisabled()
242 ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
243 : itr->value().ToString();
244
245 DCHECK(!ContainsKey(contents->incremental_sync_origins, origin));
246 contents->incremental_sync_origins[origin] = origin_resource_id;
247 continue;
248 }
249
250 if (StartsWithASCII(key, kDriveDisabledOriginKeyPrefix, true)) {
251 GURL origin(RemovePrefix(key, kDriveDisabledOriginKeyPrefix));
252 DCHECK(origin.is_valid());
253
254 std::string origin_resource_id = IsDriveAPIDisabled()
255 ? drive_backend::AddWapiFolderPrefix(itr->value().ToString())
256 : itr->value().ToString();
257
258 DCHECK(!ContainsKey(contents->disabled_origins, origin));
259 contents->disabled_origins[origin] = origin_resource_id;
260 continue;
261 }
262 }
263
264 return SYNC_STATUS_OK;
265 }
266
267 scoped_ptr<DBContents> LoadDBContents(const base::FilePath& db_path) {
268 scoped_ptr<DBContents> contents(new DBContents);
269 contents->db = OpenDatabase(db_path,
270 &contents->status,
271 &contents->created);
272 if (contents->status != SYNC_STATUS_OK)
273 return contents.Pass();
274
275 if (contents->created) {
276 contents->status = WriteInitialData(contents->db.get());
277 if (contents->status != SYNC_STATUS_OK)
278 return contents.Pass();
279 } else {
280 contents->status = MigrateDatabaseIfNeeded(contents->db.get());
281 if (contents->status != SYNC_STATUS_OK)
282 return contents.Pass();
283 }
284
285 contents->status = ReadContents(contents.get());
286 return contents.Pass();
287 }
288
289 ////////////////////////////////////////////////////////////////////////////////
290
291 // Returns a key string for the given origin.
292 // For example, when |origin| is "http://www.example.com" and |sync_type| is
293 // BATCH_SYNC_ORIGIN, returns "BSYNC_ORIGIN: http://www.example.com".
294 std::string CreateKeyForOriginRoot(const GURL& origin,
295 OriginSyncType sync_type) {
296 DCHECK(origin.is_valid());
297 switch (sync_type) {
298 case INCREMENTAL_SYNC_ORIGIN:
299 return kDriveIncrementalSyncOriginKeyPrefix + origin.spec();
300 case DISABLED_ORIGIN:
301 return kDriveDisabledOriginKeyPrefix + origin.spec();
302 }
303 NOTREACHED();
304 return std::string();
305 }
306
307 void AddOriginsToVector(std::vector<GURL>* all_origins,
308 const ResourceIdByOrigin& resource_map) {
309 for (ResourceIdByOrigin::const_iterator itr = resource_map.begin();
310 itr != resource_map.end();
311 ++itr) {
312 all_origins->push_back(itr->first);
313 }
314 }
315
316 void InsertReverseMap(const ResourceIdByOrigin& forward_map,
317 OriginByResourceId* backward_map) {
318 for (ResourceIdByOrigin::const_iterator itr = forward_map.begin();
319 itr != forward_map.end(); ++itr)
320 backward_map->insert(std::make_pair(itr->second, itr->first));
321 }
322
323 bool EraseIfExists(ResourceIdByOrigin* map,
324 const GURL& origin,
325 std::string* resource_id) {
326 ResourceIdByOrigin::iterator found = map->find(origin);
327 if (found == map->end())
328 return false;
329 *resource_id = found->second;
330 map->erase(found);
331 return true;
332 }
333
334 void AppendMetadataDeletionToBatch(const MetadataMap& metadata_map,
335 const GURL& origin,
336 leveldb::WriteBatch* batch) {
337 MetadataMap::const_iterator found = metadata_map.find(origin);
338 if (found == metadata_map.end())
339 return;
340
341 for (PathToMetadata::const_iterator itr = found->second.begin();
342 itr != found->second.end(); ++itr)
343 batch->Delete(OriginAndPathToMetadataKey(origin, itr->first));
344 }
345
346 std::string DriveTypeToString(DriveMetadata_ResourceType drive_type) {
347 switch (drive_type) {
348 case DriveMetadata_ResourceType_RESOURCE_TYPE_FILE:
349 return "file";
350 case DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER:
351 return "folder";
352 }
353
354 NOTREACHED();
355 return "unknown";
356 }
357
358 } // namespace
359
360 DriveMetadataStore::DriveMetadataStore(
361 const base::FilePath& base_dir,
362 base::SequencedTaskRunner* file_task_runner)
363 : file_task_runner_(file_task_runner),
364 base_dir_(base_dir),
365 db_status_(SYNC_STATUS_UNKNOWN),
366 largest_changestamp_(0) {
367 DCHECK(file_task_runner);
368 }
369
370 DriveMetadataStore::~DriveMetadataStore() {
371 DCHECK(CalledOnValidThread());
372 file_task_runner_->DeleteSoon(FROM_HERE, db_.release());
373 }
374
375 void DriveMetadataStore::Initialize(const InitializationCallback& callback) {
376 DCHECK(CalledOnValidThread());
377 base::PostTaskAndReplyWithResult(
378 file_task_runner_.get(), FROM_HERE,
379 base::Bind(&LoadDBContents, base_dir_.Append(kDatabaseName)),
380 base::Bind(&DriveMetadataStore::DidInitialize, AsWeakPtr(), callback));
381 }
382
383 void DriveMetadataStore::DidInitialize(const InitializationCallback& callback,
384 scoped_ptr<DBContents> contents) {
385 DCHECK(CalledOnValidThread());
386 DCHECK(contents);
387
388 db_status_ = contents->status;
389 if (db_status_ != SYNC_STATUS_OK) {
390 callback.Run(db_status_, false);
391 return;
392 }
393
394 db_ = contents->db.Pass();
395 largest_changestamp_ = contents->largest_changestamp;
396 metadata_map_.swap(contents->metadata_map);
397 sync_root_directory_resource_id_ = contents->sync_root_directory_resource_id;
398 incremental_sync_origins_.swap(contents->incremental_sync_origins);
399 disabled_origins_.swap(contents->disabled_origins);
400
401 origin_by_resource_id_.clear();
402 InsertReverseMap(incremental_sync_origins_, &origin_by_resource_id_);
403 InsertReverseMap(disabled_origins_, &origin_by_resource_id_);
404
405 callback.Run(db_status_, contents->created);
406 }
407
408 leveldb::DB* DriveMetadataStore::GetDBInstanceForTesting() {
409 return db_.get();
410 }
411
412 void DriveMetadataStore::SetLargestChangeStamp(
413 int64 largest_changestamp,
414 const SyncStatusCallback& callback) {
415 DCHECK(CalledOnValidThread());
416 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
417 largest_changestamp_ = largest_changestamp;
418
419 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
420 batch->Put(kChangeStampKey, base::Int64ToString(largest_changestamp));
421 return WriteToDB(batch.Pass(), callback);
422 }
423
424 int64 DriveMetadataStore::GetLargestChangeStamp() const {
425 DCHECK(CalledOnValidThread());
426 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
427 return largest_changestamp_;
428 }
429
430 void DriveMetadataStore::UpdateEntry(
431 const FileSystemURL& url,
432 const DriveMetadata& metadata,
433 const SyncStatusCallback& callback) {
434 DCHECK(CalledOnValidThread());
435 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
436 DCHECK(!metadata.conflicted() || !metadata.to_be_fetched());
437
438 std::pair<PathToMetadata::iterator, bool> result =
439 metadata_map_[url.origin()].insert(std::make_pair(url.path(), metadata));
440 if (!result.second)
441 result.first->second = metadata;
442
443 std::string value;
444 if (IsDriveAPIDisabled()) {
445 DriveMetadata metadata_in_db(metadata);
446 metadata_in_db.set_resource_id(
447 drive_backend::RemoveWapiIdPrefix(metadata.resource_id()));
448 bool success = metadata_in_db.SerializeToString(&value);
449 DCHECK(success);
450 } else {
451 bool success = metadata.SerializeToString(&value);
452 DCHECK(success);
453 }
454
455 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
456 batch->Put(FileSystemURLToMetadataKey(url), value);
457 WriteToDB(batch.Pass(), callback);
458 }
459
460 void DriveMetadataStore::DeleteEntry(
461 const FileSystemURL& url,
462 const SyncStatusCallback& callback) {
463 DCHECK(CalledOnValidThread());
464 MetadataMap::iterator found = metadata_map_.find(url.origin());
465 if (found == metadata_map_.end()) {
466 base::MessageLoopProxy::current()->PostTask(
467 FROM_HERE,
468 base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
469 return;
470 }
471
472 if (found->second.erase(url.path()) == 1) {
473 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
474 batch->Delete(FileSystemURLToMetadataKey(url));
475 WriteToDB(batch.Pass(), callback);
476 return;
477 }
478
479 base::MessageLoopProxy::current()->PostTask(
480 FROM_HERE,
481 base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
482 }
483
484 SyncStatusCode DriveMetadataStore::ReadEntry(const FileSystemURL& url,
485 DriveMetadata* metadata) const {
486 DCHECK(CalledOnValidThread());
487 DCHECK(metadata);
488
489 MetadataMap::const_iterator found_origin = metadata_map_.find(url.origin());
490 if (found_origin == metadata_map_.end())
491 return SYNC_DATABASE_ERROR_NOT_FOUND;
492
493 PathToMetadata::const_iterator found = found_origin->second.find(url.path());
494 if (found == found_origin->second.end())
495 return SYNC_DATABASE_ERROR_NOT_FOUND;
496
497 *metadata = found->second;
498 return SYNC_STATUS_OK;
499 }
500
501 void DriveMetadataStore::AddIncrementalSyncOrigin(
502 const GURL& origin,
503 const std::string& resource_id) {
504 DCHECK(CalledOnValidThread());
505 DCHECK(!IsIncrementalSyncOrigin(origin));
506 DCHECK(!IsOriginDisabled(origin));
507 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
508
509 incremental_sync_origins_.insert(std::make_pair(origin, resource_id));
510 origin_by_resource_id_.insert(std::make_pair(resource_id, origin));
511
512 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
513 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
514 batch->Put(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN),
515 drive_backend::RemoveWapiIdPrefix(resource_id));
516 WriteToDB(batch.Pass(),
517 base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
518 }
519
520 void DriveMetadataStore::SetSyncRootDirectory(const std::string& resource_id) {
521 DCHECK(CalledOnValidThread());
522
523 sync_root_directory_resource_id_ = resource_id;
524
525 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
526 batch->Put(kSyncRootDirectoryKey,
527 drive_backend::RemoveWapiIdPrefix(resource_id));
528 return WriteToDB(batch.Pass(),
529 base::Bind(&DriveMetadataStore::UpdateDBStatus,
530 AsWeakPtr()));
531 }
532
533 void DriveMetadataStore::SetOriginRootDirectory(
534 const GURL& origin,
535 const std::string& resource_id) {
536 DCHECK(CalledOnValidThread());
537 DCHECK(IsKnownOrigin(origin));
538
539 OriginSyncType sync_type;
540 if (UpdateResourceIdMap(
541 &incremental_sync_origins_, &origin_by_resource_id_,
542 origin, resource_id)) {
543 sync_type = INCREMENTAL_SYNC_ORIGIN;
544 } else if (UpdateResourceIdMap(&disabled_origins_, &origin_by_resource_id_,
545 origin, resource_id)) {
546 sync_type = DISABLED_ORIGIN;
547 } else {
548 return;
549 }
550
551 std::string key = CreateKeyForOriginRoot(origin, sync_type);
552 DCHECK(!key.empty());
553
554 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
555 batch->Put(key, drive_backend::RemoveWapiIdPrefix(resource_id));
556 WriteToDB(batch.Pass(),
557 base::Bind(&DriveMetadataStore::UpdateDBStatus, AsWeakPtr()));
558 }
559
560 bool DriveMetadataStore::IsKnownOrigin(const GURL& origin) const {
561 DCHECK(CalledOnValidThread());
562 return IsIncrementalSyncOrigin(origin) || IsOriginDisabled(origin);
563 }
564
565 bool DriveMetadataStore::IsIncrementalSyncOrigin(const GURL& origin) const {
566 DCHECK(CalledOnValidThread());
567 return ContainsKey(incremental_sync_origins_, origin);
568 }
569
570 bool DriveMetadataStore::IsOriginDisabled(const GURL& origin) const {
571 DCHECK(CalledOnValidThread());
572 return ContainsKey(disabled_origins_, origin);
573 }
574
575 void DriveMetadataStore::EnableOrigin(
576 const GURL& origin,
577 const SyncStatusCallback& callback) {
578 DCHECK(CalledOnValidThread());
579
580 std::map<GURL, std::string>::iterator found = disabled_origins_.find(origin);
581 if (found == disabled_origins_.end()) {
582 // |origin| has not been registered yet.
583 return;
584 }
585 disabled_origins_.erase(found);
586
587 // |origin| goes back to DriveFileSyncService::pending_batch_sync_origins_
588 // only and is not stored in drive_metadata_store.
589 found = incremental_sync_origins_.find(origin);
590 if (found != incremental_sync_origins_.end())
591 incremental_sync_origins_.erase(found);
592
593 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
594 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
595 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
596 WriteToDB(batch.Pass(), callback);
597 }
598
599 void DriveMetadataStore::DisableOrigin(
600 const GURL& origin,
601 const SyncStatusCallback& callback) {
602 DCHECK(CalledOnValidThread());
603
604 std::string resource_id;
605 if (!EraseIfExists(&incremental_sync_origins_, origin, &resource_id))
606 return;
607 disabled_origins_[origin] = resource_id;
608
609 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
610 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
611 batch->Put(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN),
612 drive_backend::RemoveWapiIdPrefix(resource_id));
613 AppendMetadataDeletionToBatch(metadata_map_, origin, batch.get());
614 metadata_map_.erase(origin);
615
616 WriteToDB(batch.Pass(), callback);
617 }
618
619 void DriveMetadataStore::RemoveOrigin(
620 const GURL& origin,
621 const SyncStatusCallback& callback) {
622 DCHECK(CalledOnValidThread());
623
624 std::string resource_id;
625 if (!EraseIfExists(&incremental_sync_origins_, origin, &resource_id) &&
626 !EraseIfExists(&disabled_origins_, origin, &resource_id))
627 return;
628 origin_by_resource_id_.erase(resource_id);
629
630 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
631 batch->Delete(CreateKeyForOriginRoot(origin, INCREMENTAL_SYNC_ORIGIN));
632 batch->Delete(CreateKeyForOriginRoot(origin, DISABLED_ORIGIN));
633 AppendMetadataDeletionToBatch(metadata_map_, origin, batch.get());
634 metadata_map_.erase(origin);
635
636 WriteToDB(batch.Pass(), callback);
637 }
638
639 void DriveMetadataStore::DidUpdateOrigin(
640 const SyncStatusCallback& callback,
641 SyncStatusCode status) {
642 UpdateDBStatus(status);
643 callback.Run(status);
644 }
645
646 void DriveMetadataStore::WriteToDB(scoped_ptr<leveldb::WriteBatch> batch,
647 const SyncStatusCallback& callback) {
648 base::PostTaskAndReplyWithResult(
649 file_task_runner_.get(),
650 FROM_HERE,
651 base::Bind(&leveldb::DB::Write,
652 base::Unretained(db_.get()),
653 leveldb::WriteOptions(),
654 base::Owned(batch.release())),
655 base::Bind(&DriveMetadataStore::UpdateDBStatusAndInvokeCallback,
656 AsWeakPtr(),
657 callback));
658 }
659
660 void DriveMetadataStore::UpdateDBStatus(SyncStatusCode status) {
661 DCHECK(CalledOnValidThread());
662 if (db_status_ != SYNC_STATUS_OK &&
663 db_status_ != SYNC_DATABASE_ERROR_NOT_FOUND) {
664 // TODO(tzik): Handle database corruption. http://crbug.com/153709
665 db_status_ = status;
666 util::Log(logging::LOG_WARNING,
667 FROM_HERE,
668 "DriveMetadataStore turned to wrong state: %s",
669 SyncStatusCodeToString(status));
670 return;
671 }
672 db_status_ = SYNC_STATUS_OK;
673 }
674
675 void DriveMetadataStore::UpdateDBStatusAndInvokeCallback(
676 const SyncStatusCallback& callback,
677 const leveldb::Status& leveldb_status) {
678 SyncStatusCode status = LevelDBStatusToSyncStatusCode(leveldb_status);
679 UpdateDBStatus(status);
680 callback.Run(status);
681 }
682
683 SyncStatusCode DriveMetadataStore::GetConflictURLs(
684 fileapi::FileSystemURLSet* urls) const {
685 DCHECK(CalledOnValidThread());
686 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
687
688 urls->clear();
689 for (MetadataMap::const_iterator origin_itr = metadata_map_.begin();
690 origin_itr != metadata_map_.end();
691 ++origin_itr) {
692 for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
693 itr != origin_itr->second.end();
694 ++itr) {
695 if (itr->second.conflicted()) {
696 urls->insert(CreateSyncableFileSystemURL(
697 origin_itr->first, itr->first));
698 }
699 }
700 }
701 return SYNC_STATUS_OK;
702 }
703
704 SyncStatusCode DriveMetadataStore::GetToBeFetchedFiles(
705 URLAndDriveMetadataList* list) const {
706 DCHECK(CalledOnValidThread());
707 DCHECK_EQ(SYNC_STATUS_OK, db_status_);
708
709 list->clear();
710 for (MetadataMap::const_iterator origin_itr = metadata_map_.begin();
711 origin_itr != metadata_map_.end();
712 ++origin_itr) {
713 for (PathToMetadata::const_iterator itr = origin_itr->second.begin();
714 itr != origin_itr->second.end();
715 ++itr) {
716 if (itr->second.to_be_fetched()) {
717 FileSystemURL url = CreateSyncableFileSystemURL(
718 origin_itr->first, itr->first);
719 list->push_back(std::make_pair(url, itr->second));
720 }
721 }
722 }
723 return SYNC_STATUS_OK;
724 }
725
726 std::string DriveMetadataStore::GetResourceIdForOrigin(
727 const GURL& origin) const {
728 DCHECK(CalledOnValidThread());
729
730 // If we don't have valid root directory (this could be reset even after
731 // initialized) just return empty string, as the origin directories
732 // in the root directory must have become invalid now too.
733 if (sync_root_directory().empty())
734 return std::string();
735
736 ResourceIdByOrigin::const_iterator found =
737 incremental_sync_origins_.find(origin);
738 if (found != incremental_sync_origins_.end())
739 return found->second;
740
741 found = disabled_origins_.find(origin);
742 if (found != disabled_origins_.end())
743 return found->second;
744
745 return std::string();
746 }
747
748 void DriveMetadataStore::GetAllOrigins(std::vector<GURL>* origins) {
749 DCHECK(CalledOnValidThread());
750 DCHECK(origins);
751 origins->clear();
752 origins->reserve(incremental_sync_origins_.size() +
753 disabled_origins_.size());
754 AddOriginsToVector(origins, incremental_sync_origins_);
755 AddOriginsToVector(origins, disabled_origins_);
756 }
757
758 bool DriveMetadataStore::GetOriginByOriginRootDirectoryId(
759 const std::string& resource_id,
760 GURL* origin) {
761 DCHECK(CalledOnValidThread());
762 DCHECK(origin);
763
764 OriginByResourceId::iterator found = origin_by_resource_id_.find(resource_id);
765 if (found == origin_by_resource_id_.end())
766 return false;
767 *origin = found->second;
768 return true;
769 }
770
771 scoped_ptr<base::ListValue> DriveMetadataStore::DumpFiles(const GURL& origin) {
772 DCHECK(CalledOnValidThread());
773
774 scoped_ptr<base::ListValue> files(new base::ListValue);
775
776 MetadataMap::const_iterator found = metadata_map_.find(origin);
777 if (found == metadata_map_.end())
778 return make_scoped_ptr(new base::ListValue);
779
780 for (PathToMetadata::const_iterator itr = found->second.begin();
781 itr != found->second.end();
782 ++itr) {
783 // Convert Drive specific metadata to Common File metadata object.
784 const DriveMetadata& metadata = itr->second;
785
786 base::DictionaryValue* file = new DictionaryValue;
787 file->SetString("path", itr->first.AsUTF8Unsafe());
788 file->SetString("title", itr->first.BaseName().AsUTF8Unsafe());
789 file->SetString("type", DriveTypeToString(metadata.type()));
790
791 base::DictionaryValue* details = new DictionaryValue;
792 details->SetString("resource_id", metadata.resource_id());
793 details->SetString("md5", metadata.md5_checksum());
794 details->SetString("dirty", metadata.to_be_fetched() ? "true" : "false");
795
796 file->Set("details", details);
797 files->Append(file);
798 }
799
800 return files.Pass();
801 }
802
803 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698