1pub mod catalog_name;
104pub mod datanode_epoch;
105pub mod datanode_table;
106pub mod flow;
107pub mod node_address;
108pub mod runtime_switch;
109mod schema_metadata_manager;
110pub mod schema_name;
111pub mod table_info;
112pub mod table_name;
113pub mod table_repart;
114pub mod table_route;
115#[cfg(any(test, feature = "testing"))]
116pub mod test_utils;
117pub mod tombstone;
118pub mod topic_name;
119pub mod topic_region;
120pub mod txn_helper;
121pub mod view_info;
122
123use std::collections::{BTreeMap, HashMap, HashSet};
124use std::fmt::Debug;
125use std::ops::{Deref, DerefMut};
126use std::sync::Arc;
127
128use bytes::Bytes;
129use common_base::regex_pattern::NAME_PATTERN;
130use common_catalog::consts::{
131 DEFAULT_CATALOG_NAME, DEFAULT_PRIVATE_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, INFORMATION_SCHEMA_NAME,
132};
133use common_telemetry::warn;
134use common_wal::options::WalOptions;
135use datanode_table::{DatanodeTableKey, DatanodeTableManager, DatanodeTableValue};
136use flow::flow_route::FlowRouteValue;
137use flow::table_flow::TableFlowValue;
138use futures_util::TryStreamExt;
139use futures_util::stream::BoxStream;
140use lazy_static::lazy_static;
141use regex::Regex;
142pub use schema_metadata_manager::{SchemaMetadataManager, SchemaMetadataManagerRef};
143use serde::de::DeserializeOwned;
144use serde::{Deserialize, Serialize};
145use snafu::{OptionExt, ResultExt, ensure};
146use store_api::storage::RegionNumber;
147use table::metadata::{TableId, TableInfo};
148use table::table_name::TableName;
149use table_info::{TableInfoKey, TableInfoManager, TableInfoValue};
150use table_name::{TableNameKey, TableNameManager, TableNameValue};
151use topic_name::TopicNameManager;
152use topic_region::{TopicRegionKey, TopicRegionManager};
153use view_info::{ViewInfoKey, ViewInfoManager, ViewInfoValue};
154
155use self::catalog_name::{CatalogManager, CatalogNameKey, CatalogNameValue};
156use self::datanode_epoch::DatanodeEpochValue;
157use self::datanode_table::RegionInfo;
158use self::flow::flow_info::FlowInfoValue;
159use self::flow::flow_name::FlowNameValue;
160use self::schema_name::{SchemaManager, SchemaNameKey, SchemaNameValue};
161use self::table_route::{TableRouteManager, TableRouteValue};
162use self::tombstone::TombstoneManager;
163use crate::DatanodeId;
164use crate::error::{self, Result, SerdeJsonSnafu};
165use crate::key::flow::flow_state::FlowStateValue;
166use crate::key::node_address::NodeAddressValue;
167use crate::key::table_repart::{TableRepartKey, TableRepartManager};
168use crate::key::table_route::TableRouteKey;
169use crate::key::topic_region::TopicRegionValue;
170use crate::key::txn_helper::TxnOpGetResponseSet;
171use crate::kv_backend::KvBackendRef;
172use crate::kv_backend::txn::{Txn, TxnOp};
173use crate::rpc::KeyValue;
174use crate::rpc::router::{LeaderState, RegionRoute, region_distribution};
175use crate::rpc::store::{BatchDeleteRequest, PutRequest};
176use crate::state_store::PoisonValue;
177use crate::wal_provider::RegionWalOptions;
178
179pub const TOPIC_NAME_PATTERN: &str = r"[a-zA-Z0-9_:-][a-zA-Z0-9_:\-\.@#]*";
180pub const LEGACY_MAINTENANCE_KEY: &str = "__maintenance";
181pub const MAINTENANCE_KEY: &str = "__switches/maintenance";
182pub const REPARTITION_GC_REQUIRED_KEY: &str = "__requirements/gc/repartition";
183pub const PAUSE_PROCEDURE_KEY: &str = "__switches/pause_procedure";
184pub const RECOVERY_MODE_KEY: &str = "__switches/recovery";
185
186pub const DATANODE_TABLE_KEY_PREFIX: &str = "__dn_table";
187pub const DATANODE_EPOCH_KEY_PREFIX: &str = "__datanode_epoch";
188pub const TABLE_INFO_KEY_PREFIX: &str = "__table_info";
189pub const VIEW_INFO_KEY_PREFIX: &str = "__view_info";
190pub const TABLE_NAME_KEY_PREFIX: &str = "__table_name";
191pub const CATALOG_NAME_KEY_PREFIX: &str = "__catalog_name";
192pub const SCHEMA_NAME_KEY_PREFIX: &str = "__schema_name";
193pub const TABLE_ROUTE_PREFIX: &str = "__table_route";
194pub const TABLE_REPART_PREFIX: &str = "__table_repart";
195pub const NODE_ADDRESS_PREFIX: &str = "__node_address";
196pub const KAFKA_TOPIC_KEY_PREFIX: &str = "__topic_name/kafka";
197pub const LEGACY_TOPIC_KEY_PREFIX: &str = "__created_wal_topics/kafka";
199pub const TOPIC_REGION_PREFIX: &str = "__topic_region";
200
201pub const ELECTION_KEY: &str = "__metasrv_election";
203pub const CANDIDATES_ROOT: &str = "__metasrv_election_candidates/";
205
206pub const CACHE_KEY_PREFIXES: [&str; 6] = [
208 TABLE_NAME_KEY_PREFIX,
209 CATALOG_NAME_KEY_PREFIX,
210 SCHEMA_NAME_KEY_PREFIX,
211 TABLE_ROUTE_PREFIX,
212 NODE_ADDRESS_PREFIX,
213 DATANODE_EPOCH_KEY_PREFIX,
214];
215
216#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
218pub struct RegionRoleSet {
219 pub leader_regions: Vec<RegionNumber>,
221 pub follower_regions: Vec<RegionNumber>,
223}
224
225impl<'de> Deserialize<'de> for RegionRoleSet {
226 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
227 where
228 D: serde::Deserializer<'de>,
229 {
230 #[derive(Deserialize)]
231 #[serde(untagged)]
232 enum RegionRoleSetOrLeaderOnly {
233 Full {
234 leader_regions: Vec<RegionNumber>,
235 follower_regions: Vec<RegionNumber>,
236 },
237 LeaderOnly(Vec<RegionNumber>),
238 }
239 match RegionRoleSetOrLeaderOnly::deserialize(deserializer)? {
240 RegionRoleSetOrLeaderOnly::Full {
241 leader_regions,
242 follower_regions,
243 } => Ok(RegionRoleSet::new(leader_regions, follower_regions)),
244 RegionRoleSetOrLeaderOnly::LeaderOnly(leader_regions) => {
245 Ok(RegionRoleSet::new(leader_regions, vec![]))
246 }
247 }
248 }
249}
250
251impl RegionRoleSet {
252 pub fn new(leader_regions: Vec<RegionNumber>, follower_regions: Vec<RegionNumber>) -> Self {
254 Self {
255 leader_regions,
256 follower_regions,
257 }
258 }
259
260 pub fn add_leader_region(&mut self, region_number: RegionNumber) {
262 self.leader_regions.push(region_number);
263 }
264
265 pub fn add_follower_region(&mut self, region_number: RegionNumber) {
267 self.follower_regions.push(region_number);
268 }
269
270 pub fn sort(&mut self) {
272 self.follower_regions.sort();
273 self.leader_regions.sort();
274 }
275}
276
277pub type RegionDistribution = BTreeMap<DatanodeId, RegionRoleSet>;
281
282pub type FlowId = u32;
284pub type FlowPartitionId = u32;
286
287lazy_static! {
288 pub static ref TOPIC_NAME_PATTERN_REGEX: Regex = Regex::new(TOPIC_NAME_PATTERN).unwrap();
289}
290
291lazy_static! {
292 static ref TABLE_INFO_KEY_PATTERN: Regex =
293 Regex::new(&format!("^{TABLE_INFO_KEY_PREFIX}/([0-9]+)$")).unwrap();
294}
295
296lazy_static! {
297 static ref VIEW_INFO_KEY_PATTERN: Regex =
298 Regex::new(&format!("^{VIEW_INFO_KEY_PREFIX}/([0-9]+)$")).unwrap();
299}
300
301lazy_static! {
302 static ref TABLE_ROUTE_KEY_PATTERN: Regex =
303 Regex::new(&format!("^{TABLE_ROUTE_PREFIX}/([0-9]+)$")).unwrap();
304}
305
306lazy_static! {
307 pub(crate) static ref TABLE_REPART_KEY_PATTERN: Regex =
308 Regex::new(&format!("^{TABLE_REPART_PREFIX}/([0-9]+)$")).unwrap();
309}
310
311lazy_static! {
312 static ref DATANODE_TABLE_KEY_PATTERN: Regex =
313 Regex::new(&format!("^{DATANODE_TABLE_KEY_PREFIX}/([0-9]+)/([0-9]+)$")).unwrap();
314}
315
316lazy_static! {
317 static ref TABLE_NAME_KEY_PATTERN: Regex = Regex::new(&format!(
318 "^{TABLE_NAME_KEY_PREFIX}/({NAME_PATTERN})/({NAME_PATTERN})/({NAME_PATTERN})$"
319 ))
320 .unwrap();
321}
322
323lazy_static! {
324 static ref CATALOG_NAME_KEY_PATTERN: Regex = Regex::new(&format!(
326 "^{CATALOG_NAME_KEY_PREFIX}/({NAME_PATTERN})$"
327 ))
328 .unwrap();
329}
330
331lazy_static! {
332 static ref SCHEMA_NAME_KEY_PATTERN:Regex=Regex::new(&format!(
334 "^{SCHEMA_NAME_KEY_PREFIX}/({NAME_PATTERN})/({NAME_PATTERN})$"
335 ))
336 .unwrap();
337}
338
339lazy_static! {
340 static ref NODE_ADDRESS_PATTERN: Regex =
341 Regex::new(&format!("^{NODE_ADDRESS_PREFIX}/([0-9]+)/([0-9]+)$")).unwrap();
342}
343
344lazy_static! {
345 pub static ref KAFKA_TOPIC_KEY_PATTERN: Regex =
346 Regex::new(&format!("^{KAFKA_TOPIC_KEY_PREFIX}/(.*)$")).unwrap();
347}
348
349lazy_static! {
350 pub static ref TOPIC_REGION_PATTERN: Regex = Regex::new(&format!(
351 "^{TOPIC_REGION_PREFIX}/({TOPIC_NAME_PATTERN})/([0-9]+)$"
352 ))
353 .unwrap();
354}
355
356pub trait MetadataKey<'a, T> {
358 fn to_bytes(&self) -> Vec<u8>;
359
360 fn from_bytes(bytes: &'a [u8]) -> Result<T>;
361}
362
363#[derive(Debug, Clone, PartialEq)]
364pub struct BytesAdapter(Vec<u8>);
365
366impl From<Vec<u8>> for BytesAdapter {
367 fn from(value: Vec<u8>) -> Self {
368 Self(value)
369 }
370}
371
372impl<'a> MetadataKey<'a, BytesAdapter> for BytesAdapter {
373 fn to_bytes(&self) -> Vec<u8> {
374 self.0.clone()
375 }
376
377 fn from_bytes(bytes: &'a [u8]) -> Result<BytesAdapter> {
378 Ok(BytesAdapter(bytes.to_vec()))
379 }
380}
381
382pub(crate) trait MetadataKeyGetTxnOp {
383 fn build_get_op(
384 &self,
385 ) -> (
386 TxnOp,
387 impl for<'a> FnMut(&'a mut TxnOpGetResponseSet) -> Option<Vec<u8>>,
388 );
389}
390
391pub trait MetadataValue {
392 fn try_from_raw_value(raw_value: &[u8]) -> Result<Self>
393 where
394 Self: Sized;
395
396 fn try_as_raw_value(&self) -> Result<Vec<u8>>;
397}
398
399pub type TableMetadataManagerRef = Arc<TableMetadataManager>;
400
401pub struct TableMetadataManager {
402 table_name_manager: TableNameManager,
403 table_info_manager: TableInfoManager,
404 view_info_manager: ViewInfoManager,
405 datanode_table_manager: DatanodeTableManager,
406 catalog_manager: CatalogManager,
407 schema_manager: SchemaManager,
408 table_route_manager: TableRouteManager,
409 table_repart_manager: TableRepartManager,
410 tombstone_manager: TombstoneManager,
411 topic_name_manager: TopicNameManager,
412 topic_region_manager: TopicRegionManager,
413 kv_backend: KvBackendRef,
414}
415
416#[macro_export]
417macro_rules! ensure_values {
418 ($got:expr, $expected_value:expr, $name:expr) => {
419 ensure!(
420 $got == $expected_value,
421 error::UnexpectedSnafu {
422 err_msg: format!(
423 "Reads the different value: {:?} during {}, expected: {:?}",
424 $got, $name, $expected_value
425 )
426 }
427 );
428 };
429}
430
431pub struct DeserializedValueWithBytes<T: DeserializeOwned + Serialize> {
441 bytes: Bytes,
443 inner: T,
445}
446
447#[derive(Debug, Clone, PartialEq, Eq)]
448pub struct DroppedTableName {
449 pub table_id: TableId,
451 pub table_name: TableName,
453 pub dropped_at: Option<i64>,
455 pub retention_expires_at: Option<i64>,
457 pub drop_generation: Option<String>,
459 pub purging: bool,
461}
462
463#[derive(Debug, Clone)]
464pub struct DroppedTableMetadata {
465 pub table_id: TableId,
467 pub table_name: TableName,
469 pub table_info_value: TableInfoValue,
471 pub table_route_value: TableRouteValue,
473 pub region_wal_options: HashMap<RegionNumber, WalOptions>,
475 pub dropped_at: Option<i64>,
477 pub retention_expires_at: Option<i64>,
479 pub drop_generation: Option<String>,
481}
482
483pub struct DroppedTableLifecycle<'a> {
485 pub dropped_at: Option<i64>,
486 pub retention_expires_at: Option<i64>,
487 pub drop_generation: Option<&'a str>,
488}
489
490const DROPPED_AT_KEY_PREFIX: &str = "__dropped_at";
491const RETENTION_EXPIRES_AT_KEY_PREFIX: &str = "__retention_expires_at";
492const DROP_GENERATION_KEY_PREFIX: &str = "__drop_generation";
493const PURGING_KEY_PREFIX: &str = "__purging";
494
495pub(crate) fn dropped_at_key(table_id: TableId) -> Vec<u8> {
496 format!("{DROPPED_AT_KEY_PREFIX}/{table_id}").into_bytes()
497}
498
499pub(crate) fn retention_expires_at_key(table_id: TableId) -> Vec<u8> {
500 format!("{RETENTION_EXPIRES_AT_KEY_PREFIX}/{table_id}").into_bytes()
501}
502
503pub(crate) fn drop_generation_key(table_id: TableId) -> Vec<u8> {
504 format!("{DROP_GENERATION_KEY_PREFIX}/{table_id}").into_bytes()
505}
506
507pub(crate) fn purging_key(table_id: TableId) -> Vec<u8> {
508 format!("{PURGING_KEY_PREFIX}/{table_id}").into_bytes()
509}
510
511impl<T: DeserializeOwned + Serialize> Deref for DeserializedValueWithBytes<T> {
512 type Target = T;
513
514 fn deref(&self) -> &Self::Target {
515 &self.inner
516 }
517}
518
519impl<T: DeserializeOwned + Serialize> DerefMut for DeserializedValueWithBytes<T> {
520 fn deref_mut(&mut self) -> &mut Self::Target {
521 &mut self.inner
522 }
523}
524
525impl<T: DeserializeOwned + Serialize + Debug> Debug for DeserializedValueWithBytes<T> {
526 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
527 write!(
528 f,
529 "DeserializedValueWithBytes(inner: {:?}, bytes: {:?})",
530 self.inner, self.bytes
531 )
532 }
533}
534
535impl<T: DeserializeOwned + Serialize> Serialize for DeserializedValueWithBytes<T> {
536 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
540 where
541 S: serde::Serializer,
542 {
543 serializer.serialize_str(&String::from_utf8_lossy(&self.bytes))
546 }
547}
548
549impl<'de, T: DeserializeOwned + Serialize + MetadataValue> Deserialize<'de>
550 for DeserializedValueWithBytes<T>
551{
552 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
556 where
557 D: serde::Deserializer<'de>,
558 {
559 let buf = String::deserialize(deserializer)?;
560 let bytes = Bytes::from(buf);
561
562 let value = DeserializedValueWithBytes::from_inner_bytes(bytes)
563 .map_err(|err| serde::de::Error::custom(err.to_string()))?;
564
565 Ok(value)
566 }
567}
568
569impl<T: Serialize + DeserializeOwned + Clone> Clone for DeserializedValueWithBytes<T> {
570 fn clone(&self) -> Self {
571 Self {
572 bytes: self.bytes.clone(),
573 inner: self.inner.clone(),
574 }
575 }
576}
577
578impl<T: Serialize + DeserializeOwned + MetadataValue> DeserializedValueWithBytes<T> {
579 pub fn from_inner_bytes(bytes: Bytes) -> Result<Self> {
582 let inner = T::try_from_raw_value(&bytes)?;
583 Ok(Self { bytes, inner })
584 }
585
586 pub fn from_inner_slice(bytes: &[u8]) -> Result<Self> {
589 Self::from_inner_bytes(Bytes::copy_from_slice(bytes))
590 }
591
592 pub fn into_inner(self) -> T {
593 self.inner
594 }
595
596 pub fn get_inner_ref(&self) -> &T {
597 &self.inner
598 }
599
600 pub fn get_raw_bytes(&self) -> Vec<u8> {
602 self.bytes.to_vec()
603 }
604
605 #[cfg(any(test, feature = "testing"))]
606 pub fn from_inner(inner: T) -> Self {
607 let bytes = serde_json::to_vec(&inner).unwrap();
608
609 Self {
610 bytes: Bytes::from(bytes),
611 inner,
612 }
613 }
614}
615
616impl TableMetadataManager {
617 pub fn new(kv_backend: KvBackendRef) -> Self {
618 TableMetadataManager {
619 table_name_manager: TableNameManager::new(kv_backend.clone()),
620 table_info_manager: TableInfoManager::new(kv_backend.clone()),
621 view_info_manager: ViewInfoManager::new(kv_backend.clone()),
622 datanode_table_manager: DatanodeTableManager::new(kv_backend.clone()),
623 catalog_manager: CatalogManager::new(kv_backend.clone()),
624 schema_manager: SchemaManager::new(kv_backend.clone()),
625 table_route_manager: TableRouteManager::new(kv_backend.clone()),
626 table_repart_manager: TableRepartManager::new(kv_backend.clone()),
627 tombstone_manager: TombstoneManager::new(kv_backend.clone()),
628 topic_name_manager: TopicNameManager::new(kv_backend.clone()),
629 topic_region_manager: TopicRegionManager::new(kv_backend.clone()),
630 kv_backend,
631 }
632 }
633
634 pub fn new_with_custom_tombstone_prefix(
636 kv_backend: KvBackendRef,
637 tombstone_prefix: &str,
638 ) -> Self {
639 Self {
640 table_name_manager: TableNameManager::new(kv_backend.clone()),
641 table_info_manager: TableInfoManager::new(kv_backend.clone()),
642 view_info_manager: ViewInfoManager::new(kv_backend.clone()),
643 datanode_table_manager: DatanodeTableManager::new(kv_backend.clone()),
644 catalog_manager: CatalogManager::new(kv_backend.clone()),
645 schema_manager: SchemaManager::new(kv_backend.clone()),
646 table_route_manager: TableRouteManager::new(kv_backend.clone()),
647 table_repart_manager: TableRepartManager::new(kv_backend.clone()),
648 tombstone_manager: TombstoneManager::new_with_prefix(
649 kv_backend.clone(),
650 tombstone_prefix,
651 ),
652 topic_name_manager: TopicNameManager::new(kv_backend.clone()),
653 topic_region_manager: TopicRegionManager::new(kv_backend.clone()),
654 kv_backend,
655 }
656 }
657
658 pub async fn init(&self) -> Result<()> {
659 let catalog_name = CatalogNameKey::new(DEFAULT_CATALOG_NAME);
660
661 self.catalog_manager().create(catalog_name, true).await?;
662
663 let internal_schemas = [
664 DEFAULT_SCHEMA_NAME,
665 INFORMATION_SCHEMA_NAME,
666 DEFAULT_PRIVATE_SCHEMA_NAME,
667 ];
668
669 for schema_name in internal_schemas {
670 let schema_key = SchemaNameKey::new(DEFAULT_CATALOG_NAME, schema_name);
671
672 self.schema_manager().create(schema_key, None, true).await?;
673 }
674
675 Ok(())
676 }
677
678 pub fn table_name_manager(&self) -> &TableNameManager {
679 &self.table_name_manager
680 }
681
682 pub fn table_info_manager(&self) -> &TableInfoManager {
683 &self.table_info_manager
684 }
685
686 pub fn view_info_manager(&self) -> &ViewInfoManager {
687 &self.view_info_manager
688 }
689
690 pub fn datanode_table_manager(&self) -> &DatanodeTableManager {
691 &self.datanode_table_manager
692 }
693
694 pub fn catalog_manager(&self) -> &CatalogManager {
695 &self.catalog_manager
696 }
697
698 pub fn schema_manager(&self) -> &SchemaManager {
699 &self.schema_manager
700 }
701
702 pub fn table_route_manager(&self) -> &TableRouteManager {
703 &self.table_route_manager
704 }
705
706 pub fn table_repart_manager(&self) -> &TableRepartManager {
707 &self.table_repart_manager
708 }
709
710 pub fn topic_name_manager(&self) -> &TopicNameManager {
711 &self.topic_name_manager
712 }
713
714 pub fn topic_region_manager(&self) -> &TopicRegionManager {
715 &self.topic_region_manager
716 }
717
718 pub fn kv_backend(&self) -> &KvBackendRef {
719 &self.kv_backend
720 }
721
722 pub async fn get_full_table_info(
723 &self,
724 table_id: TableId,
725 ) -> Result<(
726 Option<DeserializedValueWithBytes<TableInfoValue>>,
727 Option<DeserializedValueWithBytes<TableRouteValue>>,
728 )> {
729 let table_info_key = TableInfoKey::new(table_id);
730 let table_route_key = TableRouteKey::new(table_id);
731 let (table_info_txn, table_info_filter) = table_info_key.build_get_op();
732 let (table_route_txn, table_route_filter) = table_route_key.build_get_op();
733
734 let txn = Txn::new().and_then(vec![table_info_txn, table_route_txn]);
735 let mut res = self.kv_backend.txn(txn).await?;
736 let mut set = TxnOpGetResponseSet::from(&mut res.responses);
737 let table_info_value = TxnOpGetResponseSet::decode_with(table_info_filter)(&mut set)?;
738 let mut table_route_value = TxnOpGetResponseSet::decode_with(table_route_filter)(&mut set)?;
739 if let Some(table_route_value) = &mut table_route_value {
740 self.table_route_manager()
741 .table_route_storage()
742 .remap_table_route(table_route_value)
743 .await?;
744 }
745 Ok((table_info_value, table_route_value))
746 }
747
748 pub async fn create_view_metadata(
758 &self,
759 view_info: TableInfo,
760 raw_logical_plan: Vec<u8>,
761 table_names: HashSet<TableName>,
762 columns: Vec<String>,
763 plan_columns: Vec<String>,
764 definition: String,
765 ) -> Result<()> {
766 let view_id = view_info.ident.table_id;
767
768 let view_name = TableNameKey::new(
770 &view_info.catalog_name,
771 &view_info.schema_name,
772 &view_info.name,
773 );
774 let create_table_name_txn = self
775 .table_name_manager()
776 .build_create_txn(&view_name, view_id)?;
777
778 let table_info_value = TableInfoValue::new(view_info);
780
781 let (create_table_info_txn, on_create_table_info_failure) = self
782 .table_info_manager()
783 .build_create_txn(view_id, &table_info_value)?;
784
785 let view_info_value = ViewInfoValue::new(
787 raw_logical_plan.into(),
788 table_names,
789 columns,
790 plan_columns,
791 definition,
792 );
793 let (create_view_info_txn, on_create_view_info_failure) = self
794 .view_info_manager()
795 .build_create_txn(view_id, &view_info_value)?;
796
797 let txn = Txn::merge_all(vec![
798 create_table_name_txn,
799 create_table_info_txn,
800 create_view_info_txn,
801 ]);
802
803 let mut r = self.kv_backend.txn(txn).await?;
804
805 if !r.succeeded {
807 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
808 let remote_table_info = on_create_table_info_failure(&mut set)?
809 .context(error::UnexpectedSnafu {
810 err_msg: "Reads the empty table info in comparing operation of creating table metadata",
811 })?
812 .into_inner();
813
814 let remote_view_info = on_create_view_info_failure(&mut set)?
815 .context(error::UnexpectedSnafu {
816 err_msg: "Reads the empty view info in comparing operation of creating view metadata",
817 })?
818 .into_inner();
819
820 let op_name = "the creating view metadata";
821 ensure_values!(remote_table_info, table_info_value, op_name);
822 ensure_values!(remote_view_info, view_info_value, op_name);
823 }
824
825 Ok(())
826 }
827
828 pub async fn create_table_metadata(
831 &self,
832 table_info: TableInfo,
833 table_route_value: TableRouteValue,
834 region_wal_options: RegionWalOptions,
835 ) -> Result<()> {
836 let table_id = table_info.ident.table_id;
837 let engine = table_info.meta.engine.clone();
838
839 let table_name = TableNameKey::new(
841 &table_info.catalog_name,
842 &table_info.schema_name,
843 &table_info.name,
844 );
845 let create_table_name_txn = self
846 .table_name_manager()
847 .build_create_txn(&table_name, table_id)?;
848
849 let region_options = table_info.to_region_options();
850 let table_info_value = TableInfoValue::new(table_info);
852 let (create_table_info_txn, on_create_table_info_failure) = self
853 .table_info_manager()
854 .build_create_txn(table_id, &table_info_value)?;
855
856 let (create_table_route_txn, on_create_table_route_failure) = self
857 .table_route_manager()
858 .table_route_storage()
859 .build_create_txn(table_id, &table_route_value)?;
860
861 let create_topic_region_txn = self
862 .topic_region_manager
863 .build_create_txn(table_id, ®ion_wal_options)?;
864
865 let mut txn = Txn::merge_all(vec![
866 create_table_name_txn,
867 create_table_info_txn,
868 create_table_route_txn,
869 create_topic_region_txn,
870 ]);
871
872 if let TableRouteValue::Physical(x) = &table_route_value {
873 let region_storage_path = table_info_value.region_storage_path();
874 let create_datanode_table_txn = self.datanode_table_manager().build_create_txn(
875 table_id,
876 &engine,
877 ®ion_storage_path,
878 region_options,
879 region_wal_options,
880 region_distribution(&x.region_routes),
881 )?;
882 txn = txn.merge(create_datanode_table_txn);
883 }
884
885 let mut r = self.kv_backend.txn(txn).await?;
886
887 if !r.succeeded {
889 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
890 let remote_table_info = on_create_table_info_failure(&mut set)?
891 .context(error::UnexpectedSnafu {
892 err_msg: "Reads the empty table info in comparing operation of creating table metadata",
893 })?
894 .into_inner();
895
896 let remote_table_route = on_create_table_route_failure(&mut set)?
897 .context(error::UnexpectedSnafu {
898 err_msg: "Reads the empty table route in comparing operation of creating table metadata",
899 })?
900 .into_inner();
901
902 let op_name = "the creating table metadata";
903 ensure_values!(remote_table_info, table_info_value, op_name);
904 ensure_values!(remote_table_route, table_route_value, op_name);
905 }
906
907 Ok(())
908 }
909
910 pub fn create_logical_tables_metadata_chunk_size(&self) -> usize {
911 self.kv_backend.max_txn_ops() / 3
914 }
915
916 pub async fn create_logical_tables_metadata(
918 &self,
919 tables_data: Vec<(TableInfo, TableRouteValue)>,
920 ) -> Result<()> {
921 let len = tables_data.len();
922 let mut txns = Vec::with_capacity(3 * len);
923 struct OnFailure<F1, R1, F2, R2>
924 where
925 F1: FnOnce(&mut TxnOpGetResponseSet) -> R1,
926 F2: FnOnce(&mut TxnOpGetResponseSet) -> R2,
927 {
928 table_info_value: TableInfoValue,
929 on_create_table_info_failure: F1,
930 table_route_value: TableRouteValue,
931 on_create_table_route_failure: F2,
932 }
933 let mut on_failures = Vec::with_capacity(len);
934 for (table_info, table_route_value) in tables_data {
935 let table_id = table_info.ident.table_id;
936
937 let table_name = TableNameKey::new(
939 &table_info.catalog_name,
940 &table_info.schema_name,
941 &table_info.name,
942 );
943 let create_table_name_txn = self
944 .table_name_manager()
945 .build_create_txn(&table_name, table_id)?;
946 txns.push(create_table_name_txn);
947
948 let table_info_value = TableInfoValue::new(table_info);
950 let (create_table_info_txn, on_create_table_info_failure) =
951 self.table_info_manager()
952 .build_create_txn(table_id, &table_info_value)?;
953 txns.push(create_table_info_txn);
954
955 let (create_table_route_txn, on_create_table_route_failure) = self
956 .table_route_manager()
957 .table_route_storage()
958 .build_create_txn(table_id, &table_route_value)?;
959 txns.push(create_table_route_txn);
960
961 on_failures.push(OnFailure {
962 table_info_value,
963 on_create_table_info_failure,
964 table_route_value,
965 on_create_table_route_failure,
966 });
967 }
968
969 let txn = Txn::merge_all(txns);
970 let mut r = self.kv_backend.txn(txn).await?;
971
972 if !r.succeeded {
974 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
975 for on_failure in on_failures {
976 let remote_table_info = (on_failure.on_create_table_info_failure)(&mut set)?
977 .context(error::UnexpectedSnafu {
978 err_msg: "Reads the empty table info in comparing operation of creating table metadata",
979 })?
980 .into_inner();
981
982 let remote_table_route = (on_failure.on_create_table_route_failure)(&mut set)?
983 .context(error::UnexpectedSnafu {
984 err_msg: "Reads the empty table route in comparing operation of creating table metadata",
985 })?
986 .into_inner();
987
988 let op_name = "the creating logical tables metadata";
989 ensure_values!(remote_table_info, on_failure.table_info_value, op_name);
990 ensure_values!(remote_table_route, on_failure.table_route_value, op_name);
991 }
992 }
993
994 Ok(())
995 }
996
997 fn table_metadata_keys(
998 &self,
999 table_id: TableId,
1000 table_name: &TableName,
1001 table_route_value: &TableRouteValue,
1002 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1003 ) -> Result<Vec<Vec<u8>>> {
1004 let datanode_ids = if table_route_value.is_physical() {
1006 region_distribution(table_route_value.region_routes()?)
1007 .into_keys()
1008 .collect()
1009 } else {
1010 vec![]
1011 };
1012 let mut keys = Vec::with_capacity(3 + datanode_ids.len());
1013 let table_name = TableNameKey::new(
1014 &table_name.catalog_name,
1015 &table_name.schema_name,
1016 &table_name.table_name,
1017 );
1018 let table_info_key = TableInfoKey::new(table_id);
1019 let table_route_key = TableRouteKey::new(table_id);
1020 let table_repart_key = TableRepartKey::new(table_id);
1021 let datanode_table_keys = datanode_ids
1022 .into_iter()
1023 .map(|datanode_id| DatanodeTableKey::new(datanode_id, table_id))
1024 .collect::<HashSet<_>>();
1025 let topic_region_map = self
1026 .topic_region_manager
1027 .get_topic_region_mapping(table_id, region_wal_options);
1028 let topic_region_keys = topic_region_map
1029 .iter()
1030 .map(|(region_id, topic)| TopicRegionKey::new(*region_id, topic))
1031 .collect::<Vec<_>>();
1032 keys.push(table_name.to_bytes());
1033 keys.push(table_info_key.to_bytes());
1034 keys.push(table_route_key.to_bytes());
1035 keys.push(table_repart_key.to_bytes());
1036 for key in &datanode_table_keys {
1037 keys.push(key.to_bytes());
1038 }
1039 for key in topic_region_keys {
1040 keys.push(key.to_bytes());
1041 }
1042 Ok(keys)
1043 }
1044
1045 pub async fn delete_table_metadata(
1048 &self,
1049 table_id: TableId,
1050 table_name: &TableName,
1051 table_route_value: &TableRouteValue,
1052 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1053 dropped_at: Option<i64>,
1054 ) -> Result<()> {
1055 self.delete_table_metadata_with_retention(
1056 table_id,
1057 table_name,
1058 table_route_value,
1059 region_wal_options,
1060 dropped_at,
1061 None,
1062 )
1063 .await
1064 }
1065
1066 pub async fn delete_table_metadata_with_retention(
1068 &self,
1069 table_id: TableId,
1070 table_name: &TableName,
1071 table_route_value: &TableRouteValue,
1072 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1073 dropped_at: Option<i64>,
1074 retention_expires_at: Option<i64>,
1075 ) -> Result<()> {
1076 self.delete_table_metadata_with_retention_and_generation(
1077 table_id,
1078 table_name,
1079 table_route_value,
1080 region_wal_options,
1081 DroppedTableLifecycle {
1082 dropped_at,
1083 retention_expires_at,
1084 drop_generation: None,
1085 },
1086 )
1087 .await
1088 }
1089
1090 pub async fn delete_table_metadata_with_retention_and_generation(
1092 &self,
1093 table_id: TableId,
1094 table_name: &TableName,
1095 table_route_value: &TableRouteValue,
1096 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1097 lifecycle: DroppedTableLifecycle<'_>,
1098 ) -> Result<()> {
1099 let keys =
1100 self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1101 if let Some(dropped_at) = lifecycle.dropped_at {
1102 let mut markers = vec![(
1103 dropped_at_key(table_id),
1104 dropped_at.to_string().into_bytes(),
1105 )];
1106 if let Some(retention_expires_at) = lifecycle.retention_expires_at {
1107 markers.push((
1108 retention_expires_at_key(table_id),
1109 retention_expires_at.to_string().into_bytes(),
1110 ));
1111 }
1112 if let Some(drop_generation) = lifecycle.drop_generation {
1113 markers.push((
1114 drop_generation_key(table_id),
1115 drop_generation.as_bytes().to_vec(),
1116 ));
1117 }
1118 self.tombstone_manager
1119 .create_with_markers(keys, markers)
1120 .await
1121 .map(|_| ())
1122 } else {
1123 self.tombstone_manager.create(keys).await.map(|_| ())
1124 }
1125 }
1126
1127 pub async fn list_dropped_tables(&self) -> Result<Vec<DroppedTableName>> {
1129 self.collect_dropped_tables(self.tombstone_manager.tombstoned_table_names())
1130 .await
1131 }
1132
1133 pub async fn list_dropped_tables_by_catalog(
1135 &self,
1136 catalog: &str,
1137 ) -> Result<Vec<DroppedTableName>> {
1138 self.collect_dropped_tables(
1139 self.tombstone_manager
1140 .tombstoned_table_names_by_catalog(catalog),
1141 )
1142 .await
1143 }
1144
1145 async fn collect_dropped_tables(
1146 &self,
1147 mut stream: BoxStream<'static, Result<KeyValue>>,
1148 ) -> Result<Vec<DroppedTableName>> {
1149 let mut dropped_tables = Vec::new();
1150
1151 while let Some(kv) = stream.try_next().await? {
1152 let raw_key = self.tombstone_manager.strip_tombstone_prefix(&kv.key)?;
1153 let table_name = TableNameKey::from_bytes(raw_key)?.into();
1154 let table_id = TableNameValue::try_from_raw_value(&kv.value)?.table_id();
1155 dropped_tables.push(DroppedTableName {
1156 table_id,
1157 table_name,
1158 dropped_at: None,
1159 retention_expires_at: None,
1160 drop_generation: None,
1161 purging: false,
1162 });
1163 }
1164 if dropped_tables.is_empty() {
1165 return Ok(dropped_tables);
1166 }
1167
1168 let marker_keys = dropped_tables
1169 .iter()
1170 .flat_map(|table| {
1171 vec![
1172 dropped_at_key(table.table_id),
1173 retention_expires_at_key(table.table_id),
1174 drop_generation_key(table.table_id),
1175 purging_key(table.table_id),
1176 ]
1177 })
1178 .collect::<Vec<_>>();
1179 let marker_values = self.tombstone_manager.batch_get(&marker_keys).await?;
1180 for table in &mut dropped_tables {
1181 table.dropped_at = Self::parse_dropped_at(
1182 table.table_id,
1183 marker_values.get(&dropped_at_key(table.table_id)),
1184 )?;
1185 table.retention_expires_at = Self::parse_retention_expires_at(
1186 table.table_id,
1187 marker_values.get(&retention_expires_at_key(table.table_id)),
1188 )?;
1189 table.drop_generation = Self::parse_drop_generation(
1190 marker_values.get(&drop_generation_key(table.table_id)),
1191 );
1192 table.purging = marker_values.contains_key(&purging_key(table.table_id));
1193 }
1194
1195 Ok(dropped_tables)
1196 }
1197
1198 pub async fn get_dropped_table(
1200 &self,
1201 table_name: &TableName,
1202 ) -> Result<Option<DroppedTableMetadata>> {
1203 let table_name_key = TableNameKey::from(table_name);
1204 let Some(kv) = self
1205 .tombstone_manager
1206 .get(&table_name_key.to_bytes())
1207 .await?
1208 else {
1209 return Ok(None);
1210 };
1211
1212 let table_id = TableNameValue::try_from_raw_value(&kv.value)?.table_id();
1213 self.get_dropped_table_metadata(table_id, table_name.clone())
1214 .await
1215 }
1216
1217 pub async fn get_dropped_table_by_id(
1219 &self,
1220 table_id: TableId,
1221 ) -> Result<Option<DroppedTableMetadata>> {
1222 self.get_dropped_table_metadata(table_id, None).await
1223 }
1224
1225 pub async fn is_dropped_table_purging(&self, table_id: TableId) -> Result<bool> {
1227 self.dropped_table_purge_claim(table_id)
1228 .await
1229 .map(|claim| claim.is_some())
1230 }
1231
1232 pub async fn dropped_table_purge_claim(&self, table_id: TableId) -> Result<Option<String>> {
1234 self.tombstone_manager
1235 .get(&purging_key(table_id))
1236 .await
1237 .map(|marker| marker.map(|marker| String::from_utf8_lossy(&marker.value).into_owned()))
1238 }
1239
1240 pub async fn mark_dropped_table_purging(
1243 &self,
1244 table_id: TableId,
1245 drop_generation: Option<&str>,
1246 ) -> Result<()> {
1247 self.kv_backend
1248 .put(
1249 PutRequest::new()
1250 .with_key(self.tombstone_manager.to_tombstone(&purging_key(table_id)))
1251 .with_value(drop_generation.unwrap_or_default()),
1252 )
1253 .await?;
1254 Ok(())
1255 }
1256
1257 pub async fn delete_table_metadata_tombstone(
1260 &self,
1261 table_id: TableId,
1262 table_name: &TableName,
1263 table_route_value: &TableRouteValue,
1264 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1265 ) -> Result<()> {
1266 let table_metadata_keys =
1267 self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1268 self.tombstone_manager
1269 .delete_with_markers(
1270 table_metadata_keys,
1271 vec![
1272 dropped_at_key(table_id),
1273 retention_expires_at_key(table_id),
1274 drop_generation_key(table_id),
1275 purging_key(table_id),
1276 ],
1277 )
1278 .await
1279 .map(|_| ())
1280 }
1281
1282 pub async fn restore_table_metadata(
1285 &self,
1286 table_id: TableId,
1287 table_name: &TableName,
1288 table_route_value: &TableRouteValue,
1289 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1290 ) -> Result<()> {
1291 let keys =
1292 self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1293 self.tombstone_manager
1294 .restore_with_markers(
1295 keys,
1296 vec![
1297 dropped_at_key(table_id),
1298 retention_expires_at_key(table_id),
1299 drop_generation_key(table_id),
1300 ],
1301 )
1302 .await
1303 .map(|_| ())
1304 }
1305
1306 pub async fn destroy_table_metadata(
1309 &self,
1310 table_id: TableId,
1311 table_name: &TableName,
1312 table_route_value: &TableRouteValue,
1313 region_wal_options: &HashMap<RegionNumber, WalOptions>,
1314 ) -> Result<()> {
1315 let keys =
1316 self.table_metadata_keys(table_id, table_name, table_route_value, region_wal_options)?;
1317 let _ = self
1318 .kv_backend
1319 .batch_delete(BatchDeleteRequest::new().with_keys(keys))
1320 .await?;
1321 Ok(())
1322 }
1323
1324 async fn get_dropped_table_metadata<T>(
1326 &self,
1327 table_id: TableId,
1328 table_name: T,
1329 ) -> Result<Option<DroppedTableMetadata>>
1330 where
1331 T: Into<Option<TableName>>,
1332 {
1333 let table_info_key = TableInfoKey::new(table_id);
1334 let Some(table_info_kv) = self
1335 .tombstone_manager
1336 .get(&table_info_key.to_bytes())
1337 .await?
1338 else {
1339 return Ok(None);
1340 };
1341
1342 let table_info_value = TableInfoValue::try_from_raw_value(&table_info_kv.value)?;
1343 let table_name = table_name
1344 .into()
1345 .unwrap_or_else(|| table_info_value.table_name());
1346
1347 let table_route_key = TableRouteKey::new(table_id);
1348 let table_route_kv = self
1349 .tombstone_manager
1350 .get(&table_route_key.to_bytes())
1351 .await?
1352 .with_context(|| error::UnexpectedSnafu {
1353 err_msg: format!("Missing tombstoned table route metadata for table id {table_id}"),
1354 })?;
1355 let mut table_route_value = TableRouteValue::try_from_raw_value(&table_route_kv.value)?;
1356 self.table_route_manager
1357 .table_route_storage()
1358 .remap_table_route(&mut table_route_value)
1359 .await?;
1360
1361 let region_wal_options = self
1362 .dropped_region_wal_options(table_id, &table_route_value)
1363 .await?;
1364 let dropped_at_key = dropped_at_key(table_id);
1365 let retention_expires_at_key = retention_expires_at_key(table_id);
1366 let drop_generation_key = drop_generation_key(table_id);
1367 let marker_values = self
1368 .tombstone_manager
1369 .batch_get(&[
1370 dropped_at_key.clone(),
1371 retention_expires_at_key.clone(),
1372 drop_generation_key.clone(),
1373 ])
1374 .await?;
1375 let dropped_at = Self::parse_dropped_at(table_id, marker_values.get(&dropped_at_key))?;
1376 let retention_expires_at = Self::parse_retention_expires_at(
1377 table_id,
1378 marker_values.get(&retention_expires_at_key),
1379 )?;
1380 let drop_generation = Self::parse_drop_generation(marker_values.get(&drop_generation_key));
1381
1382 Ok(Some(DroppedTableMetadata {
1383 table_id,
1384 table_name,
1385 table_info_value,
1386 table_route_value,
1387 region_wal_options,
1388 dropped_at,
1389 retention_expires_at,
1390 drop_generation,
1391 }))
1392 }
1393
1394 fn parse_dropped_at(table_id: TableId, kv: Option<&KeyValue>) -> Result<Option<i64>> {
1395 Self::parse_timestamp_marker(table_id, "dropped timestamp", kv)
1396 }
1397
1398 fn parse_retention_expires_at(table_id: TableId, kv: Option<&KeyValue>) -> Result<Option<i64>> {
1399 Self::parse_timestamp_marker(table_id, "retention deadline", kv)
1400 }
1401
1402 fn parse_drop_generation(kv: Option<&KeyValue>) -> Option<String> {
1403 kv.map(|kv| String::from_utf8_lossy(&kv.value).into_owned())
1404 }
1405
1406 fn parse_timestamp_marker(
1407 table_id: TableId,
1408 description: &str,
1409 kv: Option<&KeyValue>,
1410 ) -> Result<Option<i64>> {
1411 let Some(kv) = kv else {
1412 return Ok(None);
1413 };
1414 let value = String::from_utf8_lossy(&kv.value);
1415 value.parse().map(Some).map_err(|err| {
1416 error::UnexpectedSnafu {
1417 err_msg: format!("Invalid {description} '{value}' for table id {table_id}: {err}"),
1418 }
1419 .build()
1420 })
1421 }
1422
1423 async fn dropped_region_wal_options(
1425 &self,
1426 table_id: TableId,
1427 table_route_value: &TableRouteValue,
1428 ) -> Result<HashMap<RegionNumber, WalOptions>> {
1429 let mut region_wal_options = HashMap::new();
1430 let Some(region_routes) = table_route_value.region_routes().ok() else {
1431 return Ok(region_wal_options);
1432 };
1433 let datanode_table_keys = region_distribution(region_routes)
1434 .into_keys()
1435 .map(|datanode_id| DatanodeTableKey::new(datanode_id, table_id))
1436 .collect::<Vec<_>>();
1437 let datanode_table_key_bytes = datanode_table_keys
1438 .iter()
1439 .map(|key| key.to_bytes())
1440 .collect::<Vec<_>>();
1441 let datanode_table_values = self
1442 .tombstone_manager
1443 .batch_get(&datanode_table_key_bytes)
1444 .await?;
1445
1446 for datanode_table_key in datanode_table_keys {
1447 let Some(kv) = datanode_table_values.get(&datanode_table_key.to_bytes()) else {
1448 continue;
1449 };
1450
1451 let datanode_table_value = DatanodeTableValue::try_from_raw_value(&kv.value)?;
1452 for (region_number, wal_options) in &datanode_table_value.region_info.region_wal_options
1453 {
1454 region_wal_options.insert(*region_number, wal_options.clone());
1455 }
1456 }
1457
1458 Ok(region_wal_options)
1459 }
1460
1461 fn view_info_keys(&self, view_id: TableId, view_name: &TableName) -> Result<Vec<Vec<u8>>> {
1462 let mut keys = Vec::with_capacity(3);
1463 let view_name = TableNameKey::new(
1464 &view_name.catalog_name,
1465 &view_name.schema_name,
1466 &view_name.table_name,
1467 );
1468 let table_info_key = TableInfoKey::new(view_id);
1469 let view_info_key = ViewInfoKey::new(view_id);
1470 keys.push(view_name.to_bytes());
1471 keys.push(table_info_key.to_bytes());
1472 keys.push(view_info_key.to_bytes());
1473
1474 Ok(keys)
1475 }
1476
1477 pub async fn destroy_view_info(&self, view_id: TableId, view_name: &TableName) -> Result<()> {
1480 let keys = self.view_info_keys(view_id, view_name)?;
1481 let _ = self
1482 .kv_backend
1483 .batch_delete(BatchDeleteRequest::new().with_keys(keys))
1484 .await?;
1485 Ok(())
1486 }
1487
1488 pub async fn rename_table(
1492 &self,
1493 current_table_info_value: &DeserializedValueWithBytes<TableInfoValue>,
1494 new_table_name: String,
1495 ) -> Result<()> {
1496 let current_table_info = ¤t_table_info_value.table_info;
1497 let table_id = current_table_info.ident.table_id;
1498
1499 let table_name_key = TableNameKey::new(
1500 ¤t_table_info.catalog_name,
1501 ¤t_table_info.schema_name,
1502 ¤t_table_info.name,
1503 );
1504
1505 let new_table_name_key = TableNameKey::new(
1506 ¤t_table_info.catalog_name,
1507 ¤t_table_info.schema_name,
1508 &new_table_name,
1509 );
1510
1511 let update_table_name_txn = self.table_name_manager().build_update_txn(
1513 &table_name_key,
1514 &new_table_name_key,
1515 table_id,
1516 )?;
1517
1518 let new_table_info_value = current_table_info_value
1519 .inner
1520 .with_update(move |table_info| {
1521 table_info.name = new_table_name;
1522 });
1523
1524 let (update_table_info_txn, on_update_table_info_failure) = self
1526 .table_info_manager()
1527 .build_update_txn(table_id, current_table_info_value, &new_table_info_value)?;
1528
1529 let txn = Txn::merge_all(vec![update_table_name_txn, update_table_info_txn]);
1530
1531 let mut r = self.kv_backend.txn(txn).await?;
1532
1533 if !r.succeeded {
1535 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1536 let remote_table_info = on_update_table_info_failure(&mut set)?
1537 .context(error::UnexpectedSnafu {
1538 err_msg: "Reads the empty table info in comparing operation of the rename table metadata",
1539 })?
1540 .into_inner();
1541
1542 let op_name = "the renaming table metadata";
1543 ensure_values!(remote_table_info, new_table_info_value, op_name);
1544 }
1545
1546 Ok(())
1547 }
1548
1549 pub async fn update_table_info(
1553 &self,
1554 current_table_info_value: &DeserializedValueWithBytes<TableInfoValue>,
1555 region_distribution: Option<RegionDistribution>,
1556 new_table_info: TableInfo,
1557 ) -> Result<()> {
1558 let table_id = current_table_info_value.table_info.ident.table_id;
1559 let new_table_info_value = current_table_info_value.update(new_table_info);
1560
1561 let (update_table_info_txn, on_update_table_info_failure) = self
1563 .table_info_manager()
1564 .build_update_txn(table_id, current_table_info_value, &new_table_info_value)?;
1565
1566 let txn = if let Some(region_distribution) = region_distribution {
1567 let new_region_options = new_table_info_value.table_info.to_region_options();
1569 let update_datanode_table_options_txn = self
1570 .datanode_table_manager
1571 .build_update_table_options_txn(table_id, region_distribution, new_region_options)
1572 .await?;
1573 Txn::merge_all([update_table_info_txn, update_datanode_table_options_txn])
1574 } else {
1575 update_table_info_txn
1576 };
1577
1578 let mut r = self.kv_backend.txn(txn).await?;
1579 if !r.succeeded {
1581 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1582 let remote_table_info = on_update_table_info_failure(&mut set)?
1583 .context(error::UnexpectedSnafu {
1584 err_msg: "Reads the empty table info in comparing operation of the updating table info",
1585 })?
1586 .into_inner();
1587
1588 let op_name = "the updating table info";
1589 ensure_values!(remote_table_info, new_table_info_value, op_name);
1590 }
1591 Ok(())
1592 }
1593
1594 #[allow(clippy::too_many_arguments)]
1605 pub async fn update_view_info(
1606 &self,
1607 view_id: TableId,
1608 current_view_info_value: &DeserializedValueWithBytes<ViewInfoValue>,
1609 new_view_info: Vec<u8>,
1610 table_names: HashSet<TableName>,
1611 columns: Vec<String>,
1612 plan_columns: Vec<String>,
1613 definition: String,
1614 ) -> Result<()> {
1615 let new_view_info_value = current_view_info_value.update(
1616 new_view_info.into(),
1617 table_names,
1618 columns,
1619 plan_columns,
1620 definition,
1621 );
1622
1623 let (update_view_info_txn, on_update_view_info_failure) = self
1625 .view_info_manager()
1626 .build_update_txn(view_id, current_view_info_value, &new_view_info_value)?;
1627
1628 let mut r = self.kv_backend.txn(update_view_info_txn).await?;
1629
1630 if !r.succeeded {
1632 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1633 let remote_view_info = on_update_view_info_failure(&mut set)?
1634 .context(error::UnexpectedSnafu {
1635 err_msg: "Reads the empty view info in comparing operation of the updating view info",
1636 })?
1637 .into_inner();
1638
1639 let op_name = "the updating view info";
1640 ensure_values!(remote_view_info, new_view_info_value, op_name);
1641 }
1642 Ok(())
1643 }
1644
1645 pub fn batch_update_table_info_value_chunk_size(&self) -> usize {
1646 self.kv_backend.max_txn_ops()
1647 }
1648
1649 pub async fn batch_update_table_info_values(
1650 &self,
1651 table_info_value_pairs: Vec<(DeserializedValueWithBytes<TableInfoValue>, TableInfo)>,
1652 ) -> Result<()> {
1653 let len = table_info_value_pairs.len();
1654 let mut txns = Vec::with_capacity(len);
1655 struct OnFailure<F, R>
1656 where
1657 F: FnOnce(&mut TxnOpGetResponseSet) -> R,
1658 {
1659 table_info_value: TableInfoValue,
1660 on_update_table_info_failure: F,
1661 }
1662 let mut on_failures = Vec::with_capacity(len);
1663
1664 for (table_info_value, new_table_info) in table_info_value_pairs {
1665 let table_id = table_info_value.table_info.ident.table_id;
1666
1667 let new_table_info_value = table_info_value.update(new_table_info);
1668
1669 let (update_table_info_txn, on_update_table_info_failure) =
1670 self.table_info_manager().build_update_txn(
1671 table_id,
1672 &table_info_value,
1673 &new_table_info_value,
1674 )?;
1675
1676 txns.push(update_table_info_txn);
1677
1678 on_failures.push(OnFailure {
1679 table_info_value: new_table_info_value,
1680 on_update_table_info_failure,
1681 });
1682 }
1683
1684 let txn = Txn::merge_all(txns);
1685 let mut r = self.kv_backend.txn(txn).await?;
1686
1687 if !r.succeeded {
1688 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1689 for on_failure in on_failures {
1690 let remote_table_info = (on_failure.on_update_table_info_failure)(&mut set)?
1691 .context(error::UnexpectedSnafu {
1692 err_msg: "Reads the empty table info in comparing operation of the updating table info",
1693 })?
1694 .into_inner();
1695
1696 let op_name = "the batch updating table info";
1697 ensure_values!(remote_table_info, on_failure.table_info_value, op_name);
1698 }
1699 }
1700
1701 Ok(())
1702 }
1703
1704 pub async fn update_table_route(
1705 &self,
1706 table_id: TableId,
1707 region_info: RegionInfo,
1708 current_table_route_value: &DeserializedValueWithBytes<TableRouteValue>,
1709 new_region_routes: Vec<RegionRoute>,
1710 new_region_options: &HashMap<String, String>,
1711 new_region_wal_options: &RegionWalOptions,
1712 ) -> Result<()> {
1713 let current_region_distribution =
1715 region_distribution(current_table_route_value.region_routes()?);
1716 let new_region_distribution = region_distribution(&new_region_routes);
1717
1718 let update_topic_region_txn = self.topic_region_manager.build_update_txn(
1719 table_id,
1720 ®ion_info.region_wal_options,
1721 new_region_wal_options,
1722 )?;
1723 let update_datanode_table_txn = self.datanode_table_manager().build_update_txn(
1724 table_id,
1725 region_info,
1726 current_region_distribution,
1727 new_region_distribution,
1728 new_region_options,
1729 new_region_wal_options,
1730 )?;
1731
1732 let new_table_route_value = current_table_route_value.update(new_region_routes)?;
1734 let (update_table_route_txn, on_update_table_route_failure) = self
1735 .table_route_manager()
1736 .table_route_storage()
1737 .build_update_txn(table_id, current_table_route_value, &new_table_route_value)?;
1738
1739 let txn = Txn::merge_all(vec![
1740 update_datanode_table_txn,
1741 update_table_route_txn,
1742 update_topic_region_txn,
1743 ]);
1744
1745 let mut r = self.kv_backend.txn(txn).await?;
1746
1747 if !r.succeeded {
1749 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1750 let remote_table_route = on_update_table_route_failure(&mut set)?
1751 .context(error::UnexpectedSnafu {
1752 err_msg: "Reads the empty table route in comparing operation of the updating table route",
1753 })?
1754 .into_inner();
1755
1756 let op_name = "the updating table route";
1757 ensure_values!(remote_table_route, new_table_route_value, op_name);
1758 }
1759
1760 Ok(())
1761 }
1762
1763 pub async fn update_leader_region_status<F>(
1765 &self,
1766 table_id: TableId,
1767 current_table_route_value: &DeserializedValueWithBytes<TableRouteValue>,
1768 next_region_route_status: F,
1769 ) -> Result<()>
1770 where
1771 F: Fn(&RegionRoute) -> Option<Option<LeaderState>>,
1772 {
1773 let mut new_region_routes = current_table_route_value.region_routes()?.clone();
1774
1775 let mut updated = 0;
1776 for route in &mut new_region_routes {
1777 if let Some(state) = next_region_route_status(route)
1778 && route.set_leader_state(state)
1779 {
1780 updated += 1;
1781 }
1782 }
1783
1784 if updated == 0 {
1785 warn!("No leader status updated");
1786 return Ok(());
1787 }
1788
1789 let new_table_route_value = current_table_route_value.update(new_region_routes)?;
1791
1792 let (update_table_route_txn, on_update_table_route_failure) = self
1793 .table_route_manager()
1794 .table_route_storage()
1795 .build_update_txn(table_id, current_table_route_value, &new_table_route_value)?;
1796
1797 let mut r = self.kv_backend.txn(update_table_route_txn).await?;
1798
1799 if !r.succeeded {
1801 let mut set = TxnOpGetResponseSet::from(&mut r.responses);
1802 let remote_table_route = on_update_table_route_failure(&mut set)?
1803 .context(error::UnexpectedSnafu {
1804 err_msg: "Reads the empty table route in comparing operation of the updating leader region status",
1805 })?
1806 .into_inner();
1807
1808 let op_name = "the updating leader region status";
1809 ensure_values!(remote_table_route, new_table_route_value, op_name);
1810 }
1811
1812 Ok(())
1813 }
1814}
1815
1816#[macro_export]
1817macro_rules! impl_metadata_value {
1818 ($($val_ty: ty), *) => {
1819 $(
1820 impl $crate::key::MetadataValue for $val_ty {
1821 fn try_from_raw_value(raw_value: &[u8]) -> Result<Self> {
1822 serde_json::from_slice(raw_value).context(SerdeJsonSnafu)
1823 }
1824
1825 fn try_as_raw_value(&self) -> Result<Vec<u8>> {
1826 serde_json::to_vec(self).context(SerdeJsonSnafu)
1827 }
1828 }
1829 )*
1830 }
1831}
1832
1833macro_rules! impl_metadata_key_get_txn_op {
1834 ($($key: ty), *) => {
1835 $(
1836 impl $crate::key::MetadataKeyGetTxnOp for $key {
1837 fn build_get_op(
1840 &self,
1841 ) -> (
1842 TxnOp,
1843 impl for<'a> FnMut(
1844 &'a mut TxnOpGetResponseSet,
1845 ) -> Option<Vec<u8>>,
1846 ) {
1847 let raw_key = self.to_bytes();
1848 (
1849 TxnOp::Get(raw_key.clone()),
1850 TxnOpGetResponseSet::filter(raw_key),
1851 )
1852 }
1853 }
1854 )*
1855 }
1856}
1857
1858impl_metadata_key_get_txn_op! {
1859 TableNameKey<'_>,
1860 TableInfoKey,
1861 ViewInfoKey,
1862 TableRouteKey,
1863 DatanodeTableKey
1864}
1865
1866#[macro_export]
1867macro_rules! impl_optional_metadata_value {
1868 ($($val_ty: ty), *) => {
1869 $(
1870 impl $val_ty {
1871 pub fn try_from_raw_value(raw_value: &[u8]) -> Result<Option<Self>> {
1872 serde_json::from_slice(raw_value).context(SerdeJsonSnafu)
1873 }
1874
1875 pub fn try_as_raw_value(&self) -> Result<Vec<u8>> {
1876 serde_json::to_vec(self).context(SerdeJsonSnafu)
1877 }
1878 }
1879 )*
1880 }
1881}
1882
1883impl_metadata_value! {
1884 TableNameValue,
1885 TableInfoValue,
1886 ViewInfoValue,
1887 DatanodeTableValue,
1888 FlowInfoValue,
1889 FlowNameValue,
1890 FlowRouteValue,
1891 TableFlowValue,
1892 NodeAddressValue,
1893 SchemaNameValue,
1894 FlowStateValue,
1895 PoisonValue,
1896 TopicRegionValue,
1897 DatanodeEpochValue
1898}
1899
1900impl_optional_metadata_value! {
1901 CatalogNameValue,
1902 SchemaNameValue
1903}
1904
1905#[cfg(test)]
1906mod tests {
1907 use std::collections::{BTreeMap, HashMap, HashSet};
1908 use std::sync::Arc;
1909 use std::sync::atomic::{AtomicUsize, Ordering};
1910
1911 use bytes::Bytes;
1912 use common_catalog::consts::{DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME};
1913 use common_time::util::current_time_millis;
1914 use common_wal::options::{KafkaWalOptions, WalOptions};
1915 use futures::TryStreamExt;
1916 use store_api::storage::{RegionId, RegionNumber};
1917 use table::metadata::{TableId, TableInfo};
1918 use table::table_name::TableName;
1919
1920 use super::datanode_table::DatanodeTableKey;
1921 use super::test_utils;
1922 use crate::ddl::allocator::wal_options::WalOptionsAllocator;
1923 use crate::ddl::test_util::create_table::test_create_table_task;
1924 use crate::ddl::utils::region_storage_path;
1925 use crate::error::{Error, Result};
1926 use crate::key::datanode_table::RegionInfo;
1927 use crate::key::node_address::{NodeAddressKey, NodeAddressValue};
1928 use crate::key::table_info::TableInfoValue;
1929 use crate::key::table_name::TableNameKey;
1930 use crate::key::table_route::TableRouteValue;
1931 use crate::key::topic_region::TopicRegionKey;
1932 use crate::key::{
1933 DeserializedValueWithBytes, DroppedTableMetadata, MetadataValue, RegionDistribution,
1934 RegionRoleSet, TOPIC_REGION_PREFIX, TableMetadataManager, ViewInfoValue,
1935 };
1936 use crate::kv_backend::KvBackend;
1937 use crate::kv_backend::memory::MemoryKvBackend;
1938 use crate::kv_backend::read_only::ReadOnlyKvBackend;
1939 use crate::kv_backend::test_util::MockKvBackend;
1940 use crate::peer::Peer;
1941 use crate::rpc::router::{LeaderState, Region, RegionRoute, region_distribution};
1942 use crate::rpc::store::{BatchGetResponse, PutRequest, RangeRequest, RangeResponse};
1943 use crate::wal_provider::{RegionWalOptions, WalProvider};
1944
1945 #[test]
1946 fn test_deserialized_value_with_bytes() {
1947 let region_route = new_test_region_route();
1948 let region_routes = vec![region_route.clone()];
1949
1950 let expected_region_routes =
1951 TableRouteValue::physical(vec![region_route.clone(), region_route.clone()]);
1952 let expected = serde_json::to_vec(&expected_region_routes).unwrap();
1953
1954 let value = DeserializedValueWithBytes {
1957 inner: TableRouteValue::physical(region_routes.clone()),
1959 bytes: Bytes::from(expected.clone()),
1960 };
1961
1962 let encoded = serde_json::to_vec(&value).unwrap();
1963
1964 let decoded: DeserializedValueWithBytes<TableRouteValue> =
1967 serde_json::from_slice(&encoded).unwrap();
1968
1969 assert_eq!(decoded.inner, expected_region_routes);
1970 assert_eq!(decoded.bytes, expected);
1971 }
1972
1973 fn new_test_region_route() -> RegionRoute {
1974 new_region_route(1, 2)
1975 }
1976
1977 fn new_region_route(region_id: u64, datanode: u64) -> RegionRoute {
1978 RegionRoute {
1979 region: Region {
1980 id: region_id.into(),
1981 name: "r1".to_string(),
1982 attrs: BTreeMap::new(),
1983 partition_expr: Default::default(),
1984 },
1985 leader_peer: Some(Peer::new(datanode, "a2")),
1986 follower_peers: vec![],
1987 leader_state: None,
1988 leader_down_since: None,
1989 write_route_policy: None,
1990 }
1991 }
1992
1993 fn new_test_table_info() -> TableInfo {
1994 test_utils::new_test_table_info(10)
1995 }
1996
1997 fn new_test_table_names() -> HashSet<TableName> {
1998 let mut set = HashSet::new();
1999 set.insert(TableName {
2000 catalog_name: "greptime".to_string(),
2001 schema_name: "public".to_string(),
2002 table_name: "a_table".to_string(),
2003 });
2004 set.insert(TableName {
2005 catalog_name: "greptime".to_string(),
2006 schema_name: "public".to_string(),
2007 table_name: "b_table".to_string(),
2008 });
2009 set
2010 }
2011
2012 async fn create_physical_table_metadata(
2013 table_metadata_manager: &TableMetadataManager,
2014 table_info: TableInfo,
2015 region_routes: Vec<RegionRoute>,
2016 region_wal_options: RegionWalOptions,
2017 ) -> Result<()> {
2018 table_metadata_manager
2019 .create_table_metadata(
2020 table_info,
2021 TableRouteValue::physical(region_routes),
2022 region_wal_options,
2023 )
2024 .await
2025 }
2026
2027 fn create_mock_region_wal_options() -> HashMap<RegionNumber, WalOptions> {
2028 let topics = (0..2)
2029 .map(|i| format!("greptimedb_topic{}", i))
2030 .collect::<Vec<_>>();
2031 let wal_options = topics
2032 .iter()
2033 .map(|topic| WalOptions::Kafka(KafkaWalOptions::new(topic.clone())))
2034 .collect::<Vec<_>>();
2035
2036 (0..16)
2037 .enumerate()
2038 .map(|(i, region_number)| (region_number, wal_options[i % wal_options.len()].clone()))
2039 .collect()
2040 }
2041
2042 fn create_mixed_region_wal_options() -> HashMap<RegionNumber, WalOptions> {
2043 HashMap::from([
2044 (
2045 0,
2046 WalOptions::Kafka(KafkaWalOptions::new("greptimedb_topic0".to_string())),
2047 ),
2048 (1, WalOptions::RaftEngine),
2049 (2, WalOptions::Noop),
2050 (
2051 3,
2052 WalOptions::Kafka(KafkaWalOptions::new("greptimedb_topic1".to_string())),
2053 ),
2054 ])
2055 }
2056
2057 fn test_physical_region_route(
2058 table_id: TableId,
2059 region_number: RegionNumber,
2060 leader_peer: u64,
2061 follower_peers: Vec<u64>,
2062 ) -> RegionRoute {
2063 RegionRoute {
2064 region: Region::new_test(RegionId::new(table_id, region_number)),
2065 leader_peer: Some(Peer::empty(leader_peer)),
2066 follower_peers: follower_peers.into_iter().map(Peer::empty).collect(),
2067 leader_state: None,
2068 leader_down_since: None,
2069 write_route_policy: None,
2070 }
2071 }
2072
2073 async fn create_dropped_physical_table_metadata(
2074 table_id: TableId,
2075 table_name: &str,
2076 region_routes: Vec<RegionRoute>,
2077 region_wal_options: HashMap<RegionNumber, WalOptions>,
2078 ) -> (
2079 Arc<MemoryKvBackend<Error>>,
2080 TableMetadataManager,
2081 TableName,
2082 TableInfo,
2083 Vec<RegionRoute>,
2084 HashMap<RegionNumber, WalOptions>,
2085 ) {
2086 let mem_kv = Arc::new(MemoryKvBackend::default());
2087 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2088 let task = test_create_table_task(table_name, table_id);
2089 let table_info = task.table_info.clone();
2090 table_metadata_manager
2091 .create_table_metadata(
2092 table_info.clone(),
2093 TableRouteValue::physical(region_routes),
2094 region_wal_options.clone(),
2095 )
2096 .await
2097 .unwrap();
2098
2099 let table_route_value = table_metadata_manager
2100 .table_route_manager
2101 .table_route_storage()
2102 .get_with_raw_bytes(table_id)
2103 .await
2104 .unwrap()
2105 .unwrap();
2106 let region_routes = table_route_value.region_routes().unwrap().clone();
2107 let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
2108 let table_route_value = TableRouteValue::physical(region_routes.clone());
2109 table_metadata_manager
2110 .delete_table_metadata(
2111 table_id,
2112 &table_name,
2113 &table_route_value,
2114 ®ion_wal_options,
2115 None,
2116 )
2117 .await
2118 .unwrap();
2119
2120 (
2121 mem_kv,
2122 table_metadata_manager,
2123 table_name,
2124 table_info,
2125 region_routes,
2126 region_wal_options,
2127 )
2128 }
2129
2130 fn assert_dropped_table_metadata(
2131 dropped_table: &DroppedTableMetadata,
2132 table_id: TableId,
2133 table_name: &TableName,
2134 table_info: &TableInfo,
2135 region_routes: &[RegionRoute],
2136 region_wal_options: &HashMap<RegionNumber, WalOptions>,
2137 ) {
2138 assert_eq!(dropped_table.table_id, table_id);
2139 assert_eq!(&dropped_table.table_name, table_name);
2140 assert_eq!(&dropped_table.table_info_value.table_info, table_info);
2141 assert_eq!(
2142 dropped_table.table_route_value.region_routes().unwrap(),
2143 region_routes
2144 );
2145 assert_eq!(&dropped_table.region_wal_options, region_wal_options);
2146 }
2147
2148 #[tokio::test]
2149 async fn test_raft_engine_topic_region_map() {
2150 let mem_kv = Arc::new(MemoryKvBackend::default());
2151 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2152 let region_route = new_test_region_route();
2153 let region_routes = &vec![region_route.clone()];
2154 let table_info = new_test_table_info();
2155 let wal_provider = WalProvider::RaftEngine;
2156 let regions: Vec<_> = (0..16).collect();
2157 let region_wal_options = wal_provider.allocate(®ions, false).await.unwrap();
2158 create_physical_table_metadata(
2159 &table_metadata_manager,
2160 table_info.clone(),
2161 region_routes.clone(),
2162 region_wal_options.clone(),
2163 )
2164 .await
2165 .unwrap();
2166
2167 let topic_region_key = TOPIC_REGION_PREFIX.to_string();
2168 let range_req = RangeRequest::new().with_prefix(topic_region_key);
2169 let resp = mem_kv.range(range_req).await.unwrap();
2170 assert!(resp.kvs.is_empty());
2172 }
2173
2174 #[tokio::test]
2175 async fn test_create_table_metadata() {
2176 let mem_kv = Arc::new(MemoryKvBackend::default());
2177 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2178 let region_route = new_test_region_route();
2179 let region_routes = &vec![region_route.clone()];
2180 let table_info = new_test_table_info();
2181 let region_wal_options = create_mock_region_wal_options();
2182
2183 create_physical_table_metadata(
2185 &table_metadata_manager,
2186 table_info.clone(),
2187 region_routes.clone(),
2188 region_wal_options.clone(),
2189 )
2190 .await
2191 .unwrap();
2192
2193 assert!(
2195 create_physical_table_metadata(
2196 &table_metadata_manager,
2197 table_info.clone(),
2198 region_routes.clone(),
2199 region_wal_options.clone(),
2200 )
2201 .await
2202 .is_ok()
2203 );
2204
2205 let mut modified_region_routes = region_routes.clone();
2206 modified_region_routes.push(region_route.clone());
2207 assert!(
2209 create_physical_table_metadata(
2210 &table_metadata_manager,
2211 table_info.clone(),
2212 modified_region_routes,
2213 region_wal_options.clone(),
2214 )
2215 .await
2216 .is_err()
2217 );
2218
2219 let (remote_table_info, remote_table_route) = table_metadata_manager
2220 .get_full_table_info(10)
2221 .await
2222 .unwrap();
2223
2224 assert_eq!(
2225 remote_table_info.unwrap().into_inner().table_info,
2226 table_info
2227 );
2228 assert_eq!(
2229 remote_table_route
2230 .unwrap()
2231 .into_inner()
2232 .region_routes()
2233 .unwrap(),
2234 region_routes
2235 );
2236
2237 for i in 0..2 {
2238 let region_number = i as u32;
2239 let region_id = RegionId::new(table_info.ident.table_id, region_number);
2240 let topic = format!("greptimedb_topic{}", i);
2241 let regions = table_metadata_manager
2242 .topic_region_manager
2243 .regions(&topic)
2244 .await
2245 .unwrap()
2246 .into_keys()
2247 .collect::<Vec<_>>();
2248 assert_eq!(regions.len(), 8);
2249 assert!(regions.contains(®ion_id));
2250 }
2251 }
2252
2253 #[tokio::test]
2254 async fn test_get_full_table_info_remaps_route_address() {
2255 let mem_kv = Arc::new(MemoryKvBackend::default());
2256 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2257
2258 let mut region_route = new_test_region_route();
2259 region_route.follower_peers = vec![Peer::empty(3)];
2260 let region_routes = vec![region_route];
2261 let table_info = new_test_table_info();
2262 let table_id = table_info.ident.table_id;
2263
2264 create_physical_table_metadata(
2265 &table_metadata_manager,
2266 table_info,
2267 region_routes,
2268 HashMap::new(),
2269 )
2270 .await
2271 .unwrap();
2272
2273 mem_kv
2274 .put(PutRequest {
2275 key: NodeAddressKey::with_datanode(2).to_string().into_bytes(),
2276 value: NodeAddressValue::new(Peer::new(2, "new-a2"))
2277 .try_as_raw_value()
2278 .unwrap(),
2279 ..Default::default()
2280 })
2281 .await
2282 .unwrap();
2283 mem_kv
2284 .put(PutRequest {
2285 key: NodeAddressKey::with_datanode(3).to_string().into_bytes(),
2286 value: NodeAddressValue::new(Peer::new(3, "new-a3"))
2287 .try_as_raw_value()
2288 .unwrap(),
2289 ..Default::default()
2290 })
2291 .await
2292 .unwrap();
2293
2294 let (_, table_route) = table_metadata_manager
2295 .get_full_table_info(table_id)
2296 .await
2297 .unwrap();
2298 let table_route = table_route.unwrap().into_inner();
2299 let region_routes = table_route.region_routes().unwrap();
2300
2301 assert_eq!(
2302 region_routes[0].leader_peer.as_ref().unwrap().addr,
2303 "new-a2"
2304 );
2305 assert_eq!(region_routes[0].follower_peers[0].addr, "new-a3");
2306 }
2307
2308 #[tokio::test]
2309 async fn test_get_full_table_info_with_read_only_kv_backend() {
2310 let mem_kv = Arc::new(MemoryKvBackend::default());
2311 let writable_manager = TableMetadataManager::new(mem_kv.clone());
2312
2313 let region_routes = vec![new_test_region_route()];
2314 let table_info = new_test_table_info();
2315 let table_id = table_info.ident.table_id;
2316
2317 create_physical_table_metadata(
2318 &writable_manager,
2319 table_info.clone(),
2320 region_routes.clone(),
2321 HashMap::new(),
2322 )
2323 .await
2324 .unwrap();
2325
2326 let read_only_kv = Arc::new(ReadOnlyKvBackend::new(mem_kv));
2327 let read_only_manager = TableMetadataManager::new(read_only_kv);
2328
2329 let (remote_table_info, remote_table_route) = read_only_manager
2330 .get_full_table_info(table_id)
2331 .await
2332 .unwrap();
2333
2334 assert_eq!(
2335 remote_table_info.unwrap().into_inner().table_info,
2336 table_info
2337 );
2338 assert_eq!(
2339 remote_table_route
2340 .unwrap()
2341 .into_inner()
2342 .region_routes()
2343 .unwrap(),
2344 ®ion_routes
2345 );
2346 }
2347
2348 #[tokio::test]
2349 async fn test_create_logic_tables_metadata() {
2350 let mem_kv = Arc::new(MemoryKvBackend::default());
2351 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2352 let region_route = new_test_region_route();
2353 let region_routes = vec![region_route.clone()];
2354 let table_info = new_test_table_info();
2355 let table_id = table_info.ident.table_id;
2356 let table_route_value = TableRouteValue::physical(region_routes.clone());
2357
2358 let tables_data = vec![(table_info.clone(), table_route_value.clone())];
2359 table_metadata_manager
2361 .create_logical_tables_metadata(tables_data.clone())
2362 .await
2363 .unwrap();
2364
2365 assert!(
2367 table_metadata_manager
2368 .create_logical_tables_metadata(tables_data)
2369 .await
2370 .is_ok()
2371 );
2372
2373 let mut modified_region_routes = region_routes.clone();
2374 modified_region_routes.push(new_region_route(2, 3));
2375 let modified_table_route_value = TableRouteValue::physical(modified_region_routes.clone());
2376 let modified_tables_data = vec![(table_info.clone(), modified_table_route_value)];
2377 assert!(
2379 table_metadata_manager
2380 .create_logical_tables_metadata(modified_tables_data)
2381 .await
2382 .is_err()
2383 );
2384
2385 let (remote_table_info, remote_table_route) = table_metadata_manager
2386 .get_full_table_info(table_id)
2387 .await
2388 .unwrap();
2389
2390 assert_eq!(
2391 remote_table_info.unwrap().into_inner().table_info,
2392 table_info
2393 );
2394 assert_eq!(
2395 remote_table_route
2396 .unwrap()
2397 .into_inner()
2398 .region_routes()
2399 .unwrap(),
2400 ®ion_routes
2401 );
2402 }
2403
2404 #[tokio::test]
2405 async fn test_create_many_logical_tables_metadata() {
2406 let kv_backend = Arc::new(MemoryKvBackend::default());
2407 let table_metadata_manager = TableMetadataManager::new(kv_backend);
2408
2409 let mut tables_data = vec![];
2410 for i in 0..128 {
2411 let table_id = i + 1;
2412 let regin_number = table_id * 3;
2413 let region_id = RegionId::new(table_id, regin_number);
2414 let region_route = new_region_route(region_id.as_u64(), 2);
2415 let region_routes = vec![region_route.clone()];
2416 let table_info = test_utils::new_test_table_info_with_name(
2417 table_id,
2418 &format!("my_table_{}", table_id),
2419 );
2420 let table_route_value = TableRouteValue::physical(region_routes.clone());
2421
2422 tables_data.push((table_info, table_route_value));
2423 }
2424
2425 table_metadata_manager
2427 .create_logical_tables_metadata(tables_data)
2428 .await
2429 .unwrap();
2430 }
2431
2432 #[tokio::test]
2433 async fn test_delete_table_metadata() {
2434 let mem_kv = Arc::new(MemoryKvBackend::default());
2435 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2436 let region_route = new_test_region_route();
2437 let region_routes = &vec![region_route.clone()];
2438 let table_info = new_test_table_info();
2439 let table_id = table_info.ident.table_id;
2440 let datanode_id = 2;
2441 let region_wal_options = create_mock_region_wal_options();
2442 let serialized_region_wal_options = region_wal_options.clone();
2443
2444 create_physical_table_metadata(
2446 &table_metadata_manager,
2447 table_info.clone(),
2448 region_routes.clone(),
2449 serialized_region_wal_options,
2450 )
2451 .await
2452 .unwrap();
2453
2454 let table_name = TableName::new(
2455 table_info.catalog_name,
2456 table_info.schema_name,
2457 table_info.name,
2458 );
2459 let table_route_value = &TableRouteValue::physical(region_routes.clone());
2460 table_metadata_manager
2462 .delete_table_metadata(
2463 table_id,
2464 &table_name,
2465 table_route_value,
2466 ®ion_wal_options,
2467 None,
2468 )
2469 .await
2470 .unwrap();
2471 table_metadata_manager
2473 .delete_table_metadata(
2474 table_id,
2475 &table_name,
2476 table_route_value,
2477 ®ion_wal_options,
2478 None,
2479 )
2480 .await
2481 .unwrap();
2482 assert!(
2483 table_metadata_manager
2484 .table_info_manager()
2485 .get(table_id)
2486 .await
2487 .unwrap()
2488 .is_none()
2489 );
2490 assert!(
2491 table_metadata_manager
2492 .table_route_manager()
2493 .table_route_storage()
2494 .get(table_id)
2495 .await
2496 .unwrap()
2497 .is_none()
2498 );
2499 assert!(
2500 table_metadata_manager
2501 .datanode_table_manager()
2502 .tables(datanode_id)
2503 .try_collect::<Vec<_>>()
2504 .await
2505 .unwrap()
2506 .is_empty()
2507 );
2508 let table_info = table_metadata_manager
2510 .table_info_manager()
2511 .get(table_id)
2512 .await
2513 .unwrap();
2514 assert!(table_info.is_none());
2515 let table_route = table_metadata_manager
2516 .table_route_manager()
2517 .table_route_storage()
2518 .get(table_id)
2519 .await
2520 .unwrap();
2521 assert!(table_route.is_none());
2522 let regions = table_metadata_manager
2524 .topic_region_manager
2525 .regions("greptimedb_topic0")
2526 .await
2527 .unwrap();
2528 assert_eq!(regions.len(), 0);
2529 let regions = table_metadata_manager
2530 .topic_region_manager
2531 .regions("greptimedb_topic1")
2532 .await
2533 .unwrap();
2534 assert_eq!(regions.len(), 0);
2535 }
2536
2537 #[tokio::test]
2538 async fn test_rename_table() {
2539 let mem_kv = Arc::new(MemoryKvBackend::default());
2540 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2541 let region_route = new_test_region_route();
2542 let region_routes = vec![region_route.clone()];
2543 let table_info = new_test_table_info();
2544 let table_id = table_info.ident.table_id;
2545 create_physical_table_metadata(
2547 &table_metadata_manager,
2548 table_info.clone(),
2549 region_routes.clone(),
2550 HashMap::new(),
2551 )
2552 .await
2553 .unwrap();
2554
2555 let new_table_name = "another_name".to_string();
2556 let table_info_value =
2557 DeserializedValueWithBytes::from_inner(TableInfoValue::new(table_info.clone()));
2558
2559 table_metadata_manager
2560 .rename_table(&table_info_value, new_table_name.clone())
2561 .await
2562 .unwrap();
2563 table_metadata_manager
2565 .rename_table(&table_info_value, new_table_name.clone())
2566 .await
2567 .unwrap();
2568 let mut modified_table_info = table_info.clone();
2569 modified_table_info.name = "hi".to_string();
2570 let modified_table_info_value =
2571 DeserializedValueWithBytes::from_inner(table_info_value.update(modified_table_info));
2572 assert!(
2575 table_metadata_manager
2576 .rename_table(&modified_table_info_value, new_table_name.clone())
2577 .await
2578 .is_err()
2579 );
2580
2581 let old_table_name = TableNameKey::new(
2582 &table_info.catalog_name,
2583 &table_info.schema_name,
2584 &table_info.name,
2585 );
2586 let new_table_name = TableNameKey::new(
2587 &table_info.catalog_name,
2588 &table_info.schema_name,
2589 &new_table_name,
2590 );
2591
2592 assert!(
2593 table_metadata_manager
2594 .table_name_manager()
2595 .get(old_table_name)
2596 .await
2597 .unwrap()
2598 .is_none()
2599 );
2600
2601 assert_eq!(
2602 table_metadata_manager
2603 .table_name_manager()
2604 .get(new_table_name)
2605 .await
2606 .unwrap()
2607 .unwrap()
2608 .table_id(),
2609 table_id
2610 );
2611 }
2612
2613 #[tokio::test]
2614 async fn test_update_table_info() {
2615 let mem_kv = Arc::new(MemoryKvBackend::default());
2616 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2617 let region_route = new_test_region_route();
2618 let region_routes = vec![region_route.clone()];
2619 let table_info = new_test_table_info();
2620 let table_id = table_info.ident.table_id;
2621 create_physical_table_metadata(
2623 &table_metadata_manager,
2624 table_info.clone(),
2625 region_routes.clone(),
2626 HashMap::new(),
2627 )
2628 .await
2629 .unwrap();
2630
2631 let mut new_table_info = table_info.clone();
2632 new_table_info.name = "hi".to_string();
2633 let current_table_info_value =
2634 DeserializedValueWithBytes::from_inner(TableInfoValue::new(table_info.clone()));
2635 table_metadata_manager
2637 .update_table_info(¤t_table_info_value, None, new_table_info.clone())
2638 .await
2639 .unwrap();
2640 table_metadata_manager
2642 .update_table_info(¤t_table_info_value, None, new_table_info.clone())
2643 .await
2644 .unwrap();
2645
2646 let updated_table_info = table_metadata_manager
2648 .table_info_manager()
2649 .get(table_id)
2650 .await
2651 .unwrap()
2652 .unwrap()
2653 .into_inner();
2654 assert_eq!(updated_table_info.table_info, new_table_info);
2655
2656 let mut wrong_table_info = table_info.clone();
2657 wrong_table_info.name = "wrong".to_string();
2658 let wrong_table_info_value = DeserializedValueWithBytes::from_inner(
2659 current_table_info_value.update(wrong_table_info),
2660 );
2661 assert!(
2664 table_metadata_manager
2665 .update_table_info(&wrong_table_info_value, None, new_table_info)
2666 .await
2667 .is_err()
2668 )
2669 }
2670
2671 #[tokio::test]
2672 async fn test_update_table_leader_region_status() {
2673 let mem_kv = Arc::new(MemoryKvBackend::default());
2674 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2675 let datanode = 1;
2676 let region_routes = vec![
2677 RegionRoute {
2678 region: Region {
2679 id: 1.into(),
2680 name: "r1".to_string(),
2681 attrs: BTreeMap::new(),
2682 partition_expr: Default::default(),
2683 },
2684 leader_peer: Some(Peer::new(datanode, "a2")),
2685 leader_state: Some(LeaderState::Downgrading),
2686 follower_peers: vec![],
2687 leader_down_since: Some(current_time_millis()),
2688 write_route_policy: None,
2689 },
2690 RegionRoute {
2691 region: Region {
2692 id: 2.into(),
2693 name: "r2".to_string(),
2694 attrs: BTreeMap::new(),
2695 partition_expr: Default::default(),
2696 },
2697 leader_peer: Some(Peer::new(datanode, "a1")),
2698 leader_state: None,
2699 follower_peers: vec![],
2700 leader_down_since: None,
2701 write_route_policy: None,
2702 },
2703 ];
2704 let table_info = new_test_table_info();
2705 let table_id = table_info.ident.table_id;
2706 let current_table_route_value = DeserializedValueWithBytes::from_inner(
2707 TableRouteValue::physical(region_routes.clone()),
2708 );
2709
2710 create_physical_table_metadata(
2712 &table_metadata_manager,
2713 table_info.clone(),
2714 region_routes.clone(),
2715 HashMap::new(),
2716 )
2717 .await
2718 .unwrap();
2719
2720 table_metadata_manager
2721 .update_leader_region_status(table_id, ¤t_table_route_value, |region_route| {
2722 if region_route.leader_state.is_some() {
2723 None
2724 } else {
2725 Some(Some(LeaderState::Downgrading))
2726 }
2727 })
2728 .await
2729 .unwrap();
2730
2731 let updated_route_value = table_metadata_manager
2732 .table_route_manager()
2733 .table_route_storage()
2734 .get(table_id)
2735 .await
2736 .unwrap()
2737 .unwrap();
2738
2739 assert_eq!(
2740 updated_route_value.region_routes().unwrap()[0].leader_state,
2741 Some(LeaderState::Downgrading)
2742 );
2743
2744 assert!(
2745 updated_route_value.region_routes().unwrap()[0]
2746 .leader_down_since
2747 .is_some()
2748 );
2749
2750 assert_eq!(
2751 updated_route_value.region_routes().unwrap()[1].leader_state,
2752 Some(LeaderState::Downgrading)
2753 );
2754 assert!(
2755 updated_route_value.region_routes().unwrap()[1]
2756 .leader_down_since
2757 .is_some()
2758 );
2759 }
2760
2761 async fn assert_datanode_table(
2762 table_metadata_manager: &TableMetadataManager,
2763 table_id: u32,
2764 region_routes: &[RegionRoute],
2765 ) {
2766 let region_distribution = region_distribution(region_routes);
2767 for (datanode, regions) in region_distribution {
2768 let got = table_metadata_manager
2769 .datanode_table_manager()
2770 .get(&DatanodeTableKey::new(datanode, table_id))
2771 .await
2772 .unwrap()
2773 .unwrap();
2774
2775 assert_eq!(got.regions, regions.leader_regions);
2776 assert_eq!(got.follower_regions, regions.follower_regions);
2777 }
2778 }
2779
2780 #[tokio::test]
2781 async fn test_update_table_route() {
2782 let mem_kv = Arc::new(MemoryKvBackend::default());
2783 let table_metadata_manager = TableMetadataManager::new(mem_kv);
2784 let region_route = new_test_region_route();
2785 let region_routes = vec![region_route.clone()];
2786 let table_info = new_test_table_info();
2787 let table_id = table_info.ident.table_id;
2788 let engine = table_info.meta.engine.as_str();
2789 let region_storage_path =
2790 region_storage_path(&table_info.catalog_name, &table_info.schema_name);
2791 let current_table_route_value = DeserializedValueWithBytes::from_inner(
2792 TableRouteValue::physical(region_routes.clone()),
2793 );
2794
2795 create_physical_table_metadata(
2797 &table_metadata_manager,
2798 table_info.clone(),
2799 region_routes.clone(),
2800 HashMap::new(),
2801 )
2802 .await
2803 .unwrap();
2804
2805 assert_datanode_table(&table_metadata_manager, table_id, ®ion_routes).await;
2806 let new_region_routes = vec![
2807 new_region_route(1, 1),
2808 new_region_route(2, 2),
2809 new_region_route(3, 3),
2810 ];
2811 table_metadata_manager
2813 .update_table_route(
2814 table_id,
2815 RegionInfo {
2816 engine: engine.to_string(),
2817 region_storage_path: region_storage_path.clone(),
2818 region_options: HashMap::new(),
2819 region_wal_options: HashMap::new(),
2820 },
2821 ¤t_table_route_value,
2822 new_region_routes.clone(),
2823 &HashMap::new(),
2824 &HashMap::new(),
2825 )
2826 .await
2827 .unwrap();
2828 assert_datanode_table(&table_metadata_manager, table_id, &new_region_routes).await;
2829
2830 table_metadata_manager
2832 .update_table_route(
2833 table_id,
2834 RegionInfo {
2835 engine: engine.to_string(),
2836 region_storage_path: region_storage_path.clone(),
2837 region_options: HashMap::new(),
2838 region_wal_options: HashMap::new(),
2839 },
2840 ¤t_table_route_value,
2841 new_region_routes.clone(),
2842 &HashMap::new(),
2843 &HashMap::new(),
2844 )
2845 .await
2846 .unwrap();
2847
2848 let current_table_route_value = DeserializedValueWithBytes::from_inner(
2849 current_table_route_value
2850 .inner
2851 .update(new_region_routes.clone())
2852 .unwrap(),
2853 );
2854 let new_region_routes = vec![new_region_route(2, 4), new_region_route(5, 5)];
2855 table_metadata_manager
2857 .update_table_route(
2858 table_id,
2859 RegionInfo {
2860 engine: engine.to_string(),
2861 region_storage_path: region_storage_path.clone(),
2862 region_options: HashMap::new(),
2863 region_wal_options: HashMap::new(),
2864 },
2865 ¤t_table_route_value,
2866 new_region_routes.clone(),
2867 &HashMap::new(),
2868 &HashMap::new(),
2869 )
2870 .await
2871 .unwrap();
2872 assert_datanode_table(&table_metadata_manager, table_id, &new_region_routes).await;
2873
2874 let wrong_table_route_value = DeserializedValueWithBytes::from_inner(
2877 current_table_route_value
2878 .update(vec![
2879 new_region_route(1, 1),
2880 new_region_route(2, 2),
2881 new_region_route(3, 3),
2882 new_region_route(4, 4),
2883 ])
2884 .unwrap(),
2885 );
2886 assert!(
2887 table_metadata_manager
2888 .update_table_route(
2889 table_id,
2890 RegionInfo {
2891 engine: engine.to_string(),
2892 region_storage_path: region_storage_path.clone(),
2893 region_options: HashMap::new(),
2894 region_wal_options: HashMap::new(),
2895 },
2896 &wrong_table_route_value,
2897 new_region_routes,
2898 &HashMap::new(),
2899 &HashMap::new(),
2900 )
2901 .await
2902 .is_err()
2903 );
2904 }
2905
2906 #[tokio::test]
2907 async fn test_update_table_route_with_topic_region_mapping() {
2908 let mem_kv = Arc::new(MemoryKvBackend::default());
2909 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
2910 let region_route = new_test_region_route();
2911 let region_routes = vec![region_route.clone()];
2912 let table_info = new_test_table_info();
2913 let table_id = table_info.ident.table_id;
2914 let engine = table_info.meta.engine.as_str();
2915 let region_storage_path =
2916 region_storage_path(&table_info.catalog_name, &table_info.schema_name);
2917
2918 let old_region_wal_options: RegionWalOptions = vec![
2920 (
2921 1,
2922 WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())),
2923 ),
2924 (
2925 2,
2926 WalOptions::Kafka(KafkaWalOptions::new("topic_2".to_string())),
2927 ),
2928 ]
2929 .into_iter()
2930 .collect();
2931
2932 create_physical_table_metadata(
2933 &table_metadata_manager,
2934 table_info.clone(),
2935 region_routes.clone(),
2936 old_region_wal_options.clone(),
2937 )
2938 .await
2939 .unwrap();
2940
2941 let current_table_route_value = DeserializedValueWithBytes::from_inner(
2942 TableRouteValue::physical(region_routes.clone()),
2943 );
2944
2945 let region_id_1 = RegionId::new(table_id, 1);
2947 let region_id_2 = RegionId::new(table_id, 2);
2948 let topic_1_key = TopicRegionKey::new(region_id_1, "topic_1");
2949 let topic_2_key = TopicRegionKey::new(region_id_2, "topic_2");
2950 assert!(
2951 table_metadata_manager
2952 .topic_region_manager
2953 .get(topic_1_key.clone())
2954 .await
2955 .unwrap()
2956 .is_some()
2957 );
2958 assert!(
2959 table_metadata_manager
2960 .topic_region_manager
2961 .get(topic_2_key.clone())
2962 .await
2963 .unwrap()
2964 .is_some()
2965 );
2966
2967 let new_region_routes = vec![
2969 new_region_route(1, 1),
2970 new_region_route(2, 2),
2971 new_region_route(3, 3), ];
2973 let new_region_wal_options: RegionWalOptions = vec![
2974 (
2975 1,
2976 WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())), ),
2978 (
2979 2,
2980 WalOptions::Kafka(KafkaWalOptions::new("topic_2".to_string())), ),
2982 (
2983 3,
2984 WalOptions::Kafka(KafkaWalOptions::new("topic_3".to_string())), ),
2986 ]
2987 .into_iter()
2988 .collect();
2989 let current_table_route_value_updated = DeserializedValueWithBytes::from_inner(
2990 current_table_route_value
2991 .inner
2992 .update(new_region_routes.clone())
2993 .unwrap(),
2994 );
2995 table_metadata_manager
2996 .update_table_route(
2997 table_id,
2998 RegionInfo {
2999 engine: engine.to_string(),
3000 region_storage_path: region_storage_path.clone(),
3001 region_options: HashMap::new(),
3002 region_wal_options: old_region_wal_options.clone(),
3003 },
3004 ¤t_table_route_value,
3005 new_region_routes.clone(),
3006 &HashMap::new(),
3007 &new_region_wal_options,
3008 )
3009 .await
3010 .unwrap();
3011 let region_id_3 = RegionId::new(table_id, 3);
3013 let topic_3_key = TopicRegionKey::new(region_id_3, "topic_3");
3014 assert!(
3015 table_metadata_manager
3016 .topic_region_manager
3017 .get(topic_3_key)
3018 .await
3019 .unwrap()
3020 .is_some()
3021 );
3022 let newer_region_routes = vec![
3024 new_region_route(1, 1),
3025 ];
3028 let newer_region_wal_options: RegionWalOptions = vec![
3029 (
3030 1,
3031 WalOptions::Kafka(KafkaWalOptions::new("topic_1".to_string())), ),
3033 (
3034 3,
3035 WalOptions::Kafka(KafkaWalOptions::new("topic_3_new".to_string())), ),
3037 ]
3038 .into_iter()
3039 .collect();
3040 table_metadata_manager
3041 .update_table_route(
3042 table_id,
3043 RegionInfo {
3044 engine: engine.to_string(),
3045 region_storage_path: region_storage_path.clone(),
3046 region_options: HashMap::new(),
3047 region_wal_options: new_region_wal_options.clone(),
3048 },
3049 ¤t_table_route_value_updated,
3050 newer_region_routes.clone(),
3051 &HashMap::new(),
3052 &newer_region_wal_options,
3053 )
3054 .await
3055 .unwrap();
3056 let topic_2_key_new = TopicRegionKey::new(region_id_2, "topic_2");
3058 assert!(
3059 table_metadata_manager
3060 .topic_region_manager
3061 .get(topic_2_key_new)
3062 .await
3063 .unwrap()
3064 .is_none()
3065 );
3066 let topic_3_key_old = TopicRegionKey::new(region_id_3, "topic_3");
3068 assert!(
3069 table_metadata_manager
3070 .topic_region_manager
3071 .get(topic_3_key_old)
3072 .await
3073 .unwrap()
3074 .is_none()
3075 );
3076 let topic_3_key_new = TopicRegionKey::new(region_id_3, "topic_3_new");
3078 assert!(
3079 table_metadata_manager
3080 .topic_region_manager
3081 .get(topic_3_key_new)
3082 .await
3083 .unwrap()
3084 .is_some()
3085 );
3086 assert!(
3088 table_metadata_manager
3089 .topic_region_manager
3090 .get(topic_1_key)
3091 .await
3092 .unwrap()
3093 .is_some()
3094 );
3095 }
3096
3097 #[tokio::test]
3098 async fn test_destroy_table_metadata() {
3099 let mem_kv = Arc::new(MemoryKvBackend::default());
3100 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3101 let table_id = 1025;
3102 let table_name = "foo";
3103 let task = test_create_table_task(table_name, table_id);
3104 let options = create_mixed_region_wal_options();
3105 let serialized_options = options.clone();
3106 table_metadata_manager
3107 .create_table_metadata(
3108 task.table_info,
3109 TableRouteValue::physical(vec![
3110 RegionRoute {
3111 region: Region::new_test(RegionId::new(table_id, 1)),
3112 leader_peer: Some(Peer::empty(1)),
3113 follower_peers: vec![Peer::empty(5)],
3114 leader_state: None,
3115 leader_down_since: None,
3116 write_route_policy: None,
3117 },
3118 RegionRoute {
3119 region: Region::new_test(RegionId::new(table_id, 2)),
3120 leader_peer: Some(Peer::empty(2)),
3121 follower_peers: vec![Peer::empty(4)],
3122 leader_state: None,
3123 leader_down_since: None,
3124 write_route_policy: None,
3125 },
3126 RegionRoute {
3127 region: Region::new_test(RegionId::new(table_id, 3)),
3128 leader_peer: Some(Peer::empty(3)),
3129 follower_peers: vec![],
3130 leader_state: None,
3131 leader_down_since: None,
3132 write_route_policy: None,
3133 },
3134 ]),
3135 serialized_options,
3136 )
3137 .await
3138 .unwrap();
3139 let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
3140 let table_route_value = table_metadata_manager
3141 .table_route_manager
3142 .table_route_storage()
3143 .get_with_raw_bytes(table_id)
3144 .await
3145 .unwrap()
3146 .unwrap();
3147 table_metadata_manager
3148 .destroy_table_metadata(table_id, &table_name, &table_route_value, &options)
3149 .await
3150 .unwrap();
3151 assert!(mem_kv.is_empty());
3152 }
3153
3154 #[tokio::test]
3155 async fn test_restore_table_metadata() {
3156 let mem_kv = Arc::new(MemoryKvBackend::default());
3157 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3158 let table_id = 1025;
3159 let table_name = "foo";
3160 let task = test_create_table_task(table_name, table_id);
3161 let options = create_mixed_region_wal_options();
3162 let serialized_options = options.clone();
3163 table_metadata_manager
3164 .create_table_metadata(
3165 task.table_info,
3166 TableRouteValue::physical(vec![
3167 RegionRoute {
3168 region: Region::new_test(RegionId::new(table_id, 1)),
3169 leader_peer: Some(Peer::empty(1)),
3170 follower_peers: vec![Peer::empty(5)],
3171 leader_state: None,
3172 leader_down_since: None,
3173 write_route_policy: None,
3174 },
3175 RegionRoute {
3176 region: Region::new_test(RegionId::new(table_id, 2)),
3177 leader_peer: Some(Peer::empty(2)),
3178 follower_peers: vec![Peer::empty(4)],
3179 leader_state: None,
3180 leader_down_since: None,
3181 write_route_policy: None,
3182 },
3183 RegionRoute {
3184 region: Region::new_test(RegionId::new(table_id, 3)),
3185 leader_peer: Some(Peer::empty(3)),
3186 follower_peers: vec![],
3187 leader_state: None,
3188 leader_down_since: None,
3189 write_route_policy: None,
3190 },
3191 ]),
3192 serialized_options,
3193 )
3194 .await
3195 .unwrap();
3196 let expected_result = mem_kv.dump();
3197 let table_route_value = table_metadata_manager
3198 .table_route_manager
3199 .table_route_storage()
3200 .get_with_raw_bytes(table_id)
3201 .await
3202 .unwrap()
3203 .unwrap();
3204 let region_routes = table_route_value.region_routes().unwrap();
3205 let table_name = TableName::new(DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, table_name);
3206 let table_route_value = TableRouteValue::physical(region_routes.clone());
3207 table_metadata_manager
3208 .delete_table_metadata(table_id, &table_name, &table_route_value, &options, None)
3209 .await
3210 .unwrap();
3211 table_metadata_manager
3212 .restore_table_metadata(table_id, &table_name, &table_route_value, &options)
3213 .await
3214 .unwrap();
3215 let kvs = mem_kv.dump();
3216 assert_eq!(kvs, expected_result);
3217 table_metadata_manager
3219 .restore_table_metadata(table_id, &table_name, &table_route_value, &options)
3220 .await
3221 .unwrap();
3222 let kvs = mem_kv.dump();
3223 assert_eq!(kvs, expected_result);
3224 }
3225
3226 #[tokio::test]
3227 async fn test_dropped_table_metadata_enumeration_and_lookup() {
3228 let table_id = 1025;
3229 let table_name = "foo";
3230 let (_, table_metadata_manager, table_name, table_info, region_routes, options) =
3231 create_dropped_physical_table_metadata(
3232 table_id,
3233 table_name,
3234 vec![
3235 test_physical_region_route(table_id, 1, 1, vec![5]),
3236 test_physical_region_route(table_id, 2, 2, vec![4]),
3237 test_physical_region_route(table_id, 3, 3, vec![]),
3238 ],
3239 create_mixed_region_wal_options(),
3240 )
3241 .await;
3242
3243 let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3244 assert_eq!(dropped_tables.len(), 1);
3245 assert_eq!(dropped_tables[0].table_id, table_id);
3246 assert_eq!(dropped_tables[0].table_name, table_name);
3247
3248 let dropped_table = table_metadata_manager
3249 .get_dropped_table(&table_name)
3250 .await
3251 .unwrap()
3252 .unwrap();
3253 assert_dropped_table_metadata(
3254 &dropped_table,
3255 table_id,
3256 &table_name,
3257 &table_info,
3258 ®ion_routes,
3259 &options,
3260 );
3261
3262 let dropped_table_by_id = table_metadata_manager
3263 .get_dropped_table_by_id(table_id)
3264 .await
3265 .unwrap()
3266 .unwrap();
3267 assert_dropped_table_metadata(
3268 &dropped_table_by_id,
3269 table_id,
3270 &table_name,
3271 &table_info,
3272 ®ion_routes,
3273 &options,
3274 );
3275 }
3276
3277 #[tokio::test]
3278 async fn test_list_dropped_tables_batches_timestamp_lookup() {
3279 let mem_kv = Arc::new(MemoryKvBackend::default());
3280 let table_metadata_manager = TableMetadataManager::new(mem_kv.clone());
3281 for (table_id, table_name, dropped_at) in
3282 [(1025, "legacy", None), (1026, "marked", Some(1234))]
3283 {
3284 let task = test_create_table_task(table_name, table_id);
3285 let table_name = task.table_name();
3286 let table_route = TableRouteValue::physical(vec![]);
3287 table_metadata_manager
3288 .create_table_metadata(task.table_info, table_route.clone(), HashMap::new())
3289 .await
3290 .unwrap();
3291 table_metadata_manager
3292 .delete_table_metadata(
3293 table_id,
3294 &table_name,
3295 &table_route,
3296 &HashMap::new(),
3297 dropped_at,
3298 )
3299 .await
3300 .unwrap();
3301 }
3302 let all_tombstones = mem_kv
3303 .range(RangeRequest::new().with_prefix("__tombstone/"))
3304 .await
3305 .unwrap()
3306 .kvs;
3307 let range_calls = Arc::new(AtomicUsize::new(0));
3308 let batch_get_calls = Arc::new(AtomicUsize::new(0));
3309 let mock = MockKvBackend {
3310 range_fn: Some({
3311 let all_tombstones = all_tombstones.clone();
3312 let range_calls = range_calls.clone();
3313 Arc::new(move |req| {
3314 range_calls.fetch_add(1, Ordering::Relaxed);
3315 let kvs = all_tombstones
3316 .iter()
3317 .filter(|kv| {
3318 if req.range_end.is_empty() {
3319 kv.key == req.key
3320 } else {
3321 kv.key >= req.key && kv.key < req.range_end
3322 }
3323 })
3324 .cloned()
3325 .collect();
3326 Ok(RangeResponse { kvs, more: false })
3327 })
3328 }),
3329 range_async_fn: None,
3330 batch_get_fn: Some({
3331 let batch_get_calls = batch_get_calls.clone();
3332 Arc::new(move |req| {
3333 batch_get_calls.fetch_add(1, Ordering::Relaxed);
3334 let kvs = all_tombstones
3335 .iter()
3336 .filter(|kv| req.keys.contains(&kv.key))
3337 .cloned()
3338 .collect();
3339 Ok(BatchGetResponse { kvs })
3340 })
3341 }),
3342 put_fn: None,
3343 batch_put_fn: None,
3344 delete_range_fn: None,
3345 batch_delete_fn: None,
3346 txn: None,
3347 max_txn_ops: None,
3348 };
3349 let table_metadata_manager = TableMetadataManager::new(Arc::new(mock));
3350
3351 let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3352
3353 assert_eq!(
3354 dropped_tables
3355 .iter()
3356 .map(|table| (table.table_id, table.dropped_at))
3357 .collect::<Vec<_>>(),
3358 vec![(1025, None), (1026, Some(1234))]
3359 );
3360 assert_eq!(range_calls.load(Ordering::Relaxed), 1);
3361 assert_eq!(batch_get_calls.load(Ordering::Relaxed), 1);
3362 }
3363
3364 #[tokio::test]
3365 async fn test_dropped_table_lookup_survives_live_name_recreation() {
3366 let dropped_table_id = 1025;
3367 let recreated_table_id = 1026;
3368 let table_name = "foo";
3369 let (
3370 _,
3371 table_metadata_manager,
3372 dropped_table_name,
3373 dropped_table_info,
3374 region_routes,
3375 options,
3376 ) = create_dropped_physical_table_metadata(
3377 dropped_table_id,
3378 table_name,
3379 vec![
3380 test_physical_region_route(dropped_table_id, 1, 1, vec![5]),
3381 test_physical_region_route(dropped_table_id, 2, 2, vec![4]),
3382 ],
3383 create_mock_region_wal_options(),
3384 )
3385 .await;
3386
3387 let recreated_task = test_create_table_task(table_name, recreated_table_id);
3388 table_metadata_manager
3389 .create_table_metadata(
3390 recreated_task.table_info,
3391 TableRouteValue::physical(vec![test_physical_region_route(
3392 recreated_table_id,
3393 1,
3394 4,
3395 vec![],
3396 )]),
3397 HashMap::new(),
3398 )
3399 .await
3400 .unwrap();
3401
3402 assert_eq!(
3403 table_metadata_manager
3404 .table_name_manager()
3405 .get(TableNameKey::from(&dropped_table_name))
3406 .await
3407 .unwrap()
3408 .unwrap()
3409 .table_id(),
3410 recreated_table_id
3411 );
3412
3413 let dropped_table = table_metadata_manager
3414 .get_dropped_table(&dropped_table_name)
3415 .await
3416 .unwrap()
3417 .unwrap();
3418 assert_dropped_table_metadata(
3419 &dropped_table,
3420 dropped_table_id,
3421 &dropped_table_name,
3422 &dropped_table_info,
3423 ®ion_routes,
3424 &options,
3425 );
3426
3427 let dropped_tables = table_metadata_manager.list_dropped_tables().await.unwrap();
3428 assert_eq!(dropped_tables.len(), 1);
3429 assert_eq!(dropped_tables[0].table_id, dropped_table_id);
3430 assert_eq!(dropped_tables[0].table_name, dropped_table_name);
3431 }
3432
3433 #[tokio::test]
3434 async fn test_dropped_table_exact_lookup_ignores_unrelated_malformed_table_name_tombstone() {
3435 let table_id = 1025;
3436 let table_name = "foo";
3437 let (mem_kv, table_metadata_manager, table_name, table_info, region_routes, options) =
3438 create_dropped_physical_table_metadata(
3439 table_id,
3440 table_name,
3441 vec![
3442 test_physical_region_route(table_id, 1, 1, vec![5]),
3443 test_physical_region_route(table_id, 2, 2, vec![4]),
3444 ],
3445 create_mixed_region_wal_options(),
3446 )
3447 .await;
3448
3449 mem_kv
3450 .put(
3451 PutRequest::new()
3452 .with_key("__tombstone/__table_name/not-a-table-name-key")
3453 .with_value("malformed"),
3454 )
3455 .await
3456 .unwrap();
3457
3458 let dropped_table = table_metadata_manager
3459 .get_dropped_table(&table_name)
3460 .await
3461 .unwrap()
3462 .unwrap();
3463 assert_dropped_table_metadata(
3464 &dropped_table,
3465 table_id,
3466 &table_name,
3467 &table_info,
3468 ®ion_routes,
3469 &options,
3470 );
3471 }
3472
3473 #[tokio::test]
3474 async fn test_dropped_table_exact_lookup_tracks_reused_name_after_purge() {
3475 let old_table_id = 1025;
3476 let new_table_id = 1026;
3477 let (_, manager, table_name, _, old_routes, old_options) =
3478 create_dropped_physical_table_metadata(
3479 old_table_id,
3480 "foo",
3481 vec![test_physical_region_route(old_table_id, 1, 1, vec![])],
3482 HashMap::new(),
3483 )
3484 .await;
3485
3486 manager
3487 .delete_table_metadata_tombstone(
3488 old_table_id,
3489 &table_name,
3490 &TableRouteValue::physical(old_routes),
3491 &old_options,
3492 )
3493 .await
3494 .unwrap();
3495 let new_task = test_create_table_task("foo", new_table_id);
3496 let new_info = new_task.table_info.clone();
3497 let new_route =
3498 TableRouteValue::physical(vec![test_physical_region_route(new_table_id, 1, 1, vec![])]);
3499 manager
3500 .create_table_metadata(new_task.table_info, new_route.clone(), HashMap::new())
3501 .await
3502 .unwrap();
3503 manager
3504 .delete_table_metadata(new_table_id, &table_name, &new_route, &HashMap::new(), None)
3505 .await
3506 .unwrap();
3507
3508 let dropped = manager
3509 .get_dropped_table(&table_name)
3510 .await
3511 .unwrap()
3512 .unwrap();
3513 assert_eq!(new_table_id, dropped.table_id);
3514 assert_eq!(new_info, dropped.table_info_value.table_info);
3515 }
3516
3517 #[tokio::test]
3518 async fn test_dropped_table_exact_lookup_missing() {
3519 let manager = TableMetadataManager::new(Arc::new(MemoryKvBackend::default()));
3520
3521 assert!(
3522 manager
3523 .get_dropped_table(&TableName::new("greptime", "public", "missing"))
3524 .await
3525 .unwrap()
3526 .is_none()
3527 );
3528 }
3529
3530 #[tokio::test]
3531 async fn test_create_update_view_info() {
3532 let mem_kv = Arc::new(MemoryKvBackend::default());
3533 let table_metadata_manager = TableMetadataManager::new(mem_kv);
3534
3535 let view_info = new_test_table_info();
3536
3537 let view_id = view_info.ident.table_id;
3538
3539 let logical_plan: Vec<u8> = vec![1, 2, 3];
3540 let columns = vec!["a".to_string()];
3541 let plan_columns = vec!["number".to_string()];
3542 let table_names = new_test_table_names();
3543 let definition = "CREATE VIEW test AS SELECT * FROM numbers";
3544
3545 table_metadata_manager
3547 .create_view_metadata(
3548 view_info.clone(),
3549 logical_plan.clone(),
3550 table_names.clone(),
3551 columns.clone(),
3552 plan_columns.clone(),
3553 definition.to_string(),
3554 )
3555 .await
3556 .unwrap();
3557
3558 {
3559 let current_view_info = table_metadata_manager
3561 .view_info_manager()
3562 .get(view_id)
3563 .await
3564 .unwrap()
3565 .unwrap()
3566 .into_inner();
3567 assert_eq!(current_view_info.view_info, logical_plan);
3568 assert_eq!(current_view_info.table_names, table_names);
3569 assert_eq!(current_view_info.definition, definition);
3570 assert_eq!(current_view_info.columns, columns);
3571 assert_eq!(current_view_info.plan_columns, plan_columns);
3572 let current_table_info = table_metadata_manager
3574 .table_info_manager()
3575 .get(view_id)
3576 .await
3577 .unwrap()
3578 .unwrap()
3579 .into_inner();
3580 assert_eq!(current_table_info.table_info, view_info);
3581 }
3582
3583 let new_logical_plan: Vec<u8> = vec![4, 5, 6];
3584 let new_table_names = {
3585 let mut set = HashSet::new();
3586 set.insert(TableName {
3587 catalog_name: "greptime".to_string(),
3588 schema_name: "public".to_string(),
3589 table_name: "b_table".to_string(),
3590 });
3591 set.insert(TableName {
3592 catalog_name: "greptime".to_string(),
3593 schema_name: "public".to_string(),
3594 table_name: "c_table".to_string(),
3595 });
3596 set
3597 };
3598 let new_columns = vec!["b".to_string()];
3599 let new_plan_columns = vec!["number2".to_string()];
3600 let new_definition = "CREATE VIEW test AS SELECT * FROM b_table join c_table";
3601
3602 let current_view_info_value = DeserializedValueWithBytes::from_inner(ViewInfoValue::new(
3603 logical_plan.clone().into(),
3604 table_names,
3605 columns,
3606 plan_columns,
3607 definition.to_string(),
3608 ));
3609 table_metadata_manager
3611 .update_view_info(
3612 view_id,
3613 ¤t_view_info_value,
3614 new_logical_plan.clone(),
3615 new_table_names.clone(),
3616 new_columns.clone(),
3617 new_plan_columns.clone(),
3618 new_definition.to_string(),
3619 )
3620 .await
3621 .unwrap();
3622 table_metadata_manager
3624 .update_view_info(
3625 view_id,
3626 ¤t_view_info_value,
3627 new_logical_plan.clone(),
3628 new_table_names.clone(),
3629 new_columns.clone(),
3630 new_plan_columns.clone(),
3631 new_definition.to_string(),
3632 )
3633 .await
3634 .unwrap();
3635
3636 let updated_view_info = table_metadata_manager
3638 .view_info_manager()
3639 .get(view_id)
3640 .await
3641 .unwrap()
3642 .unwrap()
3643 .into_inner();
3644 assert_eq!(updated_view_info.view_info, new_logical_plan);
3645 assert_eq!(updated_view_info.table_names, new_table_names);
3646 assert_eq!(updated_view_info.definition, new_definition);
3647 assert_eq!(updated_view_info.columns, new_columns);
3648 assert_eq!(updated_view_info.plan_columns, new_plan_columns);
3649
3650 let wrong_view_info = logical_plan.clone();
3651 let wrong_definition = "wrong_definition";
3652 let wrong_view_info_value =
3653 DeserializedValueWithBytes::from_inner(current_view_info_value.update(
3654 wrong_view_info.into(),
3655 new_table_names.clone(),
3656 new_columns.clone(),
3657 new_plan_columns.clone(),
3658 wrong_definition.to_string(),
3659 ));
3660 assert!(
3663 table_metadata_manager
3664 .update_view_info(
3665 view_id,
3666 &wrong_view_info_value,
3667 new_logical_plan.clone(),
3668 new_table_names.clone(),
3669 vec!["c".to_string()],
3670 vec!["number3".to_string()],
3671 wrong_definition.to_string(),
3672 )
3673 .await
3674 .is_err()
3675 );
3676
3677 let current_view_info = table_metadata_manager
3679 .view_info_manager()
3680 .get(view_id)
3681 .await
3682 .unwrap()
3683 .unwrap()
3684 .into_inner();
3685 assert_eq!(current_view_info.view_info, new_logical_plan);
3686 assert_eq!(current_view_info.table_names, new_table_names);
3687 assert_eq!(current_view_info.definition, new_definition);
3688 assert_eq!(current_view_info.columns, new_columns);
3689 assert_eq!(current_view_info.plan_columns, new_plan_columns);
3690 }
3691
3692 #[test]
3693 fn test_region_role_set_deserialize() {
3694 let s = r#"{"leader_regions": [1, 2, 3], "follower_regions": [4, 5, 6]}"#;
3695 let region_role_set: RegionRoleSet = serde_json::from_str(s).unwrap();
3696 assert_eq!(region_role_set.leader_regions, vec![1, 2, 3]);
3697 assert_eq!(region_role_set.follower_regions, vec![4, 5, 6]);
3698
3699 let s = r#"[1, 2, 3]"#;
3700 let region_role_set: RegionRoleSet = serde_json::from_str(s).unwrap();
3701 assert_eq!(region_role_set.leader_regions, vec![1, 2, 3]);
3702 assert!(region_role_set.follower_regions.is_empty());
3703 }
3704
3705 #[test]
3706 fn test_region_distribution_deserialize() {
3707 let s = r#"{"1": [1,2,3], "2": {"leader_regions": [7, 8, 9], "follower_regions": [10, 11, 12]}}"#;
3708 let region_distribution: RegionDistribution = serde_json::from_str(s).unwrap();
3709 assert_eq!(region_distribution.len(), 2);
3710 assert_eq!(region_distribution[&1].leader_regions, vec![1, 2, 3]);
3711 assert!(region_distribution[&1].follower_regions.is_empty());
3712 assert_eq!(region_distribution[&2].leader_regions, vec![7, 8, 9]);
3713 assert_eq!(region_distribution[&2].follower_regions, vec![10, 11, 12]);
3714 }
3715}