blob: ac15b6abd6f2a460817881eeb7eff47dcf387727 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "src/ledger/bin/storage/impl/page_db_batch_impl.h"
#include <memory>
#include "src/ledger/bin/storage/impl/data_serialization.h"
#include "src/ledger/bin/storage/impl/db_serialization.h"
#include "src/ledger/bin/storage/impl/object_digest.h"
#include "src/ledger/bin/storage/public/types.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/concatenate.h"
#define RETURN_ON_ERROR(expr) \
do { \
Status status = (expr); \
if (status != Status::OK) { \
return status; \
} \
} while (0)
namespace storage {
using coroutine::CoroutineHandler;
PageDbBatchImpl::PageDbBatchImpl(std::unique_ptr<Db::Batch> batch, PageDb* db)
: batch_(std::move(batch)), db_(db) {}
PageDbBatchImpl::~PageDbBatchImpl() {}
Status PageDbBatchImpl::AddHead(CoroutineHandler* handler, CommitIdView head,
zx::time_utc timestamp) {
return batch_->Put(handler, HeadRow::GetKeyFor(head),
SerializeData(timestamp));
}
Status PageDbBatchImpl::RemoveHead(CoroutineHandler* handler,
CommitIdView head) {
return batch_->Delete(handler, HeadRow::GetKeyFor(head));
}
Status PageDbBatchImpl::AddMerge(coroutine::CoroutineHandler* handler,
CommitIdView parent1_id,
CommitIdView parent2_id,
CommitIdView merge_commit_id) {
return batch_->Put(
handler, MergeRow::GetKeyFor(parent1_id, parent2_id, merge_commit_id),
"");
}
Status PageDbBatchImpl::AddCommitStorageBytes(CoroutineHandler* handler,
const CommitId& commit_id,
const ObjectIdentifier& root_node,
fxl::StringView storage_bytes) {
RETURN_ON_ERROR(batch_->Put(
handler,
ReferenceRow::GetKeyForCommit(commit_id, root_node.object_digest()), ""));
return batch_->Put(handler, CommitRow::GetKeyFor(commit_id), storage_bytes);
}
Status PageDbBatchImpl::WriteObject(
CoroutineHandler* handler, const Piece& piece,
PageDbObjectStatus object_status,
const ObjectReferencesAndPriority& references) {
FXL_DCHECK(object_status > PageDbObjectStatus::UNKNOWN);
const ObjectIdentifier& object_identifier = piece.GetIdentifier();
Status status = db_->HasObject(handler, object_identifier);
if (status == Status::OK) {
if (object_status == PageDbObjectStatus::TRANSIENT) {
return Status::OK;
}
return SetObjectStatus(handler, piece.GetIdentifier(), object_status);
}
if (status != Status::INTERNAL_NOT_FOUND) {
return status;
}
RETURN_ON_ERROR(batch_->Put(
handler, ObjectRow::GetKeyFor(object_identifier.object_digest()),
piece.GetData()));
for (const auto& [child, priority] : references) {
FXL_DCHECK(!GetObjectDigestInfo(child).is_inlined());
RETURN_ON_ERROR(
batch_->Put(handler,
ReferenceRow::GetKeyForObject(
object_identifier.object_digest(), child, priority),
""));
}
return batch_->Put(
handler, ObjectStatusRow::GetKeyFor(object_status, object_identifier),
"");
}
Status PageDbBatchImpl::SetObjectStatus(
CoroutineHandler* handler, const ObjectIdentifier& object_identifier,
PageDbObjectStatus object_status) {
FXL_DCHECK(object_status >= PageDbObjectStatus::LOCAL);
RETURN_ON_ERROR(DCheckHasObject(handler, object_identifier));
PageDbObjectStatus previous_object_status;
RETURN_ON_ERROR(db_->GetObjectStatus(handler, object_identifier,
&previous_object_status));
if (previous_object_status >= object_status) {
return Status::OK;
}
RETURN_ON_ERROR(batch_->Delete(
handler,
ObjectStatusRow::GetKeyFor(previous_object_status, object_identifier)));
return batch_->Put(
handler, ObjectStatusRow::GetKeyFor(object_status, object_identifier),
"");
}
Status PageDbBatchImpl::MarkCommitIdSynced(CoroutineHandler* handler,
const CommitId& commit_id) {
return batch_->Delete(handler, UnsyncedCommitRow::GetKeyFor(commit_id));
}
Status PageDbBatchImpl::MarkCommitIdUnsynced(CoroutineHandler* handler,
const CommitId& commit_id,
uint64_t generation) {
return batch_->Put(handler, UnsyncedCommitRow::GetKeyFor(commit_id),
SerializeData(generation));
}
Status PageDbBatchImpl::SetSyncMetadata(CoroutineHandler* handler,
fxl::StringView key,
fxl::StringView value) {
return batch_->Put(handler, SyncMetadataRow::GetKeyFor(key), value);
}
Status PageDbBatchImpl::MarkPageOnline(coroutine::CoroutineHandler* handler) {
return batch_->Put(handler, PageIsOnlineRow::kKey, "");
}
Status PageDbBatchImpl::Execute(CoroutineHandler* handler) {
return batch_->Execute(handler);
}
Status PageDbBatchImpl::DCheckHasObject(CoroutineHandler* handler,
const ObjectIdentifier& key) {
#ifdef NDEBUG
return Status::OK;
#else
Status status = db_->HasObject(handler, key);
if (status == Status::INTERRUPTED) {
return status;
}
FXL_DCHECK(status == Status::OK);
return Status::OK;
#endif
}
} // namespace storage