| 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
|
|
|