feat: define region group and sequence (#2100)

* define region group

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* define region sequence

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* check partition number

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* fix clippy

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* test region seq and group

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

---------

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
This commit is contained in:
Ruihang Xia
2023-08-04 17:08:07 +08:00
committed by GitHub
parent 18896739d8
commit 9718aa17c9
3 changed files with 78 additions and 8 deletions

View File

@@ -469,6 +469,9 @@ pub enum Error {
source: SendError<Message>,
location: Location,
},
#[snafu(display("Too many partitions, location: {}", location))]
TooManyPartitions { location: Location },
}
pub type Result<T> = std::result::Result<T, Error>;
@@ -525,7 +528,8 @@ impl ErrorExt for Error {
| Error::ParseNum { .. }
| Error::UnsupportedSelectorType { .. }
| Error::InvalidArguments { .. }
| Error::InvalidHeartbeatRequest { .. } => StatusCode::InvalidArguments,
| Error::InvalidHeartbeatRequest { .. }
| Error::TooManyPartitions { .. } => StatusCode::InvalidArguments,
Error::LeaseKeyFromUtf8 { .. }
| Error::LeaseValueFromUtf8 { .. }
| Error::StatKeyFromUtf8 { .. }

View File

@@ -24,14 +24,15 @@ use common_meta::rpc::ddl::{
use common_meta::rpc::router;
use common_meta::table_name::TableName;
use common_telemetry::{info, warn};
use snafu::{OptionExt, ResultExt};
use snafu::{ensure, OptionExt, ResultExt};
use store_api::storage::MAX_REGION_SEQ;
use table::metadata::RawTableInfo;
use tonic::{Request, Response};
use super::store::kv::KvStoreRef;
use super::GrpcResult;
use crate::ddl::DdlManagerRef;
use crate::error::{self, Result, TableMetadataManagerSnafu};
use crate::error::{self, Result, TableMetadataManagerSnafu, TooManyPartitionsSnafu};
use crate::metasrv::{MetaSrv, SelectorContext, SelectorRef};
use crate::sequence::SequenceRef;
use crate::table_routes::get_table_route_value;
@@ -192,6 +193,10 @@ async fn handle_create_table_route(
..Default::default()
};
ensure!(
partitions.len() <= MAX_REGION_SEQ as usize,
TooManyPartitionsSnafu
);
let region_routes = partitions
.into_iter()
.enumerate()

View File

@@ -19,16 +19,36 @@ use serde::{Deserialize, Serialize};
use crate::storage::{consts, ColumnDefaultConstraint, ColumnSchema, ConcreteDataType};
/// Id of column, unique in each region.
/// Id of column. Unique in each region.
pub type ColumnId = u32;
/// Id of column family, unique in each region.
/// Id of column family. Unique in each region.
pub type ColumnFamilyId = u32;
/// Sequence number of regions under the same table.
/// Group number of one region. Unique in each region.
pub type RegionGroup = u8;
/// Sequence number of region inside one table. Unique in each table.
/// The first 8 bits are preserved for [RegionGroup].
pub type RegionSeq = u32;
/// Id of regions under the same table. Unique in each table.
/// Is composed by [RegionGroup] and [RegionSeq].
pub type RegionNumber = u32;
/// Id of table.
/// Id of table. Universal unique.
pub type TableId = u32;
/// Id of the region. It's generated by concatenating table id and region number.
const REGION_GROUP_MASK: u32 = 0b1111_1111 << 24;
const REGION_SEQ_MASK: u32 = (0b1 << 24) - 1;
/// The max valid region sequence number.
pub const MAX_REGION_SEQ: u32 = REGION_SEQ_MASK;
/// Id of the region. It's generated by concatenating table id, region group and region number.
///
/// ```plaintext
/// 63 31 23 0
/// ┌────────────────────────────────────┬──────────┬──────────────────┐
/// │ Table Id(32) │ Group(8) │ Sequence(24) │
/// └────────────────────────────────────┴──────────┴──────────────────┘
/// Region Number(32)
/// ```
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct RegionId(u64);
@@ -48,6 +68,16 @@ impl RegionId {
self.0 as RegionNumber
}
/// Returns the group number of the region
pub const fn region_group(&self) -> RegionGroup {
((self.region_number() & REGION_GROUP_MASK) >> 24) as RegionGroup
}
/// Return the sequence number of the region
pub const fn region_sequence(&self) -> RegionSeq {
self.region_number() & REGION_SEQ_MASK
}
/// Returns the region id as u64.
pub const fn as_u64(&self) -> u64 {
self.0
@@ -57,6 +87,19 @@ impl RegionId {
pub const fn from_u64(id: u64) -> RegionId {
RegionId(id)
}
#[cfg(test)]
pub const fn with_group_and_seq(
table_id: TableId,
group: RegionGroup,
seq: RegionSeq,
) -> RegionId {
RegionId(
((table_id as u64) << 32)
| ((group as u32) << 24) as u64
| (seq & REGION_SEQ_MASK) as u64,
)
}
}
impl fmt::Debug for RegionId {
@@ -411,4 +454,22 @@ mod tests {
let parsed: RegionId = serde_json::from_str(&json).unwrap();
assert_eq!(region_id, parsed);
}
#[test]
fn test_retrieve_region_group_and_seq() {
let region_id = RegionId::with_group_and_seq(111, 222, 333);
assert_eq!(111, region_id.table_id());
assert_eq!(222, region_id.region_group());
assert_eq!(333, region_id.region_sequence());
let expected_region_number = 222 << 24 | 333;
assert_eq!(expected_region_number, region_id.region_number());
}
#[test]
fn test_invalid_large_region_sequence() {
// region sequence larger than `MAX_REGION_SEQ` will be masked into valid range
let region_id = RegionId::with_group_and_seq(111, 222, u32::MAX);
assert_eq!(MAX_REGION_SEQ, region_id.region_sequence());
}
}