metric_engine/engine/
drop.rs1use common_telemetry::{debug, info};
18use snafu::ResultExt;
19use store_api::region_engine::RegionEngine;
20use store_api::region_request::{AffectedRows, RegionDropRequest, RegionRequest};
21use store_api::storage::RegionId;
22
23use crate::engine::MetricEngineInner;
24use crate::error::{
25 CloseMitoRegionSnafu, LogicalRegionNotFoundSnafu, PhysicalRegionBusySnafu, Result,
26};
27use crate::metrics::PHYSICAL_REGION_COUNT;
28use crate::utils;
29
30impl MetricEngineInner {
31 pub async fn drop_region(
32 &self,
33 region_id: RegionId,
34 req: RegionDropRequest,
35 ) -> Result<AffectedRows> {
36 let data_region_id = utils::to_data_region_id(region_id);
37 let fast_path = req.fast_path;
38 let force = req.force;
39
40 let (is_physical_region, is_physical_region_busy) = {
42 if let Some(state) = self
43 .state
44 .read()
45 .unwrap()
46 .physical_region_states()
47 .get(&data_region_id)
48 {
49 debug!(
50 "Physical region {} is busy, there are still some logical regions: {:?}",
51 data_region_id,
52 state
53 .logical_regions()
54 .iter()
55 .map(|id| id.to_string())
56 .collect::<Vec<_>>()
57 );
58 (true, !state.logical_regions().is_empty())
59 } else {
60 (false, true)
62 }
63 };
64
65 if is_physical_region {
66 if is_physical_region_busy && !force {
68 return Err(PhysicalRegionBusySnafu {
70 region_id: data_region_id,
71 }
72 .build());
73 }
74 if is_physical_region_busy && force {
75 info!("Dropping physical region {} with force", data_region_id);
76 }
77 return self.drop_physical_region(data_region_id).await;
78 }
79
80 if fast_path {
81 self.state
86 .write()
87 .unwrap()
88 .remove_logical_region(region_id)?;
89
90 Ok(0)
91 } else {
92 let metadata_region_id = self
93 .state
94 .read()
95 .unwrap()
96 .logical_regions()
97 .get(®ion_id)
98 .copied();
99 if let Some(metadata_region_id) = metadata_region_id {
100 self.drop_logical_region(region_id, metadata_region_id)
101 .await
102 } else {
103 Err(LogicalRegionNotFoundSnafu { region_id }.build())
104 }
105 }
106 }
107
108 async fn drop_physical_region(&self, region_id: RegionId) -> Result<AffectedRows> {
109 let data_region_id = utils::to_data_region_id(region_id);
110 let metadata_region_id = utils::to_metadata_region_id(region_id);
111
112 self.mito
116 .handle_request(
117 data_region_id,
118 RegionRequest::Drop(RegionDropRequest {
119 fast_path: false,
120 force: false,
121 }),
122 )
123 .await
124 .with_context(|_| CloseMitoRegionSnafu { region_id })?;
125 self.mito
126 .handle_request(
127 metadata_region_id,
128 RegionRequest::Drop(RegionDropRequest {
129 fast_path: false,
130 force: false,
131 }),
132 )
133 .await
134 .with_context(|_| CloseMitoRegionSnafu { region_id })?;
135
136 PHYSICAL_REGION_COUNT.dec();
137
138 self.state
140 .write()
141 .unwrap()
142 .remove_physical_region(data_region_id)?;
143
144 Ok(0)
145 }
146
147 async fn drop_logical_region(
148 &self,
149 logical_region_id: RegionId,
150 physical_region_id: RegionId,
151 ) -> Result<AffectedRows> {
152 self.metadata_region
154 .remove_logical_region(physical_region_id, logical_region_id)
155 .await?;
156
157 self.state
159 .write()
160 .unwrap()
161 .remove_logical_region(logical_region_id)?;
162
163 Ok(0)
164 }
165}