Skip to content

Commit

Permalink
merge: Remove treewide dependency on boost/multiprecision
Browse files Browse the repository at this point in the history
Merged patch series from Avi Kivity:

boost/multiprecision is a heavyweight library, pulling in 20,000 lines of code into
each header that depends on it. It is used by converting_mutation_partition_applier
and types.hh. While the former is easy to put out-of-line, the latter is not.

All we really need is to forward-declare boost::multiprecision::cpp_int, but that
is not easy - it is a template taking several parameters, among which are non-type
template parameters also defined in that header. So it's quite difficult to
disentangle, and fragile wrt boost changes.

This patchset introduces a wrapper type utils::multiprecision_int which _can_
be forward declared, and together with a few other small fixes, manages to
uninclude boost/multiprecision from most of the source files. The total reduction
in number of lines compiled over a full build is 324 * 23,227 or around 7.5
million.

Tests: unit (dev)
Ref #1

https://github.com/avikivity/scylla uninclude-boost-multiprecision/v1

Avi Kivity (5):
  converting_mutation_partition_applier: move to .cc file
  utils: introduce multiprecision_int
  tests: cdc_test: explicitly convert from cdc::operation to uint8_t
  treewide: use utils::multiprecision_int for varint implementation
  types: forward-declare multiprecision_int

 configure.py                             |   2 +
 concrete_types.hh                        |   2 +-
 converting_mutation_partition_applier.hh | 163 ++-------------
 types.hh                                 |  12 +-
 utils/big_decimal.hh                     |   3 +-
 utils/multiprecision_int.hh              | 256 +++++++++++++++++++++++
 converting_mutation_partition_applier.cc | 188 +++++++++++++++++
 cql3/functions/aggregate_fcts.cc         |  10 +-
 cql3/functions/castas_fcts.cc            |  28 +--
 cql3/type_json.cc                        |   2 +-
 lua.cc                                   |  38 ++--
 mutation_partition_view.cc               |   2 +
 test/boost/cdc_test.cc                   |   6 +-
 test/boost/cql_query_test.cc             |  16 +-
 test/boost/json_cql_query_test.cc        |  12 +-
 test/boost/types_test.cc                 |  58 ++---
 test/boost/user_function_test.cc         |   2 +-
 test/lib/random_schema.cc                |  14 +-
 types.cc                                 |  20 +-
 utils/big_decimal.cc                     |   4 +-
 utils/multiprecision_int.cc              |  37 ++++
 21 files changed, 627 insertions(+), 248 deletions(-)
 create mode 100644 utils/multiprecision_int.hh
 create mode 100644 converting_mutation_partition_applier.cc
 create mode 100644 utils/multiprecision_int.cc
  • Loading branch information
nyh committed Mar 4, 2020
2 parents 354e3c3 + 5dee627 commit f67a402
Show file tree
Hide file tree
Showing 21 changed files with 628 additions and 249 deletions.
2 changes: 1 addition & 1 deletion concrete_types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ struct timeuuid_type_impl final : public concrete_type<utils::UUID> {
static utils::UUID from_sstring(sstring_view s);
};

struct varint_type_impl final : public concrete_type<boost::multiprecision::cpp_int> {
struct varint_type_impl final : public concrete_type<utils::multiprecision_int> {
varint_type_impl();
};

Expand Down
2 changes: 2 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ def find_headers(repodir, excluded_dirs):
'mutation_partition.cc',
'mutation_partition_view.cc',
'mutation_partition_serializer.cc',
'converting_mutation_partition_applier.cc',
'mutation_reader.cc',
'flat_mutation_reader.cc',
'mutation_query.cc',
Expand Down Expand Up @@ -670,6 +671,7 @@ def find_headers(repodir, excluded_dirs):
'utils/managed_bytes.cc',
'utils/exceptions.cc',
'utils/config_file.cc',
'utils/multiprecision_int.cc',
'utils/gz/crc_combine.cc',
'gms/version_generator.cc',
'gms/versioned_value.cc',
Expand Down
188 changes: 188 additions & 0 deletions converting_mutation_partition_applier.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
* 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().linearize(), cell.expiry(), cell.ttl(), cm);
}
return atomic_cell::make_live(new_type, cell.timestamp(), cell.value().linearize(), 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());
}
}
163 changes: 21 additions & 142 deletions converting_mutation_partition_applier.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@

#pragma once

#include "types/user.hh"
#include "concrete_types.hh"
#include "mutation_partition_visitor.hh"

#include "mutation_partition_view.hh"
#include "mutation_partition.hh"
#include "schema.hh"
class schema;
class row;
class mutation_partition;
class column_mapping;
class deletable_row;

// Mutation partition visitor which applies visited data into
// existing mutation_partition. The visited data may be of a different schema.
Expand All @@ -38,148 +39,26 @@ class converting_mutation_partition_applier : public mutation_partition_visitor
const column_mapping& _visited_column_mapping;
deletable_row* _current_row;
private:
static bool 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);
}
static bool is_compatible(const column_definition& new_def, const abstract_type& old_type, column_kind kind);
static atomic_cell upgrade_cell(const abstract_type& new_type, const abstract_type& old_type, atomic_cell_view cell,
atomic_cell::collection_member cm = atomic_cell::collection_member::no) {
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().linearize(), cell.expiry(), cell.ttl(), cm);
}
return atomic_cell::make_live(new_type, cell.timestamp(), cell.value().linearize(), cm);
} else {
return atomic_cell(new_type, cell);
}
}
static void 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));
}
static void 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));
}
});
}
public:
atomic_cell::collection_member cm = atomic_cell::collection_member::no);
static void accept_cell(row& dst, column_kind kind, const column_definition& new_def, const abstract_type& old_type, atomic_cell_view cell);
static void accept_cell(row& dst, column_kind kind, const column_definition& new_def, const abstract_type& old_type, collection_mutation_view cell);public:
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)
{ }

virtual void accept_partition_tombstone(tombstone t) override {
_p.apply(t);
}

void accept_static_cell(column_id id, atomic_cell cell) {
return accept_static_cell(id, atomic_cell_view(cell));
}

virtual void accept_static_cell(column_id id, atomic_cell_view cell) override {
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);
}
}

virtual void accept_static_cell(column_id id, collection_mutation_view collection) override {
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);
}
}

virtual void accept_row_tombstone(const range_tombstone& rt) override {
_p.apply_row_tombstone(_p_schema, rt);
}

virtual void accept_row(position_in_partition_view key, const row_tombstone& deleted_at, const row_marker& rm, is_dummy dummy, is_continuous continuous) override {
deletable_row& r = _p.clustered_row(_p_schema, key, dummy, continuous);
r.apply(rm);
r.apply(deleted_at);
_current_row = &r;
}

void accept_row_cell(column_id id, atomic_cell cell) {
return accept_row_cell(id, atomic_cell_view(cell));
}

virtual void accept_row_cell(column_id id, atomic_cell_view cell) override {
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);
}
}

virtual void accept_row_cell(column_id id, collection_mutation_view collection) override {
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);
}
}
mutation_partition& target);
virtual void accept_partition_tombstone(tombstone t) override;
void accept_static_cell(column_id id, atomic_cell cell);
virtual void accept_static_cell(column_id id, atomic_cell_view cell) override;
virtual void accept_static_cell(column_id id, collection_mutation_view collection) override;
virtual void accept_row_tombstone(const range_tombstone& rt) override;
virtual void accept_row(position_in_partition_view key, const row_tombstone& deleted_at, const row_marker& rm, is_dummy dummy, is_continuous continuous) override;
void accept_row_cell(column_id id, atomic_cell cell);
virtual void accept_row_cell(column_id id, atomic_cell_view cell) override;
virtual void accept_row_cell(column_id id, collection_mutation_view collection) override;

// Appends the cell to dst upgrading it to the new schema.
// Cells must have monotonic names.
static void 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());
}
}
static void append_cell(row& dst, column_kind kind, const column_definition& new_def, const column_definition& old_def, const atomic_cell_or_collection& cell);
};
Loading

0 comments on commit f67a402

Please sign in to comment.