1use std::any::Any;
18use std::collections::HashMap;
19use std::fmt::{Debug, Display};
20use std::sync::{Arc, Mutex};
21use std::time::Instant;
22
23use api::greptime_proto::v1::meta::{GrantedRegion as PbGrantedRegion, RegionRole as PbRegionRole};
24use api::region::RegionResponse;
25use async_trait::async_trait;
26use common_error::ext::BoxedError;
27use common_recordbatch::adapter::RegionQueryStatCounters;
28use common_recordbatch::{EmptyRecordBatchStream, QueryMemoryTracker, SendableRecordBatchStream};
29use common_time::Timestamp;
30use datafusion_execution::memory_pool::{MemoryPool, UnboundedMemoryPool};
31use datafusion_physical_plan::metrics::ExecutionPlanMetricsSet;
32use datafusion_physical_plan::{DisplayAs, DisplayFormatType, PhysicalExpr};
33use datatypes::schema::SchemaRef;
34use futures::FutureExt;
35use futures::future::{BoxFuture, join_all};
36use serde::{Deserialize, Serialize};
37use tokio::sync::Semaphore;
38
39use crate::logstore::entry;
40use crate::metadata::RegionMetadataRef;
41use crate::region_request::{
42 BatchRegionDdlRequest, RegionCatchupRequest, RegionOpenRequest, RegionPutRequest, RegionRequest,
43};
44use crate::storage::{FileId, RegionId, ScanRequest, SequenceNumber};
45
46#[derive(Debug, PartialEq, Eq, Clone, Copy)]
48pub enum SettableRegionRoleState {
49 Follower,
50 DowngradingLeader,
51 Leader,
53 StagingLeader,
55}
56
57impl Display for SettableRegionRoleState {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 match self {
60 SettableRegionRoleState::Follower => write!(f, "Follower"),
61 SettableRegionRoleState::DowngradingLeader => write!(f, "Leader(Downgrading)"),
62 SettableRegionRoleState::Leader => write!(f, "Leader"),
63 SettableRegionRoleState::StagingLeader => write!(f, "Leader(Staging)"),
64 }
65 }
66}
67
68impl From<SettableRegionRoleState> for RegionRole {
69 fn from(value: SettableRegionRoleState) -> Self {
70 match value {
71 SettableRegionRoleState::Follower => RegionRole::Follower,
72 SettableRegionRoleState::DowngradingLeader => RegionRole::DowngradingLeader,
73 SettableRegionRoleState::Leader => RegionRole::Leader,
74 SettableRegionRoleState::StagingLeader => RegionRole::StagingLeader,
75 }
76 }
77}
78
79#[derive(Debug, PartialEq, Eq)]
81pub struct SetRegionRoleStateRequest {
82 region_id: RegionId,
83 region_role_state: SettableRegionRoleState,
84}
85
86#[derive(Debug, PartialEq, Eq)]
88pub enum SetRegionRoleStateSuccess {
89 File,
90 Mito {
91 last_entry_id: entry::Id,
92 },
93 Metric {
94 last_entry_id: entry::Id,
95 metadata_last_entry_id: entry::Id,
96 },
97}
98
99impl SetRegionRoleStateSuccess {
100 pub fn file() -> Self {
102 Self::File
103 }
104
105 pub fn mito(last_entry_id: entry::Id) -> Self {
107 SetRegionRoleStateSuccess::Mito { last_entry_id }
108 }
109
110 pub fn metric(last_entry_id: entry::Id, metadata_last_entry_id: entry::Id) -> Self {
112 SetRegionRoleStateSuccess::Metric {
113 last_entry_id,
114 metadata_last_entry_id,
115 }
116 }
117}
118
119impl SetRegionRoleStateSuccess {
120 pub fn last_entry_id(&self) -> Option<entry::Id> {
122 match self {
123 SetRegionRoleStateSuccess::File => None,
124 SetRegionRoleStateSuccess::Mito { last_entry_id } => Some(*last_entry_id),
125 SetRegionRoleStateSuccess::Metric { last_entry_id, .. } => Some(*last_entry_id),
126 }
127 }
128
129 pub fn metadata_last_entry_id(&self) -> Option<entry::Id> {
131 match self {
132 SetRegionRoleStateSuccess::File => None,
133 SetRegionRoleStateSuccess::Mito { .. } => None,
134 SetRegionRoleStateSuccess::Metric {
135 metadata_last_entry_id,
136 ..
137 } => Some(*metadata_last_entry_id),
138 }
139 }
140}
141
142#[derive(Debug)]
144pub enum SetRegionRoleStateResponse {
145 Success(SetRegionRoleStateSuccess),
146 NotFound,
147 InvalidTransition(BoxedError),
148}
149
150impl SetRegionRoleStateResponse {
151 pub fn success(success: SetRegionRoleStateSuccess) -> Self {
153 Self::Success(success)
154 }
155
156 pub fn invalid_transition(error: BoxedError) -> Self {
158 Self::InvalidTransition(error)
159 }
160
161 pub fn is_not_found(&self) -> bool {
163 matches!(self, SetRegionRoleStateResponse::NotFound)
164 }
165
166 pub fn is_invalid_transition(&self) -> bool {
168 matches!(self, SetRegionRoleStateResponse::InvalidTransition(_))
169 }
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
173pub struct GrantedRegion {
174 pub region_id: RegionId,
175 pub region_role: RegionRole,
176 pub extensions: HashMap<String, Vec<u8>>,
177}
178
179impl GrantedRegion {
180 pub fn new(region_id: RegionId, region_role: RegionRole) -> Self {
181 Self {
182 region_id,
183 region_role,
184 extensions: HashMap::new(),
185 }
186 }
187}
188
189impl From<GrantedRegion> for PbGrantedRegion {
190 fn from(value: GrantedRegion) -> Self {
191 PbGrantedRegion {
192 region_id: value.region_id.as_u64(),
193 role: PbRegionRole::from(value.region_role).into(),
194 extensions: value.extensions,
195 }
196 }
197}
198
199impl From<PbGrantedRegion> for GrantedRegion {
200 fn from(value: PbGrantedRegion) -> Self {
201 GrantedRegion {
202 region_id: RegionId::from_u64(value.region_id),
203 region_role: value.role().into(),
204 extensions: value.extensions,
205 }
206 }
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
212pub enum RegionRole {
213 Follower,
215 Leader,
217 StagingLeader,
222 DowngradingLeader,
226}
227
228impl Display for RegionRole {
229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230 match self {
231 RegionRole::Follower => write!(f, "Follower"),
232 RegionRole::Leader => write!(f, "Leader"),
233 RegionRole::StagingLeader => write!(f, "Leader(Staging)"),
234 RegionRole::DowngradingLeader => write!(f, "Leader(Downgrading)"),
235 }
236 }
237}
238
239impl RegionRole {
240 pub fn writable(&self) -> bool {
241 matches!(self, RegionRole::Leader | RegionRole::StagingLeader)
242 }
243}
244
245impl From<RegionRole> for PbRegionRole {
246 fn from(value: RegionRole) -> Self {
247 match value {
248 RegionRole::Follower => PbRegionRole::Follower,
249 RegionRole::Leader => PbRegionRole::Leader,
250 RegionRole::StagingLeader => PbRegionRole::StagingLeader,
251 RegionRole::DowngradingLeader => PbRegionRole::DowngradingLeader,
252 }
253 }
254}
255
256impl From<PbRegionRole> for RegionRole {
257 fn from(value: PbRegionRole) -> Self {
258 match value {
259 PbRegionRole::Leader => RegionRole::Leader,
260 PbRegionRole::StagingLeader => RegionRole::StagingLeader,
261 PbRegionRole::Follower => RegionRole::Follower,
262 PbRegionRole::DowngradingLeader => RegionRole::DowngradingLeader,
263 }
264 }
265}
266
267#[derive(Debug)]
269pub enum ScannerPartitioning {
270 Unknown(usize),
272}
273
274impl ScannerPartitioning {
275 pub fn num_partitions(&self) -> usize {
277 match self {
278 ScannerPartitioning::Unknown(num_partitions) => *num_partitions,
279 }
280 }
281}
282
283#[derive(Debug, Clone, Copy, PartialEq, Eq)]
285pub struct PartitionRange {
286 pub start: Timestamp,
288 pub end: Timestamp,
290 pub num_rows: usize,
292 pub identifier: usize,
294}
295
296#[derive(Debug, Default)]
298pub struct ScannerProperties {
299 pub partitions: Vec<Vec<PartitionRange>>,
304
305 append_mode: bool,
307
308 total_rows: usize,
311
312 total_rows_is_exact: bool,
314
315 pub distinguish_partition_range: bool,
317
318 target_partitions: usize,
320
321 logical_region: bool,
323
324 query_load_region_id: Option<RegionId>,
326 query_stat_counters: Option<RegionQueryStatCounters>,
328}
329
330impl ScannerProperties {
331 pub fn with_append_mode(mut self, append_mode: bool) -> Self {
333 self.append_mode = append_mode;
334 self
335 }
336
337 pub fn with_total_rows(mut self, total_rows: usize) -> Self {
339 self.total_rows = total_rows;
340 self
341 }
342
343 pub fn with_total_rows_is_exact(mut self, exact: bool) -> Self {
345 self.total_rows_is_exact = exact;
346 self
347 }
348
349 pub fn new(partitions: Vec<Vec<PartitionRange>>, append_mode: bool, total_rows: usize) -> Self {
351 Self {
352 partitions,
353 append_mode,
354 total_rows,
355 total_rows_is_exact: false,
356 distinguish_partition_range: false,
357 target_partitions: 0,
358 logical_region: false,
359 query_load_region_id: None,
360 query_stat_counters: None,
361 }
362 }
363
364 pub fn prepare(&mut self, request: PrepareRequest) {
366 if let Some(ranges) = request.ranges {
367 self.partitions = ranges;
368 }
369 if let Some(distinguish_partition_range) = request.distinguish_partition_range {
370 self.distinguish_partition_range = distinguish_partition_range;
371 }
372 if let Some(target_partitions) = request.target_partitions {
373 self.target_partitions = target_partitions;
374 }
375 }
376
377 pub fn num_partitions(&self) -> usize {
379 self.partitions.len()
380 }
381
382 pub fn append_mode(&self) -> bool {
383 self.append_mode
384 }
385
386 pub fn total_rows(&self) -> usize {
387 self.total_rows
388 }
389
390 pub fn total_rows_is_exact(&self) -> bool {
392 self.total_rows_is_exact
393 }
394
395 pub fn is_logical_region(&self) -> bool {
397 self.logical_region
398 }
399
400 pub fn target_partitions(&self) -> usize {
402 if self.target_partitions == 0 {
403 self.num_partitions()
404 } else {
405 self.target_partitions
406 }
407 }
408
409 pub fn set_logical_region(&mut self, logical_region: bool) {
411 self.logical_region = logical_region;
412 }
413
414 pub fn query_load_region_id(&self) -> Option<RegionId> {
416 self.query_load_region_id
417 }
418
419 pub fn query_stat_counters(&self) -> Option<RegionQueryStatCounters> {
421 self.query_stat_counters.clone()
422 }
423
424 pub fn set_query_load_region_id(&mut self, region_id: RegionId) {
426 self.query_load_region_id = Some(region_id);
427 }
428
429 pub fn set_query_stat_counters(&mut self, counters: RegionQueryStatCounters) {
431 self.query_stat_counters = Some(counters);
432 }
433}
434
435#[derive(Default)]
437pub struct PrepareRequest {
438 pub ranges: Option<Vec<Vec<PartitionRange>>>,
440 pub distinguish_partition_range: Option<bool>,
442 pub target_partitions: Option<usize>,
444}
445
446impl PrepareRequest {
447 pub fn with_ranges(mut self, ranges: Vec<Vec<PartitionRange>>) -> Self {
449 self.ranges = Some(ranges);
450 self
451 }
452
453 pub fn with_distinguish_partition_range(mut self, distinguish_partition_range: bool) -> Self {
455 self.distinguish_partition_range = Some(distinguish_partition_range);
456 self
457 }
458
459 pub fn with_target_partitions(mut self, target_partitions: usize) -> Self {
461 self.target_partitions = Some(target_partitions);
462 self
463 }
464}
465
466#[derive(Clone)]
470pub struct QueryScanContext {
471 pub explain_verbose: bool,
473 pub memory_pool: Arc<dyn MemoryPool>,
475}
476
477impl Default for QueryScanContext {
478 fn default() -> Self {
479 Self {
480 explain_verbose: false,
481 memory_pool: Arc::new(UnboundedMemoryPool::default()),
482 }
483 }
484}
485
486pub trait RegionScanner: Debug + DisplayAs + Send {
491 fn name(&self) -> &str;
492
493 fn properties(&self) -> &ScannerProperties;
495
496 fn schema(&self) -> SchemaRef;
498
499 fn metadata(&self) -> RegionMetadataRef;
501
502 fn prepare(&mut self, request: PrepareRequest) -> Result<(), BoxedError>;
506
507 fn scan_partition(
512 &self,
513 ctx: &QueryScanContext,
514 metrics_set: &ExecutionPlanMetricsSet,
515 partition: usize,
516 ) -> Result<SendableRecordBatchStream, BoxedError>;
517
518 fn has_predicate_without_region(&self) -> bool;
520
521 fn add_dyn_filter_to_predicate(
526 &mut self,
527 filter_exprs: Vec<Arc<dyn PhysicalExpr>>,
528 ) -> Vec<bool>;
529
530 fn reset_state(&mut self) {}
537
538 fn set_logical_region(&mut self, logical_region: bool);
540
541 fn set_query_load_region_id(&mut self, region_id: RegionId);
543
544 fn snapshot_sequence(&self) -> Option<SequenceNumber> {
545 None
546 }
547}
548
549pub type RegionScannerRef = Box<dyn RegionScanner>;
550
551pub type BatchResponses = Vec<(RegionId, Result<RegionResponse, BoxedError>)>;
552
553pub type BatchPutResponse = (
556 Vec<RegionId>,
557 BoxFuture<'static, Result<RegionResponse, BoxedError>>,
558);
559
560#[derive(Debug, Deserialize, Serialize, Default)]
562pub struct RegionStatistic {
563 #[serde(default)]
568 pub num_rows: u64,
569 pub memtable_size: u64,
571 pub wal_size: u64,
573 pub manifest_size: u64,
575 pub sst_size: u64,
579 pub sst_num: u64,
583 #[serde(default)]
587 pub index_size: u64,
588 #[serde(default)]
590 pub manifest: RegionManifestInfo,
591 #[serde(default)]
592 pub written_bytes: u64,
594 #[serde(default)]
598 pub query_cpu_time: u64,
599 #[serde(default)]
601 pub query_scanned_bytes: u64,
602 #[serde(default)]
606 pub min_timestamp: Option<Timestamp>,
607 #[serde(default)]
609 pub max_timestamp: Option<Timestamp>,
610 #[serde(default)]
614 pub data_topic_latest_entry_id: u64,
615 #[serde(default)]
616 pub metadata_topic_latest_entry_id: u64,
617}
618
619#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
621pub enum RegionManifestInfo {
622 Mito {
623 manifest_version: u64,
624 flushed_entry_id: u64,
625 file_removed_cnt: u64,
627 },
628 Metric {
629 data_manifest_version: u64,
630 data_flushed_entry_id: u64,
631 metadata_manifest_version: u64,
632 metadata_flushed_entry_id: u64,
633 },
634}
635
636impl RegionManifestInfo {
637 pub fn mito(manifest_version: u64, flushed_entry_id: u64, file_removal_rate: u64) -> Self {
639 Self::Mito {
640 manifest_version,
641 flushed_entry_id,
642 file_removed_cnt: file_removal_rate,
643 }
644 }
645
646 pub fn metric(
648 data_manifest_version: u64,
649 data_flushed_entry_id: u64,
650 metadata_manifest_version: u64,
651 metadata_flushed_entry_id: u64,
652 ) -> Self {
653 Self::Metric {
654 data_manifest_version,
655 data_flushed_entry_id,
656 metadata_manifest_version,
657 metadata_flushed_entry_id,
658 }
659 }
660
661 pub fn is_mito(&self) -> bool {
663 matches!(self, RegionManifestInfo::Mito { .. })
664 }
665
666 pub fn is_metric(&self) -> bool {
668 matches!(self, RegionManifestInfo::Metric { .. })
669 }
670
671 pub fn data_flushed_entry_id(&self) -> u64 {
673 match self {
674 RegionManifestInfo::Mito {
675 flushed_entry_id, ..
676 } => *flushed_entry_id,
677 RegionManifestInfo::Metric {
678 data_flushed_entry_id,
679 ..
680 } => *data_flushed_entry_id,
681 }
682 }
683
684 pub fn data_manifest_version(&self) -> u64 {
686 match self {
687 RegionManifestInfo::Mito {
688 manifest_version, ..
689 } => *manifest_version,
690 RegionManifestInfo::Metric {
691 data_manifest_version,
692 ..
693 } => *data_manifest_version,
694 }
695 }
696
697 pub fn metadata_manifest_version(&self) -> Option<u64> {
699 match self {
700 RegionManifestInfo::Mito { .. } => None,
701 RegionManifestInfo::Metric {
702 metadata_manifest_version,
703 ..
704 } => Some(*metadata_manifest_version),
705 }
706 }
707
708 pub fn metadata_flushed_entry_id(&self) -> Option<u64> {
710 match self {
711 RegionManifestInfo::Mito { .. } => None,
712 RegionManifestInfo::Metric {
713 metadata_flushed_entry_id,
714 ..
715 } => Some(*metadata_flushed_entry_id),
716 }
717 }
718
719 pub fn encode_list(manifest_infos: &[(RegionId, Self)]) -> serde_json::Result<Vec<u8>> {
721 serde_json::to_vec(manifest_infos)
722 }
723
724 pub fn decode_list(value: &[u8]) -> serde_json::Result<Vec<(RegionId, Self)>> {
726 serde_json::from_slice(value)
727 }
728}
729
730impl Default for RegionManifestInfo {
731 fn default() -> Self {
732 Self::Mito {
733 manifest_version: 0,
734 flushed_entry_id: 0,
735 file_removed_cnt: 0,
736 }
737 }
738}
739
740impl RegionStatistic {
741 pub fn deserialize_from_slice(value: &[u8]) -> Option<RegionStatistic> {
745 serde_json::from_slice(value).ok()
746 }
747
748 pub fn serialize_to_vec(&self) -> Option<Vec<u8>> {
752 serde_json::to_vec(self).ok()
753 }
754}
755
756impl RegionStatistic {
757 pub fn estimated_disk_size(&self) -> u64 {
759 self.wal_size + self.sst_size + self.manifest_size + self.index_size
760 }
761}
762
763#[cfg(test)]
764mod tests {
765 use serde_json::json;
766
767 use super::*;
768
769 #[test]
770 fn region_statistic_deserializes_without_query_stats() {
771 let statistic: RegionStatistic = serde_json::from_value(json!({
772 "num_rows": 1,
773 "memtable_size": 2,
774 "wal_size": 3,
775 "manifest_size": 4,
776 "sst_size": 5,
777 "sst_num": 6,
778 "index_size": 7,
779 "manifest": {
780 "Mito": {
781 "manifest_version": 8,
782 "flushed_entry_id": 9,
783 "file_removed_cnt": 10
784 }
785 },
786 "written_bytes": 11
787 }))
788 .unwrap();
789
790 assert_eq!(statistic.query_cpu_time, 0);
791 assert_eq!(statistic.query_scanned_bytes, 0);
792 }
793}
794
795#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
797pub enum SyncRegionFromRequest {
798 FromManifest(RegionManifestInfo),
801 FromRegion {
807 source_region_id: RegionId,
809 parallelism: usize,
811 },
812}
813
814impl From<RegionManifestInfo> for SyncRegionFromRequest {
815 fn from(manifest_info: RegionManifestInfo) -> Self {
816 SyncRegionFromRequest::FromManifest(manifest_info)
817 }
818}
819
820impl SyncRegionFromRequest {
821 pub fn from_manifest(manifest_info: RegionManifestInfo) -> Self {
823 SyncRegionFromRequest::FromManifest(manifest_info)
824 }
825
826 pub fn from_region(source_region_id: RegionId, parallelism: usize) -> Self {
828 SyncRegionFromRequest::FromRegion {
829 source_region_id,
830 parallelism,
831 }
832 }
833
834 pub fn is_from_manifest(&self) -> bool {
836 matches!(self, SyncRegionFromRequest::FromManifest { .. })
837 }
838
839 pub fn into_region_manifest_info(self) -> Option<RegionManifestInfo> {
843 match self {
844 SyncRegionFromRequest::FromManifest(manifest_info) => Some(manifest_info),
845 SyncRegionFromRequest::FromRegion { .. } => None,
846 }
847 }
848}
849
850#[derive(Debug)]
852pub enum SyncRegionFromResponse {
853 NotSupported,
854 Mito {
855 synced: bool,
857 },
858 Metric {
859 metadata_synced: bool,
861 data_synced: bool,
863 new_opened_logical_region_ids: Vec<RegionId>,
866 },
867}
868
869impl SyncRegionFromResponse {
870 pub fn is_data_synced(&self) -> bool {
872 match self {
873 SyncRegionFromResponse::NotSupported => false,
874 SyncRegionFromResponse::Mito { synced } => *synced,
875 SyncRegionFromResponse::Metric { data_synced, .. } => *data_synced,
876 }
877 }
878
879 pub fn is_mito(&self) -> bool {
881 matches!(self, SyncRegionFromResponse::Mito { .. })
882 }
883
884 pub fn is_metric(&self) -> bool {
886 matches!(self, SyncRegionFromResponse::Metric { .. })
887 }
888
889 pub fn new_opened_logical_region_ids(self) -> Option<Vec<RegionId>> {
891 match self {
892 SyncRegionFromResponse::Metric {
893 new_opened_logical_region_ids,
894 ..
895 } => Some(new_opened_logical_region_ids),
896 _ => None,
897 }
898 }
899}
900
901#[derive(Debug, Clone)]
903pub struct RemapManifestsRequest {
904 pub region_id: RegionId,
906 pub input_regions: Vec<RegionId>,
908 pub region_mapping: HashMap<RegionId, Vec<RegionId>>,
910 pub new_partition_exprs: HashMap<RegionId, String>,
912}
913
914#[derive(Debug, Clone)]
916pub struct RemapManifestsResponse {
917 pub manifest_paths: HashMap<RegionId, String>,
922}
923
924#[derive(Debug, Clone)]
926pub struct MitoCopyRegionFromRequest {
927 pub source_region_id: RegionId,
929 pub parallelism: usize,
931}
932
933#[derive(Debug, Clone)]
934pub struct MitoCopyRegionFromResponse {
935 pub copied_file_ids: Vec<FileId>,
937}
938
939#[async_trait]
940pub trait RegionEngine: Send + Sync {
941 fn name(&self) -> &str;
943
944 async fn handle_batch_open_requests(
946 &self,
947 parallelism: usize,
948 requests: Vec<(RegionId, RegionOpenRequest)>,
949 ) -> Result<BatchResponses, BoxedError> {
950 let semaphore = Arc::new(Semaphore::new(parallelism));
951 let mut tasks = Vec::with_capacity(requests.len());
952
953 for (region_id, request) in requests {
954 let semaphore_moved = semaphore.clone();
955
956 tasks.push(async move {
957 let _permit = semaphore_moved.acquire().await.unwrap();
959 let result = self
960 .handle_request(region_id, RegionRequest::Open(request))
961 .await;
962 (region_id, result)
963 });
964 }
965
966 Ok(join_all(tasks).await)
967 }
968
969 async fn handle_batch_catchup_requests(
970 &self,
971 parallelism: usize,
972 requests: Vec<(RegionId, RegionCatchupRequest)>,
973 ) -> Result<BatchResponses, BoxedError> {
974 let semaphore = Arc::new(Semaphore::new(parallelism));
975 let mut tasks = Vec::with_capacity(requests.len());
976
977 for (region_id, request) in requests {
978 let semaphore_moved = semaphore.clone();
979
980 tasks.push(async move {
981 let _permit = semaphore_moved.acquire().await.unwrap();
983 let result = self
984 .handle_request(region_id, RegionRequest::Catchup(request))
985 .await;
986 (region_id, result)
987 });
988 }
989
990 Ok(join_all(tasks).await)
991 }
992
993 fn handle_batch_put_requests(
1001 self: Arc<Self>,
1002 requests: Vec<(RegionId, RegionPutRequest)>,
1003 ) -> Vec<BatchPutResponse>
1004 where
1005 Self: 'static,
1006 {
1007 requests
1008 .into_iter()
1009 .map(|(region_id, request)| {
1010 let engine = self.clone();
1011 let response = async move {
1012 engine
1013 .handle_request(region_id, RegionRequest::Put(request))
1014 .await
1015 }
1016 .boxed();
1017 (vec![region_id], response)
1018 })
1019 .collect()
1020 }
1021
1022 async fn handle_batch_ddl_requests(
1023 &self,
1024 request: BatchRegionDdlRequest,
1025 ) -> Result<RegionResponse, BoxedError> {
1026 let requests = request.into_region_requests();
1027
1028 let mut affected_rows = 0;
1029 let mut extensions = HashMap::new();
1030
1031 for (region_id, request) in requests {
1032 let result = self.handle_request(region_id, request).await?;
1033 affected_rows += result.affected_rows;
1034 extensions.extend(result.extensions);
1035 }
1036
1037 Ok(RegionResponse {
1038 affected_rows,
1039 extensions,
1040 metadata: Vec::new(),
1041 })
1042 }
1043
1044 async fn handle_request(
1046 &self,
1047 region_id: RegionId,
1048 request: RegionRequest,
1049 ) -> Result<RegionResponse, BoxedError>;
1050
1051 async fn get_committed_sequence(
1053 &self,
1054 region_id: RegionId,
1055 ) -> Result<SequenceNumber, BoxedError>;
1056
1057 async fn handle_query(
1059 &self,
1060 region_id: RegionId,
1061 request: ScanRequest,
1062 ) -> Result<RegionScannerRef, BoxedError>;
1063
1064 fn query_memory_tracker(&self) -> Option<QueryMemoryTracker> {
1066 None
1067 }
1068
1069 async fn get_metadata(&self, region_id: RegionId) -> Result<RegionMetadataRef, BoxedError>;
1071
1072 fn region_statistic(&self, region_id: RegionId) -> Option<RegionStatistic>;
1074
1075 async fn stop(&self) -> Result<(), BoxedError>;
1077
1078 fn set_region_role(&self, region_id: RegionId, role: RegionRole) -> Result<(), BoxedError>;
1084
1085 fn set_region_role_with_lease(
1091 &self,
1092 region_id: RegionId,
1093 role: RegionRole,
1094 deadline: Instant,
1095 ) -> Result<(), BoxedError>;
1096
1097 async fn sync_region(
1099 &self,
1100 region_id: RegionId,
1101 request: SyncRegionFromRequest,
1102 ) -> Result<SyncRegionFromResponse, BoxedError>;
1103
1104 async fn remap_manifests(
1106 &self,
1107 request: RemapManifestsRequest,
1108 ) -> Result<RemapManifestsResponse, BoxedError>;
1109
1110 async fn set_region_role_state_gracefully(
1114 &self,
1115 region_id: RegionId,
1116 region_role_state: SettableRegionRoleState,
1117 ) -> Result<SetRegionRoleStateResponse, BoxedError>;
1118
1119 fn role(&self, region_id: RegionId) -> Option<RegionRole>;
1123
1124 fn as_any(&self) -> &dyn Any;
1125}
1126
1127pub type RegionEngineRef = Arc<dyn RegionEngine>;
1128
1129pub struct SinglePartitionScanner {
1131 stream: Mutex<Option<SendableRecordBatchStream>>,
1132 schema: SchemaRef,
1133 properties: ScannerProperties,
1134 metadata: RegionMetadataRef,
1135 snapshot_sequence: Option<SequenceNumber>,
1136}
1137
1138impl SinglePartitionScanner {
1139 pub fn new(
1141 stream: SendableRecordBatchStream,
1142 append_mode: bool,
1143 metadata: RegionMetadataRef,
1144 snapshot_sequence: Option<SequenceNumber>,
1145 ) -> Self {
1146 let schema = stream.schema();
1147 Self {
1148 stream: Mutex::new(Some(stream)),
1149 schema,
1150 properties: ScannerProperties::default().with_append_mode(append_mode),
1151 metadata,
1152 snapshot_sequence,
1153 }
1154 }
1155}
1156
1157impl Debug for SinglePartitionScanner {
1158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1159 write!(f, "SinglePartitionScanner: <SendableRecordBatchStream>")
1160 }
1161}
1162
1163impl RegionScanner for SinglePartitionScanner {
1164 fn name(&self) -> &str {
1165 "SinglePartition"
1166 }
1167
1168 fn properties(&self) -> &ScannerProperties {
1169 &self.properties
1170 }
1171
1172 fn schema(&self) -> SchemaRef {
1173 self.schema.clone()
1174 }
1175
1176 fn prepare(&mut self, request: PrepareRequest) -> Result<(), BoxedError> {
1177 self.properties.prepare(request);
1178 Ok(())
1179 }
1180
1181 fn scan_partition(
1182 &self,
1183 _ctx: &QueryScanContext,
1184 _metrics_set: &ExecutionPlanMetricsSet,
1185 _partition: usize,
1186 ) -> Result<SendableRecordBatchStream, BoxedError> {
1187 let mut stream = self.stream.lock().unwrap();
1188 let result = stream
1189 .take()
1190 .or_else(|| Some(Box::pin(EmptyRecordBatchStream::new(self.schema.clone()))));
1191 Ok(result.unwrap())
1192 }
1193
1194 fn has_predicate_without_region(&self) -> bool {
1195 false
1196 }
1197
1198 fn add_dyn_filter_to_predicate(
1199 &mut self,
1200 filter_exprs: Vec<Arc<dyn datafusion_physical_plan::PhysicalExpr>>,
1201 ) -> Vec<bool> {
1202 vec![false; filter_exprs.len()]
1203 }
1204
1205 fn metadata(&self) -> RegionMetadataRef {
1206 self.metadata.clone()
1207 }
1208
1209 fn set_logical_region(&mut self, logical_region: bool) {
1210 self.properties.set_logical_region(logical_region);
1211 }
1212
1213 fn set_query_load_region_id(&mut self, region_id: RegionId) {
1214 self.properties.set_query_load_region_id(region_id);
1215 }
1216
1217 fn snapshot_sequence(&self) -> Option<SequenceNumber> {
1218 self.snapshot_sequence
1219 }
1220}
1221
1222impl DisplayAs for SinglePartitionScanner {
1223 fn fmt_as(&self, _t: DisplayFormatType, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1224 write!(f, "{:?}", self)
1225 }
1226}