Skip to content

Commit

Permalink
Token: add constructor and normalization
Browse files Browse the repository at this point in the history
`i64::MIN` turns out to be an invalid value for a token:
https://github.com/scylladb/scylladb/blob/4be70bfc2bc7f133cab492b4aac7bab9c790a48c/dht/token.hh#L32
Hashing algorithm should change `i64::MIN` result to `i64::MAX`.
In order to have this check in one place and make sure we always perform
it I made `value` field of `Token` non-public and created constructor and
getter for it.
  • Loading branch information
Lorak-mmk committed Mar 6, 2024
1 parent 87908f3 commit 3425851
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 149 deletions.
4 changes: 2 additions & 2 deletions examples/compare-tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ async fn main() -> Result<()> {
)
.await?;

let t = prepared.calculate_token(&(pk,))?.unwrap().value;
let t = prepared.calculate_token(&(pk,))?.unwrap().value();

println!(
"Token endpoints for query: {:?}",
session
.get_cluster_data()
.get_token_endpoints("examples_ks", Token { value: t })
.get_token_endpoints("examples_ks", Token::new(t))
.iter()
.map(|n| n.address)
.collect::<Vec<NodeAddr>>()
Expand Down
37 changes: 36 additions & 1 deletion scylla/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,43 @@ use std::num::NonZeroU16;
use thiserror::Error;

#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]

/// Token is a result of computing a hash of a primary key
///
/// It is basically an i64 with one caveat: i64::MIN is not
/// a valid token. It is used to represent infinity.
/// For this reason tokens are normalized - i64::MIN
/// is replaced with i64::MAX. See this fragment of
/// Scylla code for more information:
/// <https://github.com/scylladb/scylladb/blob/4be70bfc2bc7f133cab492b4aac7bab9c790a48c/dht/token.hh#L32>
///
/// This struct is a wrapper over i64 that performs this normalization
/// when initialized using `new()` method.
pub struct Token {
pub value: i64,
value: i64,
}

impl Token {
/// Creates a new token with given value, normalizing the value if necessary
#[inline]
pub fn new(value: i64) -> Self {
Self {
value: if value == i64::MIN { i64::MAX } else { value },
}
}

/// Creates a new token with given value, but skips the normalization.
///
/// This can be used to create incorrect token value - i64::MIN.
#[inline]
pub fn new_denormalized(value: i64) -> Self {
Self { value }
}

#[inline]
pub fn value(&self) -> i64 {
self.value
}
}

pub type Shard = u32;
Expand Down
2 changes: 1 addition & 1 deletion scylla/src/transport/connection_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl NodeConnectionPool {
}

pub(crate) fn connection_for_token(&self, token: Token) -> Result<Arc<Connection>, QueryError> {
trace!(token = token.value, "Selecting connection for token");
trace!(token = token.value(), "Selecting connection for token");
self.with_connections(|pool_conns| match pool_conns {
PoolConnections::NotSharded(conns) => {
Self::choose_random_connection_from_slice(conns).unwrap()
Expand Down
Loading

0 comments on commit 3425851

Please sign in to comment.