blob: fa10e0dc4004d08044437aa10aa7e7593f86abe1 [file] [log] [blame]
// Copyright 2017 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 "components/download/internal/background_service/download_store.h"
#include <memory>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "components/download/internal/background_service/entry.h"
#include "components/download/internal/background_service/proto/entry.pb.h"
#include "components/download/internal/background_service/proto_conversions.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
namespace download {
namespace {
using KeyVector = std::vector<std::string>;
using ProtoEntryVector = std::vector<protodb::Entry>;
using KeyProtoEntryVector = std::vector<std::pair<std::string, protodb::Entry>>;
leveldb_env::Options GetDownloadDBOptions() {
// These options reduce memory consumption.
leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
options.reuse_logs = false;
options.write_buffer_size = 64 << 10; // 64 KiB
return options;
}
} // namespace
DownloadStore::DownloadStore(
std::unique_ptr<leveldb_proto::ProtoDatabase<protodb::Entry>> db)
: db_(std::move(db)), is_initialized_(false) {}
DownloadStore::~DownloadStore() = default;
bool DownloadStore::IsInitialized() {
return is_initialized_;
}
void DownloadStore::Initialize(InitCallback callback) {
DCHECK(!IsInitialized());
db_->Init(GetDownloadDBOptions(),
base::BindOnce(&DownloadStore::OnDatabaseInited,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void DownloadStore::HardRecover(StoreCallback callback) {
is_initialized_ = false;
db_->Destroy(base::BindOnce(&DownloadStore::OnDatabaseDestroyed,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void DownloadStore::OnDatabaseInited(InitCallback callback,
leveldb_proto::Enums::InitStatus status) {
if (status != leveldb_proto::Enums::InitStatus::kOK) {
std::move(callback).Run(false, std::make_unique<std::vector<Entry>>());
return;
}
db_->LoadEntries(base::BindOnce(&DownloadStore::OnDatabaseLoaded,
weak_factory_.GetWeakPtr(),
std::move(callback)));
}
void DownloadStore::OnDatabaseLoaded(InitCallback callback,
bool success,
std::unique_ptr<ProtoEntryVector> protos) {
if (!success) {
std::move(callback).Run(success, std::make_unique<std::vector<Entry>>());
return;
}
auto entries = ProtoConversions::EntryVectorFromProto(std::move(protos));
is_initialized_ = true;
std::move(callback).Run(success, std::move(entries));
}
void DownloadStore::OnDatabaseDestroyed(StoreCallback callback, bool success) {
if (!success) {
std::move(callback).Run(success);
return;
}
db_->Init(GetDownloadDBOptions(),
base::BindOnce(&DownloadStore::OnDatabaseInitedAfterDestroy,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void DownloadStore::OnDatabaseInitedAfterDestroy(
StoreCallback callback,
leveldb_proto::Enums::InitStatus status) {
is_initialized_ = status == leveldb_proto::Enums::InitStatus::kOK;
std::move(callback).Run(is_initialized_);
}
void DownloadStore::Update(const Entry& entry, StoreCallback callback) {
DCHECK(IsInitialized());
auto entries_to_save = std::make_unique<KeyProtoEntryVector>();
protodb::Entry proto = ProtoConversions::EntryToProto(entry);
entries_to_save->emplace_back(entry.guid, std::move(proto));
db_->UpdateEntries(std::move(entries_to_save), std::make_unique<KeyVector>(),
std::move(callback));
}
void DownloadStore::Remove(const std::string& guid, StoreCallback callback) {
DCHECK(IsInitialized());
auto keys_to_remove = std::make_unique<KeyVector>();
keys_to_remove->push_back(guid);
db_->UpdateEntries(std::make_unique<KeyProtoEntryVector>(),
std::move(keys_to_remove), std::move(callback));
}
} // namespace download