blob: e75ae8570e714fdcdbfe23aa6fd7362e641d3a9d [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 "peridot/lib/ledger_client/page_client.h"
#include <memory>
#include <utility>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/functional/make_copyable.h>
#include "peridot/lib/fidl/array_to_string.h"
#include "peridot/lib/ledger_client/ledger_client.h"
namespace modular {
PageClient::PageClient(std::string context, LedgerClient* ledger_client,
LedgerPageId page_id, std::string prefix)
: binding_(this),
context_(std::move(context)),
ledger_client_(ledger_client),
page_id_(std::move(page_id)),
page_(ledger_client_->GetPage(this, context_, page_id_)),
prefix_(std::move(prefix)) {
fuchsia::ledger::PageSnapshotPtr snapshot;
page_->GetSnapshot(snapshot.NewRequest(), to_array(prefix_),
binding_.NewBinding(),
[this](fuchsia::ledger::Status status) {
if (status != fuchsia::ledger::Status::OK) {
FXL_LOG(ERROR) << context_ << " Page.GetSnapshot() "
<< fidl::ToUnderlying(status);
}
});
}
PageClient::~PageClient() {
// We assume ledger client always outlives page client.
ledger_client_->DropPageClient(this);
}
fuchsia::ledger::PageSnapshotPtr PageClient::NewSnapshot(
std::function<void()> on_error) {
fuchsia::ledger::PageSnapshotPtr ptr;
page_->GetSnapshot(
ptr.NewRequest(), to_array(prefix_), nullptr /* page_watcher */,
[this, on_error = std::move(on_error)](fuchsia::ledger::Status status) {
if (status != fuchsia::ledger::Status::OK) {
FXL_LOG(ERROR) << context_ << " Page.GetSnapshot() "
<< fidl::ToUnderlying(status);
on_error();
}
});
return ptr;
}
// |PageWatcher|
void PageClient::OnChange(fuchsia::ledger::PageChange page,
fuchsia::ledger::ResultState result_state,
OnChangeCallback callback) {
for (auto& entry : page.changed_entries) {
// Remove key prefix maybe?
OnPageChange(to_string(entry.key), std::move(entry.value));
}
for (auto& key : page.deleted_keys) {
OnPageDelete(to_string(key));
}
callback(nullptr);
}
void PageClient::OnPageChange(const std::string& key,
fuchsia::mem::BufferPtr value) {
std::string value_string;
if (fsl::StringFromVmo(*value, &value_string)) {
OnPageChange(key, value_string);
} else {
FXL_LOG(ERROR) << "PageClient::OnChange() " << context_ << ": "
<< "Unable to read/copy data.";
}
}
void PageClient::OnPageChange(const std::string& /*key*/,
const std::string& /*value*/) {}
void PageClient::OnPageDelete(const std::string& /*key*/) {}
void PageClient::OnPageConflict(Conflict* const conflict) {
FXL_LOG(INFO) << "PageClient::OnPageConflict() " << context_ << " "
<< to_hex_string(conflict->key) << " " << conflict->left << " "
<< conflict->right;
};
namespace {
void GetEntriesRecursive(fuchsia::ledger::PageSnapshot* const snapshot,
std::vector<fuchsia::ledger::Entry>* const entries,
std::unique_ptr<fuchsia::ledger::Token> next_token,
std::function<void(fuchsia::ledger::Status)> done) {
snapshot->GetEntries(
std::vector<uint8_t>{} /* key_start */, std::move(next_token),
fxl::MakeCopyable([snapshot, entries, done = std::move(done)](
fuchsia::ledger::Status status, auto new_entries,
auto next_token) mutable {
if (status != fuchsia::ledger::Status::OK &&
status != fuchsia::ledger::Status::PARTIAL_RESULT) {
done(status);
return;
}
for (size_t i = 0; i < new_entries.size(); ++i) {
entries->push_back(std::move(new_entries.at(i)));
}
if (status == fuchsia::ledger::Status::OK) {
done(fuchsia::ledger::Status::OK);
return;
}
GetEntriesRecursive(snapshot, entries, std::move(next_token),
std::move(done));
}));
}
} // namespace
void GetEntries(fuchsia::ledger::PageSnapshot* const snapshot,
std::vector<fuchsia::ledger::Entry>* const entries,
std::function<void(fuchsia::ledger::Status)> done) {
GetEntriesRecursive(snapshot, entries, nullptr /* next_token */,
std::move(done));
}
} // namespace modular