Index: chrome/browser/chromeos/contacts/contact_database.cc |
diff --git a/chrome/browser/chromeos/contacts/contact_database.cc b/chrome/browser/chromeos/contacts/contact_database.cc |
deleted file mode 100644 |
index 04eb2e88f4b25e56d88a80f713ab4668b2bbe72f..0000000000000000000000000000000000000000 |
--- a/chrome/browser/chromeos/contacts/contact_database.cc |
+++ /dev/null |
@@ -1,343 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/chromeos/contacts/contact_database.h" |
- |
-#include <set> |
- |
-#include "base/file_util.h" |
-#include "base/metrics/histogram.h" |
-#include "base/sequenced_task_runner.h" |
-#include "base/threading/sequenced_worker_pool.h" |
-#include "chrome/browser/chromeos/contacts/contact.pb.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "third_party/leveldatabase/src/include/leveldb/db.h" |
-#include "third_party/leveldatabase/src/include/leveldb/iterator.h" |
-#include "third_party/leveldatabase/src/include/leveldb/options.h" |
-#include "third_party/leveldatabase/src/include/leveldb/slice.h" |
-#include "third_party/leveldatabase/src/include/leveldb/status.h" |
-#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
- |
-using content::BrowserThread; |
- |
-namespace contacts { |
- |
-namespace { |
- |
-// Initialization results reported via the "Contacts.DatabaseInitResult" |
-// histogram. |
-enum HistogramInitResult { |
- HISTOGRAM_INIT_RESULT_SUCCESS = 0, |
- HISTOGRAM_INIT_RESULT_FAILURE = 1, |
- HISTOGRAM_INIT_RESULT_DELETED_CORRUPTED = 2, |
- HISTOGRAM_INIT_RESULT_MAX_VALUE = 3, |
-}; |
- |
-// Save results reported via the "Contacts.DatabaseSaveResult" histogram. |
-enum HistogramSaveResult { |
- HISTOGRAM_SAVE_RESULT_SUCCESS = 0, |
- HISTOGRAM_SAVE_RESULT_FAILURE = 1, |
- HISTOGRAM_SAVE_RESULT_MAX_VALUE = 2, |
-}; |
- |
-// Load results reported via the "Contacts.DatabaseLoadResult" histogram. |
-enum HistogramLoadResult { |
- HISTOGRAM_LOAD_RESULT_SUCCESS = 0, |
- HISTOGRAM_LOAD_RESULT_METADATA_PARSE_FAILURE = 1, |
- HISTOGRAM_LOAD_RESULT_CONTACT_PARSE_FAILURE = 2, |
- HISTOGRAM_LOAD_RESULT_MAX_VALUE = 3, |
-}; |
- |
-// LevelDB key used for storing UpdateMetadata messages. |
-const char kUpdateMetadataKey[] = "__chrome_update_metadata__"; |
- |
-} // namespace |
- |
-ContactDatabase::ContactDatabase() |
- : weak_ptr_factory_(this) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); |
- task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); |
-} |
- |
-void ContactDatabase::DestroyOnUIThread() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- weak_ptr_factory_.InvalidateWeakPtrs(); |
- task_runner_->PostNonNestableTask( |
- FROM_HERE, |
- base::Bind(&ContactDatabase::DestroyFromTaskRunner, |
- base::Unretained(this))); |
-} |
- |
-void ContactDatabase::Init(const base::FilePath& database_dir, |
- InitCallback callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- bool* success = new bool(false); |
- task_runner_->PostTaskAndReply( |
- FROM_HERE, |
- base::Bind(&ContactDatabase::InitFromTaskRunner, |
- base::Unretained(this), |
- database_dir, |
- success), |
- base::Bind(&ContactDatabase::RunInitCallback, |
- weak_ptr_factory_.GetWeakPtr(), |
- callback, |
- base::Owned(success))); |
-} |
- |
-void ContactDatabase::SaveContacts(scoped_ptr<ContactPointers> contacts_to_save, |
- scoped_ptr<ContactIds> contact_ids_to_delete, |
- scoped_ptr<UpdateMetadata> metadata, |
- bool is_full_update, |
- SaveCallback callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- bool* success = new bool(false); |
- task_runner_->PostTaskAndReply( |
- FROM_HERE, |
- base::Bind(&ContactDatabase::SaveContactsFromTaskRunner, |
- base::Unretained(this), |
- base::Passed(&contacts_to_save), |
- base::Passed(&contact_ids_to_delete), |
- base::Passed(&metadata), |
- is_full_update, |
- success), |
- base::Bind(&ContactDatabase::RunSaveCallback, |
- weak_ptr_factory_.GetWeakPtr(), |
- callback, |
- base::Owned(success))); |
-} |
- |
-void ContactDatabase::LoadContacts(LoadCallback callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- bool* success = new bool(false); |
- scoped_ptr<ScopedVector<Contact> > contacts(new ScopedVector<Contact>); |
- scoped_ptr<UpdateMetadata> metadata(new UpdateMetadata); |
- |
- // Extract pointers before we calling Pass() so we can use them below. |
- ScopedVector<Contact>* contacts_ptr = contacts.get(); |
- UpdateMetadata* metadata_ptr = metadata.get(); |
- |
- task_runner_->PostTaskAndReply( |
- FROM_HERE, |
- base::Bind(&ContactDatabase::LoadContactsFromTaskRunner, |
- base::Unretained(this), |
- success, |
- contacts_ptr, |
- metadata_ptr), |
- base::Bind(&ContactDatabase::RunLoadCallback, |
- weak_ptr_factory_.GetWeakPtr(), |
- callback, |
- base::Owned(success), |
- base::Passed(&contacts), |
- base::Passed(&metadata))); |
-} |
- |
-ContactDatabase::~ContactDatabase() { |
- DCHECK(IsRunByTaskRunner()); |
-} |
- |
-bool ContactDatabase::IsRunByTaskRunner() const { |
- return BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread(); |
-} |
- |
-void ContactDatabase::DestroyFromTaskRunner() { |
- DCHECK(IsRunByTaskRunner()); |
- delete this; |
-} |
- |
-void ContactDatabase::RunInitCallback(InitCallback callback, |
- const bool* success) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- callback.Run(*success); |
-} |
- |
-void ContactDatabase::RunSaveCallback(SaveCallback callback, |
- const bool* success) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- callback.Run(*success); |
-} |
- |
-void ContactDatabase::RunLoadCallback( |
- LoadCallback callback, |
- const bool* success, |
- scoped_ptr<ScopedVector<Contact> > contacts, |
- scoped_ptr<UpdateMetadata> metadata) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- callback.Run(*success, contacts.Pass(), metadata.Pass()); |
-} |
- |
-void ContactDatabase::InitFromTaskRunner(const base::FilePath& database_dir, |
- bool* success) { |
- DCHECK(IsRunByTaskRunner()); |
- DCHECK(success); |
- |
- VLOG(1) << "Opening " << database_dir.value(); |
- UMA_HISTOGRAM_MEMORY_KB("Contacts.DatabaseSizeBytes", |
- base::ComputeDirectorySize(database_dir)); |
- *success = false; |
- HistogramInitResult histogram_result = HISTOGRAM_INIT_RESULT_SUCCESS; |
- |
- leveldb::Options options; |
- options.create_if_missing = true; |
- options.max_open_files = 0; // Use minimum. |
- bool delete_and_retry_on_corruption = true; |
- |
- while (true) { |
- leveldb::DB* db = NULL; |
- leveldb::Status status = |
- leveldb::DB::Open(options, database_dir.value(), &db); |
- if (status.ok()) { |
- CHECK(db); |
- db_.reset(db); |
- *success = true; |
- return; |
- } |
- |
- LOG(WARNING) << "Unable to open " << database_dir.value() << ": " |
- << status.ToString(); |
- |
- // Delete the existing database and try again (just once, though). |
- if (status.IsCorruption() && delete_and_retry_on_corruption) { |
- LOG(WARNING) << "Deleting possibly-corrupt database"; |
- base::DeleteFile(database_dir, true); |
- delete_and_retry_on_corruption = false; |
- histogram_result = HISTOGRAM_INIT_RESULT_DELETED_CORRUPTED; |
- } else { |
- histogram_result = HISTOGRAM_INIT_RESULT_FAILURE; |
- break; |
- } |
- } |
- |
- UMA_HISTOGRAM_ENUMERATION("Contacts.DatabaseInitResult", |
- histogram_result, |
- HISTOGRAM_INIT_RESULT_MAX_VALUE); |
-} |
- |
-void ContactDatabase::SaveContactsFromTaskRunner( |
- scoped_ptr<ContactPointers> contacts_to_save, |
- scoped_ptr<ContactIds> contact_ids_to_delete, |
- scoped_ptr<UpdateMetadata> metadata, |
- bool is_full_update, |
- bool* success) { |
- DCHECK(IsRunByTaskRunner()); |
- DCHECK(success); |
- VLOG(1) << "Saving " << contacts_to_save->size() << " contact(s) to database " |
- << "and deleting " << contact_ids_to_delete->size() << " as " |
- << (is_full_update ? "full" : "incremental") << " update"; |
- |
- *success = false; |
- |
- // If we're doing a full update, find all of the existing keys first so we can |
- // delete ones that aren't present in the new set of contacts. |
- std::set<std::string> keys_to_delete; |
- if (is_full_update) { |
- leveldb::ReadOptions options; |
- scoped_ptr<leveldb::Iterator> db_iterator(db_->NewIterator(options)); |
- db_iterator->SeekToFirst(); |
- while (db_iterator->Valid()) { |
- std::string key = db_iterator->key().ToString(); |
- if (key != kUpdateMetadataKey) |
- keys_to_delete.insert(key); |
- db_iterator->Next(); |
- } |
- } else { |
- for (ContactIds::const_iterator it = contact_ids_to_delete->begin(); |
- it != contact_ids_to_delete->end(); ++it) { |
- keys_to_delete.insert(*it); |
- } |
- } |
- |
- // TODO(derat): Serializing all of the contacts and so we can write them in a |
- // single batch may be expensive, memory-wise. Consider writing them in |
- // several batches instead. (To avoid using partial writes in the event of a |
- // crash, maybe add a dummy "write completed" contact that's removed in the |
- // first batch and added in the last.) |
- leveldb::WriteBatch updates; |
- for (ContactPointers::const_iterator it = contacts_to_save->begin(); |
- it != contacts_to_save->end(); ++it) { |
- const contacts::Contact& contact = **it; |
- if (contact.contact_id() == kUpdateMetadataKey) { |
- LOG(WARNING) << "Skipping contact with reserved ID " |
- << contact.contact_id(); |
- continue; |
- } |
- updates.Put(leveldb::Slice(contact.contact_id()), |
- leveldb::Slice(contact.SerializeAsString())); |
- if (is_full_update) |
- keys_to_delete.erase(contact.contact_id()); |
- } |
- |
- for (std::set<std::string>::const_iterator it = keys_to_delete.begin(); |
- it != keys_to_delete.end(); ++it) { |
- updates.Delete(leveldb::Slice(*it)); |
- } |
- |
- updates.Put(leveldb::Slice(kUpdateMetadataKey), |
- leveldb::Slice(metadata->SerializeAsString())); |
- |
- leveldb::WriteOptions options; |
- options.sync = true; |
- leveldb::Status status = db_->Write(options, &updates); |
- if (status.ok()) |
- *success = true; |
- else |
- LOG(WARNING) << "Failed writing contacts: " << status.ToString(); |
- |
- UMA_HISTOGRAM_ENUMERATION("Contacts.DatabaseSaveResult", |
- *success ? |
- HISTOGRAM_SAVE_RESULT_SUCCESS : |
- HISTOGRAM_SAVE_RESULT_FAILURE, |
- HISTOGRAM_SAVE_RESULT_MAX_VALUE); |
-} |
- |
-void ContactDatabase::LoadContactsFromTaskRunner( |
- bool* success, |
- ScopedVector<Contact>* contacts, |
- UpdateMetadata* metadata) { |
- DCHECK(IsRunByTaskRunner()); |
- DCHECK(success); |
- DCHECK(contacts); |
- DCHECK(metadata); |
- |
- *success = false; |
- contacts->clear(); |
- metadata->Clear(); |
- |
- leveldb::ReadOptions options; |
- scoped_ptr<leveldb::Iterator> db_iterator(db_->NewIterator(options)); |
- db_iterator->SeekToFirst(); |
- while (db_iterator->Valid()) { |
- leveldb::Slice value_slice = db_iterator->value(); |
- |
- if (db_iterator->key().ToString() == kUpdateMetadataKey) { |
- if (!metadata->ParseFromArray(value_slice.data(), value_slice.size())) { |
- LOG(WARNING) << "Unable to parse metadata"; |
- UMA_HISTOGRAM_ENUMERATION("Contacts.DatabaseLoadResult", |
- HISTOGRAM_LOAD_RESULT_METADATA_PARSE_FAILURE, |
- HISTOGRAM_LOAD_RESULT_MAX_VALUE); |
- return; |
- } |
- } else { |
- scoped_ptr<Contact> contact(new Contact); |
- if (!contact->ParseFromArray(value_slice.data(), value_slice.size())) { |
- LOG(WARNING) << "Unable to parse contact " |
- << db_iterator->key().ToString(); |
- UMA_HISTOGRAM_ENUMERATION("Contacts.DatabaseLoadResult", |
- HISTOGRAM_LOAD_RESULT_CONTACT_PARSE_FAILURE, |
- HISTOGRAM_LOAD_RESULT_MAX_VALUE); |
- return; |
- } |
- contacts->push_back(contact.release()); |
- } |
- db_iterator->Next(); |
- } |
- |
- *success = true; |
- UMA_HISTOGRAM_ENUMERATION("Contacts.DatabaseLoadResult", |
- HISTOGRAM_LOAD_RESULT_SUCCESS, |
- HISTOGRAM_LOAD_RESULT_MAX_VALUE); |
-} |
- |
-} // namespace contacts |