Files
scylladb/converting_mutation_partition_applier.cc
Botond Dénes ba7a9d2ac3 imr: switch back to open-coded description of structures
Commit aab6b0ee27 introduced the
controversial new IMR format, which relied on a very template-heavy
infrastructure to generate serialization and deserialization code via
template meta-programming. The promise was that this new format, beyond
solving the problems the previous open-coded representation had (working
on linearized buffers), will speed up migrating other components to this
IMR format, as the IMR infrastructure reduces code bloat, makes the code
more readable via declarative type descriptions as well as safer.
However, the results were almost the opposite. The template
meta-programming used by the IMR infrastructure proved very hard to
understand. Developers don't want to read or modify it. Maintainers
don't want to see it being used anywhere else. In short, nobody wants to
touch it.

This commit does a conceptual revert of
aab6b0ee27. A verbatim revert is not
possible because related code evolved a lot since the merge. Also, going
back to the previous code would mean we regress as we'd revert the move
to fragmented buffers. So this revert is only conceptual, it changes the
underlying infrastructure back to the previous open-coded one, but keeps
the fragmented buffers, as well as the interface of the related
components (to the extent possible).

Fixes: #5578
2021-02-16 23:43:07 +01:00

189 lines
7.3 KiB
C++

/*
* Copyright (C) 2020 ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#include "converting_mutation_partition_applier.hh"
#include "concrete_types.hh"
#include "mutation_partition_view.hh"
#include "mutation_partition.hh"
#include "schema.hh"
bool
converting_mutation_partition_applier::is_compatible(const column_definition& new_def, const abstract_type& old_type, column_kind kind) {
return ::is_compatible(new_def.kind, kind) && new_def.type->is_value_compatible_with(old_type);
}
atomic_cell
converting_mutation_partition_applier::upgrade_cell(const abstract_type& new_type, const abstract_type& old_type, atomic_cell_view cell,
atomic_cell::collection_member cm) {
if (cell.is_live() && !old_type.is_counter()) {
if (cell.is_live_and_has_ttl()) {
return atomic_cell::make_live(new_type, cell.timestamp(), cell.value(), cell.expiry(), cell.ttl(), cm);
}
return atomic_cell::make_live(new_type, cell.timestamp(), cell.value(), cm);
} else {
return atomic_cell(new_type, cell);
}
}
void
converting_mutation_partition_applier::accept_cell(row& dst, column_kind kind, const column_definition& new_def, const abstract_type& old_type, atomic_cell_view cell) {
if (!is_compatible(new_def, old_type, kind) || cell.timestamp() <= new_def.dropped_at()) {
return;
}
dst.apply(new_def, upgrade_cell(*new_def.type, old_type, cell));
}
void
converting_mutation_partition_applier::accept_cell(row& dst, column_kind kind, const column_definition& new_def, const abstract_type& old_type, collection_mutation_view cell) {
if (!is_compatible(new_def, old_type, kind)) {
return;
}
cell.with_deserialized(old_type, [&] (collection_mutation_view_description old_view) {
collection_mutation_description new_view;
if (old_view.tomb.timestamp > new_def.dropped_at()) {
new_view.tomb = old_view.tomb;
}
visit(old_type, make_visitor(
[&] (const collection_type_impl& old_ctype) {
assert(new_def.type->is_collection()); // because is_compatible
auto& new_ctype = static_cast<const collection_type_impl&>(*new_def.type);
auto& new_value_type = *new_ctype.value_comparator();
auto& old_value_type = *old_ctype.value_comparator();
for (auto& c : old_view.cells) {
if (c.second.timestamp() > new_def.dropped_at()) {
new_view.cells.emplace_back(c.first, upgrade_cell(
new_value_type, old_value_type, c.second, atomic_cell::collection_member::yes));
}
}
},
[&] (const user_type_impl& old_utype) {
assert(new_def.type->is_user_type()); // because is_compatible
auto& new_utype = static_cast<const user_type_impl&>(*new_def.type);
for (auto& c : old_view.cells) {
if (c.second.timestamp() > new_def.dropped_at()) {
auto idx = deserialize_field_index(c.first);
assert(idx < new_utype.size() && idx < old_utype.size());
new_view.cells.emplace_back(c.first, upgrade_cell(
*new_utype.type(idx), *old_utype.type(idx), c.second, atomic_cell::collection_member::yes));
}
}
},
[&] (const abstract_type& o) {
throw std::runtime_error(format("not a multi-cell type: {}", o.name()));
}
));
if (new_view.tomb || !new_view.cells.empty()) {
dst.apply(new_def, new_view.serialize(*new_def.type));
}
});
}
converting_mutation_partition_applier::converting_mutation_partition_applier(
const column_mapping& visited_column_mapping,
const schema& target_schema,
mutation_partition& target)
: _p_schema(target_schema)
, _p(target)
, _visited_column_mapping(visited_column_mapping)
{ }
void
converting_mutation_partition_applier::accept_partition_tombstone(tombstone t) {
_p.apply(t);
}
void
converting_mutation_partition_applier::accept_static_cell(column_id id, atomic_cell cell) {
return accept_static_cell(id, atomic_cell_view(cell));
}
void
converting_mutation_partition_applier::accept_static_cell(column_id id, atomic_cell_view cell) {
const column_mapping_entry& col = _visited_column_mapping.static_column_at(id);
const column_definition* def = _p_schema.get_column_definition(col.name());
if (def) {
accept_cell(_p._static_row.maybe_create(), column_kind::static_column, *def, *col.type(), cell);
}
}
void
converting_mutation_partition_applier::accept_static_cell(column_id id, collection_mutation_view collection) {
const column_mapping_entry& col = _visited_column_mapping.static_column_at(id);
const column_definition* def = _p_schema.get_column_definition(col.name());
if (def) {
accept_cell(_p._static_row.maybe_create(), column_kind::static_column, *def, *col.type(), collection);
}
}
void
converting_mutation_partition_applier::accept_row_tombstone(const range_tombstone& rt) {
_p.apply_row_tombstone(_p_schema, rt);
}
void
converting_mutation_partition_applier::accept_row(position_in_partition_view key, const row_tombstone& deleted_at, const row_marker& rm, is_dummy dummy, is_continuous continuous) {
deletable_row& r = _p.clustered_row(_p_schema, key, dummy, continuous);
r.apply(rm);
r.apply(deleted_at);
_current_row = &r;
}
void
converting_mutation_partition_applier::accept_row_cell(column_id id, atomic_cell cell) {
return accept_row_cell(id, atomic_cell_view(cell));
}
void
converting_mutation_partition_applier::accept_row_cell(column_id id, atomic_cell_view cell) {
const column_mapping_entry& col = _visited_column_mapping.regular_column_at(id);
const column_definition* def = _p_schema.get_column_definition(col.name());
if (def) {
accept_cell(_current_row->cells(), column_kind::regular_column, *def, *col.type(), cell);
}
}
void
converting_mutation_partition_applier::accept_row_cell(column_id id, collection_mutation_view collection) {
const column_mapping_entry& col = _visited_column_mapping.regular_column_at(id);
const column_definition* def = _p_schema.get_column_definition(col.name());
if (def) {
accept_cell(_current_row->cells(), column_kind::regular_column, *def, *col.type(), collection);
}
}
void
converting_mutation_partition_applier::append_cell(row& dst, column_kind kind, const column_definition& new_def, const column_definition& old_def, const atomic_cell_or_collection& cell) {
if (new_def.is_atomic()) {
accept_cell(dst, kind, new_def, *old_def.type, cell.as_atomic_cell(old_def));
} else {
accept_cell(dst, kind, new_def, *old_def.type, cell.as_collection_mutation());
}
}