mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-31 12:06:44 +00:00
these unused includes were identified by clangd. see https://clangd.llvm.org/guides/include-cleaner#unused-include-warning for more details on the "Unused include" warning. Signed-off-by: Kefu Chai <kefu.chai@scylladb.com> Closes scylladb/scylladb#16764
136 lines
5.4 KiB
C++
136 lines
5.4 KiB
C++
/*
|
|
* Copyright (C) 2022-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#include "lang.hh"
|
|
|
|
#include <seastar/core/future.hh>
|
|
|
|
#include "data_dictionary/data_dictionary.hh"
|
|
#include "db/system_keyspace.hh"
|
|
#include "service/broadcast_tables/experimental/query_result.hh"
|
|
#include "service/raft/raft_group0_client.hh"
|
|
#include "partition_slice_builder.hh"
|
|
#include "query-request.hh"
|
|
#include "cache_temperature.hh"
|
|
#include "service/storage_proxy.hh"
|
|
|
|
namespace service::broadcast_tables {
|
|
|
|
bool is_broadcast_table_statement(const sstring& keyspace, const sstring& column_family) {
|
|
return keyspace == db::system_keyspace::NAME && column_family == db::system_keyspace::BROADCAST_KV_STORE;
|
|
}
|
|
|
|
future<query_result> execute(service::raft_group0_client& group0_client, const query& query) {
|
|
auto group0_cmd = group0_client.prepare_command(broadcast_table_query{query}, "broadcast_tables query");
|
|
auto guard = group0_client.create_result_guard(group0_cmd.new_state_id);
|
|
co_await group0_client.add_entry_unguarded(std::move(group0_cmd), nullptr);
|
|
co_return guard.get();
|
|
}
|
|
|
|
|
|
static
|
|
std::pair<lw_shared_ptr<::query::read_command>, dht::partition_range>
|
|
prepare_read_command(storage_proxy& proxy, const schema& schema, const bytes& key) {
|
|
auto slice = partition_slice_builder(schema).build();
|
|
auto partition_key = partition_key::from_single_value(schema, key);
|
|
dht::ring_position ring_position(dht::get_token(schema, partition_key), partition_key);
|
|
auto range = dht::partition_range::make_singular(ring_position);
|
|
return {make_lw_shared<::query::read_command>(
|
|
schema.id(),
|
|
schema.version(),
|
|
slice,
|
|
proxy.get_max_result_size(slice),
|
|
::query::tombstone_limit(proxy.get_tombstone_limit())
|
|
), range};
|
|
}
|
|
|
|
static
|
|
const atomic_cell_view
|
|
get_atomic_cell(const schema_ptr& schema, mutation& mutation, const bytes& name) {
|
|
const auto* column_definition = schema->get_column_definition(name);
|
|
return mutation.partition().clustered_row(*schema, clustering_key::make_empty()).cells().cell_at(column_definition->id).as_atomic_cell(*column_definition);
|
|
}
|
|
|
|
future<query_result> execute_broadcast_table_query(
|
|
storage_proxy& proxy,
|
|
const query& query,
|
|
utils::UUID cmd_id) {
|
|
// std::bind_front is used to avoid losing the captures in coroutines.
|
|
return std::visit(make_visitor(
|
|
std::bind_front([] (storage_proxy& proxy, const service::broadcast_tables::select_query& q) -> future<query_result> {
|
|
const auto schema = db::system_keyspace::broadcast_kv_store();
|
|
|
|
// Read mutations
|
|
const auto [read_cmd, range] = prepare_read_command(proxy, *schema, q.key);
|
|
auto [rs, _] = co_await proxy.query_mutations_locally(schema, read_cmd, range, db::no_timeout);
|
|
|
|
if (rs->partitions().empty()) {
|
|
co_return query_result_select{};
|
|
}
|
|
|
|
assert(rs->partitions().size() == 1); // In this version only one value per partition key is allowed.
|
|
|
|
const auto& p = rs->partitions()[0];
|
|
auto mutation = p.mut().unfreeze(schema);
|
|
const auto cell = get_atomic_cell(schema, mutation, "value");
|
|
|
|
co_return query_result_select{
|
|
.value = cell.value().linearize()
|
|
};
|
|
}, std::ref(proxy)),
|
|
std::bind_front([] (storage_proxy& proxy, utils::UUID cmd_id, const broadcast_tables::update_query& q) -> future<query_result> {
|
|
const auto schema = db::system_keyspace::broadcast_kv_store();
|
|
|
|
// Read mutations
|
|
const auto [read_cmd, range] = prepare_read_command(proxy, *schema, q.key);
|
|
auto [rs, _] = co_await proxy.query_mutations_locally(schema, read_cmd, range, db::no_timeout);
|
|
|
|
bool found = !rs->partitions().empty();
|
|
|
|
assert(!found || rs->partitions().size() == 1); // In this version at most one value per partition key is allowed.
|
|
|
|
auto new_mutation = found
|
|
? rs->partitions()[0].mut().unfreeze(schema)
|
|
: mutation(schema, partition_key::from_single_value(*schema, to_bytes(q.key)));
|
|
|
|
const auto cell = found
|
|
? std::optional<atomic_cell_view>{get_atomic_cell(schema, new_mutation, "value")}
|
|
: std::nullopt;
|
|
|
|
const auto previous_value = found
|
|
? bytes_opt{cell->value().linearize()}
|
|
: std::nullopt;
|
|
|
|
bool is_conditional = q.value_condition.has_value();
|
|
bool is_applied = !is_conditional || *q.value_condition == previous_value;
|
|
|
|
if (is_applied) {
|
|
auto old_ts = found ? cell->timestamp() : api::min_timestamp;
|
|
auto from_state_id = utils::UUID_gen::micros_timestamp(cmd_id);
|
|
auto ts = std::max(from_state_id, old_ts + 1);
|
|
|
|
auto value = utf8_type->deserialize(q.new_value);
|
|
new_mutation.set_clustered_cell(clustering_key::make_empty(), "value", std::move(value), ts);
|
|
co_await proxy.mutate_locally(new_mutation, {}, {});
|
|
}
|
|
|
|
if (is_conditional) {
|
|
co_return query_result_conditional_update{
|
|
.is_applied = is_applied,
|
|
.previous_value = previous_value
|
|
};
|
|
} else {
|
|
co_return query_result_none{};
|
|
}
|
|
}, std::ref(proxy), cmd_id)),
|
|
query.q
|
|
);
|
|
}
|
|
|
|
}
|