utils: add tagged_integer
A generic template for defining strongly typed integer types. Use it here to replace raft::internal::tagged_uint64. Will be used for defining gms generation and version as strong and distinguishable types in following patches. Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
This commit is contained in:
@@ -1155,6 +1155,7 @@ idls = ['idl/gossip_digest.idl.hh',
|
||||
'idl/position_in_partition.idl.hh',
|
||||
'idl/experimental/broadcast_tables_lang.idl.hh',
|
||||
'idl/storage_service.idl.hh',
|
||||
'idl/utils.idl.hh',
|
||||
]
|
||||
|
||||
headers = find_headers('.', excluded_dirs=['idl', 'build', 'seastar', '.git'])
|
||||
|
||||
@@ -59,7 +59,9 @@ set(idl_headers
|
||||
replica_exception.idl.hh
|
||||
per_partition_rate_limit_info.idl.hh
|
||||
position_in_partition.idl.hh
|
||||
experimental/broadcast_tables_lang.idl.hh)
|
||||
experimental/broadcast_tables_lang.idl.hh
|
||||
utils.idl.hh
|
||||
)
|
||||
|
||||
foreach(idl_header ${idl_headers})
|
||||
compile_idl(${idl_header}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "raft/raft.hh"
|
||||
|
||||
#include "idl/utils.idl.hh"
|
||||
|
||||
namespace raft {
|
||||
|
||||
struct snapshot_descriptor {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "raft/raft.hh"
|
||||
|
||||
#include "idl/uuid.idl.hh"
|
||||
#include "idl/utils.idl.hh"
|
||||
|
||||
namespace raft {
|
||||
|
||||
@@ -19,11 +20,6 @@ struct tagged_id {
|
||||
utils::UUID id;
|
||||
};
|
||||
|
||||
template<typename Tag>
|
||||
struct tagged_uint64 {
|
||||
uint64_t get_value();
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
struct server_address {
|
||||
|
||||
18
idl/utils.idl.hh
Normal file
18
idl/utils.idl.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2023-present ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "utils/tagged_integer.hh"
|
||||
|
||||
namespace utils {
|
||||
|
||||
template<typename Tag, typename ValueType>
|
||||
struct tagged_integer final {
|
||||
ValueType value();
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
@@ -98,7 +98,7 @@ const log_entry& fsm::add_entry(T command) {
|
||||
tmp.enter_joint(command.current);
|
||||
command = std::move(tmp);
|
||||
|
||||
logger.trace("[{}] appending joint config entry at {}: {}", _my_id, _log.next_idx().get_value(), command);
|
||||
logger.trace("[{}] appending joint config entry at {}: {}", _my_id, _log.next_idx(), command);
|
||||
}
|
||||
|
||||
utils::get_local_injector().inject("fsm::add_entry/test-failure",
|
||||
@@ -462,7 +462,7 @@ void fsm::maybe_commit() {
|
||||
// system then transitions to the new configuration.
|
||||
configuration cfg(_log.get_configuration());
|
||||
cfg.leave_joint();
|
||||
logger.trace("[{}] appending non-joint config entry at {}: {}", _my_id, _log.next_idx().get_value(), cfg);
|
||||
logger.trace("[{}] appending non-joint config entry at {}: {}", _my_id, _log.next_idx(), cfg);
|
||||
_log.emplace_back(seastar::make_lw_shared<log_entry>({_current_term, _log.next_idx(), std::move(cfg)}));
|
||||
leader_state().tracker.set_configuration(_log.get_configuration(), _log.last_idx());
|
||||
// Leaving joint configuration may commit more entries
|
||||
|
||||
@@ -14,66 +14,8 @@
|
||||
namespace raft {
|
||||
namespace internal {
|
||||
|
||||
template<typename Tag>
|
||||
class tagged_uint64 {
|
||||
uint64_t _val;
|
||||
public:
|
||||
tagged_uint64() : _val(0) {}
|
||||
explicit tagged_uint64(uint64_t v) : _val(v) {}
|
||||
tagged_uint64(const tagged_uint64&) = default;
|
||||
tagged_uint64(tagged_uint64&&) = default;
|
||||
tagged_uint64& operator=(const tagged_uint64&) = default;
|
||||
auto operator<=>(const tagged_uint64&) const = default;
|
||||
explicit operator bool() const { return _val != 0; }
|
||||
|
||||
uint64_t get_value() const {
|
||||
return _val;
|
||||
}
|
||||
operator uint64_t() const {
|
||||
return get_value();
|
||||
}
|
||||
tagged_uint64& operator++() { // pre increment
|
||||
++_val;
|
||||
return *this;
|
||||
}
|
||||
tagged_uint64 operator++(int) { // post increment
|
||||
uint64_t v = _val++;
|
||||
return tagged_uint64(v);
|
||||
}
|
||||
tagged_uint64& operator--() { // pre decrement
|
||||
--_val;
|
||||
return *this;
|
||||
}
|
||||
tagged_uint64 operator--(int) { // post decrement
|
||||
uint64_t v = _val--;
|
||||
return tagged_uint64(v);
|
||||
}
|
||||
tagged_uint64 operator+(const tagged_uint64& o) const {
|
||||
return tagged_uint64(_val + o._val);
|
||||
}
|
||||
tagged_uint64 operator-(const tagged_uint64& o) const {
|
||||
return tagged_uint64(_val - o._val);
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& os, const tagged_uint64<Tag>& u) {
|
||||
os << u._val;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Tag>
|
||||
using tagged_id = utils::tagged_uuid<Tag>;
|
||||
|
||||
} // end of namespace internal
|
||||
} // end of namespace raft
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename Tag>
|
||||
struct hash<raft::internal::tagged_uint64<Tag>> {
|
||||
size_t operator()(const raft::internal::tagged_uint64<Tag>& val) const {
|
||||
return hash<uint64_t>()(val);
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace std
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <seastar/core/abort_source.hh>
|
||||
#include "bytes_ostream.hh"
|
||||
#include "utils/UUID.hh"
|
||||
#include "utils/tagged_integer.hh"
|
||||
#include "internal.hh"
|
||||
#include "logical_clock.hh"
|
||||
|
||||
@@ -39,11 +40,11 @@ using server_id = internal::tagged_id<struct server_id_tag>;
|
||||
using group_id = raft::internal::tagged_id<struct group_id_tag>;
|
||||
|
||||
// This type represents the raft term
|
||||
using term_t = internal::tagged_uint64<struct term_tag>;
|
||||
using term_t = utils::tagged_integer<struct term_tag, int64_t>;
|
||||
// This type represensts the index into the raft log
|
||||
using index_t = internal::tagged_uint64<struct index_tag>;
|
||||
using index_t = utils::tagged_integer<struct index_tag, uint64_t>;
|
||||
// Identifier for a read barrier request
|
||||
using read_id = internal::tagged_uint64<struct read_id_tag>;
|
||||
using read_id = utils::tagged_integer<struct read_id_tag, uint64_t>;
|
||||
|
||||
// Opaque connection properties. May contain ip:port pair for instance.
|
||||
// This value is disseminated between cluster member
|
||||
|
||||
@@ -893,7 +893,7 @@ class persistence {
|
||||
if (b == _stored_entries.end() || (*b)->idx >= idx) {
|
||||
return b;
|
||||
}
|
||||
return b + std::min((idx - (*b)->idx).get_value(), _stored_entries.size());
|
||||
return b + std::min(size_t(idx - (*b)->idx), _stored_entries.size());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
93
utils/tagged_integer.hh
Normal file
93
utils/tagged_integer.hh
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2020-present ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <compare>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
namespace utils {
|
||||
|
||||
template <typename Tag, std::integral ValueType>
|
||||
class tagged_integer {
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
private:
|
||||
value_type _value;
|
||||
public:
|
||||
tagged_integer() noexcept : _value(0) {}
|
||||
explicit tagged_integer(value_type v) noexcept : _value(v) {}
|
||||
|
||||
tagged_integer& operator=(value_type v) noexcept {
|
||||
_value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type value() const noexcept { return _value; }
|
||||
operator value_type() const noexcept { return _value; }
|
||||
|
||||
explicit operator bool() const { return _value != 0; }
|
||||
|
||||
auto operator<=>(const tagged_integer& o) const = default;
|
||||
|
||||
tagged_integer& operator++() noexcept {
|
||||
++_value;
|
||||
return *this;
|
||||
}
|
||||
tagged_integer& operator--() noexcept {
|
||||
--_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
tagged_integer operator++(int) noexcept {
|
||||
auto ret = *this;
|
||||
++_value;
|
||||
return ret;
|
||||
}
|
||||
tagged_integer operator--(int) noexcept {
|
||||
auto ret = *this;
|
||||
--_value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
tagged_integer operator+(const tagged_integer& o) const {
|
||||
return tagged_integer(_value + o._value);
|
||||
}
|
||||
tagged_integer operator-(const tagged_integer& o) const {
|
||||
return tagged_integer(_value - o._value);
|
||||
}
|
||||
|
||||
tagged_integer& operator+=(const tagged_integer& o) const {
|
||||
_value += o._value;
|
||||
return *this;
|
||||
}
|
||||
tagged_integer& operator-=(const tagged_integer& o) const {
|
||||
_value -= o._value;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename Tag, std::integral ValueType>
|
||||
struct hash<utils::tagged_integer<Tag, ValueType>> {
|
||||
size_t operator()(const utils::tagged_integer<Tag, ValueType>& x) const noexcept {
|
||||
return hash<ValueType>{}(x.value());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tag, std::integral ValueType>
|
||||
[[maybe_unused]] ostream& operator<<(ostream& s, const utils::tagged_integer<Tag, ValueType>& x) {
|
||||
return s << x.value();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
Reference in New Issue
Block a user