keys: specialize fmt::formatter<partition_key> and friends

this is a part of a series to migrating from `operator<<(ostream&, ..)`
based formatting to fmtlib based formatting. the goal here is to enable
fmtlib to print following classes without the help of `operator<<`.

- partition_key_view
- partition_key
- partition_key::with_schema_wrapper
- key_with_schema
- clustering_key_prefix
- clustering_key_prefix::with_schema_wrapper

the corresponding `operator<<()` are dropped dropped in this change,
as all its callers are now using fmtlib for formatting now. the helper
of `print_key()` is removed, as its only caller is
`operator<<(std::ostream&, const
clustering_key_prefix::with_schema_wrapper&)`.

the reason why all these operators are replaced in one go is that
we have a template function of `key_to_str()` in `db/large_data_handler.cc`.
this template function is actually the caller of operator<< of
`partition_key::with_schema_wrapper` and
`clustering_key_prefix::with_schema_wrapper`.
so, in order to drop either of these two operator<<, we need to remove
both of them, so that we can switch over to `fmt::to_string()` in this
template function.

Refs scylladb#13245

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
This commit is contained in:
Kefu Chai
2023-04-13 18:19:24 +08:00
parent b71f229fc2
commit 3738fcbe05
7 changed files with 86 additions and 73 deletions

View File

@@ -46,9 +46,7 @@ void data_listeners::on_write(const schema_ptr& s, const frozen_mutation& m) {
}
toppartitions_item_key::operator sstring() const {
std::ostringstream oss;
oss << key.key().with_schema(*schema);
return oss.str();
return fmt::to_string(key.key().with_schema(*schema));
}
toppartitions_data_listener::toppartitions_data_listener(replica::database& db, std::unordered_set<std::tuple<sstring, sstring>, utils::tuple_hash> table_filters,

View File

@@ -72,9 +72,7 @@ void large_data_handler::unplug_system_keyspace() noexcept {
}
template <typename T> static std::string key_to_str(const T& key, const schema& s) {
std::ostringstream oss;
oss << key.with_schema(s);
return oss.str();
return fmt::to_string(key.with_schema(s));
}
sstring large_data_handler::sst_filename(const sstables::sstable& sst) {

View File

@@ -16,6 +16,7 @@
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <compare>
#include <fmt/format.h>
template <typename Comparator, typename T>
concept IntervalComparatorFor = requires (T a, T b, Comparator& cmp) {
@@ -410,7 +411,8 @@ private:
template<typename U>
std::ostream& operator<<(std::ostream& out, const wrapping_interval<U>& r) {
if (r.is_singular()) {
return out << "{" << r.start()->value() << "}";
fmt::print(out, "{{{}}}", r.start()->value());
return out;
}
if (!r.start()) {
@@ -421,13 +423,13 @@ std::ostream& operator<<(std::ostream& out, const wrapping_interval<U>& r) {
} else {
out << "(";
}
out << r.start()->value() << ", ";
fmt::print(out, "{},", r.start()->value());
}
if (!r.end()) {
out << "+inf)";
} else {
out << r.end()->value();
fmt::print(out, "{}", r.end()->value());
if (r.end()->is_inclusive()) {
out << "]";
} else {

53
keys.cc
View File

@@ -12,62 +12,9 @@
#include "dht/i_partitioner.hh"
#include "clustering_bounds_comparator.hh"
#include <boost/algorithm/string.hpp>
#include "utils/utf8.hh"
logging::logger klog("keys");
std::ostream& operator<<(std::ostream& out, const partition_key& pk) {
fmt::print(out, "pk{{{}}}", managed_bytes_view(pk.representation()));
return out;
}
template<typename T>
static std::ostream& print_key(std::ostream& out, const T& key_with_schema) {
const auto& [schema, key] = key_with_schema;
auto type_iterator = key.get_compound_type(schema)->types().begin();
bool first = true;
for (auto&& e : key.components(schema)) {
if (!first) {
out << ":";
}
first = false;
out << (*type_iterator)->to_string(to_bytes(e));
++type_iterator;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const partition_key::with_schema_wrapper& pk) {
const auto& [schema, key] = pk;
auto type_iterator = key.get_compound_type(schema)->types().begin();
bool first = true;
for (auto&& e : key.components(schema)) {
if (!first) {
out << ":";
}
first = false;
auto keystr = (*type_iterator)->to_string(to_bytes(e));
out << (utils::utf8::validate((const uint8_t *) keystr.data(), keystr.size()) ? keystr : "<non-utf8-key>");
++type_iterator;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const clustering_key_prefix::with_schema_wrapper& ck) {
return print_key(out, ck);
}
std::ostream& operator<<(std::ostream& out, const partition_key_view& pk) {
return with_linearized(pk.representation(), [&] (bytes_view v) {
return std::ref(out << "pk{" << to_hex(v) << "}");
});
}
std::ostream& operator<<(std::ostream& out, const clustering_key_prefix& ckp) {
fmt::print(out, "ckp{{{}}}", managed_bytes_view(ckp.representation()));
return out;
}
const legacy_compound_view<partition_key_view::c_type>
partition_key_view::legacy_form(const schema& s) const {
return { *get_compound_type(s), _bytes };

83
keys.hh
View File

@@ -13,8 +13,12 @@
#include "compound_compat.hh"
#include "utils/managed_bytes.hh"
#include "utils/hashing.hh"
#include "utils/utf8.hh"
#include "replica/database_fwd.hh"
#include "schema/schema_fwd.hh"
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <compare>
//
@@ -669,8 +673,16 @@ public:
// A trichotomic comparator which orders keys according to their ordering on the ring.
std::strong_ordering ring_order_tri_compare(const schema& s, partition_key_view o) const;
};
friend std::ostream& operator<<(std::ostream& out, const partition_key_view& pk);
template <>
struct fmt::formatter<partition_key_view> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const partition_key_view& pk, FormatContext& ctx) const {
return with_linearized(pk.representation(), [&] (bytes_view v) {
return fmt::format_to(ctx.out(), "pk{{{}}}", fmt_hex(v));
});
}
};
class partition_key : public compound_wrapper<partition_key, partition_key_view> {
@@ -745,11 +757,42 @@ public:
void validate(const schema& s) const {
return s.partition_key_type()->validate(representation());
}
friend std::ostream& operator<<(std::ostream& out, const partition_key& pk);
};
std::ostream& operator<<(std::ostream& out, const partition_key::with_schema_wrapper& pk);
template <>
struct fmt::formatter<partition_key> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const partition_key& pk, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "pk{{{}}}", managed_bytes_view(pk.representation()));
}
};
template <>
struct fmt::formatter<partition_key::with_schema_wrapper> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const partition_key::with_schema_wrapper& pk, FormatContext& ctx) const {
const auto& [schema, key] = pk;
const auto& types = key.get_compound_type(schema)->types();
const auto components = key.components(schema);
return fmt::format_to(
ctx.out(), "{}",
fmt::join(boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(types.begin(),
components.begin())),
boost::make_zip_iterator(boost::make_tuple(types.end(),
components.end()))) |
boost::adaptors::transformed([](const auto& type_and_component) {
auto& [type, component] = type_and_component;
auto key = type->to_string(to_bytes(component));
if (utils::utf8::validate((const uint8_t *) key.data(), key.size())) {
return key;
} else {
return sstring("<non-utf8-key>");
}
}),
":"));
}
};
class exploded_clustering_prefix {
std::vector<bytes> _v;
@@ -859,11 +902,37 @@ public:
}
return false;
}
friend std::ostream& operator<<(std::ostream& out, const clustering_key_prefix& ckp);
};
std::ostream& operator<<(std::ostream& out, const clustering_key_prefix::with_schema_wrapper& pk);
template <>
struct fmt::formatter<clustering_key_prefix> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const clustering_key_prefix& ckp, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "ckp{{{}}}", managed_bytes_view(ckp.representation()));
}
};
template <>
struct fmt::formatter<clustering_key_prefix::with_schema_wrapper> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const clustering_key_prefix::with_schema_wrapper& pk, FormatContext& ctx) const {
const auto& [schema, key] = pk;
const auto& types = key.get_compound_type(schema)->types();
const auto components = key.components(schema);
return fmt::format_to(
ctx.out(), "{}",
fmt::join(boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(types.begin(),
components.begin())),
boost::make_zip_iterator(boost::make_tuple(types.end(),
components.end()))) |
boost::adaptors::transformed([](const auto& type_and_component) {
auto& [type, component] = type_and_component;
return type->to_string(to_bytes(component));
}),
":"));
}
};
template<>
struct appending_hash<partition_key_view> {

View File

@@ -85,9 +85,8 @@ public:
};
inline friend std::ostream& operator<<(std::ostream& o, const mp_row_consumer_m::range_tombstone_start& rt_start) {
o << "{ clustering: " << rt_start.ck
<< ", kind: " << rt_start.kind
<< ", tombstone: " << rt_start.tomb << " }";
fmt::print(o, "{{ clustering: {}, kind: {}, tombstone: {}}}",
rt_start.ck, rt_start.kind, rt_start.tomb);
return o;
}

View File

@@ -583,7 +583,7 @@ void test_sliced_read_row_presence(shared_sstable sst, schema_ptr s, reader_perm
return ck_eq(x, cr.key());
});
if (it == expected_cr.end()) {
std::cout << "unexpected clustering row: " << cr.key() << "\n";
fmt::print(std::cout, "unexpected clustering row: {}\n", cr.key());
}
BOOST_REQUIRE(it != expected_cr.end());
expected_cr.erase(it);