From 097aa4f891322afdcc7bd0eb3d6c7855f971b584 Mon Sep 17 00:00:00 2001 From: Bisheng Huang Date: Wed, 17 Jul 2024 09:23:59 +0800 Subject: [PATCH 001/144] Revert "raftstore: handle region destroy in a separate thread pool (#17121)" (#17275) close tikv/tikv#17258 This reverts commit 273ec868a794cf4637c9c8c5a2d8bb462d701217. The previous commit introduced a bug that could result in data loss. Specifically, the region worker might delete data from a range where a snapshot has just been applied. Signed-off-by: Bisheng Huang --- .../raftstore/src/store/worker/region.rs | 443 ++++++++---------- tests/failpoints/cases/test_merge.rs | 44 -- 2 files changed, 203 insertions(+), 284 deletions(-) diff --git a/components/raftstore/src/store/worker/region.rs b/components/raftstore/src/store/worker/region.rs index 05fdf5b746c..2316aeb0239 100644 --- a/components/raftstore/src/store/worker/region.rs +++ b/components/raftstore/src/store/worker/region.rs @@ -10,7 +10,7 @@ use std::{ sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, mpsc::SyncSender, - Arc, Mutex, + Arc, }, time::Duration, u64, @@ -341,215 +341,13 @@ where } } -struct RegionCleaner -where - EK: KvEngine, -{ - use_delete_range: bool, - engine: EK, - // Ranges that have been logically destroyed at a specific sequence number. We can - // assume there will be no reader (engine snapshot) newer than that sequence number. Therefore, - // they can be physically deleted with `DeleteFiles` when we're sure there is no older - // reader as well. - // To protect this assumption, before a new snapshot is applied, the overlapping pending ranges - // must first be removed. - // The sole purpose of maintaining this list is to optimize deletion with `DeleteFiles` - // whenever we can. Errors while processing them can be ignored. - pending_delete_ranges: PendingDeleteRanges, - mgr: SnapManager, -} - -impl RegionCleaner -where - EK: KvEngine, -{ - /// Tries to clean up files in pending ranges overlapping with the given - /// bounds. These pending ranges will be removed. Returns an updated range - /// that also includes these ranges. Caller must ensure the remaining keys - /// in the returning range will be deleted properly. - fn clean_overlap_ranges_roughly( - &mut self, - mut start_key: Vec, - mut end_key: Vec, - ) -> (Vec, Vec) { - let overlap_ranges = self - .pending_delete_ranges - .drain_overlap_ranges(&start_key, &end_key); - if overlap_ranges.is_empty() { - return (start_key, end_key); - } - CLEAN_COUNTER_VEC.with_label_values(&["overlap"]).inc(); - let oldest_sequence = self - .engine - .get_oldest_snapshot_sequence_number() - .unwrap_or(u64::MAX); - let df_ranges: Vec<_> = overlap_ranges - .iter() - .filter_map(|(region_id, cur_start, cur_end, stale_sequence)| { - info!( - "delete data in range because of overlap"; "region_id" => region_id, - "start_key" => log_wrappers::Value::key(cur_start), - "end_key" => log_wrappers::Value::key(cur_end) - ); - if &start_key > cur_start { - start_key = cur_start.clone(); - } - if &end_key < cur_end { - end_key = cur_end.clone(); - } - if *stale_sequence < oldest_sequence { - Some(Range::new(cur_start, cur_end)) - } else { - SNAP_COUNTER_VEC - .with_label_values(&["overlap", "not_delete_files"]) - .inc(); - None - } - }) - .collect(); - self.engine - .delete_ranges_cfs( - &WriteOptions::default(), - DeleteStrategy::DeleteFiles, - &df_ranges, - ) - .map_err(|e| { - error!("failed to delete files in range"; "err" => %e); - }) - .unwrap(); - (start_key, end_key) - } - - /// Cleans up data in the given range and all pending ranges overlapping - /// with it. - fn clean_overlap_ranges(&mut self, start_key: Vec, end_key: Vec) -> Result<()> { - let (start_key, end_key) = self.clean_overlap_ranges_roughly(start_key, end_key); - self.delete_all_in_range(&[Range::new(&start_key, &end_key)]) - } - - /// Inserts a new pending range, and it will be cleaned up with some delay. - fn insert_pending_delete_range( - &mut self, - region_id: u64, - start_key: Vec, - end_key: Vec, - ) { - let (start_key, end_key) = self.clean_overlap_ranges_roughly(start_key, end_key); - info!("register deleting data in range"; - "region_id" => region_id, - "start_key" => log_wrappers::Value::key(&start_key), - "end_key" => log_wrappers::Value::key(&end_key), - ); - let seq = self.engine.get_latest_sequence_number(); - self.pending_delete_ranges - .insert(region_id, start_key, end_key, seq); - } - - /// Cleans up stale ranges. - fn clean_stale_ranges(&mut self) { - STALE_PEER_PENDING_DELETE_RANGE_GAUGE.set(self.pending_delete_ranges.len() as f64); - if self.ingest_maybe_stall() { - return; - } - let oldest_sequence = self - .engine - .get_oldest_snapshot_sequence_number() - .unwrap_or(u64::MAX); - let mut region_ranges: Vec<(u64, Vec, Vec)> = self - .pending_delete_ranges - .stale_ranges(oldest_sequence) - .map(|(region_id, s, e)| (region_id, s.to_vec(), e.to_vec())) - .collect(); - if region_ranges.is_empty() { - return; - } - CLEAN_COUNTER_VEC.with_label_values(&["destroy"]).inc_by(1); - region_ranges.sort_by(|a, b| a.1.cmp(&b.1)); - region_ranges.truncate(CLEANUP_MAX_REGION_COUNT); - let ranges: Vec<_> = region_ranges - .iter() - .map(|(region_id, start, end)| { - info!("delete data in range because of stale"; "region_id" => region_id, - "start_key" => log_wrappers::Value::key(start), - "end_key" => log_wrappers::Value::key(end)); - Range::new(start, end) - }) - .collect(); - - self.engine - .delete_ranges_cfs( - &WriteOptions::default(), - DeleteStrategy::DeleteFiles, - &ranges, - ) - .map_err(|e| { - error!("failed to delete files in range"; "err" => %e); - }) - .unwrap(); - if let Err(e) = self.delete_all_in_range(&ranges) { - error!("failed to cleanup stale range"; "err" => %e); - return; - } - self.engine - .delete_ranges_cfs( - &WriteOptions::default(), - DeleteStrategy::DeleteBlobs, - &ranges, - ) - .map_err(|e| { - error!("failed to delete blobs in range"; "err" => %e); - }) - .unwrap(); - - for (_, key, _) in region_ranges { - assert!( - self.pending_delete_ranges.remove(&key).is_some(), - "cleanup pending_delete_ranges {} should exist", - log_wrappers::Value::key(&key) - ); - } - } - - /// Checks the number of files at level 0 to avoid write stall after - /// ingesting sst. Returns true if the ingestion causes write stall. - fn ingest_maybe_stall(&self) -> bool { - for cf in SNAPSHOT_CFS { - // no need to check lock cf - if plain_file_used(cf) { - continue; - } - if self.engine.ingest_maybe_slowdown_writes(cf).expect("cf") { - return true; - } - } - false - } - - fn delete_all_in_range(&self, ranges: &[Range<'_>]) -> Result<()> { - let wopts = WriteOptions::default(); - for cf in self.engine.cf_names() { - // CF_LOCK usually contains fewer keys than other CFs, so we delete them by key. - let strategy = if cf == CF_LOCK { - DeleteStrategy::DeleteByKey - } else if self.use_delete_range { - DeleteStrategy::DeleteByRange - } else { - DeleteStrategy::DeleteByWriter { - sst_path: self.mgr.get_temp_path_for_ingest(), - } - }; - box_try!(self.engine.delete_ranges_cf(&wopts, cf, strategy, ranges)); - } - Ok(()) - } -} - pub struct Runner where EK: KvEngine, T: PdClient + 'static, { batch_size: usize, + use_delete_range: bool, ingest_copy_symlink: bool, clean_stale_tick: usize, clean_stale_check_interval: Duration, @@ -559,15 +357,22 @@ where // we may delay some apply tasks if level 0 files to write stall threshold, // pending_applies records all delayed apply task, and will check again later pending_applies: VecDeque>, + // Ranges that have been logically destroyed at a specific sequence number. We can + // assume there will be no reader (engine snapshot) newer than that sequence number. Therefore, + // they can be physically deleted with `DeleteFiles` when we're sure there is no older + // reader as well. + // To protect this assumption, before a new snapshot is applied, the overlapping pending ranges + // must first be removed. + // The sole purpose of maintaining this list is to optimize deletion with `DeleteFiles` + // whenever we can. Errors while processing them can be ignored. + pending_delete_ranges: PendingDeleteRanges, engine: EK, mgr: SnapManager, coprocessor_host: CoprocessorHost, router: R, pd_client: Option>, - snap_gen_pool: FuturePool, - region_cleanup_pool: FuturePool, - region_cleaner: Arc>>, + pool: FuturePool, } impl Runner @@ -586,6 +391,7 @@ where ) -> Runner { Runner { batch_size: cfg.value().snap_apply_batch_size.0 as usize, + use_delete_range: cfg.value().use_delete_range, ingest_copy_symlink: cfg.value().snap_apply_copy_symlink, clean_stale_tick: 0, clean_stale_check_interval: Duration::from_millis( @@ -594,12 +400,13 @@ where clean_stale_ranges_tick: cfg.value().clean_stale_ranges_tick, tiflash_stores: HashMap::default(), pending_applies: VecDeque::new(), - engine: engine.clone(), - mgr: mgr.clone(), + pending_delete_ranges: PendingDeleteRanges::default(), + engine, + mgr, coprocessor_host, router, pd_client, - snap_gen_pool: YatpPoolBuilder::new(DefaultTicker::default()) + pool: YatpPoolBuilder::new(DefaultTicker::default()) .name_prefix("snap-generator") .thread_count( 1, @@ -607,21 +414,11 @@ where SNAP_GENERATOR_MAX_POOL_SIZE, ) .build_future_pool(), - region_cleanup_pool: YatpPoolBuilder::new(DefaultTicker::default()) - .name_prefix("region-cleanup") - .thread_count(1, 1, 1) - .build_future_pool(), - region_cleaner: Arc::new(Mutex::new(RegionCleaner { - use_delete_range: cfg.value().use_delete_range, - engine, - pending_delete_ranges: PendingDeleteRanges::default(), - mgr, - })), } } pub fn snap_generator_pool(&self) -> FuturePool { - self.snap_gen_pool.clone() + self.pool.clone() } fn region_state(&self, region_id: u64) -> Result { @@ -669,10 +466,7 @@ where let start_key = keys::enc_start_key(®ion); let end_key = keys::enc_end_key(®ion); check_abort(&abort)?; - { - let mut region_cleaner = self.region_cleaner.lock().unwrap(); - region_cleaner.clean_overlap_ranges(start_key, end_key)?; - } + self.clean_overlap_ranges(start_key, end_key)?; check_abort(&abort)?; fail_point!("apply_snap_cleanup_range"); @@ -772,6 +566,153 @@ where ); } + /// Tries to clean up files in pending ranges overlapping with the given + /// bounds. These pending ranges will be removed. Returns an updated range + /// that also includes these ranges. Caller must ensure the remaining keys + /// in the returning range will be deleted properly. + fn clean_overlap_ranges_roughly( + &mut self, + mut start_key: Vec, + mut end_key: Vec, + ) -> (Vec, Vec) { + let overlap_ranges = self + .pending_delete_ranges + .drain_overlap_ranges(&start_key, &end_key); + if overlap_ranges.is_empty() { + return (start_key, end_key); + } + CLEAN_COUNTER_VEC.with_label_values(&["overlap"]).inc(); + let oldest_sequence = self + .engine + .get_oldest_snapshot_sequence_number() + .unwrap_or(u64::MAX); + let df_ranges: Vec<_> = overlap_ranges + .iter() + .filter_map(|(region_id, cur_start, cur_end, stale_sequence)| { + info!( + "delete data in range because of overlap"; "region_id" => region_id, + "start_key" => log_wrappers::Value::key(cur_start), + "end_key" => log_wrappers::Value::key(cur_end) + ); + if &start_key > cur_start { + start_key = cur_start.clone(); + } + if &end_key < cur_end { + end_key = cur_end.clone(); + } + if *stale_sequence < oldest_sequence { + Some(Range::new(cur_start, cur_end)) + } else { + SNAP_COUNTER_VEC + .with_label_values(&["overlap", "not_delete_files"]) + .inc(); + None + } + }) + .collect(); + self.engine + .delete_ranges_cfs( + &WriteOptions::default(), + DeleteStrategy::DeleteFiles, + &df_ranges, + ) + .map_err(|e| { + error!("failed to delete files in range"; "err" => %e); + }) + .unwrap(); + (start_key, end_key) + } + + /// Cleans up data in the given range and all pending ranges overlapping + /// with it. + fn clean_overlap_ranges(&mut self, start_key: Vec, end_key: Vec) -> Result<()> { + let (start_key, end_key) = self.clean_overlap_ranges_roughly(start_key, end_key); + self.delete_all_in_range(&[Range::new(&start_key, &end_key)]) + } + + /// Inserts a new pending range, and it will be cleaned up with some delay. + fn insert_pending_delete_range( + &mut self, + region_id: u64, + start_key: Vec, + end_key: Vec, + ) { + let (start_key, end_key) = self.clean_overlap_ranges_roughly(start_key, end_key); + info!("register deleting data in range"; + "region_id" => region_id, + "start_key" => log_wrappers::Value::key(&start_key), + "end_key" => log_wrappers::Value::key(&end_key), + ); + let seq = self.engine.get_latest_sequence_number(); + self.pending_delete_ranges + .insert(region_id, start_key, end_key, seq); + } + + /// Cleans up stale ranges. + fn clean_stale_ranges(&mut self) { + STALE_PEER_PENDING_DELETE_RANGE_GAUGE.set(self.pending_delete_ranges.len() as f64); + if self.ingest_maybe_stall() { + return; + } + let oldest_sequence = self + .engine + .get_oldest_snapshot_sequence_number() + .unwrap_or(u64::MAX); + let mut region_ranges: Vec<(u64, Vec, Vec)> = self + .pending_delete_ranges + .stale_ranges(oldest_sequence) + .map(|(region_id, s, e)| (region_id, s.to_vec(), e.to_vec())) + .collect(); + if region_ranges.is_empty() { + return; + } + CLEAN_COUNTER_VEC.with_label_values(&["destroy"]).inc_by(1); + region_ranges.sort_by(|a, b| a.1.cmp(&b.1)); + region_ranges.truncate(CLEANUP_MAX_REGION_COUNT); + let ranges: Vec<_> = region_ranges + .iter() + .map(|(region_id, start, end)| { + info!("delete data in range because of stale"; "region_id" => region_id, + "start_key" => log_wrappers::Value::key(start), + "end_key" => log_wrappers::Value::key(end)); + Range::new(start, end) + }) + .collect(); + + self.engine + .delete_ranges_cfs( + &WriteOptions::default(), + DeleteStrategy::DeleteFiles, + &ranges, + ) + .map_err(|e| { + error!("failed to delete files in range"; "err" => %e); + }) + .unwrap(); + if let Err(e) = self.delete_all_in_range(&ranges) { + error!("failed to cleanup stale range"; "err" => %e); + return; + } + self.engine + .delete_ranges_cfs( + &WriteOptions::default(), + DeleteStrategy::DeleteBlobs, + &ranges, + ) + .map_err(|e| { + error!("failed to delete blobs in range"; "err" => %e); + }) + .unwrap(); + + for (_, key, _) in region_ranges { + assert!( + self.pending_delete_ranges.remove(&key).is_some(), + "cleanup pending_delete_ranges {} should exist", + log_wrappers::Value::key(&key) + ); + } + } + /// Checks the number of files at level 0 to avoid write stall after /// ingesting sst. Returns true if the ingestion causes write stall. fn ingest_maybe_stall(&self) -> bool { @@ -787,6 +728,36 @@ where false } + fn delete_all_in_range(&self, ranges: &[Range<'_>]) -> Result<()> { + let wopts = WriteOptions::default(); + for cf in self.engine.cf_names() { + // CF_LOCK usually contains fewer keys than other CFs, so we delete them by key. + let (strategy, observer) = if cf == CF_LOCK { + ( + DeleteStrategy::DeleteByKey, + &CLEAR_OVERLAP_REGION_DURATION.by_key, + ) + } else if self.use_delete_range { + ( + DeleteStrategy::DeleteByRange, + &CLEAR_OVERLAP_REGION_DURATION.by_range, + ) + } else { + ( + DeleteStrategy::DeleteByWriter { + sst_path: self.mgr.get_temp_path_for_ingest(), + }, + &CLEAR_OVERLAP_REGION_DURATION.by_ingest_files, + ) + }; + let start = Instant::now(); + box_try!(self.engine.delete_ranges_cf(&wopts, cf, strategy, ranges)); + observer.observe(start.saturating_elapsed_secs()); + } + + Ok(()) + } + /// Calls observer `pre_apply_snapshot` for every task. /// Multiple task can be `pre_apply_snapshot` at the same time. fn pre_apply_snapshot(&self, task: &Task) -> Result<()> { @@ -920,7 +891,7 @@ where start: UnixSecs::now(), }; let scheduled_time = Instant::now_coarse(); - self.snap_gen_pool.spawn(async move { + self.pool.spawn(async move { SNAP_GEN_WAIT_DURATION_HISTOGRAM .observe(scheduled_time.saturating_elapsed_secs()); @@ -961,19 +932,11 @@ where start_key, end_key, } => { - let region_cleaner = self.region_cleaner.clone(); - self.region_cleanup_pool - .spawn(async move { - fail_point!("on_region_worker_destroy", region_id == 1000, |_| {}); - let mut region_cleaner = region_cleaner.lock().unwrap(); - // try to delay the range deletion because - // there might be a coprocessor request related to this range - region_cleaner.insert_pending_delete_range(region_id, start_key, end_key); - region_cleaner.clean_stale_ranges(); - }) - .unwrap_or_else(|e| { - error!("failed to destroy region"; "region_id" => region_id, "err" => ?e); - }); + fail_point!("on_region_worker_destroy", true, |_| {}); + // try to delay the range deletion because + // there might be a coprocessor request related to this range + self.insert_pending_delete_range(region_id, start_key, end_key); + self.clean_stale_ranges(); } } } @@ -989,7 +952,7 @@ where self.handle_pending_applies(true); self.clean_stale_tick += 1; if self.clean_stale_tick >= self.clean_stale_ranges_tick { - self.region_cleaner.lock().unwrap().clean_stale_ranges(); + self.clean_stale_ranges(); self.clean_stale_tick = 0; } } diff --git a/tests/failpoints/cases/test_merge.rs b/tests/failpoints/cases/test_merge.rs index 6a1e892b515..b56490435c9 100644 --- a/tests/failpoints/cases/test_merge.rs +++ b/tests/failpoints/cases/test_merge.rs @@ -1787,50 +1787,6 @@ fn test_destroy_source_peer_while_merging() { } } -// Test that a store is able to generate snapshots while destroying a region. It -// confirms the resolution of issue #12587. -#[test] -fn test_snap_gen_while_destroy_is_stuck() { - let mut cluster = new_node_cluster(0, 5); - configure_for_merge(&mut cluster.cfg); - let pd_client = Arc::clone(&cluster.pd_client); - pd_client.disable_default_operator(); - - cluster.run(); - - cluster.must_put(b"k1", b"v1"); - cluster.must_put(b"k3", b"v3"); - for i in 1..=5 { - must_get_equal(&cluster.get_engine(i), b"k1", b"v1"); - must_get_equal(&cluster.get_engine(i), b"k3", b"v3"); - } - cluster.must_split(&pd_client.get_region(b"k1").unwrap(), b"k2"); - - let region_1 = pd_client.get_region(b"k1").unwrap(); - let region_2 = pd_client.get_region(b"k3").unwrap(); - // Ensure that store 5 is the leader of region_1 and store 1 is the leader of - // region_2. - cluster.must_transfer_leader(region_1.get_id(), new_peer(5, 1001)); - cluster.must_transfer_leader(region_2.get_id(), new_peer(1, 1)); - - let on_region_worker_destroy_fp = "on_region_worker_destroy"; - fail::cfg(on_region_worker_destroy_fp, "pause").unwrap(); - - // Remove region_1 from from store 1 so that a destory task is scheduled. - // The destory task will be stuck due to the fail point above to simulate a - // slow destory scenario. - pd_client.must_remove_peer(region_1.get_id(), find_peer(®ion_1, 1).unwrap().clone()); - must_get_equal(&cluster.get_engine(1), b"k1", b"v1"); - - // Trigger a snapshot gen task on store 1 by removing and adding region_2 on - // store 5. The snapshot generation should go through without issues. - pd_client.must_remove_peer(region_2.get_id(), new_peer(5, 5)); - must_get_none(&cluster.get_engine(5), b"k3"); - - pd_client.must_add_peer(region_2.get_id(), new_peer(5, 6)); - must_get_equal(&cluster.get_engine(5), b"k3", b"v3"); -} - struct MsgTimeoutFilter { // wrap with mutex to make tx Sync. tx: Mutex>, From 254ceaaa654a70d78919ee5d85f5b4cbe3c444a3 Mon Sep 17 00:00:00 2001 From: lucasliang Date: Wed, 17 Jul 2024 13:13:29 +0800 Subject: [PATCH 002/144] metrics: fix incorrect unit of grpc source requests' duration. (#17279) ref tikv/tikv#16265 Fix incorrect format unit of the `grpc source requests' duration` panel. Signed-off-by: lucasliang --- metrics/grafana/tikv_details.dashboard.py | 4 +++- metrics/grafana/tikv_details.json | 4 ++-- metrics/grafana/tikv_details.json.sha256 | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index c34b35d5530..f2d62c19327 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -1096,7 +1096,9 @@ def gRPC() -> RowPanel: graph_panel( title="gRPC request sources duration", description="The duration of different sources of gRPC request", - yaxes=yaxes(left_format=UNITS.MICRO_SECONDS), + yaxes=yaxes( + left_format=UNITS.NANO_SECONDS, right_format=UNITS.NANO_SECONDS + ), lines=False, stack=True, targets=[ diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index b149925ec4d..e92dc44a2d1 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -7755,7 +7755,7 @@ "yaxes": [ { "decimals": null, - "format": "\u00b5s", + "format": "ns", "label": null, "logBase": 1, "max": null, @@ -7764,7 +7764,7 @@ }, { "decimals": null, - "format": "short", + "format": "ns", "label": null, "logBase": 1, "max": null, diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index 2cb20d444a4..7ee1f2cd41e 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -4a5b360a219dfd53a3589809cd51bd94afe5333dcf9b3388b2b460fed58c4b7d ./metrics/grafana/tikv_details.json +573466dbc2466856b440e7a2cdc239ca35bc655321544e5c607dae2d67cf6a63 ./metrics/grafana/tikv_details.json From ac3760983a9aedf08952aecb8738d2acdd598951 Mon Sep 17 00:00:00 2001 From: lucasliang Date: Wed, 17 Jul 2024 16:13:30 +0800 Subject: [PATCH 003/144] Revert "metrics: fix incorrect unit of grpc source requests' duration(#17279)" (#17280) ref tikv/tikv#16265 Revert duplicated changes. Signed-off-by: lucasliang --- metrics/grafana/tikv_details.dashboard.py | 4 +--- metrics/grafana/tikv_details.json | 4 ++-- metrics/grafana/tikv_details.json.sha256 | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index f2d62c19327..c34b35d5530 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -1096,9 +1096,7 @@ def gRPC() -> RowPanel: graph_panel( title="gRPC request sources duration", description="The duration of different sources of gRPC request", - yaxes=yaxes( - left_format=UNITS.NANO_SECONDS, right_format=UNITS.NANO_SECONDS - ), + yaxes=yaxes(left_format=UNITS.MICRO_SECONDS), lines=False, stack=True, targets=[ diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index e92dc44a2d1..b149925ec4d 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -7755,7 +7755,7 @@ "yaxes": [ { "decimals": null, - "format": "ns", + "format": "\u00b5s", "label": null, "logBase": 1, "max": null, @@ -7764,7 +7764,7 @@ }, { "decimals": null, - "format": "ns", + "format": "short", "label": null, "logBase": 1, "max": null, diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index 7ee1f2cd41e..2cb20d444a4 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -573466dbc2466856b440e7a2cdc239ca35bc655321544e5c607dae2d67cf6a63 ./metrics/grafana/tikv_details.json +4a5b360a219dfd53a3589809cd51bd94afe5333dcf9b3388b2b460fed58c4b7d ./metrics/grafana/tikv_details.json From cc2f344f0bb2bc484b04f9261adb140fb374c8d2 Mon Sep 17 00:00:00 2001 From: Wenqi Mou Date: Wed, 17 Jul 2024 05:16:32 -0400 Subject: [PATCH 004/144] doc: make c++ complier requirement more accurate (#17266) close tikv/tikv#17265 Signed-off-by: Wenqi Mou Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b2e1c37bc44..8add755c48d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ To build TiKV you'll need to at least have the following installed: * `cmake` - Build tool (required for gRPC) * `awk` - Pattern scanning/processing language * [`protoc`](https://github.com/protocolbuffers/protobuf/releases) - Google protocol buffer compiler -* C++ compiler - gcc 5+ (required for gRPC) +* `C++ compiler` - gcc 5+ or clang (required for gRPC) If you are targeting platforms other than x86_64/aarch64 Linux or macOS, you'll also need: From 60c3271684c692135e7c2a6ffbf376df84b597d4 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 23 Jul 2024 11:06:04 +0800 Subject: [PATCH 005/144] *: ignore unsound `openssl::bio::MemBio::get_buf` (#17292) close tikv/tikv#17291 Ignore RUSTSEC-2024-0357 (unsound `openssl::bio::MemBio::get_buf`) as we have banned relevant APIs in the TiKV codebase. Also, TiKV temporarily pins OpenSSL 1.1.1 because OpenSSL 3.0.0 has performance regressions. See details in deny.toml. Signed-off-by: Neil Shen --- clippy.toml | 31 +++++++++++++++++++++++++++++++ deny.toml | 9 +++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/clippy.toml b/clippy.toml index 15e0f1f549c..b6c0b2dc320 100644 --- a/clippy.toml +++ b/clippy.toml @@ -51,5 +51,36 @@ reason = """ X509StoreRef::objects is unsound, see RUSTSEC-2020-0071 """ +# See more about RUSTSEC-2024-0357 in deny.toml. +[[disallowed-types]] +path = "openssl::bio::MemBio" +reason = """ +openssl::bio::MemBio::get_buf is unsound, see RUSTSEC-2024-0357 +""" +[[disallowed-types]] +path = "openssl::pkcs7::Pkcs7" +reason = """ +openssl::pkcs7::Pkcs7 may call openssl::bio::MemBio::get_buf, \ +see RUSTSEC-2024-0357 +""" +[[disallowed-types]] +path = "openssl::pkey::PKeyRef" +reason = """ +openssl::pkey::PKeyRef may call openssl::bio::MemBio::get_buf, \ +see RUSTSEC-2024-0357 +""" +[[disallowed-types]] +path = "openssl::cms::CmsContentInfoRef" +reason = """ +openssl::cms::CmsContentInfoRef may call openssl::bio::MemBio::get_buf, \ +see RUSTSEC-2024-0357 +""" +[[disallowed-types]] +path = "openssl::asn1::Asn1GeneralizedTimeRef" +reason = """ +openssl::asn1::Asn1GeneralizedTimeRef may call openssl::bio::MemBio::get_buf, \ +see RUSTSEC-2024-0357 +""" + avoid-breaking-exported-api = false upper-case-acronyms-aggressive = true diff --git a/deny.toml b/deny.toml index f971effde8a..c49499ce8f5 100644 --- a/deny.toml +++ b/deny.toml @@ -55,13 +55,18 @@ ignore = [ # are required by TiKV. # See https://github.com/time-rs/time/blob/8067540c/CHANGELOG.md#L703 "RUSTSEC-2020-0071", - # Ignore RUSTSEC-2023-0072 as we bans the unsound `X509StoreRef::objects`. + # Ignore RUSTSEC-2023-0072 as we ban the unsound `X509StoreRef::objects`. # # NB: Upgrading rust-openssl the latest version do fix the issue but it # also upgrade the OpenSSL to v3.x which causes performance degradation. # See https://github.com/openssl/openssl/issues/17064 "RUSTSEC-2023-0072", - # Ignore RUSTSEC-2023-0072 (unsound issue of "atty" crate) as it only + # Ignore RUSTSEC-2024-0357 as there is no `MemBio::get_buf` in TiKV, also + # we ban all openssl (Rust) APIs that call `MemBio::get_buf`. + # + # See https://github.com/sfackler/rust-openssl/pull/2266 + "RUSTSEC-2024-0357", + # Ignore RUSTSEC-2021-0145 (unsound issue of "atty" crate) as it only # affects Windows plaform which is not supported offically by TiKV, and 2) # we have disabled the clap feature "color" so that the "atty" crate is not # included in production code. From 7146b71c4d26e0a93c0026ad6c25cd029fcc9b63 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:10:34 +0800 Subject: [PATCH 006/144] In-memory engine: fix gc may filter keys of onging snapshot (#17288) close tikv/tikv#17282 fix gc may filter keys of onging snapshot Signed-off-by: SpadeA-Tang --- .../src/background.rs | 151 ++++++++++++++++++ .../src/range_manager.rs | 4 + 2 files changed, 155 insertions(+) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 140f4645cbe..290ef716580 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -353,6 +353,20 @@ impl BackgroundRunnerCore { fn gc_range(&self, range: &CacheRange, safe_point: u64, oldest_seqno: u64) -> FilterMetrics { let (skiplist_engine, safe_ts) = { let mut core = self.engine.write(); + // We should also consider the ongoing snapshot of the historical ranges (ranges + // that have been evicted). + let historical_safe_point = core + .range_manager() + .historical_ranges() + .iter() + .find_map(|(r, m)| { + if r.contains_range(range) { + m.range_snapshot_list().min_snapshot_ts() + } else { + None + } + }) + .unwrap_or(u64::MAX); let Some(range_meta) = core.mut_range_manager().mut_range_meta(range) else { return FilterMetrics::default(); }; @@ -361,6 +375,7 @@ impl BackgroundRunnerCore { .min_snapshot_ts() .unwrap_or(u64::MAX); let safe_point = u64::min(safe_point, min_snapshot); + let safe_point = u64::min(safe_point, historical_safe_point); if safe_point <= range_meta.safe_point() { info!( @@ -2191,6 +2206,142 @@ pub mod tests { assert_eq!(3, element_count(&write)); } + #[test] + fn test_gc_range_contained_in_historical_range() { + let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(RangeCacheEngineConfig::config_for_test()), + ))); + let memory_controller = engine.memory_controller(); + let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); + engine.new_range(range.clone()); + let (write, default) = { + let skiplist_engine = engine.core().write().engine(); + ( + skiplist_engine.cf_handle(CF_WRITE), + skiplist_engine.cf_handle(CF_DEFAULT), + ) + }; + + put_data( + b"key1", + b"value1", + 9, + 10, + 10, + false, + &default, + &write, + memory_controller.clone(), + ); + put_data( + b"key1", + b"value2", + 11, + 12, + 11, + false, + &default, + &write, + memory_controller.clone(), + ); + put_data( + b"key1", + b"value3", + 30, + 31, + 20, + false, + &default, + &write, + memory_controller.clone(), + ); + + put_data( + b"key9", + b"value4", + 13, + 14, + 12, + false, + &default, + &write, + memory_controller.clone(), + ); + put_data( + b"key9", + b"value5", + 14, + 15, + 13, + false, + &default, + &write, + memory_controller.clone(), + ); + put_data( + b"key9", + b"value6", + 30, + 31, + 21, + false, + &default, + &write, + memory_controller.clone(), + ); + + let snap1 = engine.snapshot(range.clone(), 20, 1000).unwrap(); + let snap2 = engine.snapshot(range.clone(), 22, 1000).unwrap(); + let _snap3 = engine.snapshot(range.clone(), 60, 1000).unwrap(); + + let range2 = CacheRange::new(b"key5".to_vec(), b"key8".to_vec()); + engine.evict_range(&range2); + + assert_eq!(6, element_count(&default)); + assert_eq!(6, element_count(&write)); + + let (worker, _) = BackgroundRunner::new( + engine.core.clone(), + memory_controller, + None, + engine.expected_region_size(), + ); + + let ranges: Vec<_> = engine + .core + .read() + .range_manager() + .ranges() + .keys() + .cloned() + .collect(); + let mut filter = FilterMetrics::default(); + for r in &ranges { + filter.merge(&worker.core.gc_range(r, 50, 1000)); + } + assert_eq!(2, filter.filtered); + assert_eq!(4, element_count(&default)); + assert_eq!(4, element_count(&write)); + + drop(snap1); + let mut filter = FilterMetrics::default(); + for r in &ranges { + filter.merge(&worker.core.gc_range(r, 50, 1000)); + } + assert_eq!(0, filter.filtered); + assert_eq!(4, element_count(&default)); + assert_eq!(4, element_count(&write)); + + drop(snap2); + let mut filter = FilterMetrics::default(); + for r in &ranges { + filter.merge(&worker.core.gc_range(r, 50, 1000)); + } + assert_eq!(2, filter.filtered); + assert_eq!(2, element_count(&default)); + assert_eq!(2, element_count(&write)); + } + #[test] fn test_background_worker_load() { let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index c649f72463a..3911e31be2b 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -169,6 +169,10 @@ impl RangeManager { &self.ranges } + pub(crate) fn historical_ranges(&self) -> &BTreeMap { + &self.historical_ranges + } + pub fn new_range(&mut self, range: CacheRange) { assert!(!self.overlap_with_range(&range)); let range_meta = RangeMeta::new(self.id_allocator.allocate_id()); From d60c7fb6f3657dc5f3c83b0e3fc6ac75636e1a48 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:01:35 +0800 Subject: [PATCH 007/144] In-memory engine: fix repeatable schedule delete-range for the same range (#17261) close tikv/tikv#17259 fix repeatable schedule delete-range for the same range Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 27 +++++++- .../range_cache_memory_engine/src/engine.rs | 4 +- .../src/range_manager.rs | 27 ++++++-- .../range_cache_memory_engine/src/read.rs | 10 ++- .../src/write_batch.rs | 14 ++-- .../tests/failpoints/test_memory_engine.rs | 68 +++++++++++++++++++ 6 files changed, 131 insertions(+), 19 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 290ef716580..43d2e4b3dfd 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -492,7 +492,7 @@ impl BackgroundRunnerCore { assert_eq!(r, range); core.mut_range_manager() .ranges_being_deleted - .insert(r.clone()); + .insert(r.clone(), true); core.remove_cached_write_batch(&range); drop(core); fail::fail_point!("in_memory_engine_snapshot_load_canceled"); @@ -557,7 +557,7 @@ impl BackgroundRunnerCore { core.remove_cached_write_batch(&range); core.mut_range_manager() .ranges_being_deleted - .insert(r.clone()); + .insert(r.clone(), true); if let Err(e) = delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(vec![r])) { @@ -628,6 +628,10 @@ impl BackgroundRunnerCore { range_stats_manager.handle_range_evicted(range); } } + self.engine + .write() + .mut_range_manager() + .mark_delete_ranges_scheduled(&mut ranges_to_delete); if !ranges_to_delete.is_empty() { if let Err(e) = @@ -680,6 +684,12 @@ impl BackgroundRunnerCore { ranges_to_delete.append(&mut ranges); } } + + self.engine + .write() + .mut_range_manager() + .mark_delete_ranges_scheduled(&mut ranges_to_delete); + if !ranges_to_delete.is_empty() { if let Err(e) = delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(ranges_to_delete)) @@ -1156,11 +1166,24 @@ impl Runnable for DeleteRangeRunner { fn run(&mut self, task: Self::Task) { match task { BackgroundTask::DeleteRange(ranges) => { + fail::fail_point!("on_in_memory_engine_delete_range"); let (mut ranges_to_delay, ranges_to_delete) = { let core = self.engine.read(); let mut ranges_to_delay = vec![]; let mut ranges_to_delete = vec![]; for r in ranges { + // Check whether range exists in `ranges_being_deleted` and it's scheduled + if !core.range_manager.ranges_being_deleted.iter().any( + |(range_being_delete, scheduled)| { + if range_being_delete == &r && !scheduled { + panic!("range to delete with scheduled false; range={:?}", r,); + }; + range_being_delete == &r + }, + ) { + panic!("range to delete not in ranges_being_deleted; range={:?}", r,); + } + // If the range is overlapped with ranges in `ranges_being_written`, the // range has to be delayed to delete. See comment on `delay_ranges`. if core diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 58db7117977..a73f738073c 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -369,7 +369,9 @@ impl RangeCacheMemoryEngine { /// immediately due to some ongoing snapshots. pub fn evict_range(&self, range: &CacheRange) { let mut core = self.core.write(); - let ranges_to_delete = core.range_manager.evict_range(range); + let mut ranges_to_delete = core.range_manager.evict_range(range); + core.mut_range_manager() + .mark_delete_ranges_scheduled(&mut ranges_to_delete); if !ranges_to_delete.is_empty() { drop(core); // The range can be deleted directly. diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 3911e31be2b..416ac397f23 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -118,7 +118,8 @@ pub struct RangeManager { historical_ranges: BTreeMap, // `ranges_being_deleted` contains ranges that are evicted but not finished the delete (or even // not start to delete due to ongoing snapshot) - pub(crate) ranges_being_deleted: BTreeSet, + // `bool` means whether the range has been scheduled to the delete range worker + pub(crate) ranges_being_deleted: BTreeMap, // ranges that are cached now ranges: BTreeMap, @@ -224,7 +225,9 @@ impl RangeManager { } fn overlap_with_evicting_range(&self, range: &CacheRange) -> bool { - self.ranges_being_deleted.iter().any(|r| r.overlaps(range)) + self.ranges_being_deleted + .iter() + .any(|(r, _)| r.overlaps(range)) } fn overlap_with_range_in_gc(&self, range: &CacheRange) -> bool { @@ -290,7 +293,7 @@ impl RangeManager { return self .ranges_being_deleted - .iter() + .keys() .filter(|evicted_range| { !self .historical_ranges @@ -401,7 +404,7 @@ impl RangeManager { self.ranges.insert(right_range, right_meta); } - self.ranges_being_deleted.insert(evict_range.clone()); + self.ranges_being_deleted.insert(evict_range.clone(), false); if !meta.range_snapshot_list.is_empty() { self.historical_ranges.insert(cached_range.clone(), meta); @@ -421,7 +424,7 @@ impl RangeManager { pub fn on_delete_ranges(&mut self, ranges: &[CacheRange]) { for r in ranges { - self.ranges_being_deleted.remove(r); + assert!(self.ranges_being_deleted.remove(r).unwrap()); } } @@ -483,6 +486,16 @@ impl RangeManager { pub fn get_and_reset_range_evictions(&self) -> u64 { self.range_evictions.swap(0, Ordering::Relaxed) } + + // Only ranges that have not been scheduled will be retained in `ranges` + pub fn mark_delete_ranges_scheduled(&mut self, ranges: &mut Vec) { + ranges.retain(|r| { + let scheduled = self.ranges_being_deleted.get_mut(r).unwrap(); + let has_scheduled = *scheduled; + *scheduled = true; + !has_scheduled + }); + } } #[derive(Debug, PartialEq)] @@ -537,7 +550,7 @@ mod tests { let r_right = CacheRange::new(b"k06".to_vec(), b"k10".to_vec()); range_mgr.evict_range(&r_evict); let meta1 = range_mgr.historical_ranges.get(&r1).unwrap(); - assert!(range_mgr.ranges_being_deleted.contains(&r_evict)); + assert!(range_mgr.ranges_being_deleted.get(&r_evict).is_some()); assert!(range_mgr.ranges.get(&r1).is_none()); let meta2 = range_mgr.ranges.get(&r_left).unwrap(); let meta3 = range_mgr.ranges.get(&r_right).unwrap(); @@ -547,7 +560,7 @@ mod tests { let _ = range_mgr.range_snapshot(&r_left, 10); range_mgr.evict_range(&r_left); assert!(range_mgr.historical_ranges.get(&r_left).is_some()); - assert!(range_mgr.ranges_being_deleted.contains(&r_left)); + assert!(range_mgr.ranges_being_deleted.get(&r_left).is_some()); assert!(range_mgr.ranges.get(&r_left).is_none()); assert!(range_mgr.evict_range(&r_right).is_empty()); diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index 1d307b79ffa..fdcb24374ad 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -89,9 +89,11 @@ impl RangeCacheSnapshot { impl Drop for RangeCacheSnapshot { fn drop(&mut self) { let mut core = self.engine.core.write(); - let ranges_removable = core + let mut ranges_removable = core .range_manager .remove_range_snapshot(&self.snapshot_meta); + core.mut_range_manager() + .mark_delete_ranges_scheduled(&mut ranges_removable); if !ranges_removable.is_empty() { drop(core); if let Err(e) = self @@ -1880,7 +1882,8 @@ mod tests { .read() .range_manager() .ranges_being_deleted - .contains(&evict_range) + .get(&evict_range) + .is_some() ); } @@ -1893,7 +1896,8 @@ mod tests { .read() .range_manager() .ranges_being_deleted - .contains(&evict_range) + .get(&evict_range) + .is_some() ); } drop(s2); diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 60da9dc7e38..f018564f016 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -174,7 +174,7 @@ impl RangeCacheWriteBatch { // that all keys have unique sequence numbers. fn write_impl(&mut self, mut seq: u64) -> Result<()> { fail::fail_point!("on_write_impl"); - let ranges_to_delete = self.handle_ranges_to_evict(); + let mut ranges_to_delete = self.handle_ranges_to_evict(); let (entries_to_write, engine) = self.engine.handle_pending_range_in_loading_buffer( &mut seq, std::mem::take(&mut self.pending_range_in_loading_buffer), @@ -202,11 +202,13 @@ impl RangeCacheWriteBatch { fail::fail_point!("in_memory_engine_write_batch_consumed"); fail::fail_point!("before_clear_ranges_in_being_written"); - self.engine - .core - .write() - .mut_range_manager() - .clear_ranges_in_being_written(self.id, have_entry_applied); + { + let mut core = self.engine.core.write(); + core.mut_range_manager() + .clear_ranges_in_being_written(self.id, have_entry_applied); + core.mut_range_manager() + .mark_delete_ranges_scheduled(&mut ranges_to_delete); + } self.engine .lock_modification_bytes diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index f43e600cdca..91ce612defd 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -497,3 +497,71 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { let _ = handle.join(); } + +#[test] +fn test_double_delete_range_schedule() { + let path = Builder::new().prefix("test").tempdir().unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + + let config = RangeCacheEngineConfig::config_for_test(); + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(config), + ))); + engine.set_disk_engine(rocks_engine); + + let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); + let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); + let range3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); + let (snapshot_load_tx, snapshot_load_rx) = sync_channel(0); + let engine_clone = engine.clone(); + let r = CacheRange::new(b"k00".to_vec(), b"k60".to_vec()); + fail::cfg_callback("on_snapshot_load_finished", move || { + let _ = snapshot_load_tx.send(true); + // evict all ranges. So the loading ranges will also be evicted and a delete + // range task will be scheduled. + engine_clone.evict_range(&r); + }) + .unwrap(); + + let (delete_range_tx, delete_range_rx) = sync_channel(0); + fail::cfg_callback("on_in_memory_engine_delete_range", move || { + let _ = delete_range_tx.send(true); + }) + .unwrap(); + + engine.new_range(range1.clone()); + engine.new_range(range2.clone()); + engine.load_range(range3.clone()).unwrap(); + + let snap1 = engine.snapshot(range1.clone(), 100, 100).unwrap(); + let snap2 = engine.snapshot(range2.clone(), 100, 100).unwrap(); + + let mut wb = engine.write_batch(); + // prepare range to trigger loading + wb.prepare_for_range(range3.clone()); + wb.set_sequence_number(10).unwrap(); + wb.write().unwrap(); + + snapshot_load_rx + .recv_timeout(Duration::from_secs(5)) + .unwrap(); + delete_range_rx + .recv_timeout(Duration::from_secs(5)) + .unwrap(); + + drop(snap1); + drop(snap2); + + // two cached ranges + delete_range_rx + .recv_timeout(Duration::from_secs(5)) + .unwrap(); + delete_range_rx + .recv_timeout(Duration::from_secs(5)) + .unwrap(); + // sleep a while to ensure no further delete range will be scheduled + delete_range_rx + .recv_timeout(Duration::from_secs(2)) + .unwrap_err(); +} From dc76d90c259880a9042572a4742169847c5d807b Mon Sep 17 00:00:00 2001 From: Purelind Date: Thu, 25 Jul 2024 17:55:35 +0800 Subject: [PATCH 008/144] chore: bump nightly version to 8.3.0-alpha (#17289) ref tikv/tikv#16890 Signed-off-by: purelind Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29c2fa600d9..76131c4f90f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6444,7 +6444,7 @@ dependencies = [ [[package]] name = "tikv" -version = "8.2.0-alpha" +version = "8.3.0-alpha" dependencies = [ "anyhow", "api_version", diff --git a/Cargo.toml b/Cargo.toml index 2bd25ee591e..5ba83b30a82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tikv" -version = "8.2.0-alpha" +version = "8.3.0-alpha" authors = ["The TiKV Authors"] description = "A distributed transactional key-value database powered by Rust and Raft" license = "Apache-2.0" From 5b3bdf7ce9b076effb223307722cfa9540fdd482 Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 26 Jul 2024 16:14:17 +0800 Subject: [PATCH 009/144] raftstore: Fix too large slow log (#17295) close tikv/tikv#17294 Fix too large slow log Signed-off-by: Connor1996 --- .../raftstore/src/store/entry_storage.rs | 15 +++++++++++++- components/raftstore/src/store/msg.rs | 20 ++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/components/raftstore/src/store/entry_storage.rs b/components/raftstore/src/store/entry_storage.rs index 8085de7273b..1c261e3b238 100644 --- a/components/raftstore/src/store/entry_storage.rs +++ b/components/raftstore/src/store/entry_storage.rs @@ -416,7 +416,7 @@ pub enum RaftlogFetchState { Fetched(Box), } -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub struct RaftlogFetchResult { pub ents: raft::Result>, // because entries may be empty, so store the original low index that the task issued @@ -431,6 +431,19 @@ pub struct RaftlogFetchResult { pub term: u64, } +impl std::fmt::Debug for RaftlogFetchResult { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // avoid dumping entries content + f.debug_struct("RaftlogFetchResult") + .field("low", &self.low) + .field("max_size", &self.max_size) + .field("hit_size_limit", &self.hit_size_limit) + .field("tried_cnt", &self.tried_cnt) + .field("term", &self.term) + .finish() + } +} + #[derive(Default)] struct AsyncFetchStats { async_fetch: Cell, diff --git a/components/raftstore/src/store/msg.rs b/components/raftstore/src/store/msg.rs index 21add281570..a947790e6db 100644 --- a/components/raftstore/src/store/msg.rs +++ b/components/raftstore/src/store/msg.rs @@ -733,7 +733,6 @@ pub struct RaftCmdExtraOpts { /// Raft command is the command that is expected to be proposed by the /// leader of the target raft group. -#[derive(Debug)] pub struct RaftCommand { pub send_time: Instant, pub request: RaftCmdRequest, @@ -741,6 +740,21 @@ pub struct RaftCommand { pub extra_opts: RaftCmdExtraOpts, } +impl fmt::Debug for RaftCommand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RaftCommand") + .field("send_time", &self.send_time) + .field("request", &self.request.get_requests().len()) + .field( + "admin_request", + &self.request.get_admin_request().get_cmd_type(), + ) + .field("callback", &self.callback) + .field("extra_opts", &self.extra_opts) + .finish() + } +} + impl RaftCommand { #[inline] pub fn new(request: RaftCmdRequest, callback: Callback) -> RaftCommand { @@ -874,8 +888,8 @@ impl PeerMsg { PeerMsg::RaftMessage(..) => 0, PeerMsg::RaftCommand(_) => 1, PeerMsg::Tick(_) => 2, - PeerMsg::SignificantMsg(_) => 3, - PeerMsg::ApplyRes { .. } => 4, + PeerMsg::ApplyRes { .. } => 3, + PeerMsg::SignificantMsg(_) => 4, PeerMsg::Start => 5, PeerMsg::Noop => 6, PeerMsg::Persisted { .. } => 7, From ccd84b4a4940011391214e8a5d1ba237304b5bce Mon Sep 17 00:00:00 2001 From: lucasliang Date: Fri, 26 Jul 2024 17:36:48 +0800 Subject: [PATCH 010/144] raftstore: optimize the batching mechanism when enabling async-ios. (#17029) ref tikv/tikv#16907 Introduce a simple algorithm to make the batching mechanism on WriteBatch larger as expected, for reducing the cost on IO resources. Signed-off-by: lucasliang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../raftstore/src/store/async_io/write.rs | 157 +++++++++++++++++- .../src/store/async_io/write_tests.rs | 31 ++++ components/raftstore/src/store/config.rs | 34 ++++ components/tikv_util/src/time.rs | 63 ++++++- tests/integrations/config/mod.rs | 2 + tests/integrations/config/test-custom.toml | 2 + 6 files changed, 283 insertions(+), 6 deletions(-) diff --git a/components/raftstore/src/store/async_io/write.rs b/components/raftstore/src/store/async_io/write.rs index 4b468d900fe..1fc99993ab1 100644 --- a/components/raftstore/src/store/async_io/write.rs +++ b/components/raftstore/src/store/async_io/write.rs @@ -8,6 +8,7 @@ //! raft db and then invoking callback or sending msgs if any. use std::{ + collections::VecDeque, fmt, mem, sync::Arc, thread::{self, JoinHandle}, @@ -39,7 +40,7 @@ use tikv_util::{ debug, info, slow_log, sys::thread::StdThreadBuildWrapper, thd_name, - time::{duration_to_sec, Instant}, + time::{duration_to_sec, setup_for_spin_interval, spin_at_least, Duration, Instant}, warn, }; @@ -61,6 +62,8 @@ const KV_WB_DEFAULT_SIZE: usize = 16 * 1024; const RAFT_WB_SHRINK_SIZE: usize = 10 * 1024 * 1024; const RAFT_WB_DEFAULT_SIZE: usize = 256 * 1024; const RAFT_WB_SPLIT_SIZE: usize = ReadableSize::gb(1).0 as usize; +/// The default size of the raft write batch recorder. +const RAFT_WB_DEFAULT_RECORDER_SIZE: usize = 30; /// Notify the event to the specified region. pub trait PersistedNotifier: Clone + Send + 'static { @@ -373,6 +376,105 @@ impl ExtraBatchWrite { } } +/// WriteTaskBatchRecorder is a sliding window, used to record the batch size +/// and calculate the wait duration. +/// If the batch size is smaller than the threshold, it will return a +/// recommended wait duration for the caller as a hint to wait for more writes. +/// The wait duration is calculated based on the trend of the change of the +/// batch size. The range of the trend is [0.5, 2.0]. If the batch size is +/// increasing, the trend will be larger than 1.0, and the wait duration will +/// be shorter. +/// By default, the wait duration is 20us, the relative range for wait duration +/// is [10us, 40us]. +struct WriteTaskBatchRecorder { + batch_size_hint: usize, + capacity: usize, + history: VecDeque, + sum: usize, + avg: usize, + trend: f64, + /// Wait duration in nanoseconds. + wait_duration: Duration, + /// The count of wait. + wait_count: u64, + /// The max count of wait. + wait_max_count: u64, +} + +impl WriteTaskBatchRecorder { + fn new(batch_size_hint: usize, wait_duration: Duration) -> Self { + // Initialize the spin duration in advance. + setup_for_spin_interval(); + Self { + batch_size_hint, + history: VecDeque::new(), + capacity: RAFT_WB_DEFAULT_RECORDER_SIZE, + sum: 0, + avg: 0, + trend: 1.0, + wait_duration, + wait_count: 0, + wait_max_count: 1, + } + } + + #[cfg(test)] + fn get_avg(&self) -> usize { + self.avg + } + + #[cfg(test)] + fn get_trend(&self) -> f64 { + self.trend + } + + #[inline] + fn update_config(&mut self, batch_size: usize, wait_duration: Duration) { + self.batch_size_hint = batch_size; + self.wait_duration = wait_duration; + } + + fn record(&mut self, size: usize) { + self.history.push_back(size); + self.sum += size; + + let mut len = self.history.len(); + if len > self.capacity { + self.sum = self + .sum + .saturating_sub(self.history.pop_front().unwrap_or(0)); + len = self.capacity; + } + self.avg = self.sum / len; + + if len >= self.capacity && self.batch_size_hint > 0 { + // The trend ranges from 0.5 to 2.0. + let trend = self.avg as f64 / self.batch_size_hint as f64; + self.trend = trend.clamp(0.5, 2.0); + } else { + self.trend = 1.0; + } + } + + #[inline] + fn reset_wait_count(&mut self) { + self.wait_count = 0; + } + + #[inline] + fn should_wait(&self, batch_size: usize) -> bool { + batch_size < self.batch_size_hint && self.wait_count < self.wait_max_count + } + + fn wait_for_a_while(&mut self) { + self.wait_count += 1; + // Use a simple linear function to calculate the wait duration. + spin_at_least(Duration::from_nanos( + (self.wait_duration.as_nanos() as f64 * (1.0 / self.trend)) as u64, + )); + } +} + /// WriteTaskBatch is used for combining several WriteTask into one. struct WriteTaskBatch where @@ -393,6 +495,7 @@ where // region_id -> (peer_id, ready_number) pub readies: HashMap, pub(crate) raft_wb_split_size: usize, + recorder: WriteTaskBatchRecorder, } impl WriteTaskBatch @@ -400,7 +503,11 @@ where EK: KvEngine, ER: RaftEngine, { - fn new(raft_wb: ER::LogBatch) -> Self { + fn new( + raft_wb: ER::LogBatch, + write_batch_size_hint: usize, + write_wait_duration: Duration, + ) -> Self { Self { raft_wbs: vec![raft_wb], raft_states: HashMap::default(), @@ -410,6 +517,7 @@ where persisted_cbs: vec![], readies: HashMap::default(), raft_wb_split_size: RAFT_WB_SPLIT_SIZE, + recorder: WriteTaskBatchRecorder::new(write_batch_size_hint, write_wait_duration), } } @@ -490,6 +598,8 @@ where self.persisted_cbs.push(v); } self.tasks.push(task); + // Record the size of the batch. + self.recorder.record(self.get_raft_size()); } fn clear(&mut self) { @@ -500,6 +610,7 @@ where self.state_size = 0; self.tasks.clear(); self.readies.clear(); + self.recorder.reset_wait_count(); } #[inline] @@ -563,6 +674,20 @@ where } } } + + #[inline] + fn update_config(&mut self, batch_size: usize, wait_duration: Duration) { + self.recorder.update_config(batch_size, wait_duration); + } + + #[inline] + fn should_wait(&self) -> bool { + self.recorder.should_wait(self.get_raft_size()) + } + + fn wait_for_a_while(&mut self) { + self.recorder.wait_for_a_while(); + } } pub struct Worker @@ -604,7 +729,11 @@ where trans: T, cfg: &Arc>, ) -> Self { - let batch = WriteTaskBatch::new(raft_engine.log_batch(RAFT_WB_DEFAULT_SIZE)); + let batch = WriteTaskBatch::new( + raft_engine.log_batch(RAFT_WB_DEFAULT_SIZE), + cfg.value().raft_write_batch_size_hint.0 as usize, + cfg.value().raft_write_wait_duration.0, + ); let perf_context = ER::get_perf_context(cfg.value().perf_level, PerfContextKind::RaftstoreStore); let cfg_tracker = cfg.clone().tracker(tag.clone()); @@ -643,7 +772,17 @@ where Ok(msg) => { stopped |= self.handle_msg(msg); } - Err(TryRecvError::Empty) => break, + Err(TryRecvError::Empty) => { + // If the size of the batch is small enough, it will wait for + // a while to make the batch larger. This can reduce the IOPS + // amplification if there are many trivial writes. + if self.batch.should_wait() { + self.batch.wait_for_a_while(); + continue; + } else { + break; + } + } Err(TryRecvError::Disconnected) => { stopped = true; break; @@ -881,6 +1020,10 @@ where if let Some(incoming) = self.cfg_tracker.any_new() { self.raft_write_size_limit = incoming.raft_write_size_limit.0 as usize; self.metrics.waterfall_metrics = incoming.waterfall_metrics; + self.batch.update_config( + incoming.raft_write_batch_size_hint.0 as usize, + incoming.raft_write_wait_duration.0, + ); } } @@ -1064,7 +1207,11 @@ pub fn write_to_db_for_test( EK: KvEngine, ER: RaftEngine, { - let mut batch = WriteTaskBatch::new(engines.raft.log_batch(RAFT_WB_DEFAULT_SIZE)); + let mut batch = WriteTaskBatch::new( + engines.raft.log_batch(RAFT_WB_DEFAULT_SIZE), + 0, + Duration::default(), + ); batch.add_write_task(&engines.raft, task); let metrics = StoreWriteMetrics::new(false); batch.before_write_to_db(&metrics); diff --git a/components/raftstore/src/store/async_io/write_tests.rs b/components/raftstore/src/store/async_io/write_tests.rs index 97e865a6bfe..bc0cde09fa8 100644 --- a/components/raftstore/src/store/async_io/write_tests.rs +++ b/components/raftstore/src/store/async_io/write_tests.rs @@ -277,6 +277,37 @@ impl TestWriters { } } +#[test] +fn test_write_task_batch_recorder() { + let mut recorder = WriteTaskBatchRecorder::new(1024, Duration::from_nanos(50)); // 1kb, 50 nanoseconds + assert_eq!(recorder.get_avg(), 0); + assert_eq!(recorder.get_trend(), 1.0); + assert!(!recorder.should_wait(4096)); + assert!(recorder.should_wait(512)); + // [512 ...] + for _ in 0..30 { + recorder.record(512); + } + assert_eq!(recorder.get_avg(), 512); + assert_eq!(recorder.get_trend(), 0.5); + assert!(recorder.should_wait(128)); + let start = Instant::now(); + recorder.wait_for_a_while(); + assert!(start.saturating_elapsed() >= Duration::from_nanos(100)); + // [4096 ...] + for _ in 0..30 { + recorder.record(4096); + } + assert_eq!(recorder.get_avg(), 4096); + assert_eq!(recorder.get_trend(), 2.0); + assert!(!recorder.should_wait(128)); + recorder.reset_wait_count(); + assert!(recorder.should_wait(128)); + let start = Instant::now(); + recorder.wait_for_a_while(); + assert!(start.saturating_elapsed() >= Duration::from_nanos(20)); +} + #[test] fn test_worker() { let region_1 = 1; diff --git a/components/raftstore/src/store/config.rs b/components/raftstore/src/store/config.rs index 152c49de0bd..0e10b467faf 100644 --- a/components/raftstore/src/store/config.rs +++ b/components/raftstore/src/store/config.rs @@ -327,6 +327,19 @@ pub struct Config { /// triggered. pub raft_write_size_limit: ReadableSize, + /// When the size of raft db writebatch is smaller than this value, write + /// will wait for a while to make the writebatch larger, which will reduce + /// the write amplification. + #[doc(hidden)] + pub raft_write_batch_size_hint: ReadableSize, + + /// When the size of raft db writebatch is smaller than this value, write + /// will wait for a while. This is used to reduce the write amplification. + /// It should be smaller than 1ms. Invalid to use too long duration because + /// it will make the write request wait too long. + #[doc(hidden)] + pub raft_write_wait_duration: ReadableDuration, + pub waterfall_metrics: bool, pub io_reschedule_concurrent_max_count: usize, @@ -516,6 +529,8 @@ impl Default for Config { cmd_batch: true, cmd_batch_concurrent_ready_max_count: 1, raft_write_size_limit: ReadableSize::mb(1), + raft_write_batch_size_hint: ReadableSize::kb(8), + raft_write_wait_duration: ReadableDuration::micros(20), waterfall_metrics: true, io_reschedule_concurrent_max_count: 4, io_reschedule_hotpot_duration: ReadableDuration::secs(5), @@ -827,6 +842,13 @@ impl Config { return Err(box_err!("local-read-batch-size must be greater than 0")); } + if self.raft_write_wait_duration.as_micros() > 1000 { + return Err(box_err!( + "raft-write-wait-duration should be less than 1ms, current value is {}ms", + self.raft_write_wait_duration.as_millis() + )); + } + // Since the following configuration supports online update, in order to // prevent mistakenly inputting too large values, the max limit is made // according to the cpu quota * 10. Notice 10 is only an estimate, not an @@ -1186,6 +1208,12 @@ impl Config { CONFIG_RAFTSTORE_GAUGE .with_label_values(&["raft_write_size_limit"]) .set(self.raft_write_size_limit.0 as f64); + CONFIG_RAFTSTORE_GAUGE + .with_label_values(&["raft_write_batch_size_hint"]) + .set(self.raft_write_batch_size_hint.0 as f64); + CONFIG_RAFTSTORE_GAUGE + .with_label_values(&["raft_write_wait_duration"]) + .set(self.raft_write_wait_duration.as_micros() as f64); CONFIG_RAFTSTORE_GAUGE .with_label_values(&["waterfall_metrics"]) .set((self.waterfall_metrics as i32).into()); @@ -1595,5 +1623,11 @@ mod tests { cfg.raft_log_gc_count_limit(), split_size * 3 / 4 / ReadableSize::kb(1) ); + + cfg = Config::new(); + cfg.optimize_for(false); + cfg.raft_write_wait_duration = ReadableDuration::micros(1001); + cfg.validate(split_size, true, split_size / 20, false) + .unwrap_err(); } } diff --git a/components/tikv_util/src/time.rs b/components/tikv_util/src/time.rs index c710b174dee..efab331e9f1 100644 --- a/components/tikv_util/src/time.rs +++ b/components/tikv_util/src/time.rs @@ -6,7 +6,10 @@ use std::{ cell::RefCell, cmp::Ordering, ops::{Add, AddAssign, Sub, SubAssign}, - sync::mpsc::{self, Sender}, + sync::{ + mpsc::{self, Sender}, + Once, + }, thread::{self, Builder, JoinHandle}, time::{SystemTime, UNIX_EPOCH}, }; @@ -532,6 +535,55 @@ impl Default for ThreadReadId { } } +/// Default duration cost for spinning one round. +/// +/// Heuristically, spin duration for one round is about 3~4ns. +static mut DEFAULT_DURATION_SPIN_ONE_ROUND: u64 = 1; + +/// Setup the default ratio for spin duration. +pub fn setup_for_spin_interval() { + static INIT: Once = Once::new(); + INIT.call_once(|| { + let inspect_duration = Duration::from_millis(10); + let start = Instant::now(); + let mut count = 0; + // Spin for a while to get the duration for one round. + for _ in 0..2_097_152 { + count += 1; + if count % 1024 == 0 && start.saturating_elapsed() >= inspect_duration { + break; + } + } + let elapsed_one_round = start.saturating_elapsed().as_nanos() as u64 / count; + if elapsed_one_round > 0 { + unsafe { + DEFAULT_DURATION_SPIN_ONE_ROUND = elapsed_one_round; + } + } + debug!("setup duration for spinning one round: {}ns", unsafe { + DEFAULT_DURATION_SPIN_ONE_ROUND + }); + }); +} + +/// Wait for at least `elaspsed` duration synchronously by looping. +/// +/// Attention, this function is only suitable for short-time spinning, so +/// the `elaspsed` should be small, like 1ms. And the caller should not +/// rely on it to guarantee the exact time to sleep. +pub fn spin_at_least(elaspsed: Duration) { + // Initialize default spin loop interval. + setup_for_spin_interval(); + + let rounds = unsafe { elaspsed.as_nanos() as u64 / DEFAULT_DURATION_SPIN_ONE_ROUND }; + let now = Instant::now(); + for i in 1..=rounds { + if i % 100 == 0 && now.saturating_elapsed() >= elaspsed { + return; + } + } +} + #[cfg(test)] mod tests { use std::{ @@ -687,6 +739,15 @@ mod tests { } } + #[test] + fn test_wait_at_least() { + setup_for_spin_interval(); + + let start = Instant::now(); + spin_at_least(Duration::from_micros(500)); + assert!(start.saturating_elapsed() >= Duration::from_micros(100)); + } + #[bench] fn bench_instant_now(b: &mut Bencher) { b.iter(|| { diff --git a/tests/integrations/config/mod.rs b/tests/integrations/config/mod.rs index f8d9d7ac310..231ad2190ce 100644 --- a/tests/integrations/config/mod.rs +++ b/tests/integrations/config/mod.rs @@ -248,6 +248,8 @@ fn test_serde_custom_tikv_config() { cmd_batch: false, cmd_batch_concurrent_ready_max_count: 123, raft_write_size_limit: ReadableSize::mb(34), + raft_write_batch_size_hint: ReadableSize::mb(1), + raft_write_wait_duration: ReadableDuration::micros(444), waterfall_metrics: true, io_reschedule_concurrent_max_count: 1234, io_reschedule_hotpot_duration: ReadableDuration::secs(4321), diff --git a/tests/integrations/config/test-custom.toml b/tests/integrations/config/test-custom.toml index 8177a08a4b2..5554c0165c4 100644 --- a/tests/integrations/config/test-custom.toml +++ b/tests/integrations/config/test-custom.toml @@ -220,6 +220,8 @@ evict-cache-on-memory-ratio = 0.8 cmd-batch = false cmd-batch-concurrent-ready-max-count = 123 raft-write-size-limit = "34MB" +raft-write-batch-size-hint = "1MB" +raft-write-wait-duration = "444us" waterfall-metrics = true io-reschedule-concurrent-max-count = 1234 io-reschedule-hotpot-duration = "4321s" From 6488a12389a8c8c59e8e8ca3c83301f510a27813 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:13:17 +0800 Subject: [PATCH 011/144] In-memory engine: add eviction duration metrics (#17321) ref tikv/tikv#16141 add eviction duration metrics Signed-off-by: SpadeA-Tang --- .../src/background.rs | 16 +- .../range_cache_memory_engine/src/metrics.rs | 6 + .../src/range_manager.rs | 29 +- metrics/grafana/tikv_details.dashboard.py | 46 +- metrics/grafana/tikv_details.json | 1120 +++++++++++------ metrics/grafana/tikv_details.json.sha256 | 2 +- 6 files changed, 811 insertions(+), 408 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 43d2e4b3dfd..14cc96d103f 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -492,7 +492,7 @@ impl BackgroundRunnerCore { assert_eq!(r, range); core.mut_range_manager() .ranges_being_deleted - .insert(r.clone(), true); + .insert(r.clone(), (true, Instant::now())); core.remove_cached_write_batch(&range); drop(core); fail::fail_point!("in_memory_engine_snapshot_load_canceled"); @@ -557,7 +557,7 @@ impl BackgroundRunnerCore { core.remove_cached_write_batch(&range); core.mut_range_manager() .ranges_being_deleted - .insert(r.clone(), true); + .insert(r.clone(), (true, Instant::now())); if let Err(e) = delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(vec![r])) { @@ -1105,8 +1105,6 @@ impl RunnableWithTimer for BackgroundRunner { let core = self.core.engine.read(); let pending = core.range_manager.pending_ranges.len(); let cached = core.range_manager.ranges().len(); - let loading = core.range_manager.pending_ranges_loading_data.len(); - let evictions = core.range_manager.get_and_reset_range_evictions(); drop(core); RANGE_CACHE_COUNT .with_label_values(&["pending_range"]) @@ -1114,16 +1112,10 @@ impl RunnableWithTimer for BackgroundRunner { RANGE_CACHE_COUNT .with_label_values(&["cached_range"]) .set(cached as i64); - RANGE_CACHE_COUNT - .with_label_values(&["loading_range"]) - .set(loading as i64); - RANGE_CACHE_COUNT - .with_label_values(&["range_evictions"]) - .set(evictions as i64); } fn get_interval(&self) -> Duration { - Duration::from_secs(1) + Duration::from_secs(10) } } @@ -1174,7 +1166,7 @@ impl Runnable for DeleteRangeRunner { for r in ranges { // Check whether range exists in `ranges_being_deleted` and it's scheduled if !core.range_manager.ranges_being_deleted.iter().any( - |(range_being_delete, scheduled)| { + |(range_being_delete, &(scheduled, _))| { if range_being_delete == &r && !scheduled { panic!("range to delete with scheduled false; range={:?}", r,); }; diff --git a/components/range_cache_memory_engine/src/metrics.rs b/components/range_cache_memory_engine/src/metrics.rs index b4cf285e0c8..4436c639ea0 100644 --- a/components/range_cache_memory_engine/src/metrics.rs +++ b/components/range_cache_memory_engine/src/metrics.rs @@ -63,6 +63,12 @@ lazy_static! { exponential_buckets(0.001, 2.0, 20).unwrap() ) .unwrap(); + pub static ref RANGE_EVICTION_DURATION_HISTOGRAM: Histogram = register_histogram!( + "tikv_range_eviction_duration_secs", + "Bucketed histogram of range eviction time duration.", + exponential_buckets(0.001, 2.0, 20).unwrap() + ) + .unwrap(); pub static ref WRITE_DURATION_HISTOGRAM: Histogram = register_histogram!( "tikv_range_cache_engine_write_duration_seconds", "Bucketed histogram of write duration in range cache engine.", diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 416ac397f23..0de5a315573 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -3,18 +3,15 @@ use std::{ collections::{BTreeMap, BTreeSet, VecDeque}, result, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, - }, + sync::Arc, }; use collections::HashMap; use engine_rocks::RocksSnapshot; use engine_traits::{CacheRange, FailedReason}; -use tikv_util::info; +use tikv_util::{info, time::Instant}; -use crate::read::RangeCacheSnapshotMeta; +use crate::{metrics::RANGE_EVICTION_DURATION_HISTOGRAM, read::RangeCacheSnapshotMeta}; // read_ts -> ref_count #[derive(Default, Debug)] @@ -119,7 +116,7 @@ pub struct RangeManager { // `ranges_being_deleted` contains ranges that are evicted but not finished the delete (or even // not start to delete due to ongoing snapshot) // `bool` means whether the range has been scheduled to the delete range worker - pub(crate) ranges_being_deleted: BTreeMap, + pub(crate) ranges_being_deleted: BTreeMap, // ranges that are cached now ranges: BTreeMap, @@ -162,7 +159,6 @@ pub struct RangeManager { // the ranges of this batch. So, when the write batch is consumed by the in-memory engine, // all ranges of it are cleared from `ranges_being_written`. ranges_being_written: HashMap>, - range_evictions: AtomicU64, } impl RangeManager { @@ -389,7 +385,6 @@ impl RangeManager { "evict_range" => ?evict_range, "cached_range" => ?cached_range, ); - self.range_evictions.fetch_add(1, Ordering::Relaxed); let meta = self.ranges.remove(cached_range).unwrap(); let (left_range, right_range) = cached_range.split_off(evict_range); assert!((left_range.is_some() || right_range.is_some()) || evict_range == cached_range); @@ -404,7 +399,8 @@ impl RangeManager { self.ranges.insert(right_range, right_meta); } - self.ranges_being_deleted.insert(evict_range.clone(), false); + self.ranges_being_deleted + .insert(evict_range.clone(), (false, Instant::now())); if !meta.range_snapshot_list.is_empty() { self.historical_ranges.insert(cached_range.clone(), meta); @@ -424,7 +420,12 @@ impl RangeManager { pub fn on_delete_ranges(&mut self, ranges: &[CacheRange]) { for r in ranges { - assert!(self.ranges_being_deleted.remove(r).unwrap()); + let (_, t) = self.ranges_being_deleted.remove(r).unwrap(); + RANGE_EVICTION_DURATION_HISTOGRAM.observe(t.saturating_elapsed_secs()); + info!( + "range eviction done"; + "range" => ?r, + ); } } @@ -483,14 +484,10 @@ impl RangeManager { Ok(()) } - pub fn get_and_reset_range_evictions(&self) -> u64 { - self.range_evictions.swap(0, Ordering::Relaxed) - } - // Only ranges that have not been scheduled will be retained in `ranges` pub fn mark_delete_ranges_scheduled(&mut self, ranges: &mut Vec) { ranges.retain(|r| { - let scheduled = self.ranges_being_deleted.get_mut(r).unwrap(); + let (ref mut scheduled, _) = self.ranges_being_deleted.get_mut(r).unwrap(); let has_scheduled = *scheduled; *scheduled = true; !has_scheduled diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index c34b35d5530..3fefd74714c 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -4221,21 +4221,59 @@ def RangeCacheMemoryEngine() -> RowPanel: ), ], ), + heatmap_panel( + title="Range GC Duration", + description="The handle duration of range gc", + yaxis=yaxis(format=UNITS.SECONDS), + metric="tikv_range_gc_duration_secs_bucket", + ), ] ) layout.row( [ heatmap_panel( - title="Range load duration", + title="Range Load Duration", description="The handle duration of range load", yaxis=yaxis(format=UNITS.SECONDS), metric="tikv_range_load_duration_secs_bucket", ), + graph_panel( + title="Range Load Count", + description="The count of range loading per seconds", + yaxes=yaxes(left_format=UNITS.OPS_PER_SEC), + targets=[ + target( + expr=expr_sum_rate( + "tikv_range_load_duration_secs_count", + by_labels=["instance"], + ), + legend_format="{{instance}}", + ), + ], + ), + ] + ) + layout.row( + [ heatmap_panel( - title="Range gc duration", - description="The handle duration of range gc", + title="Range Eviction Duration", + description="The handle duration of range eviction", yaxis=yaxis(format=UNITS.SECONDS), - metric="tikv_range_gc_duration_secs_bucket", + metric="tikv_range_eviction_duration_secs_bucket", + ), + graph_panel( + title="Range Eviction Count", + description="The count of range eviction per seconds", + yaxes=yaxes(left_format=UNITS.OPS_PER_SEC), + targets=[ + target( + expr=expr_sum_rate( + "tikv_range_load_duration_secs_count", + by_labels=["instance"], + ), + legend_format="{{instance}}--loading2", + ), + ], ), ] ) diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index b149925ec4d..b16c8426f5d 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -37439,7 +37439,7 @@ }, "gridPos": { "h": 7, - "w": 12, + "w": 8, "x": 0, "y": 7 }, @@ -37572,8 +37572,8 @@ }, "gridPos": { "h": 7, - "w": 12, - "x": 12, + "w": 8, + "x": 8, "y": 7 }, "height": null, @@ -37696,7 +37696,7 @@ }, "dataFormat": "tsbuckets", "datasource": "${DS_TEST-CLUSTER}", - "description": "The handle duration of range load", + "description": "The handle duration of range gc", "editable": true, "error": false, "fieldConfig": { @@ -37709,9 +37709,9 @@ }, "gridPos": { "h": 7, - "w": 12, - "x": 0, - "y": 14 + "w": 8, + "x": 16, + "y": 7 }, "heatmap": {}, "height": null, @@ -37735,7 +37735,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_load_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "expr": "sum(rate(\n tikv_range_gc_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "format": "heatmap", "hide": false, "instant": false, @@ -37743,7 +37743,7 @@ "intervalFactor": 1, "legendFormat": "{{le}}", "metric": "", - "query": "sum(rate(\n tikv_range_load_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "query": "sum(rate(\n tikv_range_gc_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "refId": "", "step": 10, "target": "" @@ -37751,7 +37751,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Range load duration", + "title": "Range GC Duration", "tooltip": { "msResolution": true, "shared": true, @@ -37800,7 +37800,7 @@ }, "dataFormat": "tsbuckets", "datasource": "${DS_TEST-CLUSTER}", - "description": "The handle duration of range gc", + "description": "The handle duration of range load", "editable": true, "error": false, "fieldConfig": { @@ -37814,7 +37814,7 @@ "gridPos": { "h": 7, "w": 12, - "x": 12, + "x": 0, "y": 14 }, "heatmap": {}, @@ -37839,7 +37839,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_gc_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "expr": "sum(rate(\n tikv_range_load_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "format": "heatmap", "hide": false, "instant": false, @@ -37847,7 +37847,7 @@ "intervalFactor": 1, "legendFormat": "{{le}}", "metric": "", - "query": "sum(rate(\n tikv_range_gc_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "query": "sum(rate(\n tikv_range_load_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "refId": "", "step": 10, "target": "" @@ -37855,7 +37855,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Range gc duration", + "title": "Range Load Duration", "tooltip": { "msResolution": true, "shared": true, @@ -37887,6 +37887,139 @@ "yBucketNumber": null, "yBucketSize": null }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The count of range loading per seconds", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [] + } + } + }, + "fill": 1, + "fillGradient": 1, + "grid": { + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 14 + }, + "height": null, + "hideTimeOverride": false, + "id": 266, + "interval": null, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxDataPoints": null, + "maxPerRow": null, + "minSpan": null, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true, + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": null, + "seriesOverrides": [], + "span": null, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "query": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "refId": "", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Range Load Count", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transformations": [], + "transparent": false, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": 0 + } + }, { "cacheTimeout": null, "cards": { @@ -37904,7 +38037,7 @@ }, "dataFormat": "tsbuckets", "datasource": "${DS_TEST-CLUSTER}", - "description": "The time consumed of write in range cache engine", + "description": "The handle duration of range eviction", "editable": true, "error": false, "fieldConfig": { @@ -37926,7 +38059,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 266, + "id": 267, "interval": null, "legend": { "show": false @@ -37943,7 +38076,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "expr": "sum(rate(\n tikv_range_eviction_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "format": "heatmap", "hide": false, "instant": false, @@ -37951,7 +38084,7 @@ "intervalFactor": 1, "legendFormat": "{{le}}", "metric": "", - "query": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "query": "sum(rate(\n tikv_range_eviction_duration_secs_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "refId": "", "step": 10, "target": "" @@ -37959,7 +38092,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Write duration", + "title": "Range Eviction Duration", "tooltip": { "msResolution": true, "shared": true, @@ -37996,7 +38129,7 @@ "bars": false, "cacheTimeout": null, "datasource": "${DS_TEST-CLUSTER}", - "description": "The time consumed of write in range cache engine per TiKV instance", + "description": "The count of range eviction per seconds", "editable": true, "error": false, "fieldConfig": { @@ -38023,7 +38156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 267, + "id": 268, "interval": null, "isNew": true, "legend": { @@ -38059,90 +38192,22 @@ "renderer": "flot", "repeat": null, "repeatDirection": null, - "seriesOverrides": [ - { - "alias": "count", - "bars": false, - "dashLength": 1, - "dashes": true, - "fill": 2, - "fillBelowTo": null, - "lines": true, - "spaceLength": 1, - "transform": "negative-Y", - "yaxis": 2, - "zindex": -3 - }, - { - "alias": "avg", - "bars": false, - "fill": 7, - "fillBelowTo": null, - "lines": true, - "yaxis": 1, - "zindex": 0 - } - ], + "seriesOverrides": [], "span": null, "stack": false, "steppedLine": false, "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "99.99%-{{instance}}", - "metric": "", - "query": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", - "refId": "", - "step": 10, - "target": "" - }, - { - "datasource": "${DS_TEST-CLUSTER}", - "expr": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "expr": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "format": "time_series", "hide": false, "instant": false, "interval": "", "intervalFactor": 1, - "legendFormat": "99%-{{instance}}", - "metric": "", - "query": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", - "refId": "", - "step": 10, - "target": "" - }, - { - "datasource": "${DS_TEST-CLUSTER}", - "expr": "(sum(rate(\n tikv_range_cache_engine_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", - "format": "time_series", - "hide": true, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "avg-{{instance}}", - "metric": "", - "query": "(sum(rate(\n tikv_range_cache_engine_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", - "refId": "", - "step": 10, - "target": "" - }, - { - "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", - "format": "time_series", - "hide": true, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "count-{{instance}}", + "legendFormat": "{{instance}}--loading2", "metric": "", - "query": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "query": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "refId": "", "step": 10, "target": "" @@ -38151,7 +38216,7 @@ "thresholds": [], "timeFrom": null, "timeShift": null, - "title": "99% Range cache engine write duration per server", + "title": "Range Eviction Count", "tooltip": { "msResolution": true, "shared": true, @@ -38170,7 +38235,7 @@ "yaxes": [ { "decimals": null, - "format": "s", + "format": "ops", "label": null, "logBase": 1, "max": null, @@ -38209,7 +38274,7 @@ }, "dataFormat": "tsbuckets", "datasource": "${DS_TEST-CLUSTER}", - "description": "The time consumed of prepare for write in range cache engine", + "description": "The time consumed of write in range cache engine", "editable": true, "error": false, "fieldConfig": { @@ -38231,7 +38296,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 268, + "id": 269, "interval": null, "legend": { "show": false @@ -38248,7 +38313,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "expr": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "format": "heatmap", "hide": false, "instant": false, @@ -38256,7 +38321,7 @@ "intervalFactor": 1, "legendFormat": "{{le}}", "metric": "", - "query": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "query": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", "refId": "", "step": 10, "target": "" @@ -38264,7 +38329,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Prepare for write duration", + "title": "Write duration", "tooltip": { "msResolution": true, "shared": true, @@ -38301,7 +38366,7 @@ "bars": false, "cacheTimeout": null, "datasource": "${DS_TEST-CLUSTER}", - "description": "The time consumed of prepare for write in range cache engine per TiKV instance", + "description": "The time consumed of write in range cache engine per TiKV instance", "editable": true, "error": false, "fieldConfig": { @@ -38328,7 +38393,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 269, + "id": 270, "interval": null, "isNew": true, "legend": { @@ -38394,7 +38459,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "expr": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", "format": "time_series", "hide": false, "instant": false, @@ -38402,14 +38467,14 @@ "intervalFactor": 1, "legendFormat": "99.99%-{{instance}}", "metric": "", - "query": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "query": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", "refId": "", "step": 10, "target": "" }, { "datasource": "${DS_TEST-CLUSTER}", - "expr": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "expr": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", "format": "time_series", "hide": false, "instant": false, @@ -38417,14 +38482,14 @@ "intervalFactor": 1, "legendFormat": "99%-{{instance}}", "metric": "", - "query": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "query": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", "refId": "", "step": 10, "target": "" }, { "datasource": "${DS_TEST-CLUSTER}", - "expr": "(sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", + "expr": "(sum(rate(\n tikv_range_cache_engine_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", "format": "time_series", "hide": true, "instant": false, @@ -38432,14 +38497,14 @@ "intervalFactor": 1, "legendFormat": "avg-{{instance}}", "metric": "", - "query": "(sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", + "query": "(sum(rate(\n tikv_range_cache_engine_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", "refId": "", "step": 10, "target": "" }, { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "expr": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "format": "time_series", "hide": true, "instant": false, @@ -38447,7 +38512,7 @@ "intervalFactor": 1, "legendFormat": "count-{{instance}}", "metric": "", - "query": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "query": "sum(rate(\n tikv_range_cache_engine_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "refId": "", "step": 10, "target": "" @@ -38456,7 +38521,312 @@ "thresholds": [], "timeFrom": null, "timeShift": null, - "title": "99% Range cache engine prepare for write duration per server", + "title": "99% Range cache engine write duration per server", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transformations": [], + "transparent": false, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": 0 + } + }, + { + "cacheTimeout": null, + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateSpectral", + "exponent": 0.5, + "max": null, + "min": null, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "${DS_TEST-CLUSTER}", + "description": "The time consumed of prepare for write in range cache engine", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [] + } + } + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 35 + }, + "heatmap": {}, + "height": null, + "hideTimeOverride": false, + "hideZeroBuckets": true, + "highlightCards": true, + "id": 271, + "interval": null, + "legend": { + "show": false + }, + "links": [], + "maxDataPoints": 512, + "maxPerRow": null, + "minSpan": null, + "options": {}, + "repeat": null, + "repeatDirection": null, + "reverseYBuckets": false, + "span": null, + "targets": [ + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "format": "heatmap", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{le}}", + "metric": "", + "query": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (le) ", + "refId": "", + "step": 10, + "target": "" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Prepare for write duration", + "tooltip": { + "msResolution": true, + "shared": true, + "showHistogram": true, + "sort": 0, + "value_type": "individual" + }, + "transformations": [], + "transparent": false, + "type": "heatmap", + "xAxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 1, + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + "yBucketBound": "upper", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The time consumed of prepare for write in range cache engine per TiKV instance", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [] + } + } + }, + "fill": 1, + "fillGradient": 1, + "grid": { + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 35 + }, + "height": null, + "hideTimeOverride": false, + "id": 272, + "interval": null, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxDataPoints": null, + "maxPerRow": null, + "minSpan": null, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true, + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": null, + "seriesOverrides": [ + { + "alias": "count", + "bars": false, + "dashLength": 1, + "dashes": true, + "fill": 2, + "fillBelowTo": null, + "lines": true, + "spaceLength": 1, + "transform": "negative-Y", + "yaxis": 2, + "zindex": -3 + }, + { + "alias": "avg", + "bars": false, + "fill": 7, + "fillBelowTo": null, + "lines": true, + "yaxis": 1, + "zindex": 0 + } + ], + "span": null, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "99.99%-{{instance}}", + "metric": "", + "query": "histogram_quantile(0.9999,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "refId": "", + "step": 10, + "target": "" + }, + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "99%-{{instance}}", + "metric": "", + "query": "histogram_quantile(0.99,(\n sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_bucket\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance, le) \n \n \n)) ", + "refId": "", + "step": 10, + "target": "" + }, + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "(sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", + "format": "time_series", + "hide": true, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "avg-{{instance}}", + "metric": "", + "query": "(sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_sum\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) / sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) )", + "refId": "", + "step": 10, + "target": "" + }, + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "format": "time_series", + "hide": true, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "count-{{instance}}", + "metric": "", + "query": "sum(rate(\n tikv_range_cache_engine_prepare_for_write_duration_seconds_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "refId": "", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "99% Range cache engine prepare for write duration per server", "tooltip": { "msResolution": true, "shared": true, @@ -38525,11 +38895,11 @@ "h": 7, "w": 12, "x": 0, - "y": 35 + "y": 42 }, "height": null, "hideTimeOverride": false, - "id": 270, + "id": 273, "interval": null, "isNew": true, "legend": { @@ -38733,11 +39103,11 @@ "h": 7, "w": 12, "x": 12, - "y": 35 + "y": 42 }, "height": null, "hideTimeOverride": false, - "id": 271, + "id": 274, "interval": null, "isNew": true, "legend": { @@ -38918,7 +39288,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 272, + "id": 275, "interval": null, "links": [], "maxDataPoints": 100, @@ -38957,7 +39327,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 273, + "id": 276, "interval": null, "isNew": true, "legend": { @@ -39105,7 +39475,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 274, + "id": 277, "interval": null, "isNew": true, "legend": { @@ -39245,7 +39615,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 275, + "id": 278, "interval": null, "legend": { "show": false @@ -39342,7 +39712,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 276, + "id": 279, "interval": null, "isNew": true, "legend": { @@ -39475,7 +39845,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 277, + "id": 280, "interval": null, "isNew": true, "legend": { @@ -39608,7 +39978,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 278, + "id": 281, "interval": null, "isNew": true, "legend": { @@ -39786,7 +40156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 279, + "id": 282, "interval": null, "isNew": true, "legend": { @@ -39949,7 +40319,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 280, + "id": 283, "interval": null, "isNew": true, "legend": { @@ -40097,7 +40467,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 281, + "id": 284, "interval": null, "isNew": true, "legend": { @@ -40230,7 +40600,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 282, + "id": 285, "interval": null, "isNew": true, "legend": { @@ -40366,7 +40736,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 283, + "id": 286, "interval": null, "links": [], "maxDataPoints": 100, @@ -40405,7 +40775,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 284, + "id": 287, "interval": null, "isNew": true, "legend": { @@ -40553,7 +40923,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 285, + "id": 288, "interval": null, "isNew": true, "legend": { @@ -40686,7 +41056,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 286, + "id": 289, "interval": null, "isNew": true, "legend": { @@ -40819,7 +41189,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 287, + "id": 290, "interval": null, "isNew": true, "legend": { @@ -40952,7 +41322,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 288, + "id": 291, "interval": null, "isNew": true, "legend": { @@ -41085,7 +41455,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 289, + "id": 292, "interval": null, "isNew": true, "legend": { @@ -41240,7 +41610,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 290, + "id": 293, "interval": null, "legend": { "show": false @@ -41340,7 +41710,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 291, + "id": 294, "interval": null, "links": [], "maxDataPoints": 100, @@ -41379,7 +41749,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 292, + "id": 295, "interval": null, "isNew": true, "legend": { @@ -41527,7 +41897,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 293, + "id": 296, "interval": null, "isNew": true, "legend": { @@ -41728,7 +42098,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 294, + "id": 297, "interval": null, "isNew": true, "legend": { @@ -41929,7 +42299,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 295, + "id": 298, "interval": null, "isNew": true, "legend": { @@ -42130,7 +42500,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 296, + "id": 299, "interval": null, "isNew": true, "legend": { @@ -42331,7 +42701,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 297, + "id": 300, "interval": null, "isNew": true, "legend": { @@ -42464,7 +42834,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 298, + "id": 301, "interval": null, "isNew": true, "legend": { @@ -42597,7 +42967,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 299, + "id": 302, "interval": null, "isNew": true, "legend": { @@ -42730,7 +43100,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 300, + "id": 303, "interval": null, "isNew": true, "legend": { @@ -42863,7 +43233,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 301, + "id": 304, "interval": null, "isNew": true, "legend": { @@ -43071,7 +43441,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 302, + "id": 305, "interval": null, "legend": { "show": false @@ -43171,7 +43541,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 303, + "id": 306, "interval": null, "links": [], "maxDataPoints": 100, @@ -43217,7 +43587,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 304, + "id": 307, "interval": null, "legend": { "show": false @@ -43314,7 +43684,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 305, + "id": 308, "interval": null, "isNew": true, "legend": { @@ -43515,7 +43885,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 306, + "id": 309, "interval": null, "isNew": true, "legend": { @@ -43648,7 +44018,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 307, + "id": 310, "interval": null, "isNew": true, "legend": { @@ -43781,7 +44151,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 308, + "id": 311, "interval": null, "isNew": true, "legend": { @@ -43914,7 +44284,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 309, + "id": 312, "interval": null, "isNew": true, "legend": { @@ -44115,7 +44485,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 310, + "id": 313, "interval": null, "isNew": true, "legend": { @@ -44248,7 +44618,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 311, + "id": 314, "interval": null, "isNew": true, "legend": { @@ -44381,7 +44751,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 312, + "id": 315, "interval": null, "isNew": true, "legend": { @@ -44517,7 +44887,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 313, + "id": 316, "interval": null, "links": [], "maxDataPoints": 100, @@ -44556,7 +44926,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 314, + "id": 317, "interval": null, "isNew": true, "legend": { @@ -44757,7 +45127,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 315, + "id": 318, "interval": null, "isNew": true, "legend": { @@ -44958,7 +45328,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 316, + "id": 319, "interval": null, "isNew": true, "legend": { @@ -45159,7 +45529,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 317, + "id": 320, "interval": null, "isNew": true, "legend": { @@ -45360,7 +45730,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 318, + "id": 321, "interval": null, "isNew": true, "legend": { @@ -45493,7 +45863,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 319, + "id": 322, "interval": null, "isNew": true, "legend": { @@ -45626,7 +45996,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 320, + "id": 323, "interval": null, "isNew": true, "legend": { @@ -45759,7 +46129,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 321, + "id": 324, "interval": null, "isNew": true, "legend": { @@ -45892,7 +46262,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 322, + "id": 325, "interval": null, "isNew": true, "legend": { @@ -46025,7 +46395,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 323, + "id": 326, "interval": null, "isNew": true, "legend": { @@ -46165,7 +46535,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 324, + "id": 327, "interval": null, "legend": { "show": false @@ -46262,7 +46632,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 325, + "id": 328, "interval": null, "isNew": true, "legend": { @@ -46466,7 +46836,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 326, + "id": 329, "interval": null, "links": [], "maxDataPoints": 100, @@ -46505,7 +46875,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 327, + "id": 330, "interval": null, "isNew": true, "legend": { @@ -46638,7 +47008,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 328, + "id": 331, "interval": null, "isNew": true, "legend": { @@ -46771,7 +47141,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 329, + "id": 332, "interval": null, "isNew": true, "legend": { @@ -46911,7 +47281,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 330, + "id": 333, "interval": null, "legend": { "show": false @@ -47008,7 +47378,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 331, + "id": 334, "interval": null, "isNew": true, "legend": { @@ -47209,7 +47579,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 332, + "id": 335, "interval": null, "isNew": true, "legend": { @@ -47410,7 +47780,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 333, + "id": 336, "interval": null, "isNew": true, "legend": { @@ -47614,7 +47984,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 334, + "id": 337, "interval": null, "links": [], "maxDataPoints": 100, @@ -47653,7 +48023,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 335, + "id": 338, "interval": null, "isNew": true, "legend": { @@ -47831,7 +48201,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 336, + "id": 339, "interval": null, "isNew": true, "legend": { @@ -48032,7 +48402,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 337, + "id": 340, "interval": null, "isNew": true, "legend": { @@ -48165,7 +48535,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 338, + "id": 341, "interval": null, "isNew": true, "legend": { @@ -48298,7 +48668,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 339, + "id": 342, "interval": null, "isNew": true, "legend": { @@ -48431,7 +48801,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 340, + "id": 343, "interval": null, "isNew": true, "legend": { @@ -48564,7 +48934,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 341, + "id": 344, "interval": null, "isNew": true, "legend": { @@ -48697,7 +49067,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 342, + "id": 345, "interval": null, "isNew": true, "legend": { @@ -48826,7 +49196,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 343, + "id": 346, "interval": null, "links": [], "maxDataPoints": 100, @@ -48901,7 +49271,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 344, + "id": 347, "interval": null, "links": [], "maxDataPoints": 100, @@ -48980,7 +49350,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 345, + "id": 348, "interval": null, "isNew": true, "legend": { @@ -49233,7 +49603,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 346, + "id": 349, "interval": null, "isNew": true, "legend": { @@ -49366,7 +49736,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 347, + "id": 350, "interval": null, "isNew": true, "legend": { @@ -49502,7 +49872,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 348, + "id": 351, "interval": null, "links": [], "maxDataPoints": 100, @@ -49541,7 +49911,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 349, + "id": 352, "interval": null, "isNew": true, "legend": { @@ -49689,7 +50059,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 350, + "id": 353, "interval": null, "isNew": true, "legend": { @@ -49822,7 +50192,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 351, + "id": 354, "interval": null, "isNew": true, "legend": { @@ -50023,7 +50393,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 352, + "id": 355, "interval": null, "isNew": true, "legend": { @@ -50171,7 +50541,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 353, + "id": 356, "interval": null, "isNew": true, "legend": { @@ -50372,7 +50742,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 354, + "id": 357, "interval": null, "isNew": true, "legend": { @@ -50505,7 +50875,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 355, + "id": 358, "interval": null, "isNew": true, "legend": { @@ -50638,7 +51008,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 356, + "id": 359, "interval": null, "isNew": true, "legend": { @@ -50771,7 +51141,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 357, + "id": 360, "interval": null, "isNew": true, "legend": { @@ -50904,7 +51274,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 358, + "id": 361, "interval": null, "isNew": true, "legend": { @@ -51044,7 +51414,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 359, + "id": 362, "interval": null, "legend": { "show": false @@ -51141,7 +51511,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 360, + "id": 363, "interval": null, "isNew": true, "legend": { @@ -51345,7 +51715,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 361, + "id": 364, "interval": null, "links": [], "maxDataPoints": 100, @@ -51384,7 +51754,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 362, + "id": 365, "interval": null, "isNew": true, "legend": { @@ -51517,7 +51887,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 363, + "id": 366, "interval": null, "isNew": true, "legend": { @@ -51650,7 +52020,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 364, + "id": 367, "interval": null, "isNew": true, "legend": { @@ -51783,7 +52153,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 365, + "id": 368, "interval": null, "isNew": true, "legend": { @@ -51919,7 +52289,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 366, + "id": 369, "interval": null, "links": [], "maxDataPoints": 100, @@ -51958,7 +52328,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 367, + "id": 370, "interval": null, "isNew": true, "legend": { @@ -52091,7 +52461,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 368, + "id": 371, "interval": null, "isNew": true, "legend": { @@ -52224,7 +52594,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 369, + "id": 372, "interval": null, "isNew": true, "legend": { @@ -52372,7 +52742,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 370, + "id": 373, "interval": null, "isNew": true, "legend": { @@ -52505,7 +52875,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 371, + "id": 374, "interval": null, "isNew": true, "legend": { @@ -52638,7 +53008,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 372, + "id": 375, "interval": null, "isNew": true, "legend": { @@ -52771,7 +53141,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 373, + "id": 376, "interval": null, "isNew": true, "legend": { @@ -52907,7 +53277,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 374, + "id": 377, "interval": null, "links": [], "maxDataPoints": 100, @@ -52946,7 +53316,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 375, + "id": 378, "interval": null, "isNew": true, "legend": { @@ -53079,7 +53449,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 376, + "id": 379, "interval": null, "isNew": true, "legend": { @@ -53212,7 +53582,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 377, + "id": 380, "interval": null, "isNew": true, "legend": { @@ -53345,7 +53715,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 378, + "id": 381, "interval": null, "isNew": true, "legend": { @@ -53478,7 +53848,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 379, + "id": 382, "interval": null, "isNew": true, "legend": { @@ -53611,7 +53981,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 380, + "id": 383, "interval": null, "isNew": true, "legend": { @@ -53747,7 +54117,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 381, + "id": 384, "interval": null, "links": [], "maxDataPoints": 100, @@ -53786,7 +54156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 382, + "id": 385, "interval": null, "isNew": true, "legend": { @@ -53919,7 +54289,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 383, + "id": 386, "interval": null, "isNew": true, "legend": { @@ -54052,7 +54422,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 384, + "id": 387, "interval": null, "isNew": true, "legend": { @@ -54200,7 +54570,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 385, + "id": 388, "interval": null, "isNew": true, "legend": { @@ -54363,7 +54733,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 386, + "id": 389, "interval": null, "isNew": true, "legend": { @@ -54496,7 +54866,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 387, + "id": 390, "interval": null, "isNew": true, "legend": { @@ -54629,7 +54999,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 388, + "id": 391, "interval": null, "isNew": true, "legend": { @@ -54777,7 +55147,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 389, + "id": 392, "interval": null, "isNew": true, "legend": { @@ -54925,7 +55295,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 390, + "id": 393, "interval": null, "isNew": true, "legend": { @@ -55061,7 +55431,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 391, + "id": 394, "interval": null, "links": [], "maxDataPoints": 100, @@ -55100,7 +55470,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 392, + "id": 395, "interval": null, "isNew": true, "legend": { @@ -55233,7 +55603,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 393, + "id": 396, "interval": null, "isNew": true, "legend": { @@ -55366,7 +55736,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 394, + "id": 397, "interval": null, "isNew": true, "legend": { @@ -55499,7 +55869,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 395, + "id": 398, "interval": null, "isNew": true, "legend": { @@ -55632,7 +56002,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 396, + "id": 399, "interval": null, "isNew": true, "legend": { @@ -55765,7 +56135,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 397, + "id": 400, "interval": null, "isNew": true, "legend": { @@ -55898,7 +56268,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 398, + "id": 401, "interval": null, "isNew": true, "legend": { @@ -56031,7 +56401,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 399, + "id": 402, "interval": null, "isNew": true, "legend": { @@ -56164,7 +56534,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 400, + "id": 403, "interval": null, "isNew": true, "legend": { @@ -56304,7 +56674,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 401, + "id": 404, "interval": null, "legend": { "show": false @@ -56401,7 +56771,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 402, + "id": 405, "interval": null, "isNew": true, "legend": { @@ -56534,7 +56904,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 403, + "id": 406, "interval": null, "isNew": true, "legend": { @@ -56682,7 +57052,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 404, + "id": 407, "interval": null, "isNew": true, "legend": { @@ -56830,7 +57200,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 405, + "id": 408, "interval": null, "isNew": true, "legend": { @@ -56970,7 +57340,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 406, + "id": 409, "interval": null, "legend": { "show": false @@ -57067,7 +57437,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 407, + "id": 410, "interval": null, "isNew": true, "legend": { @@ -57200,7 +57570,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 408, + "id": 411, "interval": null, "isNew": true, "legend": { @@ -57336,7 +57706,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 409, + "id": 412, "interval": null, "links": [], "maxDataPoints": 100, @@ -57375,7 +57745,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 410, + "id": 413, "interval": null, "isNew": true, "legend": { @@ -57508,7 +57878,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 411, + "id": 414, "interval": null, "isNew": true, "legend": { @@ -57671,7 +58041,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 412, + "id": 415, "interval": null, "isNew": true, "legend": { @@ -57819,7 +58189,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 413, + "id": 416, "interval": null, "isNew": true, "legend": { @@ -57952,7 +58322,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 414, + "id": 417, "interval": null, "isNew": true, "legend": { @@ -58092,7 +58462,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 415, + "id": 418, "interval": null, "legend": { "show": false @@ -58196,7 +58566,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 416, + "id": 419, "interval": null, "legend": { "show": false @@ -58300,7 +58670,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 417, + "id": 420, "interval": null, "legend": { "show": false @@ -58397,7 +58767,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 418, + "id": 421, "interval": null, "isNew": true, "legend": { @@ -58537,7 +58907,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 419, + "id": 422, "interval": null, "legend": { "show": false @@ -58641,7 +59011,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 420, + "id": 423, "interval": null, "legend": { "show": false @@ -58745,7 +59115,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 421, + "id": 424, "interval": null, "legend": { "show": false @@ -58842,7 +59212,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 422, + "id": 425, "interval": null, "isNew": true, "legend": { @@ -58975,7 +59345,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 423, + "id": 426, "interval": null, "isNew": true, "legend": { @@ -59108,7 +59478,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 424, + "id": 427, "interval": null, "isNew": true, "legend": { @@ -59248,7 +59618,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 425, + "id": 428, "interval": null, "legend": { "show": false @@ -59345,7 +59715,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 426, + "id": 429, "interval": null, "isNew": true, "legend": { @@ -59481,7 +59851,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 427, + "id": 430, "interval": null, "links": [], "maxDataPoints": 100, @@ -59520,7 +59890,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 428, + "id": 431, "interval": null, "isNew": true, "legend": { @@ -59683,7 +60053,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 429, + "id": 432, "interval": null, "isNew": true, "legend": { @@ -59816,7 +60186,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 430, + "id": 433, "interval": null, "isNew": true, "legend": { @@ -59956,7 +60326,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 431, + "id": 434, "interval": null, "legend": { "show": false @@ -60060,7 +60430,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 432, + "id": 435, "interval": null, "legend": { "show": false @@ -60157,7 +60527,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 433, + "id": 436, "interval": null, "isNew": true, "legend": { @@ -60312,7 +60682,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 434, + "id": 437, "interval": null, "legend": { "show": false @@ -60416,7 +60786,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 435, + "id": 438, "interval": null, "legend": { "show": false @@ -60520,7 +60890,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 436, + "id": 439, "interval": null, "legend": { "show": false @@ -60617,7 +60987,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 437, + "id": 440, "interval": null, "isNew": true, "legend": { @@ -60787,7 +61157,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 438, + "id": 441, "interval": null, "legend": { "show": false @@ -60884,7 +61254,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 439, + "id": 442, "interval": null, "isNew": true, "legend": { @@ -61085,7 +61455,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 440, + "id": 443, "interval": null, "isNew": true, "legend": { @@ -61286,7 +61656,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 441, + "id": 444, "interval": null, "isNew": true, "legend": { @@ -61419,7 +61789,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 442, + "id": 445, "interval": null, "isNew": true, "legend": { @@ -61582,7 +61952,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 443, + "id": 446, "interval": null, "isNew": true, "legend": { @@ -61715,7 +62085,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 444, + "id": 447, "interval": null, "isNew": true, "legend": { @@ -61848,7 +62218,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 445, + "id": 448, "interval": null, "isNew": true, "legend": { @@ -62049,7 +62419,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 446, + "id": 449, "interval": null, "isNew": true, "legend": { @@ -62182,7 +62552,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 447, + "id": 450, "interval": null, "isNew": true, "legend": { @@ -62322,7 +62692,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 448, + "id": 451, "interval": null, "legend": { "show": false @@ -62426,7 +62796,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 449, + "id": 452, "interval": null, "legend": { "show": false @@ -62530,7 +62900,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 450, + "id": 453, "interval": null, "legend": { "show": false @@ -62634,7 +63004,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 451, + "id": 454, "interval": null, "legend": { "show": false @@ -62738,7 +63108,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 452, + "id": 455, "interval": null, "legend": { "show": false @@ -62842,7 +63212,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 453, + "id": 456, "interval": null, "legend": { "show": false @@ -62946,7 +63316,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 454, + "id": 457, "interval": null, "legend": { "show": false @@ -63043,7 +63413,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 455, + "id": 458, "interval": null, "isNew": true, "legend": { @@ -63191,7 +63561,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 456, + "id": 459, "interval": null, "isNew": true, "legend": { @@ -63324,7 +63694,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 457, + "id": 460, "interval": null, "isNew": true, "legend": { @@ -63457,7 +63827,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 458, + "id": 461, "interval": null, "isNew": true, "legend": { @@ -63605,7 +63975,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 459, + "id": 462, "interval": null, "isNew": true, "legend": { @@ -63741,7 +64111,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 460, + "id": 463, "interval": null, "links": [], "maxDataPoints": 100, @@ -63792,7 +64162,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 461, + "id": 464, "interval": null, "links": [], "maxDataPoints": 100, @@ -63888,7 +64258,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 462, + "id": 465, "interval": null, "links": [], "maxDataPoints": 100, @@ -63963,7 +64333,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 463, + "id": 466, "interval": null, "links": [], "maxDataPoints": 100, @@ -64038,7 +64408,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 464, + "id": 467, "interval": null, "links": [], "maxDataPoints": 100, @@ -64113,7 +64483,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 465, + "id": 468, "interval": null, "links": [], "maxDataPoints": 100, @@ -64188,7 +64558,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 466, + "id": 469, "interval": null, "links": [], "maxDataPoints": 100, @@ -64263,7 +64633,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 467, + "id": 470, "interval": null, "links": [], "maxDataPoints": 100, @@ -64338,7 +64708,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 468, + "id": 471, "interval": null, "links": [], "maxDataPoints": 100, @@ -64417,7 +64787,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 469, + "id": 472, "interval": null, "isNew": true, "legend": { @@ -64550,7 +64920,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 470, + "id": 473, "interval": null, "isNew": true, "legend": { @@ -64683,7 +65053,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 471, + "id": 474, "interval": null, "isNew": true, "legend": { @@ -64816,7 +65186,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 472, + "id": 475, "interval": null, "isNew": true, "legend": { @@ -64949,7 +65319,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 473, + "id": 476, "interval": null, "isNew": true, "legend": { @@ -65082,7 +65452,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 474, + "id": 477, "interval": null, "isNew": true, "legend": { @@ -65230,7 +65600,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 475, + "id": 478, "interval": null, "isNew": true, "legend": { @@ -65363,7 +65733,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 476, + "id": 479, "interval": null, "isNew": true, "legend": { @@ -65496,7 +65866,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 477, + "id": 480, "interval": null, "isNew": true, "legend": { @@ -65662,7 +66032,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 478, + "id": 481, "interval": null, "legend": { "show": false @@ -65766,7 +66136,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 479, + "id": 482, "interval": null, "legend": { "show": false @@ -65870,7 +66240,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 480, + "id": 483, "interval": null, "legend": { "show": false @@ -65974,7 +66344,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 481, + "id": 484, "interval": null, "legend": { "show": false @@ -66078,7 +66448,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 482, + "id": 485, "interval": null, "legend": { "show": false @@ -66182,7 +66552,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 483, + "id": 486, "interval": null, "legend": { "show": false @@ -66286,7 +66656,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 484, + "id": 487, "interval": null, "legend": { "show": false @@ -66390,7 +66760,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 485, + "id": 488, "interval": null, "legend": { "show": false @@ -66487,7 +66857,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 486, + "id": 489, "interval": null, "isNew": true, "legend": { @@ -66620,7 +66990,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 487, + "id": 490, "interval": null, "isNew": true, "legend": { @@ -66753,7 +67123,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 488, + "id": 491, "interval": null, "isNew": true, "legend": { @@ -66886,7 +67256,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 489, + "id": 492, "interval": null, "isNew": true, "legend": { @@ -67019,7 +67389,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 490, + "id": 493, "interval": null, "isNew": true, "legend": { @@ -67152,7 +67522,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 491, + "id": 494, "interval": null, "isNew": true, "legend": { @@ -67285,7 +67655,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 492, + "id": 495, "interval": null, "isNew": true, "legend": { @@ -67418,7 +67788,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 493, + "id": 496, "interval": null, "isNew": true, "legend": { @@ -67558,7 +67928,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 494, + "id": 497, "interval": null, "legend": { "show": false @@ -67662,7 +68032,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 495, + "id": 498, "interval": null, "legend": { "show": false @@ -67759,7 +68129,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 496, + "id": 499, "interval": null, "isNew": true, "legend": { @@ -67892,7 +68262,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 497, + "id": 500, "interval": null, "isNew": true, "legend": { @@ -68025,7 +68395,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 498, + "id": 501, "interval": null, "isNew": true, "legend": { @@ -68158,7 +68528,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 499, + "id": 502, "interval": null, "isNew": true, "legend": { @@ -68291,7 +68661,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 500, + "id": 503, "interval": null, "isNew": true, "legend": { @@ -68424,7 +68794,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 501, + "id": 504, "interval": null, "isNew": true, "legend": { @@ -68560,7 +68930,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 502, + "id": 505, "interval": null, "links": [], "maxDataPoints": 100, @@ -68599,7 +68969,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 503, + "id": 506, "interval": null, "isNew": true, "legend": { @@ -68747,7 +69117,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 504, + "id": 507, "interval": null, "isNew": true, "legend": { @@ -68880,7 +69250,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 505, + "id": 508, "interval": null, "isNew": true, "legend": { @@ -69013,7 +69383,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 506, + "id": 509, "interval": null, "isNew": true, "legend": { @@ -69149,7 +69519,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 507, + "id": 510, "interval": null, "links": [], "maxDataPoints": 100, @@ -69188,7 +69558,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 508, + "id": 511, "interval": null, "isNew": true, "legend": { @@ -69321,7 +69691,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 509, + "id": 512, "interval": null, "isNew": true, "legend": { @@ -69454,7 +69824,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 510, + "id": 513, "interval": null, "isNew": true, "legend": { @@ -69587,7 +69957,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 511, + "id": 514, "interval": null, "isNew": true, "legend": { @@ -69720,7 +70090,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 512, + "id": 515, "interval": null, "isNew": true, "legend": { @@ -69853,7 +70223,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 513, + "id": 516, "interval": null, "isNew": true, "legend": { @@ -69989,7 +70359,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 514, + "id": 517, "interval": null, "links": [], "maxDataPoints": 100, @@ -70028,7 +70398,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 515, + "id": 518, "interval": null, "isNew": true, "legend": { @@ -70229,7 +70599,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 516, + "id": 519, "interval": null, "isNew": true, "legend": { @@ -70365,7 +70735,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 517, + "id": 520, "interval": null, "links": [], "maxDataPoints": 100, @@ -70404,7 +70774,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 518, + "id": 521, "interval": null, "isNew": true, "legend": { @@ -70537,7 +70907,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 519, + "id": 522, "interval": null, "isNew": true, "legend": { @@ -70670,7 +71040,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 520, + "id": 523, "interval": null, "isNew": true, "legend": { @@ -70803,7 +71173,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 521, + "id": 524, "interval": null, "isNew": true, "legend": { @@ -70936,7 +71306,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 522, + "id": 525, "interval": null, "isNew": true, "legend": { @@ -71084,7 +71454,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 523, + "id": 526, "interval": null, "isNew": true, "legend": { @@ -71288,7 +71658,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 524, + "id": 527, "interval": null, "links": [], "maxDataPoints": 100, @@ -71327,7 +71697,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 525, + "id": 528, "interval": null, "isNew": true, "legend": { @@ -71460,7 +71830,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 526, + "id": 529, "interval": null, "isNew": true, "legend": { @@ -71593,7 +71963,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 527, + "id": 530, "interval": null, "isNew": true, "legend": { @@ -71726,7 +72096,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 528, + "id": 531, "interval": null, "isNew": true, "legend": { @@ -71859,7 +72229,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 529, + "id": 532, "interval": null, "isNew": true, "legend": { @@ -72056,7 +72426,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 530, + "id": 533, "interval": null, "links": [], "maxDataPoints": 100, diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index 2cb20d444a4..db599173fe6 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -4a5b360a219dfd53a3589809cd51bd94afe5333dcf9b3388b2b460fed58c4b7d ./metrics/grafana/tikv_details.json +1c5a149c9ff8753b505e48e5ad0d1a6008eb36820b0a512ef8c8a550a08106cf ./metrics/grafana/tikv_details.json From b700fbaaf8747e634b12089849212ff58abf2f08 Mon Sep 17 00:00:00 2001 From: cfzjywxk Date: Tue, 30 Jul 2024 14:56:48 +0800 Subject: [PATCH 012/144] txn: refactor scheduler and add more information for error type (#17297) ref tikv/tikv#14474 1. Refactor the `ProcessWrite` function in the transaction scheduler. 2. Add `start_ts` information to the `AlreadyExist` error types, so it would be easier to know the conflict write record and related transactions. 3. Abstract memory quota count into task allocation, ensure the re-scheduled commands and tasks are considered by the memory quota statistics. Signed-off-by: cfzjywxk --- components/tikv_util/src/memory.rs | 4 + components/tracker/src/lib.rs | 8 +- src/storage/errors.rs | 2 +- src/storage/lock_manager/lock_wait_context.rs | 10 + src/storage/mvcc/mod.rs | 17 +- src/storage/mvcc/txn.rs | 1 + .../txn/actions/check_data_constraint.rs | 34 +- src/storage/txn/actions/prewrite.rs | 1 + src/storage/txn/commands/flush.rs | 6 +- src/storage/txn/commands/mod.rs | 31 +- src/storage/txn/scheduler.rs | 440 +++++++++++------- src/storage/txn/task.rs | 69 +-- 12 files changed, 422 insertions(+), 201 deletions(-) diff --git a/components/tikv_util/src/memory.rs b/components/tikv_util/src/memory.rs index 4be0e657589..6e2e933d762 100644 --- a/components/tikv_util/src/memory.rs +++ b/components/tikv_util/src/memory.rs @@ -181,6 +181,7 @@ impl std::error::Error for MemoryQuotaExceeded {} impl_display_as_debug!(MemoryQuotaExceeded); +#[derive(Debug)] pub struct MemoryQuota { // We suppose the memory quota should not exceed the upper bound of `isize`. // As we don't support 32bit(or lower) arch, this won't be a problem. @@ -188,6 +189,9 @@ pub struct MemoryQuota { capacity: AtomicUsize, } +#[derive(Debug)] +/// OwnedAllocated should not be cloned, the counted memory is freed when its +/// owner is dropped. pub struct OwnedAllocated { allocated: usize, from: Arc, diff --git a/components/tracker/src/lib.rs b/components/tracker/src/lib.rs index b80ebe52eed..db748c94d4b 100644 --- a/components/tracker/src/lib.rs +++ b/components/tracker/src/lib.rs @@ -85,13 +85,17 @@ impl Tracker { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct RequestInfo { pub region_id: u64, pub start_ts: u64, pub task_id: u64, pub resource_group_tag: Vec, + + // Information recorded after the task is scheduled. pub request_type: RequestType, + pub cid: u64, + pub is_external_req: bool, } impl RequestInfo { @@ -102,6 +106,8 @@ impl RequestInfo { task_id: ctx.get_task_id(), resource_group_tag: ctx.get_resource_group_tag().to_vec(), request_type, + cid: 0, + is_external_req: ctx.get_request_source().starts_with("external"), } } } diff --git a/src/storage/errors.rs b/src/storage/errors.rs index 0cd14d7ff8a..02888cc93e8 100644 --- a/src/storage/errors.rs +++ b/src/storage/errors.rs @@ -385,7 +385,7 @@ pub fn extract_key_error(err: &Error) -> kvrpcpb::KeyError { key_error.set_retryable(format!("{:?}", err)); } Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(MvccError( - box MvccErrorInner::AlreadyExist { key }, + box MvccErrorInner::AlreadyExist { key, .. }, ))))) => { let mut exist = kvrpcpb::AlreadyExist::default(); exist.set_key(key.clone()); diff --git a/src/storage/lock_manager/lock_wait_context.rs b/src/storage/lock_manager/lock_wait_context.rs index 1eba8cd81b7..2677aee9a33 100644 --- a/src/storage/lock_manager/lock_wait_context.rs +++ b/src/storage/lock_manager/lock_wait_context.rs @@ -175,6 +175,16 @@ impl LockWaitContextSharedState { } } +impl std::fmt::Debug for LockWaitContextSharedState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("LockWaitContextSharedState") + .field("lock_wait_token", &self.lock_wait_token) + .field("key", &self.key) + .field("is_canceled", &self.is_canceled) + .finish() + } +} + enum FinishRequestKind { Executed, Canceled, diff --git a/src/storage/mvcc/mod.rs b/src/storage/mvcc/mod.rs index 70f59bf7999..30e20a2afc6 100644 --- a/src/storage/mvcc/mod.rs +++ b/src/storage/mvcc/mod.rs @@ -110,8 +110,13 @@ pub enum ErrorInner { wait_chain: Vec, }, - #[error("key {} already exists", log_wrappers::Value::key(.key))] - AlreadyExist { key: Vec }, + #[error( + "key {} already exists with existing_start_ts={}", log_wrappers::Value::key(.key), + .existing_start_ts)] + AlreadyExist { + key: Vec, + existing_start_ts: TimeStamp, + }, #[error( "default not found: key:{}, maybe read truncated/dropped table data?", @@ -238,7 +243,13 @@ impl ErrorInner { deadlock_key_hash: *deadlock_key_hash, wait_chain: wait_chain.clone(), }), - ErrorInner::AlreadyExist { key } => Some(ErrorInner::AlreadyExist { key: key.clone() }), + ErrorInner::AlreadyExist { + key, + existing_start_ts, + } => Some(ErrorInner::AlreadyExist { + key: key.clone(), + existing_start_ts: *existing_start_ts, + }), ErrorInner::DefaultNotFound { key } => Some(ErrorInner::DefaultNotFound { key: key.to_owned(), }), diff --git a/src/storage/mvcc/txn.rs b/src/storage/mvcc/txn.rs index 08f72bf777a..7a9a4b82663 100644 --- a/src/storage/mvcc/txn.rs +++ b/src/storage/mvcc/txn.rs @@ -296,6 +296,7 @@ pub(crate) fn make_txn_error( }, "alreadyexist" => ErrorInner::AlreadyExist { key: key.to_raw().unwrap(), + existing_start_ts: start_ts, }, "committsexpired" => ErrorInner::CommitTsExpired { start_ts, diff --git a/src/storage/txn/actions/check_data_constraint.rs b/src/storage/txn/actions/check_data_constraint.rs index d90a95a24ab..9be878df2ee 100644 --- a/src/storage/txn/actions/check_data_constraint.rs +++ b/src/storage/txn/actions/check_data_constraint.rs @@ -31,8 +31,20 @@ pub(crate) fn check_data_constraint( // 1.The current write type is `PUT` // 2.The current write type is `Rollback` or `Lock`, and the key have an older // version. - if write.write_type == WriteType::Put || reader.key_exist(key, write_commit_ts.prev())? { - return Err(ErrorInner::AlreadyExist { key: key.to_raw()? }.into()); + let existing_start_ts = if write.write_type == WriteType::Put { + Some(write.start_ts) + } else if let Some(prev_write) = reader.get_write(key, write_commit_ts.prev())? { + Some(prev_write.start_ts) + } else { + None + }; + + if let Some(existing_start_ts) = existing_start_ts { + return Err(ErrorInner::AlreadyExist { + key: key.to_raw()?, + existing_start_ts, + } + .into()); } Ok(()) } @@ -93,7 +105,11 @@ mod tests { }, Case { // should detect conflict `Put` - expected: Err(ErrorInner::AlreadyExist { key: b"a".to_vec() }.into()), + expected: Err(ErrorInner::AlreadyExist { + key: b"a".to_vec(), + existing_start_ts: TimeStamp::new(3), + } + .into()), should_not_exist: true, write: Write::new(WriteType::Put, TimeStamp::new(3), None), write_commit_ts: Default::default(), @@ -101,7 +117,11 @@ mod tests { }, Case { // should detect an older version when the current write type is `Rollback` - expected: Err(ErrorInner::AlreadyExist { key: b"a".to_vec() }.into()), + expected: Err(ErrorInner::AlreadyExist { + key: b"a".to_vec(), + existing_start_ts: TimeStamp::new(2), + } + .into()), should_not_exist: true, write: Write::new(WriteType::Rollback, TimeStamp::new(3), None), write_commit_ts: TimeStamp::new(6), @@ -109,7 +129,11 @@ mod tests { }, Case { // should detect an older version when the current write type is `Lock` - expected: Err(ErrorInner::AlreadyExist { key: b"a".to_vec() }.into()), + expected: Err(ErrorInner::AlreadyExist { + key: b"a".to_vec(), + existing_start_ts: TimeStamp::new(2), + } + .into()), should_not_exist: true, write: Write::new(WriteType::Lock, TimeStamp::new(10), None), write_commit_ts: TimeStamp::new(15), diff --git a/src/storage/txn/actions/prewrite.rs b/src/storage/txn/actions/prewrite.rs index f446ac01dbf..6c21de599bc 100644 --- a/src/storage/txn/actions/prewrite.rs +++ b/src/storage/txn/actions/prewrite.rs @@ -462,6 +462,7 @@ impl<'a> PrewriteMutation<'a> { if lock.generation > 0 && self.should_not_exist && matches!(lock.lock_type, LockType::Put) { return Err(ErrorInner::AlreadyExist { key: self.key.to_raw()?, + existing_start_ts: lock.ts, } .into()); } diff --git a/src/storage/txn/commands/flush.rs b/src/storage/txn/commands/flush.rs index abeb91a91e8..63c05385a30 100644 --- a/src/storage/txn/commands/flush.rs +++ b/src/storage/txn/commands/flush.rs @@ -469,12 +469,14 @@ mod tests { must_locked(&mut engine, k, 1); assert_matches!( must_flush_insert_err(&mut engine, k, *v, k, 1, 2), - Error(box ErrorInner::Mvcc(MvccError(box MvccErrorInner::AlreadyExist { key }))) if key == k + Error(box ErrorInner::Mvcc(MvccError(box MvccErrorInner::AlreadyExist { key, existing_start_ts}))) + if key == k && existing_start_ts == 1.into() ); must_commit(&mut engine, k, 1, 2); assert_matches!( must_flush_insert_err(&mut engine, k, *v, k, 3, 1), - Error(box ErrorInner::Mvcc(MvccError(box MvccErrorInner::AlreadyExist { key }))) if key == k + Error(box ErrorInner::Mvcc(MvccError(box MvccErrorInner::AlreadyExist { key, existing_start_ts}))) + if key == k && existing_start_ts == 1.into() ); } diff --git a/src/storage/txn/commands/mod.rs b/src/storage/txn/commands/mod.rs index aad792dabc8..5ff54b334cb 100644 --- a/src/storage/txn/commands/mod.rs +++ b/src/storage/txn/commands/mod.rs @@ -463,6 +463,35 @@ pub struct WriteResult { pub known_txn_status: Vec<(TimeStamp, TimeStamp)>, } +impl WriteResult { + pub fn new( + ctx: Context, + to_be_write: WriteData, + rows: usize, + pr: ProcessResult, + lock_info: Vec, + released_locks: ReleasedLocks, + new_acquired_locks: Vec, + lock_guards: Vec, + response_policy: ResponsePolicy, + known_txn_status: Vec<(TimeStamp, TimeStamp)>, + ) -> Self { + Self { + ctx, + to_be_write, + rows, + pr, + lock_info, + released_locks, + new_acquired_locks, + lock_guards, + response_policy, + known_txn_status, + } + } +} + +#[derive(Debug)] pub struct WriteResultLockInfo { pub lock_digest: lock_manager::LockDigest, pub key: Key, @@ -504,7 +533,7 @@ impl WriteResultLockInfo { } } -#[derive(Default)] +#[derive(Default, Debug)] pub struct ReleasedLocks(Vec); impl ReleasedLocks { diff --git a/src/storage/txn/scheduler.rs b/src/storage/txn/scheduler.rs index 25f47ff4481..cf75a0fed54 100644 --- a/src/storage/txn/scheduler.rs +++ b/src/storage/txn/scheduler.rs @@ -179,7 +179,7 @@ impl TaskContext { fn on_schedule(&mut self) { let elapsed = self.latch_timer.saturating_elapsed(); if let Some(task) = &self.task.as_ref() { - GLOBAL_TRACKERS.with_tracker(task.tracker(), |tracker| { + GLOBAL_TRACKERS.with_tracker(task.tracker_token(), |tracker| { tracker.metrics.latch_wait_nanos = elapsed.as_nanos() as u64; }); } @@ -233,6 +233,12 @@ impl SchedulerTaskCallback { } } +impl From for SchedulerTaskCallback { + fn from(cb: StorageCallback) -> Self { + Self::NormalRequestCallback(cb) + } +} + struct TxnSchedulerInner { // slot_id -> { cid -> `TaskContext` } in the slot. task_slots: Vec>>>, @@ -508,37 +514,34 @@ impl TxnScheduler { self.inner.memory_quota.set_capacity(cap) } + fn fail_with_busy(tag: CommandKind, callback: SchedulerTaskCallback) { + SCHED_TOO_BUSY_COUNTER_VEC.get(tag).inc(); + callback.execute(ProcessResult::Failed { + err: StorageError::from(StorageErrorInner::SchedTooBusy), + }); + } + pub(in crate::storage) fn run_cmd(&self, cmd: Command, callback: StorageCallback) { let tag = cmd.tag(); - let fail_with_busy = |callback: StorageCallback| { - SCHED_TOO_BUSY_COUNTER_VEC.get(tag).inc(); - callback.execute(ProcessResult::Failed { - err: StorageError::from(StorageErrorInner::SchedTooBusy), - }); - }; // write flow control // // TODO: Consider deprecating this write flow control. Reasons being: // 1) The flow_controller accomplishes the same task, and // 2) The "admission control" functionality has been superseded by memory quota. if cmd.need_flow_control() && self.inner.too_busy(cmd.ctx().region_id) { - fail_with_busy(callback); + Self::fail_with_busy(tag, callback.into()); return; } let cid = self.inner.gen_id(); - let mut task = Task::new(cid, cmd); - if task - .alloc_memory_quota(self.inner.memory_quota.clone()) - .is_err() - { - fail_with_busy(callback); - return; + if let Ok(task) = Task::allocate(cid, cmd, self.inner.memory_quota.clone()) { + self.schedule_command( + task, + SchedulerTaskCallback::NormalRequestCallback(callback), + None, + ); + } else { + Self::fail_with_busy(tag, callback.into()); } - self.schedule_command( - task, - SchedulerTaskCallback::NormalRequestCallback(callback), - None, - ); } /// Releases all the latches held by a command. @@ -565,12 +568,13 @@ impl TxnScheduler { ) { let now = Instant::now(); let cid = task.cid(); - let tracker = task.tracker(); + let tracker_token = task.tracker_token(); let cmd = task.cmd(); - debug!("received new command"; "cid" => cid, "cmd" => ?cmd, "tracker" => ?tracker); + debug!("received new command"; "cid" => cid, "cmd" => ?cmd, "tracker" => ?tracker_token); let tag = cmd.tag(); let priority_tag = get_priority_tag(cmd.priority()); + let cmd_type = cmd.request_type(); cmd.incr_cmd_metric(); SCHED_STAGE_COUNTER_VEC.get(tag).new.inc(); SCHED_COMMANDS_PRI_COUNTER_VEC_STATIC @@ -582,8 +586,10 @@ impl TxnScheduler { self.inner .new_task_context(task, callback, prepared_latches) }); - GLOBAL_TRACKERS.with_tracker(tracker, |tracker| { + GLOBAL_TRACKERS.with_tracker(tracker_token, |tracker| { tracker.metrics.grpc_process_nanos = now.saturating_elapsed().as_nanos() as u64; + tracker.req_info.request_type = cmd_type; + tracker.req_info.cid = cid; }); if self.inner.latches.acquire(&mut tctx.lock, cid) { fail_point!("txn_scheduler_acquire_success"); @@ -688,8 +694,7 @@ impl TxnScheduler { let cmd = commands::AcquirePessimisticLockResumed::from_lock_wait_entries(awakened_entries); let cid = specified_cid.unwrap_or_else(|| self.inner.gen_id()); - let task = Task::new(cid, cmd.into()); - + let task = Task::force_create(cid, cmd.into()); // TODO: Make flow control take effect on this thing. self.schedule_command( task, @@ -705,7 +710,7 @@ impl TxnScheduler { /// Executes the task in the sched pool. fn execute(&self, mut task: Task) { - set_tls_tracker_token(task.tracker()); + set_tls_tracker_token(task.tracker_token()); let sched = self.clone(); let metadata = TaskMetadata::from_ctx(task.cmd().resource_control_ctx()); let priority = task.cmd().priority(); @@ -759,14 +764,14 @@ impl TxnScheduler { debug!( "process cmd with snapshot"; "cid" => task.cid(), "term" => ?term, "extra_op" => ?extra_op, - "tracker" => ?task.tracker() + "tracker" => ?task.tracker_token() ); sched.process(snapshot, task).await; } Err(err) => { SCHED_STAGE_COUNTER_VEC.get(tag).snapshot_err.inc(); - info!("get snapshot failed"; "cid" => task.cid(), "err" => ?err); + info!("get snapshot failed"; "cid" => task.cid(), "err" => ?err, "cmd" => ?task.cmd()); sched.finish_with_err(task.cid(), Error::from(err), None); } } @@ -834,7 +839,7 @@ impl TxnScheduler { let tctx = self.inner.dequeue_task_context(cid); if let ProcessResult::NextCommand { cmd } = pr { SCHED_STAGE_COUNTER_VEC.get(tag).next_cmd.inc(); - let task = Task::new(self.inner.gen_id(), cmd); + let task = Task::force_create(self.inner.gen_id(), cmd); self.schedule_command(task, tctx.cb.unwrap(), None); } else { tctx.cb.unwrap().execute(pr); @@ -912,7 +917,7 @@ impl TxnScheduler { }; if let ProcessResult::NextCommand { cmd } = pr { SCHED_STAGE_COUNTER_VEC.get(tag).next_cmd.inc(); - let task = Task::new(self.inner.gen_id(), cmd); + let task = Task::force_create(self.inner.gen_id(), cmd); self.schedule_command(task, cb, None); } else { GLOBAL_TRACKERS.with_tracker(sched_details.tracker, |tracker| { @@ -1186,7 +1191,7 @@ impl TxnScheduler { let region_id = task.cmd().ctx().get_region_id(); let ts = task.cmd().ts(); - let mut sched_details = SchedulerDetails::new(task.tracker(), timer); + let mut sched_details = SchedulerDetails::new(task.tracker_token(), timer); match task.cmd() { Command::Prewrite(_) | Command::PrewritePessimistic(_) => { tls_collect_query(region_id, QueryKind::Prewrite); @@ -1246,24 +1251,18 @@ impl TxnScheduler { self.on_read_finished(cid, pr, tag); } - /// Processes a write command within a worker thread, then posts either a - /// `WriteFinished` message if successful or a `FinishedWithErr` message - /// back to the `TxnScheduler`. - async fn process_write( - self, + /// Use the command handler to process the write command and return the + /// write result. + async fn handle_task( + txn_scheduler: TxnScheduler, snapshot: E::Snap, task: Task, sched_details: &mut SchedulerDetails, - ) { - fail_point!("txn_before_process_write"); + ) -> super::Result { let write_bytes = task.cmd().write_bytes(); let tag = task.cmd().tag(); - let cid = task.cid(); - let metadata = TaskMetadata::from_ctx(task.cmd().resource_control_ctx()); - let tracker = task.tracker(); - let scheduler = self.clone(); - let quota_limiter = self.inner.quota_limiter.clone(); - let resource_limiter = self.inner.resource_manager.as_ref().and_then(|m| { + let quota_limiter = txn_scheduler.inner.quota_limiter.clone(); + let resource_limiter = txn_scheduler.inner.resource_manager.as_ref().and_then(|m| { let ctx = task.cmd().ctx(); m.get_resource_limiter( ctx.get_resource_control_context().get_resource_group_name(), @@ -1275,13 +1274,9 @@ impl TxnScheduler { if resource_limiter.is_some() { sample.enable_cpu_limit(); } - let pessimistic_lock_mode = self.pessimistic_lock_mode(); - let pipelined = task.cmd().can_be_pipelined() - && pessimistic_lock_mode == PessimisticLockMode::Pipelined; - let txn_ext = snapshot.ext().get_txn_ext().cloned(); let max_ts_synced = snapshot.ext().is_max_ts_synced(); - let causal_ts_provider = self.inner.causal_ts_provider.clone(); - let concurrency_manager = self.inner.concurrency_manager.clone(); + let causal_ts_provider = txn_scheduler.inner.causal_ts_provider.clone(); + let concurrency_manager = txn_scheduler.inner.concurrency_manager.clone(); let raw_ext = get_raw_ext( causal_ts_provider, @@ -1289,32 +1284,21 @@ impl TxnScheduler { max_ts_synced, task.cmd(), ) - .await; - if let Err(err) = raw_ext { - info!("get_raw_ext failed"; "cid" => cid, "err" => ?err); - scheduler.finish_with_err(cid, err, Some(sched_details)); - return; - } - let raw_ext = raw_ext.unwrap(); - - let deadline = task.cmd().deadline(); + .await?; let write_result = { let _guard = sample.observe_cpu(); let context = WriteContext { - lock_mgr: &self.inner.lock_mgr, + lock_mgr: &txn_scheduler.inner.lock_mgr, concurrency_manager, extra_op: task.extra_op(), statistics: &mut sched_details.stat, - async_apply_prewrite: self.inner.enable_async_apply_prewrite, + async_apply_prewrite: txn_scheduler.inner.enable_async_apply_prewrite, raw_ext, - txn_status_cache: &self.inner.txn_status_cache, + txn_status_cache: &txn_scheduler.inner.txn_status_cache, }; let begin_instant = Instant::now(); let res = unsafe { - with_perf_context::(tag, || { - task.process_write(snapshot, context) - .map_err(StorageError::from) - }) + with_perf_context::(tag, || task.process_write(snapshot, context)) }; let cmd_process_duration = begin_instant.saturating_elapsed(); sched_details.cmd_process_nanos = cmd_process_duration.as_nanos() as u64; @@ -1371,39 +1355,37 @@ impl TxnScheduler { .inc_by(quota_delay.as_micros() as u64); } + write_result + } + + /// Process the locks encountered or released by the write command, and try + /// to write pessimistic locks in the memory if `in-memory` lock is + /// enabled. Return updated `WriteResult` if there are still data to be + /// persisted, or None if there is nothing left to do. + fn handle_non_persistent_write_result<'a>( + txn_scheduler: TxnScheduler, + cid: u64, + tag: CommandKind, + tracker_token: TrackerToken, + task_meta_data: TaskMetadata<'a>, + write_result: WriteResult, + sched_details: &mut SchedulerDetails, + txn_ext: Option>, + ) -> Option<(WriteResult, TaskMetadata<'a>)> { let WriteResult { ctx, mut to_be_write, rows, - pr, + mut pr, lock_info, released_locks, new_acquired_locks, lock_guards, response_policy, known_txn_status, - } = match deadline - .check() - .map_err(StorageError::from) - .and(write_result) - { - // Write prepare failure typically means conflicting transactions are detected. Delivers - // the error to the callback, and releases the latches. - Err(err) => { - SCHED_STAGE_COUNTER_VEC.get(tag).prepare_write_err.inc(); - debug!("write command failed"; "cid" => cid, "err" => ?err); - scheduler.finish_with_err(cid, err, Some(sched_details)); - return; - } - // Initiates an async write operation on the storage engine, there'll be a - // `WriteFinished` message when it finishes. - Ok(res) => res, - }; - let region_id = ctx.get_region_id(); - SCHED_STAGE_COUNTER_VEC.get(tag).write.inc(); - - let mut pr = Some(pr); + } = write_result; + // Process the possible encountered locks. if !lock_info.is_empty() { if tag == CommandKind::acquire_pessimistic_lock { assert_eq!(lock_info.len(), 1); @@ -1414,24 +1396,24 @@ impl TxnScheduler { // immediately. if lock_info.parameters.wait_timeout.is_some() { assert_eq!(to_be_write.size(), 0); - pr = Some(ProcessResult::Res); + pr = ProcessResult::Res; - scheduler.on_wait_for_lock(&ctx, cid, lock_info, tracker); + txn_scheduler.on_wait_for_lock(&ctx, cid, lock_info, tracker_token); } else { // For requests with `allow_lock_with_conflict`, key errors are set key-wise. // TODO: It's better to return this error from // `commands::AcquirePessimisticLocks::process_write`. if lock_info.parameters.allow_lock_with_conflict { - pr = Some(ProcessResult::PessimisticLockRes { + pr = ProcessResult::PessimisticLockRes { res: Err(StorageError::from(Error::from(MvccError::from( MvccErrorInner::KeyIsLocked(lock_info.lock_info_pb), )))), - }); + }; } } } else if tag == CommandKind::acquire_pessimistic_lock_resumed { // Some requests meets lock again after waiting and resuming. - scheduler.on_wait_for_lock_after_resuming(cid, pr.as_mut().unwrap(), lock_info); + txn_scheduler.on_wait_for_lock_after_resuming(cid, &mut pr, lock_info); } else { // WriteResult returning lock info is only expected to exist for pessimistic // lock requests. @@ -1440,21 +1422,21 @@ impl TxnScheduler { } let woken_up_resumable_entries = if !released_locks.is_empty() { - scheduler.on_release_locks(&metadata, released_locks) + txn_scheduler.on_release_locks(&task_meta_data, released_locks) } else { smallvec![] }; if !woken_up_resumable_entries.is_empty() { - scheduler + txn_scheduler .inner .store_lock_changes(cid, woken_up_resumable_entries); } if to_be_write.modifies.is_empty() { - scheduler.on_write_finished( + txn_scheduler.on_write_finished( cid, - pr, + Some(pr), Ok(()), lock_guards, false, @@ -1462,16 +1444,16 @@ impl TxnScheduler { new_acquired_locks, known_txn_status, tag, - metadata, + task_meta_data, sched_details, ); - return; + return None; } if (tag == CommandKind::acquire_pessimistic_lock || tag == CommandKind::acquire_pessimistic_lock_resumed) - && pessimistic_lock_mode == PessimisticLockMode::InMemory - && self.try_write_in_memory_pessimistic_locks( + && txn_scheduler.pessimistic_lock_mode() == PessimisticLockMode::InMemory + && txn_scheduler.try_write_in_memory_pessimistic_locks( txn_ext.as_deref(), &mut to_be_write, &ctx, @@ -1488,9 +1470,9 @@ impl TxnScheduler { engine.schedule_txn_extra(to_be_write.extra); }) } - scheduler.on_write_finished( + txn_scheduler.on_write_finished( cid, - pr, + Some(pr), Ok(()), lock_guards, false, @@ -1498,59 +1480,75 @@ impl TxnScheduler { new_acquired_locks, known_txn_status, tag, - metadata, + task_meta_data, sched_details, ); - return; - } - - let mut is_async_apply_prewrite = false; - let write_size = to_be_write.size(); - if ctx.get_disk_full_opt() == DiskFullOpt::AllowedOnAlmostFull { - to_be_write.disk_full_opt = DiskFullOpt::AllowedOnAlmostFull - } - to_be_write.deadline = Some(deadline); - - let sched = scheduler.clone(); - - let mut subscribed = WriteEvent::BASIC_EVENT; - match response_policy { - ResponsePolicy::OnCommitted => { - subscribed |= WriteEvent::EVENT_COMMITTED; - is_async_apply_prewrite = true; - } - ResponsePolicy::OnProposed if pipelined => subscribed |= WriteEvent::EVENT_PROPOSED, - _ => (), + return None; } + Some(( + WriteResult::new( + ctx, + to_be_write, + rows, + pr, + vec![], + ReleasedLocks::new(), + new_acquired_locks, + lock_guards, + response_policy, + known_txn_status, + ), + task_meta_data, + )) + } - if self.inner.flow_controller.enabled() { - if self.inner.flow_controller.is_unlimited(region_id) { + /// Handle the flow control of the write command, return true + /// if the command should is already timed out. + async fn handle_flow_control( + txn_scheduler: TxnScheduler, + cid: u64, + write_result: &WriteResult, + sched_details: &mut SchedulerDetails, + ) -> bool { + if txn_scheduler.inner.flow_controller.enabled() { + let region_id = write_result.ctx.region_id; + let write_size = write_result.to_be_write.size(); + if txn_scheduler.inner.flow_controller.is_unlimited(region_id) { // no need to delay if unthrottled, just call consume to record write flow - let _ = self.inner.flow_controller.consume(region_id, write_size); + let _ = txn_scheduler + .inner + .flow_controller + .consume(region_id, write_size); } else { let start = Instant::now_coarse(); // Control mutex is used to ensure there is only one request consuming the // quota. The delay may exceed 1s, and the speed limit is changed every second. // If the speed of next second is larger than the one of first second, without // the mutex, the write flow can't throttled strictly. - let control_mutex = self.inner.control_mutex.clone(); + let control_mutex = txn_scheduler.inner.control_mutex.clone(); let _guard = control_mutex.lock().await; - let delay = self.inner.flow_controller.consume(region_id, write_size); + let delay = txn_scheduler + .inner + .flow_controller + .consume(region_id, write_size); let delay_end = Instant::now_coarse() + delay; - while !self.inner.flow_controller.is_unlimited(region_id) { + while !txn_scheduler.inner.flow_controller.is_unlimited(region_id) { let now = Instant::now_coarse(); if now >= delay_end { break; } - if now >= deadline.inner() { - scheduler.finish_with_err( + if now >= write_result.to_be_write.deadline.as_ref().unwrap().inner() { + txn_scheduler.finish_with_err( cid, StorageErrorInner::DeadlineExceeded, Some(sched_details), ); - self.inner.flow_controller.unconsume(region_id, write_size); + txn_scheduler + .inner + .flow_controller + .unconsume(region_id, write_size); SCHED_THROTTLE_TIME.observe(start.saturating_elapsed_secs()); - return; + return true; } GLOBAL_TIMER_HANDLE .delay(std::time::Instant::now() + Duration::from_millis(1)) @@ -1563,7 +1561,46 @@ impl TxnScheduler { sched_details.flow_control_nanos = elapsed.as_nanos() as u64; } } + false + } + /// Propose the to be persisted data into raftstore, handle the response and + /// invoke callbacks according to the write policy. + async fn handle_async_write( + txn_scheduler: TxnScheduler, + cid: u64, + tag: CommandKind, + pipelined: bool, + txn_ext: Option>, + sched_details: &mut SchedulerDetails, + task_meta_data: TaskMetadata<'_>, + mut write_result: WriteResult, + ) { + let region_id = write_result.ctx.region_id; + let write_size = write_result.to_be_write.size(); + let mut is_async_apply_prewrite = false; + if write_result.ctx.get_disk_full_opt() == DiskFullOpt::AllowedOnAlmostFull { + write_result.to_be_write.disk_full_opt = DiskFullOpt::AllowedOnAlmostFull + } + let mut subscribed = WriteEvent::BASIC_EVENT; + match write_result.response_policy { + ResponsePolicy::OnCommitted => { + subscribed |= WriteEvent::EVENT_COMMITTED; + is_async_apply_prewrite = true; + } + ResponsePolicy::OnProposed if pipelined => subscribed |= WriteEvent::EVENT_PROPOSED, + _ => (), + } + let WriteResult { + ctx, + to_be_write, + rows, + pr, + new_acquired_locks, + lock_guards, + known_txn_status, + .. + } = write_result; let (version, term) = (ctx.get_region_epoch().get_version(), ctx.get_term()); // Mutations on the lock CF should overwrite the memory locks. // We only set a deleted flag here, and the lock will be finally removed when it @@ -1575,23 +1612,23 @@ impl TxnScheduler { .map(|txn_ext| txn_ext.pessimistic_locks.write()); let removed_pessimistic_locks = match pessimistic_locks_guard.as_mut() { Some(locks) - // If there is a leader or region change, removing the locks is unnecessary. - if locks.term == term && locks.version == version && !locks.is_empty() => - { - to_be_write - .modifies - .iter() - .filter_map(|write| match write { - Modify::Put(cf, key, ..) | Modify::Delete(cf, key) if *cf == CF_LOCK => { - locks.get_mut(key).map(|(_, deleted)| { - *deleted = true; - key.to_owned() - }) - } - _ => None, - }) - .collect::>() - } + // If there is a leader or region change, removing the locks is unnecessary. + if locks.term == term && locks.version == version && !locks.is_empty() => + { + to_be_write + .modifies + .iter() + .filter_map(|write| match write { + Modify::Put(cf, key, ..) | Modify::Delete(cf, key) if *cf == CF_LOCK => { + locks.get_mut(key).map(|(_, deleted)| { + *deleted = true; + key.to_owned() + }) + } + _ => None, + }) + .collect::>() + } _ => vec![], }; // Keep the read lock guard of the pessimistic lock table until the request is @@ -1634,6 +1671,7 @@ impl TxnScheduler { }; drop(downgraded_guard); + let mut final_pr = Some(pr); while let Some(ev) = res.next().await { match ev { WriteEvent::Committed => { @@ -1644,11 +1682,11 @@ impl TxnScheduler { if WriteEvent::subscribed_committed(subscribed) && early_return { // Currently, the only case that response is returned after finishing // commit is async applying prewrites for async commit transactions. - let cb = scheduler.inner.take_task_cb(cid); + let cb = txn_scheduler.inner.take_task_cb(cid); Self::early_response( cid, cb.unwrap(), - pr.take().unwrap(), + final_pr.take().unwrap(), tag, CommandStageKind::async_apply_prewrite, ); @@ -1670,11 +1708,11 @@ impl TxnScheduler { // proposed phase is pipelined pessimistic lock. // TODO: Unify the code structure of pipelined pessimistic lock and // async apply prewrite. - let cb = scheduler.inner.take_task_cb(cid); + let cb = txn_scheduler.inner.take_task_cb(cid); Self::early_response( cid, cb.unwrap(), - pr.take().unwrap(), + final_pr.take().unwrap(), tag, CommandStageKind::pipelined_write, ); @@ -1684,9 +1722,9 @@ impl TxnScheduler { fail_point!("scheduler_async_write_finish"); let ok = res.is_ok(); - sched.on_write_finished( + txn_scheduler.on_write_finished( cid, - pr, + final_pr, res, lock_guards, pipelined, @@ -1694,7 +1732,7 @@ impl TxnScheduler { new_acquired_locks, known_txn_status, tag, - metadata, + task_meta_data, sched_details, ); KV_COMMAND_KEYWRITE_HISTOGRAM_VEC @@ -1705,8 +1743,11 @@ impl TxnScheduler { // Only consume the quota when write succeeds, otherwise failed write // requests may exhaust the quota and other write requests would be in long // delay. - if sched.inner.flow_controller.enabled() { - sched.inner.flow_controller.unconsume(region_id, write_size); + if txn_scheduler.inner.flow_controller.enabled() { + txn_scheduler + .inner + .flow_controller + .unconsume(region_id, write_size); } } sched_details.async_write_nanos = @@ -1733,6 +1774,85 @@ impl TxnScheduler { } } + /// Processes a write command within a worker thread, then posts either a + /// `WriteFinished` message if successful or a `FinishedWithErr` message + /// back to the `TxnScheduler`. + async fn process_write( + self, + snapshot: E::Snap, + task: Task, + sched_details: &mut SchedulerDetails, + ) { + fail_point!("txn_before_process_write"); + let cid = task.cid(); + let tag = task.cmd().tag(); + let tracker_token = task.tracker_token(); + let mut task_meta_data = TaskMetadata::from_ctx(task.cmd().resource_control_ctx()); + let pipelined = task.cmd().can_be_pipelined() + && self.pessimistic_lock_mode() == PessimisticLockMode::Pipelined; + let txn_ext = snapshot.ext().get_txn_ext().cloned(); + let deadline = task.cmd().deadline(); + let write_result = Self::handle_task(self.clone(), snapshot, task, sched_details).await; + + let mut write_result = match deadline + .check() + .map_err(StorageError::from) + .and(write_result.map_err(StorageError::from)) + { + // Write prepare failure typically means conflicting transactions are detected. Delivers + // the error to the callback, and releases the latches. + Err(err) => { + SCHED_STAGE_COUNTER_VEC.get(tag).prepare_write_err.inc(); + let req_info = + GLOBAL_TRACKERS.with_tracker(tracker_token, |tracker| tracker.req_info.clone()); + debug!("write command failed"; "cid" => cid, "err" => ?err, "req_info" => ?req_info); + self.finish_with_err(cid, err, Some(sched_details)); + return; + } + // Initiates an async write operation on the storage engine, there'll be a + // `WriteFinished` message when it finishes. + Ok(res) => res, + }; + SCHED_STAGE_COUNTER_VEC.get(tag).write.inc(); + + // Continue to process if there is data to be persisted in the `WriteResult`, or + // return. + if let Some((write_result_res, task_meta_data_res)) = + Self::handle_non_persistent_write_result( + self.clone(), + cid, + tag, + tracker_token, + task_meta_data, + write_result, + sched_details, + txn_ext.clone(), + ) + { + write_result = write_result_res; + task_meta_data = task_meta_data_res; + } else { + return; + } + + write_result.to_be_write.deadline = Some(deadline); + // Return if the task is already timed out. + if Self::handle_flow_control(self.clone(), cid, &write_result, sched_details).await { + return; + } + Self::handle_async_write( + self.clone(), + cid, + tag, + pipelined, + txn_ext, + sched_details, + task_meta_data, + write_result, + ) + .await; + } + /// Returns whether it succeeds to write pessimistic locks to the in-memory /// lock table. fn try_write_in_memory_pessimistic_locks( diff --git a/src/storage/txn/task.rs b/src/storage/txn/task.rs index 4d2b41a25d3..0defc77afd0 100644 --- a/src/storage/txn/task.rs +++ b/src/storage/txn/task.rs @@ -19,19 +19,50 @@ use crate::storage::{ pub(super) struct Task { cid: u64, - tracker: TrackerToken, + tracker_token: TrackerToken, cmd: Option, extra_op: ExtraOp, + /// The owned_quota is allocated when Task is created, and freed when Task + /// is dropped. owned_quota: Option, } impl Task { - /// Creates a task for a running command. - pub(super) fn new(cid: u64, cmd: Command) -> Task { - let tracker = get_tls_tracker_token(); + /// Creates a task for a running command. The TLS tracker token is set + /// in the future processing logic in the kv.rs. + pub(super) fn allocate( + cid: u64, + cmd: Command, + memory_quota: Arc, + ) -> Result { + let tracker_token = get_tls_tracker_token(); + let cmd_size = cmd.approximate_heap_size(); + let mut task = Task { + cid, + tracker_token, + cmd: Some(cmd), + extra_op: ExtraOp::Noop, + owned_quota: None, + }; + let mut quota = OwnedAllocated::new(memory_quota); + quota.alloc(cmd_size)?; + SCHED_TXN_MEMORY_QUOTA + .in_use + .set(quota.source().in_use() as i64); + task.owned_quota = Some(quota); + + Ok(task) + } + + /// Creates a task without considering memory count. This is just a + /// temporary solution for the re-schedule command task generations, it + /// would be deprecated after the re-schedule command and callback + /// processing are refactored. Do NOT use this function in other places. + pub(super) fn force_create(cid: u64, cmd: Command) -> Self { + let tracker_token = get_tls_tracker_token(); Task { cid, - tracker, + tracker_token, cmd: Some(cmd), extra_op: ExtraOp::Noop, owned_quota: None, @@ -42,8 +73,8 @@ impl Task { self.cid } - pub(super) fn tracker(&self) -> TrackerToken { - self.tracker + pub(super) fn tracker_token(&self) -> TrackerToken { + self.tracker_token } pub(super) fn cmd(&self) -> &Command { @@ -58,25 +89,12 @@ impl Task { self.extra_op } + /// extra_op is set after getting snapshot and before the command is + /// processed. pub(super) fn set_extra_op(&mut self, extra_op: ExtraOp) { self.extra_op = extra_op } - pub(super) fn alloc_memory_quota( - &mut self, - memory_quota: Arc, - ) -> Result<(), MemoryQuotaExceeded> { - if self.owned_quota.is_none() { - let mut owned = OwnedAllocated::new(memory_quota); - owned.alloc(self.cmd.approximate_heap_size())?; - SCHED_TXN_MEMORY_QUOTA - .in_use - .set(owned.source().in_use() as i64); - self.owned_quota = Some(owned); - } - Ok(()) - } - pub(super) fn process_write( mut self, snapshot: S, @@ -107,14 +125,9 @@ mod tests { fn test_alloc_memory_quota() { let p = PrewriteRequest::default(); let cmd: TypedCommand<_> = p.into(); - let mut task = Task::new(0, cmd.cmd); let quota = Arc::new(MemoryQuota::new(1 << 32)); - task.alloc_memory_quota(quota.clone()).unwrap(); + let task = Task::allocate(0, cmd.cmd, quota.clone()).unwrap(); assert_ne!(quota.in_use(), 0); - let in_use = quota.in_use(); - task.alloc_memory_quota(quota.clone()).unwrap(); - let in_use_new = quota.in_use(); - assert_eq!(in_use, in_use_new); drop(task); assert_eq!(quota.in_use(), 0); } From b834daca4dae5c8fa933ad14538fe0644659897e Mon Sep 17 00:00:00 2001 From: qupeng Date: Tue, 30 Jul 2024 15:58:18 +0800 Subject: [PATCH 013/144] cdc: re-design delegate and downstream to support partial region subscription better (#17274) close tikv/tikv#16362 Signed-off-by: qupeng Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/cdc/src/delegate.rs | 1246 ++++++++++------- components/cdc/src/endpoint.rs | 716 +++++----- components/cdc/src/initializer.rs | 502 ++++--- components/cdc/src/observer.rs | 2 +- components/cdc/src/service.rs | 64 +- .../cdc/tests/failpoints/test_memory_quota.rs | 23 +- components/cdc/tests/integrations/test_cdc.rs | 226 ++- components/cdc/tests/mod.rs | 58 + components/txn_types/src/types.rs | 4 + 9 files changed, 1620 insertions(+), 1221 deletions(-) diff --git a/components/cdc/src/delegate.rs b/components/cdc/src/delegate.rs index 050e9419cb0..a4e04c6540a 100644 --- a/components/cdc/src/delegate.rs +++ b/components/cdc/src/delegate.rs @@ -1,16 +1,20 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - mem, + collections::btree_map::{BTreeMap, Entry as BTreeMapEntry}, + fmt, + ops::Bound, + result::Result as StdResult, string::String, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, Arc, }, + time::Duration, }; use api_version::{ApiV2, KeyMode, KvFormat}; -use collections::{HashMap, HashMapEntry}; +use collections::HashMap; use crossbeam::atomic::AtomicCell; use kvproto::{ cdcpb::{ @@ -28,21 +32,22 @@ use raftstore::{ store::util::compare_region_epoch, Error as RaftStoreError, }; -use resolved_ts::{Resolver, TsSource, ON_DROP_WARN_HEAP_SIZE}; use tikv::storage::{txn::TxnEntry, Statistics}; use tikv_util::{ debug, info, memory::{HeapSize, MemoryQuota}, + time::Instant, warn, }; use txn_types::{Key, Lock, LockType, TimeStamp, WriteBatchFlags, WriteRef, WriteType}; use crate::{ channel::{CdcEvent, SendError, Sink, CDC_EVENT_MAX_BYTES}, + endpoint::Advance, initializer::KvEntry, metrics::*, old_value::{OldValueCache, OldValueCallback}, - service::ConnId, + service::{Conn, ConnId, FeatureGate, RequestId}, txn_source::TxnSource, Error, Result, }; @@ -70,7 +75,7 @@ pub enum DownstreamState { /// It's just created and rejects change events and resolved timestamps. Uninitialized, /// It has got a snapshot for incremental scan, and change events will be - /// accepted. However it still rejects resolved timestamps. + /// accepted. However, it still rejects resolved timestamps. Initializing, /// Incremental scan is finished so that resolved timestamps are acceptable /// now. @@ -120,26 +125,39 @@ impl DownstreamState { } } -#[derive(Clone)] pub struct Downstream { - // TODO: include cdc request. /// A unique identifier of the Downstream. - id: DownstreamId, - // The request ID set by CDC to identify events corresponding different requests. - req_id: u64, - conn_id: ConnId, - // The IP address of downstream. - peer: String, - region_epoch: RegionEpoch, + pub id: DownstreamId, + /// The IP address of downstream. + pub peer: String, + pub region_epoch: RegionEpoch, + /// The request ID set by CDC to identify events corresponding different + /// requests. + pub req_id: RequestId, + pub conn_id: ConnId, + + pub kv_api: ChangeDataRequestKvApi, + pub filter_loop: bool, + pub observed_range: ObservedRange, + sink: Option, state: Arc>, - kv_api: ChangeDataRequestKvApi, - filter_loop: bool, - pub(crate) observed_range: ObservedRange, - - // When meet region errors like split or merge, we can cancel incremental scan draining - // by `scan_truncated`. pub(crate) scan_truncated: Arc, + + // Fields to handle ResolvedTs advancing. If `lock_heap` is none it means + // the downstream hasn't finished the incremental scanning. + lock_heap: Option>, + advanced_to: TimeStamp, +} + +impl fmt::Debug for Downstream { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Downstream") + .field("id", &self.id) + .field("req_id", &self.req_id) + .field("conn_id", &self.conn_id) + .finish() + } } impl Downstream { @@ -150,7 +168,7 @@ impl Downstream { pub fn new( peer: String, region_epoch: RegionEpoch, - req_id: u64, + req_id: RequestId, conn_id: ConnId, kv_api: ChangeDataRequestKvApi, filter_loop: bool, @@ -158,17 +176,21 @@ impl Downstream { ) -> Downstream { Downstream { id: DownstreamId::new(), - req_id, - conn_id, peer, region_epoch, - sink: None, - state: Arc::new(AtomicCell::new(DownstreamState::default())), + req_id, + conn_id, kv_api, filter_loop, + observed_range, + sink: None, + state: Arc::new(AtomicCell::new(DownstreamState::default())), scan_truncated: Arc::new(AtomicBool::new(false)), + + lock_heap: None, + advanced_to: TimeStamp::zero(), } } @@ -176,10 +198,10 @@ impl Downstream { // because the sink can be also used by an incremental scan. We must ensure // no more events can be pushed to the sink after an `EventError` is sent. pub fn sink_event(&self, mut event: Event, force: bool) -> Result<()> { - event.set_request_id(self.req_id); + event.set_request_id(self.req_id.0); if self.sink.is_none() { info!("cdc drop event, no sink"; - "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => self.req_id); + "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => ?self.req_id); return Err(Error::Sink(SendError::Disconnected)); } let sink = self.sink.as_ref().unwrap(); @@ -187,13 +209,13 @@ impl Downstream { Ok(_) => Ok(()), Err(SendError::Disconnected) => { debug!("cdc send event failed, disconnected"; - "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => self.req_id); + "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => ?self.req_id); Err(Error::Sink(SendError::Disconnected)) } // TODO handle errors. Err(e @ SendError::Full) | Err(e @ SendError::Congested) => { info!("cdc send event failed, full"; - "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => self.req_id); + "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => ?self.req_id); Err(Error::Sink(e)) } } @@ -204,7 +226,7 @@ impl Downstream { /// `sink_error_event` is called. pub fn sink_error_event(&self, region_id: u64, err_event: EventError) -> Result<()> { info!("cdc downstream meets region error"; - "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => self.req_id); + "conn_id" => ?self.conn_id, "downstream_id" => ?self.id, "req_id" => ?self.req_id); self.scan_truncated.store(true, Ordering::Release); let mut change_data_event = Event::default(); @@ -219,107 +241,76 @@ impl Downstream { self.sink = Some(sink); } - pub fn get_id(&self) -> DownstreamId { - self.id - } - - pub fn get_filter_loop(&self) -> bool { - self.filter_loop - } - pub fn get_state(&self) -> Arc> { self.state.clone() } - - pub fn get_conn_id(&self) -> ConnId { - self.conn_id - } - pub fn get_req_id(&self) -> u64 { - self.req_id - } } -struct Pending { - downstreams: Vec, - locks: Vec, - pending_bytes: usize, - memory_quota: Arc, +// In `PendingLock`, `key` is encoded. +pub enum PendingLock { + Track { key: Key, start_ts: MiniLock }, + Untrack { key: Key }, } -impl Pending { - fn new(memory_quota: Arc) -> Pending { - Pending { - downstreams: vec![], - locks: vec![], - pending_bytes: 0, - memory_quota, +impl HeapSize for PendingLock { + fn approximate_heap_size(&self) -> usize { + match self { + PendingLock::Track { key, .. } | PendingLock::Untrack { key } => { + key.approximate_heap_size() + } } } +} - fn push_pending_lock(&mut self, lock: PendingLock) -> Result<()> { - let bytes = lock.approximate_heap_size(); - self.memory_quota.alloc(bytes)?; - self.locks.push(lock); - self.pending_bytes += bytes; - CDC_PENDING_BYTES_GAUGE.add(bytes as i64); - Ok(()) - } +pub enum LockTracker { + Pending, + Preparing(Vec), + Prepared { + region: Region, + locks: BTreeMap, + }, +} - fn on_region_ready(&mut self, resolver: &mut Resolver) -> Result<()> { - fail::fail_point!("cdc_pending_on_region_ready", |_| Err( - Error::MemoryQuotaExceeded(tikv_util::memory::MemoryQuotaExceeded) - )); - // Must take locks, otherwise it may double free memory quota on drop. - for lock in mem::take(&mut self.locks) { - self.memory_quota.free(lock.approximate_heap_size()); - match lock { - PendingLock::Track { key, start_ts } => { - resolver.track_lock(start_ts, key, None)?; - } - PendingLock::Untrack { key } => resolver.untrack_lock(&key, None), +impl fmt::Debug for LockTracker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LockTracker::Pending => write!(f, "LockTracker::Pending"), + LockTracker::Preparing(ref locks) => { + write!(f, "LockTracker::Preparing({})", locks.len()) + } + LockTracker::Prepared { locks, .. } => { + write!(f, "LockTracker::Prepared({})", locks.len()) } } - Ok(()) } } -impl Drop for Pending { - fn drop(&mut self) { - CDC_PENDING_BYTES_GAUGE.sub(self.pending_bytes as i64); - let locks = mem::take(&mut self.locks); - if locks.is_empty() { - return; - } +/// `MiniLock` is like `Lock`, but only contains fields that CDC cares about. +#[derive(Eq, PartialEq, Debug)] +pub struct MiniLock { + pub ts: TimeStamp, + pub txn_source: u64, +} - // Free memory quota used by pending locks and unlocks. - let mut bytes = 0; - let num_locks = locks.len(); - for lock in locks { - bytes += lock.approximate_heap_size(); - } - if bytes > ON_DROP_WARN_HEAP_SIZE { - warn!("cdc drop huge Pending"; - "bytes" => bytes, - "num_locks" => num_locks, - "memory_quota_in_use" => self.memory_quota.in_use(), - "memory_quota_capacity" => self.memory_quota.capacity(), - ); +impl MiniLock { + pub fn new(ts: T, txn_source: u64) -> Self + where + TimeStamp: From, + { + MiniLock { + ts: TimeStamp::from(ts), + txn_source, } - self.memory_quota.free(bytes); } -} -enum PendingLock { - Track { key: Vec, start_ts: TimeStamp }, - Untrack { key: Vec }, -} - -impl HeapSize for PendingLock { - fn approximate_heap_size(&self) -> usize { - match self { - PendingLock::Track { key, .. } | PendingLock::Untrack { key } => { - key.approximate_heap_size() - } + #[cfg(test)] + pub fn from_ts(ts: T) -> Self + where + TimeStamp: From, + { + MiniLock { + ts: TimeStamp::from(ts), + txn_source: 0, } } } @@ -327,47 +318,202 @@ impl HeapSize for PendingLock { /// A CDC delegate of a raftstore region peer. /// /// It converts raft commands into CDC events and broadcast to downstreams. -/// It also track trancation on the fly in order to compute resolved ts. +/// It also tracks transactions on the fly in order to compute resolved ts. pub struct Delegate { - pub handle: ObserveHandle, pub region_id: u64, + pub handle: ObserveHandle, + memory_quota: Arc, - // None if the delegate is not initialized. - region: Option, - pub resolver: Option, - - // Downstreams after the delegate has been resolved. - resolved_downstreams: Vec, - pending: Option, + lock_tracker: LockTracker, + downstreams: Vec, txn_extra_op: Arc>, failed: bool, + + created: Instant, + last_lag_warn: Instant, +} + +impl Drop for Delegate { + fn drop(&mut self) { + match &self.lock_tracker { + LockTracker::Pending => {} + LockTracker::Preparing(locks) => { + let mut free_bytes = 0; + for lock in locks { + free_bytes += lock.approximate_heap_size(); + } + self.memory_quota.free(free_bytes); + CDC_PENDING_BYTES_GAUGE.sub(free_bytes as _); + } + LockTracker::Prepared { locks, .. } => { + let mut free_bytes = 0; + for lock in locks.keys() { + free_bytes += lock.approximate_heap_size(); + } + self.memory_quota.free(free_bytes); + CDC_PENDING_BYTES_GAUGE.sub(free_bytes as _); + } + } + } } impl Delegate { + fn push_lock(&mut self, key: Key, start_ts: MiniLock) -> Result { + let bytes = key.approximate_heap_size(); + let mut lock_count_modify = 0; + match &mut self.lock_tracker { + LockTracker::Pending => unreachable!(), + LockTracker::Preparing(locks) => { + self.memory_quota.alloc(bytes)?; + CDC_PENDING_BYTES_GAUGE.add(bytes as _); + locks.push(PendingLock::Track { key, start_ts }); + } + LockTracker::Prepared { locks, .. } => { + if locks.insert(key, start_ts).is_none() { + self.memory_quota.alloc(bytes)?; + CDC_PENDING_BYTES_GAUGE.add(bytes as _); + lock_count_modify = 1; + } + } + } + Ok(lock_count_modify) + } + + fn pop_lock(&mut self, key: Key) -> Result { + let mut lock_count_modify = 0; + match &mut self.lock_tracker { + LockTracker::Pending => unreachable!(), + LockTracker::Preparing(locks) => { + let bytes = key.approximate_heap_size(); + self.memory_quota.alloc(bytes)?; + CDC_PENDING_BYTES_GAUGE.add(bytes as _); + locks.push(PendingLock::Untrack { key }); + } + LockTracker::Prepared { locks, .. } => { + if let Some((key, _)) = locks.remove_entry(&key) { + let bytes = key.approximate_heap_size(); + self.memory_quota.free(bytes); + CDC_PENDING_BYTES_GAUGE.sub(bytes as _); + lock_count_modify = -1; + } + } + } + Ok(lock_count_modify) + } + + pub(crate) fn init_lock_tracker(&mut self) -> bool { + if matches!(self.lock_tracker, LockTracker::Pending) { + self.lock_tracker = LockTracker::Preparing(vec![]); + return true; + } + false + } + + fn finish_prepare_lock_tracker( + &mut self, + region: Region, + mut locks: BTreeMap, + ) -> Result<()> { + let delta_locks = match std::mem::replace(&mut self.lock_tracker, LockTracker::Pending) { + LockTracker::Preparing(locks) => locks, + _ => unreachable!(), + }; + + let mut free_bytes = 0usize; + for delta_lock in delta_locks { + free_bytes += delta_lock.approximate_heap_size(); + match delta_lock { + PendingLock::Track { key, start_ts } => match locks.entry(key) { + BTreeMapEntry::Vacant(x) => { + x.insert(start_ts); + } + BTreeMapEntry::Occupied(x) => { + assert_eq!(*x.get(), start_ts); + } + }, + PendingLock::Untrack { key } => match locks.entry(key.clone()) { + BTreeMapEntry::Vacant(..) => { + warn!("untrack lock not found when try to finish prepare lock tracker"; + "key" => %key); + } + BTreeMapEntry::Occupied(x) => { + x.remove(); + } + }, + } + } + self.memory_quota.free(free_bytes); + CDC_PENDING_BYTES_GAUGE.sub(free_bytes as _); + + let mut alloc_bytes = 0usize; + for key in locks.keys() { + alloc_bytes += key.approximate_heap_size(); + } + self.memory_quota.alloc(alloc_bytes)?; + CDC_PENDING_BYTES_GAUGE.add(alloc_bytes as _); + + self.lock_tracker = LockTracker::Prepared { region, locks }; + Ok(()) + } + + pub(crate) fn finish_scan_locks( + &mut self, + region: Region, + locks: BTreeMap, + ) -> Result> { + fail::fail_point!("cdc_finish_scan_locks_memory_quota_exceed", |_| Err( + Error::MemoryQuotaExceeded(tikv_util::memory::MemoryQuotaExceeded) + )); + + info!("cdc region is ready"; "region_id" => self.region_id); + self.finish_prepare_lock_tracker(region, locks)?; + + let region = match &self.lock_tracker { + LockTracker::Prepared { region, .. } => region, + _ => unreachable!(), + }; + + // Check observed key range in region. + let mut failed_downstreams = Vec::new(); + for downstream in &mut self.downstreams { + downstream.observed_range.update_region_key_range(region); + if let Err(e) = Self::check_epoch_on_ready(downstream, region) { + failed_downstreams.push((&*downstream, e)); + } + } + + Ok(failed_downstreams) + } + /// Create a Delegate the given region. pub fn new( region_id: u64, - txn_extra_op: Arc>, memory_quota: Arc, + txn_extra_op: Arc>, ) -> Delegate { Delegate { region_id, handle: ObserveHandle::new(), - resolver: None, - region: None, - resolved_downstreams: Vec::new(), - pending: Some(Pending::new(memory_quota)), + memory_quota, + + lock_tracker: LockTracker::Pending, + downstreams: Vec::new(), txn_extra_op, failed: false, + + created: Instant::now_coarse(), + last_lag_warn: Instant::now_coarse(), } } /// Let downstream subscribe the delegate. /// Return error if subscribe fails and the `Delegate` won't be changed. - pub fn subscribe(&mut self, downstream: Downstream) -> Result<()> { - if self.region.is_some() { - // Check if the downstream is out dated. - self.check_epoch_on_ready(&downstream)?; + pub fn subscribe(&mut self, downstream: Downstream) -> StdResult<(), (Error, Downstream)> { + if let LockTracker::Prepared { ref region, .. } = &self.lock_tracker { + // Check if the downstream is outdated. + if let Err(e) = Self::check_epoch_on_ready(&downstream, region) { + return Err((e, downstream)); + } } self.add_downstream(downstream); Ok(()) @@ -378,17 +524,11 @@ impl Delegate { } pub fn downstreams(&self) -> &Vec { - self.pending - .as_ref() - .map(|p| &p.downstreams) - .unwrap_or(&self.resolved_downstreams) + &self.downstreams } pub fn downstreams_mut(&mut self) -> &mut Vec { - self.pending - .as_mut() - .map(|p| &mut p.downstreams) - .unwrap_or(&mut self.resolved_downstreams) + &mut self.downstreams } /// Let downstream unsubscribe the delegate. @@ -402,7 +542,7 @@ impl Delegate { warn!("cdc send unsubscribe failed"; "region_id" => region_id, "error" => ?err, "origin_error" => ?error_event, "downstream_id" => ?d.id, "downstream" => ?d.peer, - "request_id" => d.req_id, "conn_id" => ?d.conn_id); + "request_id" => ?d.req_id, "conn_id" => ?d.conn_id); } } d.state.store(DownstreamState::Stopped); @@ -437,19 +577,18 @@ impl Delegate { warn!("cdc send region error failed"; "region_id" => region_id, "error" => ?err, "origin_error" => ?error, "downstream_id" => ?downstream.id, "downstream" => ?downstream.peer, - "request_id" => downstream.req_id, "conn_id" => ?downstream.conn_id); + "request_id" => ?downstream.req_id, "conn_id" => ?downstream.conn_id); } else { info!("cdc send region error success"; "region_id" => region_id, "origin_error" => ?error, "downstream_id" => ?downstream.id, "downstream" => ?downstream.peer, - "request_id" => downstream.req_id, "conn_id" => ?downstream.conn_id); + "request_id" => ?downstream.req_id, "conn_id" => ?downstream.conn_id); } - Ok(()) }; - // TODO: In case we drop error messages, maybe we need a heartbeat mechanism - // to allow TiCDC detect region status. - let _ = self.broadcast(send); + for downstream in &self.downstreams { + send(downstream); + } } /// `txn_extra_op` returns a shared flag which is accessed in TiKV's @@ -462,74 +601,101 @@ impl Delegate { self.txn_extra_op.as_ref() } - fn broadcast(&self, send: F) -> Result<()> - where - F: Fn(&Downstream) -> Result<()>, - { - let downstreams = self.downstreams(); - assert!( - !downstreams.is_empty(), - "region {} miss downstream", - self.region_id - ); - for downstream in downstreams { - send(downstream)?; - } - Ok(()) - } - - /// Install a resolver. Return downstreams which fail because of the - /// region's internal changes. - pub fn on_region_ready( + /// Try advance and broadcast resolved ts. + pub(crate) fn on_min_ts( &mut self, - mut resolver: Resolver, - region: Region, - ) -> Result> { - assert!( - self.resolver.is_none(), - "region {} resolver should not be ready", - self.region_id, - ); + min_ts: TimeStamp, + current_ts: TimeStamp, + connections: &HashMap, + advance: &mut Advance, + ) { + let locks = match &self.lock_tracker { + LockTracker::Prepared { locks, .. } => locks, + _ => { + let now = Instant::now_coarse(); + let elapsed = now.duration_since(self.created); + if elapsed > WARN_LAG_THRESHOLD + && now.duration_since(self.last_lag_warn) > WARN_LAG_INTERVAL + { + warn!( + "cdc region scan locks too slow"; + "region_id" => self.region_id, + "elapsed" => ?elapsed, + "stage" => ?self.lock_tracker, + ); + self.last_lag_warn = now; + } + return; + } + }; - // Check observed key range in region. - for downstream in self.downstreams_mut() { - downstream.observed_range.update_region_key_range(®ion); - } + let mut handle_downstream = |downstream: &mut Downstream| -> Option { + if !downstream.state.load().ready_for_advancing_ts() { + advance.blocked_on_scan += 1; + return None; + } + advance.scan_finished += 1; - // Mark the delegate as initialized. - info!("cdc region is ready"; "region_id" => self.region_id); - // Downstreams in pending must be moved to resolved_downstreams - // immediately and must not return in the middle, otherwise the delegate - // loses downstreams. - let mut pending = self.pending.take().unwrap(); - self.resolved_downstreams = mem::take(&mut pending.downstreams); + if downstream.lock_heap.is_none() { + let mut lock_heap = BTreeMap::::new(); + for (_, lock) in locks.range(downstream.observed_range.to_range()) { + let lock_count = lock_heap.entry(lock.ts).or_default(); + *lock_count += 1; + } + downstream.lock_heap = Some(lock_heap); + } + + let lock_heap = downstream.lock_heap.as_ref().unwrap(); + let min_lock = lock_heap.keys().next().cloned().unwrap_or(min_ts); + let advanced_to = std::cmp::min(min_lock, min_ts); + if advanced_to > downstream.advanced_to { + downstream.advanced_to = advanced_to; + } else { + advance.blocked_on_locks += 1; + } + Some(downstream.advanced_to) + }; - pending.on_region_ready(&mut resolver)?; - self.resolver = Some(resolver); - self.region = Some(region); + let mut slow_downstreams = Vec::new(); + for d in &mut self.downstreams { + let advanced_to = match handle_downstream(d) { + Some(ts) => ts, + None => continue, + }; - let mut failed_downstreams = Vec::new(); - for downstream in self.downstreams() { - if let Err(e) = self.check_epoch_on_ready(downstream) { - failed_downstreams.push((downstream, e)); + let features = connections.get(&d.conn_id).unwrap().features(); + if features.contains(FeatureGate::STREAM_MULTIPLEXING) { + let k = (d.conn_id, d.req_id); + let v = advance.multiplexing.entry(k).or_default(); + v.push(self.region_id, advanced_to); + } else if features.contains(FeatureGate::BATCH_RESOLVED_TS) { + let v = advance.exclusive.entry(d.conn_id).or_default(); + v.push(self.region_id, advanced_to); + } else { + let k = (d.conn_id, self.region_id); + let v = (d.req_id, advanced_to); + advance.compat.insert(k, v); + } + + let lag = current_ts + .physical() + .saturating_sub(d.advanced_to.physical()); + if Duration::from_millis(lag) > WARN_LAG_THRESHOLD { + slow_downstreams.push(d.id); } } - Ok(failed_downstreams) - } - /// Try advance and broadcast resolved ts. - pub fn on_min_ts(&mut self, min_ts: TimeStamp) -> Option { - if self.resolver.is_none() { - debug!("cdc region resolver not ready"; - "region_id" => self.region_id, "min_ts" => min_ts); - return None; + if !slow_downstreams.is_empty() { + let now = Instant::now_coarse(); + if now.duration_since(self.last_lag_warn) > WARN_LAG_INTERVAL { + warn!( + "cdc region downstreams are too slow"; + "region_id" => self.region_id, + "downstreams" => ?slow_downstreams, + ); + self.last_lag_warn = now; + } } - debug!("cdc try to advance ts"; "region_id" => self.region_id, "min_ts" => min_ts); - let resolver = self.resolver.as_mut().unwrap(); - let resolved_ts = resolver.resolve(min_ts, None, TsSource::Cdc); - debug!("cdc resolved ts updated"; - "region_id" => self.region_id, "resolved_ts" => resolved_ts); - Some(resolved_ts) } pub fn on_batch( @@ -552,19 +718,17 @@ impl Delegate { } = cmd; if response.get_header().has_error() { let err_header = response.mut_header().take_error(); - self.mark_failed(); return Err(Error::request(err_header)); } if !request.has_admin_request() { let flags = WriteBatchFlags::from_bits_truncate(request.get_header().get_flags()); - let is_one_pc = flags.contains(WriteBatchFlags::ONE_PC); self.sink_data( index, request.requests.into(), + flags, old_value_cb, old_value_cache, statistics, - is_one_pc, )?; } else { self.sink_admin(request.take_admin_request(), response.take_admin_response())?; @@ -575,7 +739,7 @@ impl Delegate { pub(crate) fn convert_to_grpc_events( region_id: u64, - request_id: u64, + request_id: RequestId, entries: Vec>, filter_loop: bool, observed_range: &ObservedRange, @@ -641,10 +805,9 @@ impl Delegate { row_size = 0; } } - let lossy_ddl_filter = TxnSource::is_lossy_ddl_reorg_source_set(row.txn_source); - let cdc_write_filter = - TxnSource::is_cdc_write_source_set(row.txn_source) && filter_loop; - if lossy_ddl_filter || cdc_write_filter { + if TxnSource::is_lossy_ddl_reorg_source_set(row.txn_source) + || filter_loop && TxnSource::is_cdc_write_source_set(row.txn_source) + { continue; } if current_rows_size + row_size >= CDC_EVENT_MAX_BYTES { @@ -665,7 +828,7 @@ impl Delegate { }; CdcEvent::Event(Event { region_id, - request_id, + request_id: request_id.0, event: Some(Event_oneof_event::Entries(event_entries)), ..Default::default() }) @@ -678,12 +841,13 @@ impl Delegate { &mut self, index: u64, requests: Vec, + flags: WriteBatchFlags, old_value_cb: &OldValueCallback, old_value_cache: &mut OldValueCache, statistics: &mut Statistics, - is_one_pc: bool, ) -> Result<()> { debug_assert_eq!(self.txn_extra_op.load(), TxnExtraOp::ReadOldValue); + let mut read_old_value = |row: &mut EventRow, read_old_ts| -> Result<()> { let key = Key::from_raw(&row.key).append_ts(row.start_ts.into()); let old_value = old_value_cb(key, read_old_ts, old_value_cache, statistics)?; @@ -691,274 +855,219 @@ impl Delegate { Ok(()) }; - // map[key] -> (event, has_value). - let mut txn_rows: HashMap, (EventRow, bool)> = HashMap::default(); - let mut raw_rows: Vec = Vec::new(); + let mut rows_builder = RowsBuilder::default(); + rows_builder.is_one_pc = flags.contains(WriteBatchFlags::ONE_PC); for mut req in requests { - let res = match req.get_cmd_type() { - CmdType::Put => self.sink_put( - req.take_put(), - is_one_pc, - &mut txn_rows, - &mut raw_rows, - &mut read_old_value, - ), - CmdType::Delete => self.sink_delete(req.take_delete()), - _ => { - debug!( - "skip other command"; - "region_id" => self.region_id, - "command" => ?req, - ); - Ok(()) + match req.get_cmd_type() { + CmdType::Put => { + self.sink_put(req.take_put(), &mut rows_builder, &mut read_old_value)? } + CmdType::Delete => self.sink_delete(req.take_delete(), &mut rows_builder)?, + _ => debug!("cdc skip other command"; + "region_id" => self.region_id, + "command" => ?req), }; - if res.is_err() { - self.mark_failed(); - return res; - } } - let mut rows = Vec::with_capacity(txn_rows.len()); - for (_, (v, has_value)) in txn_rows { - if v.r_type == EventLogType::Prewrite && v.op_type == EventRowOpType::Put && !has_value + let (raws, txns) = rows_builder.finish_build(); + self.sink_downstream_raw(raws, index)?; + self.sink_downstream_tidb(txns)?; + Ok(()) + } + + fn sink_downstream_raw(&mut self, entries: Vec, index: u64) -> Result<()> { + let mut downstreams = Vec::with_capacity(self.downstreams.len()); + for d in &mut self.downstreams { + if d.kv_api == ChangeDataRequestKvApi::RawKv && d.state.load().ready_for_change_events() { - // It's possible that a prewrite command only contains lock but without - // default. It's not documented by classic Percolator but introduced with - // Large-Transaction. Those prewrites are not complete, we must skip them. + downstreams.push(d); + } + } + if downstreams.is_empty() { + return Ok(()); + } + + for downstream in downstreams { + let filtered_entries: Vec<_> = entries + .iter() + .filter(|x| downstream.observed_range.contains_raw_key(&x.key)) + .cloned() + .collect(); + if filtered_entries.is_empty() { continue; } - rows.push(v); + let event = Event { + region_id: self.region_id, + index, + request_id: downstream.req_id.0, + event: Some(Event_oneof_event::Entries(EventEntries { + entries: filtered_entries.into(), + ..Default::default() + })), + ..Default::default() + }; + downstream.sink_event(event, false)?; } - self.sink_downstream(rows, index, ChangeDataRequestKvApi::TiDb)?; - self.sink_downstream(raw_rows, index, ChangeDataRequestKvApi::RawKv) + Ok(()) } - fn sink_downstream( - &mut self, - entries: Vec, - index: u64, - kv_api: ChangeDataRequestKvApi, - ) -> Result<()> { - if entries.is_empty() { + fn sink_downstream_tidb(&mut self, entries: Vec<(EventRow, isize)>) -> Result<()> { + let mut downstreams = Vec::with_capacity(self.downstreams.len()); + for d in &mut self.downstreams { + if d.kv_api == ChangeDataRequestKvApi::TiDb && d.state.load().ready_for_change_events() + { + downstreams.push(d); + } + } + if downstreams.is_empty() { return Ok(()); } - // Filter the entries which are lossy DDL events. - // We don't need to send them to downstream. - let entries = entries - .iter() - .filter(|x| !TxnSource::is_lossy_ddl_reorg_source_set(x.txn_source)) - .cloned() - .collect::>(); - - let downstreams = self.downstreams(); - assert!( - !downstreams.is_empty(), - "region {} miss downstream", - self.region_id - ); - - // Collect the change event cause by user write, which cdc write source is not - // set. For changefeed which only need the user write, - // send the `filtered_entries`, or else, send them all. - let mut filtered_entries = None; for downstream in downstreams { - if downstream.filter_loop { - let filtered = entries - .iter() - .filter(|x| !TxnSource::is_cdc_write_source_set(x.txn_source)) - .cloned() - .collect::>(); - if !filtered.is_empty() { - filtered_entries = Some(filtered); + let mut filtered_entries = Vec::with_capacity(entries.len()); + for (entry, lock_count_modify) in &entries { + if !downstream.observed_range.contains_raw_key(&entry.key) { + continue; } - break; - } - } - let region_id = self.region_id; - let send = move |downstream: &Downstream| { - // No ready downstream or a downstream that does not match the kv_api type, will - // be ignored. There will be one region that contains both Txn & Raw entries. - // The judgement here is for sending entries to downstreams with correct kv_api. - if !downstream.state.load().ready_for_change_events() || downstream.kv_api != kv_api { - return Ok(()); - } - if downstream.filter_loop && filtered_entries.is_none() { - return Ok(()); - } + if *lock_count_modify != 0 && downstream.lock_heap.is_some() { + let lock_heap = downstream.lock_heap.as_mut().unwrap(); + match lock_heap.entry(entry.start_ts.into()) { + BTreeMapEntry::Vacant(x) => { + x.insert(*lock_count_modify); + } + BTreeMapEntry::Occupied(mut x) => { + *x.get_mut() += *lock_count_modify; + assert!( + *x.get() >= 0, + "lock_count_modify should never be negative, start_ts: {}", + entry.start_ts + ); + if *x.get() == 0 { + x.remove(); + } + } + } + } - let entries_clone = if downstream.filter_loop { - downstream - .observed_range - .filter_entries(filtered_entries.clone().unwrap()) - } else { - downstream.observed_range.filter_entries(entries.clone()) - }; + if TxnSource::is_lossy_ddl_reorg_source_set(entry.txn_source) + || downstream.filter_loop + && TxnSource::is_cdc_write_source_set(entry.txn_source) + { + continue; + } - if entries_clone.is_empty() { - return Ok(()); + filtered_entries.push(entry.clone()); + } + if filtered_entries.is_empty() { + continue; } - let event = Event { - region_id, - request_id: downstream.get_req_id(), - index, + region_id: self.region_id, + request_id: downstream.req_id.0, event: Some(Event_oneof_event::Entries(EventEntries { - entries: entries_clone.into(), + entries: filtered_entries.into(), ..Default::default() })), ..Default::default() }; - - // Do not force send for real time change data events. - let force_send = false; - downstream.sink_event(event, force_send) - }; - match self.broadcast(send) { - Ok(()) => Ok(()), - Err(e) => { - self.mark_failed(); - Err(e) - } + downstream.sink_event(event, false)?; } + Ok(()) } fn sink_put( &mut self, put: PutRequest, - is_one_pc: bool, - txn_rows: &mut HashMap, (EventRow, bool)>, - raw_rows: &mut Vec, + rows_builder: &mut RowsBuilder, read_old_value: impl FnMut(&mut EventRow, TimeStamp) -> Result<()>, ) -> Result<()> { let key_mode = ApiV2::parse_key_mode(put.get_key()); if key_mode == KeyMode::Raw { - self.sink_raw_put(put, raw_rows) + self.sink_raw_put(put, rows_builder) } else { - self.sink_txn_put(put, is_one_pc, txn_rows, read_old_value) + self.sink_txn_put(put, read_old_value, rows_builder) } } - fn sink_raw_put(&mut self, mut put: PutRequest, rows: &mut Vec) -> Result<()> { + fn sink_raw_put(&mut self, mut put: PutRequest, rows: &mut RowsBuilder) -> Result<()> { let mut row = EventRow::default(); decode_rawkv(put.take_key(), put.take_value(), &mut row)?; - rows.push(row); + rows.raws.push(row); Ok(()) } fn sink_txn_put( &mut self, mut put: PutRequest, - is_one_pc: bool, - rows: &mut HashMap, (EventRow, bool)>, mut read_old_value: impl FnMut(&mut EventRow, TimeStamp) -> Result<()>, + rows: &mut RowsBuilder, ) -> Result<()> { match put.cf.as_str() { "write" => { - let (mut row, mut has_value) = (EventRow::default(), false); - if decode_write(put.take_key(), &put.value, &mut row, &mut has_value, true) { + let key = Key::from_encoded_slice(&put.key).truncate_ts().unwrap(); + let row = rows.txns_by_key.entry(key).or_default(); + if decode_write( + put.take_key(), + &put.value, + &mut row.v, + &mut row.has_value, + true, + ) { return Ok(()); } - let commit_ts = if is_one_pc { - set_event_row_type(&mut row, EventLogType::Committed); - let commit_ts = TimeStamp::from(row.commit_ts); - read_old_value(&mut row, commit_ts.prev())?; - Some(commit_ts) - } else { - // 2PC - if row.commit_ts == 0 { - None - } else { - Some(TimeStamp::from(row.commit_ts)) - } - }; - // validate commit_ts must be greater than the current resolved_ts - if let (Some(resolver), Some(commit_ts)) = (&self.resolver, commit_ts) { - let resolved_ts = resolver.resolved_ts(); - assert!( - commit_ts > resolved_ts, - "region {} commit_ts: {:?}, resolved_ts: {:?}", - self.region_id, - commit_ts, - resolved_ts - ); - } - - match rows.entry(row.key.clone()) { - HashMapEntry::Occupied(o) => { - let o = o.into_mut(); - mem::swap(&mut o.0.value, &mut row.value); - o.0 = row; - } - HashMapEntry::Vacant(v) => { - v.insert((row, has_value)); - } + if rows.is_one_pc { + set_event_row_type(&mut row.v, EventLogType::Committed); + let read_old_ts = TimeStamp::from(row.v.commit_ts).prev(); + read_old_value(&mut row.v, read_old_ts)?; } } "lock" => { - let (mut row, mut has_value) = (EventRow::default(), false); let lock = Lock::parse(put.get_value()).unwrap(); let for_update_ts = lock.for_update_ts; - if decode_lock(put.take_key(), lock, &mut row, &mut has_value) { + let txn_source = lock.txn_source; + + let key = Key::from_encoded_slice(&put.key); + let row = rows.txns_by_key.entry(key.clone()).or_default(); + if decode_lock(put.take_key(), lock, &mut row.v, &mut row.has_value) { return Ok(()); } - let read_old_ts = std::cmp::max(for_update_ts, row.start_ts.into()); - read_old_value(&mut row, read_old_ts)?; - - // In order to compute resolved ts, we must track inflight txns. - match self.resolver { - Some(ref mut resolver) => { - resolver.track_lock(row.start_ts.into(), row.key.clone(), None)?; - } - None => { - assert!(self.pending.is_some(), "region resolver not ready"); - let pending = self.pending.as_mut().unwrap(); - pending.push_pending_lock(PendingLock::Track { - key: row.key.clone(), - start_ts: row.start_ts.into(), - })?; - } - } + assert_eq!(row.lock_count_modify, 0); + let mini_lock = MiniLock::new(row.v.start_ts, txn_source); + row.lock_count_modify = self.push_lock(key, mini_lock)?; - let occupied = rows.entry(row.key.clone()).or_default(); - if occupied.1 { - assert!(!has_value); - has_value = true; - mem::swap(&mut occupied.0.value, &mut row.value); - } - *occupied = (row, has_value); + let read_old_ts = std::cmp::max(for_update_ts, row.v.start_ts.into()); + read_old_value(&mut row.v, read_old_ts)?; } "" | "default" => { let key = Key::from_encoded(put.take_key()).truncate_ts().unwrap(); - let row = rows.entry(key.into_raw().unwrap()).or_default(); - decode_default(put.take_value(), &mut row.0, &mut row.1); + let row = rows.txns_by_key.entry(key).or_default(); + decode_default(put.take_value(), &mut row.v, &mut row.has_value); } other => panic!("invalid cf {}", other), } Ok(()) } - fn sink_delete(&mut self, mut delete: DeleteRequest) -> Result<()> { + fn sink_delete(&mut self, mut delete: DeleteRequest, rows: &mut RowsBuilder) -> Result<()> { + // RawKV (API v2, and only API v2 can use CDC) has no lock and will write to + // default cf only. match delete.cf.as_str() { "lock" => { - let raw_key = Key::from_encoded(delete.take_key()).into_raw().unwrap(); - match self.resolver { - Some(ref mut resolver) => resolver.untrack_lock(&raw_key, None), - None => { - assert!(self.pending.is_some(), "region resolver not ready"); - let pending = self.pending.as_mut().unwrap(); - pending.push_pending_lock(PendingLock::Untrack { key: raw_key })?; - } + let key = Key::from_encoded(delete.take_key()); + let lock_count_modify = self.pop_lock(key.clone())?; + if lock_count_modify != 0 { + // If lock_count_modify isn't 0 it means the deletion must come from a commit + // or rollback, instead of any `Unlock` operations. + let row = rows.txns_by_key.get_mut(&key).unwrap(); + assert_eq!(row.lock_count_modify, 0); + row.lock_count_modify = lock_count_modify; } } "" | "default" | "write" => {} - other => { - panic!("invalid cf {}", other); - } + other => panic!("invalid cf {}", other), } Ok(()) } @@ -983,7 +1092,6 @@ impl Delegate { } _ => return Ok(()), }; - self.mark_failed(); Err(Error::request(store_err.into())) } @@ -993,10 +1101,9 @@ impl Delegate { } fn remove_downstream(&mut self, id: DownstreamId) -> Option { - let downstreams = self.downstreams_mut(); - if let Some(index) = downstreams.iter().position(|x| x.id == id) { - let downstream = downstreams.swap_remove(index); - if downstreams.is_empty() { + if let Some(index) = self.downstreams.iter().position(|x| x.id == id) { + let downstream = self.downstreams.swap_remove(index); + if self.downstreams.is_empty() { // Stop observing when the last downstream is removed. Otherwise the observer // will keep pushing events to the delegate. self.stop_observing(); @@ -1006,8 +1113,7 @@ impl Delegate { None } - fn check_epoch_on_ready(&self, downstream: &Downstream) -> Result<()> { - let region = self.region.as_ref().unwrap(); + fn check_epoch_on_ready(downstream: &Downstream, region: &Region) -> Result<()> { if let Err(e) = compare_region_epoch( &downstream.region_epoch, region, @@ -1020,7 +1126,7 @@ impl Delegate { "region_id" => region.id, "downstream_id" => ?downstream.id, "conn_id" => ?downstream.conn_id, - "req_id" => downstream.req_id, + "req_id" => ?downstream.req_id, "err" => ?e ); // Downstream is outdated, mark stop. @@ -1039,6 +1145,45 @@ impl Delegate { } } +#[derive(Default)] +struct RowsBuilder { + // map[Key]->(row, has_value, lock_count_modify) + txns_by_key: HashMap, + + raws: Vec, + + is_one_pc: bool, +} + +#[derive(Default)] +struct RowInBuilding { + v: EventRow, + has_value: bool, + lock_count_modify: isize, +} + +impl RowsBuilder { + fn finish_build(self) -> (Vec, Vec<(EventRow, isize)>) { + let mut txns = Vec::with_capacity(self.txns_by_key.len()); + for RowInBuilding { + v, + has_value, + lock_count_modify, + } in self.txns_by_key.into_values() + { + if v.r_type == EventLogType::Prewrite && v.op_type == EventRowOpType::Put && !has_value + { + // It's possible that a prewrite command only contains lock but without + // default. It's not documented by classic Percolator but introduced with + // Large-Transaction. Those prewrites are not complete, we must skip them. + continue; + } + txns.push((v, lock_count_modify)); + } + (self.raws, txns) + } +} + fn set_event_row_type(row: &mut EventRow, ty: EventLogType) { row.r_type = ty; } @@ -1108,29 +1253,26 @@ fn decode_write( false } -fn decode_lock(key: Vec, lock: Lock, row: &mut EventRow, has_value: &mut bool) -> bool { +fn decode_lock(key: Vec, mut lock: Lock, row: &mut EventRow, has_value: &mut bool) -> bool { + let key = Key::from_encoded(key); let op_type = match lock.lock_type { LockType::Put => EventRowOpType::Put, LockType::Delete => EventRowOpType::Delete, other => { - debug!("cdc skip lock record"; - "type" => ?other, - "start_ts" => ?lock.ts, - "key" => &log_wrappers::Value::key(&key), - "for_update_ts" => ?lock.for_update_ts); + debug!("cdc skip lock record"; "lock" => ?other, "key" => %key); return true; } }; - let key = Key::from_encoded(key); + row.start_ts = lock.ts.into_inner(); row.key = key.into_raw().unwrap(); row.op_type = op_type as _; - // used for filter out the event. see `txn_source` field for more detail. row.txn_source = lock.txn_source; set_event_row_type(row, EventLogType::Prewrite); - if let Some(value) = lock.short_value { - row.value = value; + if let Some(value) = lock.short_value.take() { + assert!(!*has_value, "unexpected lock with value: {:?}", lock); *has_value = true; + row.value = value; } false @@ -1167,21 +1309,37 @@ fn decode_default(value: Vec, row: &mut EventRow, has_value: &mut bool) { } /// Observed key range. -#[derive(Clone, Default)] +#[derive(Clone)] pub struct ObservedRange { - start_key_encoded: Vec, - end_key_encoded: Vec, - start_key_raw: Vec, - end_key_raw: Vec, - pub(crate) all_key_covered: bool, + pub start_key_encoded: Key, + pub end_key_encoded: Key, + pub start_key_raw: Vec, + pub end_key_raw: Vec, + pub all_key_covered: bool, +} + +impl Default for ObservedRange { + fn default() -> Self { + ObservedRange { + start_key_encoded: Key::from_encoded(vec![]), + end_key_encoded: Key::from_encoded(vec![]), + start_key_raw: vec![], + end_key_raw: vec![], + all_key_covered: false, + } + } } impl ObservedRange { pub fn new(start_key_encoded: Vec, end_key_encoded: Vec) -> Result { - let start_key_raw = Key::from_encoded(start_key_encoded.clone()) + let start_key_encoded = Key::from_encoded(start_key_encoded); + let end_key_encoded = Key::from_encoded(end_key_encoded); + let start_key_raw = start_key_encoded + .clone() .into_raw() .map_err(|e| Error::Other(e.into()))?; - let end_key_raw = Key::from_encoded(end_key_encoded.clone()) + let end_key_raw = end_key_encoded + .clone() .into_raw() .map_err(|e| Error::Other(e.into()))?; Ok(ObservedRange { @@ -1196,9 +1354,10 @@ impl ObservedRange { #[allow(clippy::collapsible_if)] pub fn update_region_key_range(&mut self, region: &Region) { // Check observed key range in region. - if self.start_key_encoded <= region.start_key { + if self.start_key_encoded.as_encoded() <= ®ion.start_key { if self.end_key_encoded.is_empty() - || (region.end_key <= self.end_key_encoded && !region.end_key.is_empty()) + || (®ion.end_key <= self.end_key_encoded.as_encoded() + && !region.end_key.is_empty()) { // Observed range covers the region. self.all_key_covered = true; @@ -1217,7 +1376,15 @@ impl ObservedRange { } pub fn contains_encoded_key(&self, key: &[u8]) -> bool { - self.is_key_in_range(&self.start_key_encoded, &self.end_key_encoded, key) + self.is_key_in_range( + self.start_key_encoded.as_encoded(), + self.end_key_encoded.as_encoded(), + key, + ) + } + + pub fn contains_raw_key(&self, key: &[u8]) -> bool { + self.is_key_in_range(&self.start_key_raw, &self.end_key_raw, key) } pub fn filter_entries(&self, mut entries: Vec) -> Vec { @@ -1228,8 +1395,21 @@ impl ObservedRange { entries.retain(|e| self.is_key_in_range(&self.start_key_raw, &self.end_key_raw, &e.key)); entries } + + fn to_range(&self) -> (Bound<&Key>, Bound<&Key>) { + let start = Bound::Included(&self.start_key_encoded); + let end = if self.end_key_encoded.is_empty() { + Bound::Unbounded + } else { + Bound::Excluded(&self.end_key_encoded) + }; + (start, end) + } } +const WARN_LAG_THRESHOLD: Duration = Duration::from_secs(600); +const WARN_LAG_INTERVAL: Duration = Duration::from_secs(60); + #[cfg(test)] mod tests { use std::cell::Cell; @@ -1253,9 +1433,9 @@ mod tests { let region_epoch = region.get_region_epoch().clone(); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (sink, mut drain) = crate::channel::channel(1, quota); + let (sink, mut drain) = crate::channel::channel(1, quota.clone()); let rx = drain.drain(); - let request_id = 123; + let request_id = RequestId(123); let mut downstream = Downstream::new( String::new(), region_epoch, @@ -1266,32 +1446,24 @@ mod tests { ObservedRange::default(), ); downstream.set_sink(sink); - let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); - let mut delegate = Delegate::new(region_id, Default::default(), memory_quota); + + let mut delegate = Delegate::new(region_id, quota, Default::default()); delegate.subscribe(downstream).unwrap(); assert!(delegate.handle.is_observing()); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let resolver = Resolver::new(region_id, memory_quota); - assert!( - delegate - .on_region_ready(resolver, region) - .unwrap() - .is_empty() - ); - assert!(delegate.downstreams()[0].observed_range.all_key_covered); + + assert!(delegate.init_lock_tracker()); + let fails = delegate + .finish_scan_locks(region, Default::default()) + .unwrap(); + assert!(fails.is_empty()); + assert!(delegate.downstreams[0].observed_range.all_key_covered); let rx_wrap = Cell::new(Some(rx)); let receive_error = || { let (event, rx) = block_on(rx_wrap.replace(None).unwrap().into_future()); rx_wrap.set(Some(rx)); - let event = event.unwrap(); - assert!( - matches!(event.0, CdcEvent::Event(_)), - "unknown event {:?}", - event - ); - if let CdcEvent::Event(mut e) = event.0 { - assert_eq!(e.get_request_id(), request_id); + if let CdcEvent::Event(mut e) = event.unwrap().0 { + assert_eq!(e.get_request_id(), request_id.0); let event = e.event.take().unwrap(); match event { Event_oneof_event::Error(err) => err, @@ -1384,8 +1556,8 @@ mod tests { #[test] fn test_delegate_subscribe_unsubscribe() { - let new_downstream = |id: u64, region_version: u64| { - let peer = format!("{}", id); + let new_downstream = |id: RequestId, region_version: u64| { + let peer = format!("{:?}", id); let mut epoch = RegionEpoch::default(); epoch.set_conf_ver(region_version); epoch.set_version(region_version); @@ -1403,19 +1575,19 @@ mod tests { // Create a new delegate. let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); let txn_extra_op = Arc::new(AtomicCell::new(TxnExtraOp::Noop)); - let mut delegate = Delegate::new(1, txn_extra_op.clone(), memory_quota); + let mut delegate = Delegate::new(1, memory_quota, txn_extra_op.clone()); assert_eq!(txn_extra_op.load(), TxnExtraOp::Noop); assert!(delegate.handle.is_observing()); // Subscribe once. - let downstream1 = new_downstream(1, 1); + let downstream1 = new_downstream(RequestId(1), 1); let downstream1_id = downstream1.id; delegate.subscribe(downstream1).unwrap(); assert_eq!(txn_extra_op.load(), TxnExtraOp::ReadOldValue); assert!(delegate.handle.is_observing()); // Subscribe twice and then unsubscribe the second downstream. - let downstream2 = new_downstream(2, 1); + let downstream2 = new_downstream(RequestId(2), 1); let downstream2_id = downstream2.id; delegate.subscribe(downstream2).unwrap(); assert!(!delegate.unsubscribe(downstream2_id, None)); @@ -1423,14 +1595,14 @@ mod tests { assert!(delegate.handle.is_observing()); // `on_region_ready` when the delegate isn't resolved. - delegate.subscribe(new_downstream(1, 2)).unwrap(); + delegate.subscribe(new_downstream(RequestId(1), 2)).unwrap(); let mut region = Region::default(); region.mut_region_epoch().set_conf_ver(1); region.mut_region_epoch().set_version(1); { - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); + assert!(delegate.init_lock_tracker()); let failures = delegate - .on_region_ready(Resolver::new(1, memory_quota), region) + .finish_scan_locks(region, Default::default()) .unwrap(); assert_eq!(failures.len(), 1); let id = failures[0].0.id; @@ -1441,7 +1613,9 @@ mod tests { assert!(delegate.handle.is_observing()); // Subscribe with an invalid epoch. - delegate.subscribe(new_downstream(1, 2)).unwrap_err(); + delegate + .subscribe(new_downstream(RequestId(1), 2)) + .unwrap_err(); assert_eq!(delegate.downstreams().len(), 1); // Unsubscribe all downstreams. @@ -1524,10 +1698,11 @@ mod tests { .unwrap(); let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); let txn_extra_op = Arc::new(AtomicCell::new(TxnExtraOp::Noop)); - let mut delegate = Delegate::new(1, txn_extra_op, memory_quota); + let mut delegate = Delegate::new(1, memory_quota, txn_extra_op); assert!(delegate.handle.is_observing()); + assert!(delegate.init_lock_tracker()); - let mut map = HashMap::default(); + let mut rows_builder = RowsBuilder::default(); for k in b'a'..=b'e' { let mut put = PutRequest::default(); put.key = Key::from_raw(&[k]).into_encoded(); @@ -1537,7 +1712,7 @@ mod tests { put.key.clone(), 1.into(), 10, - None, + Some(b"test".to_vec()), TimeStamp::zero(), 0, TimeStamp::zero(), @@ -1545,35 +1720,26 @@ mod tests { ) .to_bytes(); delegate - .sink_txn_put( - put, - false, - &mut map, - |_: &mut EventRow, _: TimeStamp| Ok(()), - ) + .sink_txn_put(put, |_, _| Ok(()), &mut rows_builder) .unwrap(); } - assert_eq!(map.len(), 5); + assert_eq!(rows_builder.txns_by_key.len(), 5); let (sink, mut drain) = channel(1, Arc::new(MemoryQuota::new(1024))); - let downstream = Downstream { - id: DownstreamId::new(), - req_id: 1, - conn_id: ConnId::new(), - peer: String::new(), - region_epoch: RegionEpoch::default(), - sink: Some(sink), - state: Arc::new(AtomicCell::new(DownstreamState::Normal)), - scan_truncated: Arc::new(Default::default()), - kv_api: ChangeDataRequestKvApi::TiDb, - filter_loop: false, + let mut downstream = Downstream::new( + "peer".to_owned(), + RegionEpoch::default(), + RequestId(1), + ConnId::new(), + ChangeDataRequestKvApi::TiDb, + false, observed_range, - }; + ); + downstream.set_sink(sink); + downstream.get_state().store(DownstreamState::Normal); delegate.add_downstream(downstream); - let entries = map.values().map(|(r, _)| r).cloned().collect(); - delegate - .sink_downstream(entries, 1, ChangeDataRequestKvApi::TiDb) - .unwrap(); + let (_, entries) = rows_builder.finish_build(); + delegate.sink_downstream_tidb(entries).unwrap(); let (mut tx, mut rx) = futures::channel::mpsc::unbounded(); let runtime = tokio::runtime::Runtime::new().unwrap(); @@ -1595,10 +1761,11 @@ mod tests { .unwrap(); let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); let txn_extra_op = Arc::new(AtomicCell::new(TxnExtraOp::Noop)); - let mut delegate = Delegate::new(1, txn_extra_op, memory_quota); + let mut delegate = Delegate::new(1, memory_quota, txn_extra_op); assert!(delegate.handle.is_observing()); + assert!(delegate.init_lock_tracker()); - let mut map = HashMap::default(); + let mut rows_builder = RowsBuilder::default(); for k in b'a'..=b'e' { let mut put = PutRequest::default(); put.key = Key::from_raw(&[k]).into_encoded(); @@ -1608,7 +1775,7 @@ mod tests { put.key.clone(), 1.into(), 10, - None, + Some(b"test".to_vec()), TimeStamp::zero(), 0, TimeStamp::zero(), @@ -1620,35 +1787,26 @@ mod tests { } put.value = lock.to_bytes(); delegate - .sink_txn_put( - put, - false, - &mut map, - |_: &mut EventRow, _: TimeStamp| Ok(()), - ) + .sink_txn_put(put, |_, _| Ok(()), &mut rows_builder) .unwrap(); } - assert_eq!(map.len(), 5); + assert_eq!(rows_builder.txns_by_key.len(), 5); let (sink, mut drain) = channel(1, Arc::new(MemoryQuota::new(1024))); - let downstream = Downstream { - id: DownstreamId::new(), - req_id: 1, - conn_id: ConnId::new(), - peer: String::new(), - region_epoch: RegionEpoch::default(), - sink: Some(sink), - state: Arc::new(AtomicCell::new(DownstreamState::Normal)), - scan_truncated: Arc::new(Default::default()), - kv_api: ChangeDataRequestKvApi::TiDb, + let mut downstream = Downstream::new( + "peer".to_owned(), + RegionEpoch::default(), + RequestId(1), + ConnId::new(), + ChangeDataRequestKvApi::TiDb, filter_loop, observed_range, - }; + ); + downstream.set_sink(sink); + downstream.get_state().store(DownstreamState::Normal); delegate.add_downstream(downstream); - let entries = map.values().map(|(r, _)| r).cloned().collect(); - delegate - .sink_downstream(entries, 1, ChangeDataRequestKvApi::TiDb) - .unwrap(); + let (_, entries) = rows_builder.finish_build(); + delegate.sink_downstream_tidb(entries).unwrap(); let (mut tx, mut rx) = futures::channel::mpsc::unbounded(); let runtime = tokio::runtime::Runtime::new().unwrap(); @@ -1726,4 +1884,66 @@ mod tests { } } } + + #[test] + fn test_lock_tracker() { + let quota = Arc::new(MemoryQuota::new(usize::MAX)); + let mut delegate = Delegate::new(1, quota.clone(), Default::default()); + assert!(delegate.init_lock_tracker()); + assert!(!delegate.init_lock_tracker()); + + let mut k1 = Vec::with_capacity(100); + k1.extend_from_slice(Key::from_raw(b"key1").as_encoded()); + let k1 = Key::from_encoded(k1); + assert_eq!(delegate.push_lock(k1, MiniLock::from_ts(100)).unwrap(), 0); + assert_eq!(quota.in_use(), 100); + + delegate.pop_lock(Key::from_raw(b"key1")).unwrap(); + assert_eq!(quota.in_use(), 117); + + let mut k2 = Vec::with_capacity(200); + k2.extend_from_slice(Key::from_raw(b"key2").as_encoded()); + let k2 = Key::from_encoded(k2); + assert_eq!(delegate.push_lock(k2, MiniLock::from_ts(100)).unwrap(), 0); + assert_eq!(quota.in_use(), 317); + + let mut scaned_locks = BTreeMap::default(); + scaned_locks.insert(Key::from_raw(b"key1"), MiniLock::from_ts(100)); + scaned_locks.insert(Key::from_raw(b"key2"), MiniLock::from_ts(100)); + scaned_locks.insert(Key::from_raw(b"key3"), MiniLock::from_ts(100)); + delegate + .finish_prepare_lock_tracker(Default::default(), scaned_locks) + .unwrap(); + assert_eq!(quota.in_use(), 34); + + delegate.pop_lock(Key::from_raw(b"key2")).unwrap(); + delegate.pop_lock(Key::from_raw(b"key3")).unwrap(); + assert_eq!(quota.in_use(), 0); + + let v = delegate + .push_lock(Key::from_raw(b"key1"), MiniLock::from_ts(300)) + .unwrap(); + assert_eq!(v, 1); + assert_eq!(quota.in_use(), 17); + let v = delegate + .push_lock(Key::from_raw(b"key1"), MiniLock::from_ts(300)) + .unwrap(); + assert_eq!(v, 0); + assert_eq!(quota.in_use(), 17); + } + + #[test] + fn test_lock_tracker_untrack_vacant() { + let quota = Arc::new(MemoryQuota::new(usize::MAX)); + let mut delegate = Delegate::new(1, quota.clone(), Default::default()); + assert!(delegate.init_lock_tracker()); + assert!(!delegate.init_lock_tracker()); + + delegate.pop_lock(Key::from_raw(b"key1")).unwrap(); + let mut scaned_locks = BTreeMap::default(); + scaned_locks.insert(Key::from_raw(b"key2"), MiniLock::from_ts(100)); + delegate + .finish_prepare_lock_tracker(Default::default(), scaned_locks) + .unwrap(); + } } diff --git a/components/cdc/src/endpoint.rs b/components/cdc/src/endpoint.rs index a436da351c1..9bfe2fd88e6 100644 --- a/components/cdc/src/endpoint.rs +++ b/components/cdc/src/endpoint.rs @@ -1,12 +1,11 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - cell::RefCell, cmp::{Ord, Ordering as CmpOrdering, PartialOrd, Reverse}, - collections::BinaryHeap, + collections::{BTreeMap, BinaryHeap}, fmt, sync::{ - atomic::{AtomicIsize, Ordering}, + atomic::{AtomicBool, AtomicIsize, Ordering}, Arc, Mutex as StdMutex, }, time::Duration, @@ -34,9 +33,9 @@ use pd_client::{Feature, PdClient}; use raftstore::{ coprocessor::{CmdBatch, ObserveId}, router::CdcHandle, - store::fsm::{store::StoreRegionMeta, ChangeObserver}, + store::fsm::store::StoreRegionMeta, }; -use resolved_ts::{resolve_by_raft, LeadershipResolver, Resolver}; +use resolved_ts::{resolve_by_raft, LeadershipResolver}; use security::SecurityManager; use tikv::{ config::{CdcConfig, ResolvedTsConfig}, @@ -57,40 +56,35 @@ use tokio::{ runtime::{Builder, Runtime}, sync::Semaphore, }; -use txn_types::{TimeStamp, TxnExtra, TxnExtraScheduler}; +use txn_types::{Key, TimeStamp, TxnExtra, TxnExtraScheduler}; use crate::{ channel::{CdcEvent, SendError}, - delegate::{on_init_downstream, Delegate, Downstream, DownstreamId, DownstreamState}, + delegate::{on_init_downstream, Delegate, Downstream, DownstreamId, DownstreamState, MiniLock}, initializer::Initializer, metrics::*, old_value::{OldValueCache, OldValueCallback}, - service::{validate_kv_api, Conn, ConnId, FeatureGate}, + service::{validate_kv_api, Conn, ConnId, FeatureGate, RequestId}, CdcObserver, Error, }; const FEATURE_RESOLVED_TS_STORE: Feature = Feature::require(5, 0, 0); const METRICS_FLUSH_INTERVAL: u64 = 1_000; // 1s -// 10 minutes, it's the default gc life time of TiDB -// and is long enough for most transactions. -const WARN_RESOLVED_TS_LAG_THRESHOLD: Duration = Duration::from_secs(600); -// Suppress repeat resolved ts lag warning. -const WARN_RESOLVED_TS_COUNT_THRESHOLD: usize = 10; pub enum Deregister { Conn(ConnId), Request { conn_id: ConnId, - request_id: u64, + request_id: RequestId, }, Region { conn_id: ConnId, - request_id: u64, + request_id: RequestId, region_id: u64, }, Downstream { conn_id: ConnId, - request_id: u64, + request_id: RequestId, region_id: u64, downstream_id: DownstreamId, err: Option, @@ -169,7 +163,6 @@ pub enum Task { Register { request: ChangeDataRequest, downstream: Downstream, - conn_id: ConnId, }, Deregister(Deregister), OpenConn { @@ -189,10 +182,10 @@ pub enum Task { min_ts: TimeStamp, current_ts: TimeStamp, }, - ResolverReady { + FinishScanLocks { observe_id: ObserveId, region: Region, - resolver: Resolver, + locks: BTreeMap, }, RegisterMinTsEvent { leader_resolver: LeadershipResolver, @@ -203,11 +196,13 @@ pub enum Task { // the downstream switches to Normal after the previous commands was sunk. InitDownstream { region_id: u64, + observe_id: ObserveId, downstream_id: DownstreamId, downstream_state: Arc>, + sink: crate::channel::Sink, + build_resolver: Arc, // `incremental_scan_barrier` will be sent into `sink` to ensure all delta changes // are delivered to the downstream. And then incremental scan can start. - sink: crate::channel::Sink, incremental_scan_barrier: CdcEvent, cb: InitCallback, }, @@ -225,14 +220,13 @@ impl fmt::Debug for Task { Task::Register { ref request, ref downstream, - ref conn_id, .. } => de .field("type", &"register") .field("register request", request) .field("request", request) - .field("id", &downstream.get_id()) - .field("conn_id", conn_id) + .field("id", &downstream.id) + .field("conn_id", &downstream.conn_id) .finish(), Task::Deregister(deregister) => de .field("type", &"deregister") @@ -265,12 +259,12 @@ impl fmt::Debug for Task { .field("current_ts", current_ts) .field("min_ts", min_ts) .finish(), - Task::ResolverReady { + Task::FinishScanLocks { ref observe_id, ref region, .. } => de - .field("type", &"resolver_ready") + .field("type", &"finish_scan_locks") .field("observe_id", &observe_id) .field("region_id", ®ion.get_id()) .finish(), @@ -279,11 +273,13 @@ impl fmt::Debug for Task { } Task::InitDownstream { ref region_id, + ref observe_id, ref downstream_id, .. } => de .field("type", &"init_downstream") .field("region_id", ®ion_id) + .field("observe_id", &observe_id) .field("downstream", &downstream_id) .finish(), Task::TxnExtra(_) => de.field("type", &"txn_extra").finish(), @@ -299,8 +295,8 @@ impl fmt::Debug for Task { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -struct ResolvedRegion { +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) struct ResolvedRegion { region_id: u64, resolved_ts: TimeStamp, } @@ -317,13 +313,14 @@ impl Ord for ResolvedRegion { } } -struct ResolvedRegionHeap { +#[derive(Default, Debug)] +pub(crate) struct ResolvedRegionHeap { // BinaryHeap is max heap, so we reverse order to get a min heap. heap: BinaryHeap>, } impl ResolvedRegionHeap { - fn push(&mut self, region_id: u64, resolved_ts: TimeStamp) { + pub(crate) fn push(&mut self, region_id: u64, resolved_ts: TimeStamp) { self.heap.push(Reverse(ResolvedRegion { region_id, resolved_ts, @@ -350,14 +347,118 @@ impl ResolvedRegionHeap { fn is_empty(&self) -> bool { self.heap.is_empty() } +} - fn clear(&mut self) { - self.heap.clear(); - } +#[derive(Default, Debug)] +pub(crate) struct Advance { + // multiplexing means one region can be subscribed multiple times in one `Conn`, + // in which case progresses are grouped by (ConnId, request_id). + pub(crate) multiplexing: HashMap<(ConnId, RequestId), ResolvedRegionHeap>, + + // exclusive means one region can only be subscribed one time in one `Conn`, + // in which case progresses are grouped by ConnId. + pub(crate) exclusive: HashMap, + + // To be compatible with old TiCDC client before v4.0.8. + // TODO(qupeng): we can deprecate support for too old TiCDC clients. + // map[(ConnId, region_id)]->(request_id, ts). + pub(crate) compat: HashMap<(ConnId, u64), (RequestId, TimeStamp)>, + + pub(crate) scan_finished: usize, + + pub(crate) blocked_on_scan: usize, + + pub(crate) blocked_on_locks: usize, + + min_resolved_ts: u64, + min_ts_region_id: u64, +} + +impl Advance { + fn emit_resolved_ts(&mut self, connections: &HashMap) { + let handle_send_result = |conn: &Conn, res: Result<(), SendError>| match res { + Ok(_) => {} + Err(SendError::Disconnected) => { + debug!("cdc send event failed, disconnected"; + "conn_id" => ?conn.get_id(), "downstream" => ?conn.get_peer()); + } + Err(SendError::Full) | Err(SendError::Congested) => { + info!("cdc send event failed, full"; + "conn_id" => ?conn.get_id(), "downstream" => ?conn.get_peer()); + } + }; + + let mut batch_min_resolved_ts = 0; + let mut batch_min_ts_region_id = 0; + let mut batch_send = |ts: u64, conn: &Conn, req_id: RequestId, regions: Vec| { + if batch_min_resolved_ts == 0 || batch_min_resolved_ts > ts { + batch_min_resolved_ts = ts; + if !regions.is_empty() { + batch_min_ts_region_id = regions[0]; + } + } + + let mut resolved_ts = ResolvedTs::default(); + resolved_ts.ts = ts; + resolved_ts.request_id = req_id.0; + *resolved_ts.mut_regions() = regions; + + let res = conn + .get_sink() + .unbounded_send(CdcEvent::ResolvedTs(resolved_ts), false); + handle_send_result(conn, res); + }; + + let mut compat_min_resolved_ts = 0; + let mut compat_min_ts_region_id = 0; + let mut compat_send = |ts: u64, conn: &Conn, region_id: u64, req_id: RequestId| { + if compat_min_resolved_ts == 0 || compat_min_resolved_ts > ts { + compat_min_resolved_ts = ts; + compat_min_ts_region_id = region_id; + } - fn reset_and_shrink_to(&mut self, min_capacity: usize) { - self.clear(); - self.heap.shrink_to(min_capacity); + let event = Event { + region_id, + request_id: req_id.0, + event: Some(Event_oneof_event::ResolvedTs(ts)), + ..Default::default() + }; + let res = conn + .get_sink() + .unbounded_send(CdcEvent::Event(event), false); + handle_send_result(conn, res); + }; + + let multiplexing = std::mem::take(&mut self.multiplexing).into_iter(); + let exclusive = std::mem::take(&mut self.exclusive).into_iter(); + let unioned = multiplexing + .map(|((a, b), c)| (a, b, c)) + .chain(exclusive.map(|(a, c)| (a, RequestId(0), c))); + + for (conn_id, req_id, mut region_ts_heap) in unioned { + let conn = connections.get(&conn_id).unwrap(); + let mut batch_count = 8; + while !region_ts_heap.is_empty() { + let (ts, regions) = region_ts_heap.pop(batch_count); + if conn.features().contains(FeatureGate::BATCH_RESOLVED_TS) { + batch_send(ts.into_inner(), conn, req_id, Vec::from_iter(regions)); + } + batch_count *= 4; + } + } + + for ((conn_id, region_id), (req_id, ts)) in std::mem::take(&mut self.compat) { + let conn = connections.get(&conn_id).unwrap(); + compat_send(ts.into_inner(), conn, region_id, req_id); + } + + if batch_min_resolved_ts > 0 { + self.min_resolved_ts = batch_min_resolved_ts; + self.min_ts_region_id = batch_min_ts_region_id; + } else { + self.min_resolved_ts = compat_min_resolved_ts; + self.min_ts_region_id = compat_min_ts_region_id; + } } } @@ -384,9 +485,8 @@ pub struct Endpoint { resolved_ts_config: ResolvedTsConfig, api_version: ApiVersion, - // Incremental scan + // Incremental scan stuffs. workers: Runtime, - // The total number of scan tasks including running and pending. scan_task_counter: Arc, scan_concurrency_semaphore: Arc, scan_speed_limiter: Limiter, @@ -396,7 +496,6 @@ pub struct Endpoint { sink_memory_quota: Arc, old_value_cache: OldValueCache, - resolved_region_heap: RefCell, causal_ts_provider: Option>, @@ -406,7 +505,6 @@ pub struct Endpoint { min_ts_region_id: u64, resolved_region_count: usize, unresolved_region_count: usize, - warn_resolved_ts_repeat_count: usize, } impl, E: KvEngine, S: StoreRegionMeta> Endpoint { @@ -476,41 +574,42 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, E: KvEngine, S: StoreRegionMeta> Endpoint, E: KvEngine, S: StoreRegionMeta> Endpoint conn, @@ -709,7 +804,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint region_id, "conn_id" => ?conn_id, - "req_id" => request_id, + "req_id" => ?request_id, "downstream_id" => ?downstream_id); return; } @@ -747,11 +842,11 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint self.config.incremental_scan_concurrency_limit as isize { + if scan_task_count >= self.config.incremental_scan_concurrency_limit as isize { debug!("cdc rejects registration, too many scan tasks"; "region_id" => region_id, "conn_id" => ?conn_id, - "req_id" => request_id, + "req_id" => ?request_id, "scan_task_count" => scan_task_count, "incremental_scan_concurrency_limit" => self.config.incremental_scan_concurrency_limit, ); @@ -786,7 +881,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint region_id, "conn_id" => ?conn_id, - "req_id" => request_id, + "req_id" => ?request_id, "downstream_id" => ?downstream_id); return; } @@ -798,8 +893,8 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, E: KvEngine, S: StoreRegionMeta> Endpoint region_id, "conn_id" => ?conn.get_id(), - "req_id" => request_id, + "req_id" => ?request_id, "observe_id" => ?observe_id, "downstream_id" => ?downstream_id); + let observed_range = downstream.observed_range.clone(); let downstream_state = downstream.get_state(); - let checkpoint_ts = request.checkpoint_ts; let sched = self.scheduler.clone(); + let scan_truncated = downstream.scan_truncated.clone(); - let downstream_ = downstream.clone(); - if let Err(err) = delegate.subscribe(downstream) { + if let Err((err, downstream)) = delegate.subscribe(downstream) { let error_event = err.into_error_event(region_id); - let _ = downstream_.sink_error_event(region_id, error_event); + let _ = downstream.sink_error_event(region_id, error_event); conn.unsubscribe(request_id, region_id); if is_new_delegate { self.capture_regions.remove(®ion_id); @@ -839,43 +934,39 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint { CDC_SCAN_TASKS.with_label_values(&["finish"]).inc(); } @@ -883,7 +974,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint region_id, - "conn_id" => ?init.conn_id, "request_id" => init.request_id, + "conn_id" => ?init.conn_id, "request_id" => ?init.request_id, ); init.deregister_downstream(e) } @@ -909,7 +1000,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, E: KvEngine, S: StoreRegionMeta> Endpoint, + ) { let region_id = region.get_id(); let mut deregisters = Vec::new(); if let Some(delegate) = self.capture_regions.get_mut(®ion_id) { if delegate.handle.id == observe_id { - match delegate.on_region_ready(resolver, region) { + match delegate.finish_scan_locks(region, locks) { Ok(fails) => { for (downstream, e) in fails { deregisters.push(Deregister::Downstream { - conn_id: downstream.get_conn_id(), - request_id: downstream.get_req_id(), + conn_id: downstream.conn_id, + request_id: downstream.req_id, region_id, - downstream_id: downstream.get_id(), + downstream_id: downstream.id, err: Some(e), }); } @@ -955,7 +1051,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint ?delegate.handle.id); } } else { - debug!("cdc region not found on region ready (finish building resolver)"; + debug!("cdc region not found on region ready (finish scan locks)"; "region_id" => region.get_id()); } @@ -966,184 +1062,21 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, min_ts: TimeStamp, current_ts: TimeStamp) { - // Reset resolved_regions to empty. - let mut resolved_regions = self.resolved_region_heap.borrow_mut(); - resolved_regions.clear(); - - let total_region_count = regions.len(); - self.min_resolved_ts = TimeStamp::max(); - let mut advance_ok = 0; - let mut advance_failed_none = 0; - let mut advance_failed_same = 0; - let mut advance_failed_stale = 0; - for region_id in regions { - if let Some(delegate) = self.capture_regions.get_mut(®ion_id) { - let old_resolved_ts = delegate - .resolver - .as_ref() - .map_or(TimeStamp::zero(), |r| r.resolved_ts()); - if old_resolved_ts > min_ts { - advance_failed_stale += 1; - } - if let Some(resolved_ts) = delegate.on_min_ts(min_ts) { - if resolved_ts < self.min_resolved_ts { - self.min_resolved_ts = resolved_ts; - self.min_ts_region_id = region_id; - } - resolved_regions.push(region_id, resolved_ts); - if resolved_ts == old_resolved_ts { - advance_failed_same += 1; - } else { - advance_ok += 1; - } - } else { - advance_failed_none += 1; - } - } - } self.current_ts = current_ts; - let lag_millis = min_ts - .physical() - .saturating_sub(self.min_resolved_ts.physical()); - if Duration::from_millis(lag_millis) > WARN_RESOLVED_TS_LAG_THRESHOLD { - self.warn_resolved_ts_repeat_count += 1; - if self.warn_resolved_ts_repeat_count >= WARN_RESOLVED_TS_COUNT_THRESHOLD { - self.warn_resolved_ts_repeat_count = 0; - warn!("cdc resolved ts lag too large"; - "min_resolved_ts" => self.min_resolved_ts, - "min_ts_region_id" => self.min_ts_region_id, - "min_ts" => min_ts, - "lag" => ?Duration::from_millis(lag_millis), - "ok" => advance_ok, - "none" => advance_failed_none, - "stale" => advance_failed_stale, - "same" => advance_failed_same); - } - } - self.resolved_region_count = resolved_regions.heap.len(); - self.unresolved_region_count = total_region_count - self.resolved_region_count; + self.min_resolved_ts = current_ts; - // Separate broadcasting outlier regions and normal regions, - // so 1) downstreams know where they should send resolve lock requests, - // and 2) resolved ts of normal regions does not fallback. - // - // Regions are separated exponentially to reduce resolved ts events and - // save CPU for both TiKV and TiCDC. - let mut batch_count = 8; - while !resolved_regions.is_empty() { - let (outlier_min_resolved_ts, outlier_regions) = resolved_regions.pop(batch_count); - self.broadcast_resolved_ts(outlier_min_resolved_ts, outlier_regions); - batch_count *= 4; - } - } - - fn broadcast_resolved_ts(&self, min_resolved_ts: TimeStamp, regions: HashSet) { - let send_cdc_event = |ts: u64, conn: &Conn, request_id: u64, regions: Vec| { - let mut resolved_ts = ResolvedTs::default(); - resolved_ts.ts = ts; - resolved_ts.request_id = request_id; - *resolved_ts.mut_regions() = regions; - - let force_send = false; - match conn - .get_sink() - .unbounded_send(CdcEvent::ResolvedTs(resolved_ts), force_send) - { - Ok(_) => (), - Err(SendError::Disconnected) => { - debug!("cdc send event failed, disconnected"; - "conn_id" => ?conn.get_id(), "downstream" => ?conn.get_peer()); - } - Err(SendError::Full) | Err(SendError::Congested) => { - info!("cdc send event failed, full"; - "conn_id" => ?conn.get_id(), "downstream" => ?conn.get_peer()); - } - } - }; - - // multiplexing is for STREAM_MULTIPLEXING enabled. - let mut multiplexing = HashMap::<(ConnId, u64), Vec>::default(); - // one_way is fro STREAM_MULTIPLEXING disabled. - let mut one_way = HashMap::, Vec)>::default(); - for region_id in ®ions { - let d = match self.capture_regions.get(region_id) { - Some(d) => d, - None => continue, - }; - for downstream in d.downstreams() { - if !downstream.get_state().load().ready_for_advancing_ts() { - continue; - } - let conn_id = downstream.get_conn_id(); - let features = self.connections.get(&conn_id).unwrap().features(); - if features.contains(FeatureGate::STREAM_MULTIPLEXING) { - multiplexing - .entry((conn_id, downstream.get_req_id())) - .or_insert_with(Default::default) - .push(*region_id); - } else { - let x = one_way.entry(conn_id).or_insert_with(Default::default); - x.0.push(downstream.get_req_id()); - x.1.push(*region_id); - } - } - } - - let min_resolved_ts = min_resolved_ts.into_inner(); - - for ((conn_id, request_id), regions) in multiplexing { - let conn = self.connections.get(&conn_id).unwrap(); - if conn.features().contains(FeatureGate::BATCH_RESOLVED_TS) { - send_cdc_event(min_resolved_ts, conn, request_id, regions); - } else { - for region_id in regions { - self.broadcast_resolved_ts_compact( - conn, - request_id, - region_id, - min_resolved_ts, - ); - } - } - } - for (conn_id, reqs_regions) in one_way { - let conn = self.connections.get(&conn_id).unwrap(); - if conn.features().contains(FeatureGate::BATCH_RESOLVED_TS) { - send_cdc_event(min_resolved_ts, conn, 0, reqs_regions.1); - } else { - for i in 0..reqs_regions.0.len() { - self.broadcast_resolved_ts_compact( - conn, - reqs_regions.0[i], - reqs_regions.1[i], - min_resolved_ts, - ); - } + let mut advance = Advance::default(); + for region_id in regions { + if let Some(d) = self.capture_regions.get_mut(®ion_id) { + d.on_min_ts(min_ts, current_ts, &self.connections, &mut advance); } } - } - fn broadcast_resolved_ts_compact( - &self, - conn: &Conn, - request_id: u64, - region_id: u64, - resolved_ts: u64, - ) { - let downstream_id = conn.get_downstream(request_id, region_id).unwrap(); - let delegate = self.capture_regions.get(®ion_id).unwrap(); - let downstream = delegate.downstream(downstream_id).unwrap(); - if !downstream.get_state().load().ready_for_advancing_ts() { - return; - } - let resolved_ts_event = Event { - region_id, - request_id, - event: Some(Event_oneof_event::ResolvedTs(resolved_ts)), - ..Default::default() - }; - let force_send = false; - let _ = downstream.sink_event(resolved_ts_event, force_send); + self.resolved_region_count = advance.scan_finished; + self.unresolved_region_count = advance.blocked_on_scan; + advance.emit_resolved_ts(&self.connections); + self.min_resolved_ts = advance.min_resolved_ts.into(); + self.min_ts_region_id = advance.min_ts_region_id; } fn register_min_ts_event(&self, mut leader_resolver: LeadershipResolver, event_time: Instant) { @@ -1180,7 +1113,6 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint pd_client.get_tso().await.unwrap_or_default(), }; let mut min_ts = min_ts_pd; - let mut min_ts_min_lock = min_ts_pd; // Sync with concurrency manager so that it can work correctly when // optimizations like async commit is enabled. @@ -1191,7 +1123,6 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, E: KvEngine, S: StoreRegionMeta> Endpoint panic!("failed to schedule min ts event, error: {:?}", err), } } - let lag_millis = min_ts_pd.physical().saturating_sub(min_ts.physical()); - if Duration::from_millis(lag_millis) > WARN_RESOLVED_TS_LAG_THRESHOLD { - // TODO: Suppress repeat logs by using WARN_RESOLVED_TS_COUNT_THRESHOLD. - info!("cdc min_ts lag too large"; - "min_ts" => min_ts, "min_ts_pd" => min_ts_pd, - "min_ts_min_lock" => min_ts_min_lock); - } }; self.tso_worker.spawn(fut); } @@ -1284,13 +1208,12 @@ impl, E: KvEngine, S: StoreRegionMeta + Send> Runnable Task::Register { request, downstream, - conn_id, - } => self.on_register(request, downstream, conn_id), - Task::ResolverReady { + } => self.on_register(request, downstream), + Task::FinishScanLocks { observe_id, - resolver, region, - } => self.on_region_ready(observe_id, resolver, region), + locks, + } => self.finish_scan_locks(observe_id, region, locks), Task::Deregister(deregister) => self.on_deregister(deregister), Task::MultiBatch { multi, @@ -1310,25 +1233,39 @@ impl, E: KvEngine, S: StoreRegionMeta + Send> Runnable } => self.register_min_ts_event(leader_resolver, event_time), Task::InitDownstream { region_id, + observe_id, downstream_id, downstream_state, sink, + build_resolver, incremental_scan_barrier, cb, } => { + match self.capture_regions.get_mut(®ion_id) { + Some(delegate) if delegate.handle.id == observe_id => { + if delegate.init_lock_tracker() { + build_resolver.store(true, Ordering::Release); + } + } + _ => return, + } if let Err(e) = sink.unbounded_send(incremental_scan_barrier, true) { error!("cdc failed to schedule barrier for delta before delta scan"; "region_id" => region_id, + "observe_id" => ?observe_id, + "downstream_id" => ?downstream_id, "error" => ?e); return; } if on_init_downstream(&downstream_state) { info!("cdc downstream starts to initialize"; "region_id" => region_id, + "observe_id" => ?observe_id, "downstream_id" => ?downstream_id); } else { - warn!("cdc downstream fails to initialize"; + warn!("cdc downstream fails to initialize: canceled"; "region_id" => region_id, + "observe_id" => ?observe_id, "downstream_id" => ?downstream_id); } cb(); @@ -1355,11 +1292,6 @@ impl, E: KvEngine, S: StoreRegionMeta + Send> Runnable for Endpoint { fn on_timeout(&mut self) { - // Reclaim resolved_region_heap memory. - self.resolved_region_heap - .borrow_mut() - .reset_and_shrink_to(self.capture_regions.len()); - CDC_ENDPOINT_PENDING_TASKS.set(self.scheduler.pending_tasks() as _); CDC_CAPTURED_REGION_COUNT.set(self.capture_regions.len() as i64); CDC_REGION_RESOLVE_STATUS_GAUGE_VEC @@ -1608,7 +1540,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::RawKv, false, @@ -1618,7 +1550,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) .unwrap() @@ -1644,7 +1575,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 2, + RequestId(2), conn_id, ChangeDataRequestKvApi::TxnKv, false, @@ -1654,7 +1585,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) .unwrap() @@ -1681,7 +1611,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 3, + RequestId(3), conn_id, ChangeDataRequestKvApi::TxnKv, false, @@ -1691,7 +1621,6 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) .unwrap() @@ -1892,7 +1821,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -1901,7 +1830,6 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); @@ -1945,7 +1873,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -1954,7 +1882,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); suite @@ -1967,7 +1894,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -1976,7 +1903,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) .unwrap() @@ -2012,7 +1938,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2022,7 +1948,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); // Region 100 is inserted into capture_regions. assert_eq!(suite.endpoint.capture_regions.len(), 2); @@ -2045,7 +1970,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2054,7 +1979,6 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); // Drop CaptureChange message, it should cause scan task failure. let timeout = Duration::from_millis(100); @@ -2062,9 +1986,9 @@ mod tests { assert_eq!(suite.endpoint.capture_regions.len(), 3); let task = suite.task_rx.recv_timeout(timeout).unwrap(); match task.unwrap() { - Task::Deregister(Deregister::Delegate { region_id, err, .. }) => { + Task::Deregister(Deregister::Downstream { region_id, err, .. }) => { assert_eq!(region_id, 101); - assert!(matches!(err, Error::Other(_)), "{:?}", err); + assert!(matches!(err, Some(Error::Other(_))), "{:?}", err); } other => panic!("unexpected task {:?}", other), } @@ -2112,7 +2036,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2121,7 +2045,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); @@ -2130,7 +2053,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 2, + RequestId(2), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2139,7 +2062,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) .unwrap() @@ -2217,7 +2139,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2227,12 +2149,14 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let resolver = Resolver::new(1, memory_quota); let observe_id = suite.endpoint.capture_regions[&1].handle.id; - suite.on_region_ready(observe_id, resolver, region.clone()); + suite + .capture_regions + .get_mut(&1) + .unwrap() + .init_lock_tracker(); + suite.finish_scan_locks(observe_id, region.clone(), Default::default()); suite.run(Task::MinTs { regions: vec![1], min_ts: TimeStamp::from(1), @@ -2253,7 +2177,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2264,13 +2188,15 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let resolver = Resolver::new(2, memory_quota); region.set_id(2); let observe_id = suite.endpoint.capture_regions[&2].handle.id; - suite.on_region_ready(observe_id, resolver, region); + suite + .capture_regions + .get_mut(&2) + .unwrap() + .init_lock_tracker(); + suite.finish_scan_locks(observe_id, region, Default::default()); suite.run(Task::MinTs { regions: vec![1, 2], min_ts: TimeStamp::from(2), @@ -2306,7 +2232,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 3, + RequestId(3), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2317,13 +2243,15 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let resolver = Resolver::new(3, memory_quota); region.set_id(3); let observe_id = suite.endpoint.capture_regions[&3].handle.id; - suite.on_region_ready(observe_id, resolver, region); + suite + .capture_regions + .get_mut(&3) + .unwrap() + .init_lock_tracker(); + suite.finish_scan_locks(observe_id, region, Default::default()); suite.run(Task::MinTs { regions: vec![1, 2, 3], min_ts: TimeStamp::from(3), @@ -2383,17 +2311,16 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, ObservedRange::default(), ); - let downstream_id = downstream.get_id(); + let downstream_id = downstream.id; suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); @@ -2401,7 +2328,7 @@ mod tests { err_header.set_not_leader(Default::default()); let deregister = Deregister::Downstream { conn_id, - request_id: 0, + request_id: RequestId(0), region_id: 1, downstream_id, err: Some(Error::request(err_header.clone())), @@ -2427,23 +2354,22 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, ObservedRange::default(), ); - let new_downstream_id = downstream.get_id(); + let new_downstream_id = downstream.id; suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); let deregister = Deregister::Downstream { conn_id, - request_id: 0, + request_id: RequestId(0), region_id: 1, downstream_id, err: Some(Error::request(err_header.clone())), @@ -2454,7 +2380,7 @@ mod tests { let deregister = Deregister::Downstream { conn_id, - request_id: 0, + request_id: RequestId(0), region_id: 1, downstream_id: new_downstream_id, err: Some(Error::request(err_header.clone())), @@ -2481,7 +2407,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch, - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2490,7 +2416,6 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); let deregister = Deregister::Delegate { @@ -2538,7 +2463,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2548,14 +2473,16 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let resolver = Resolver::new(region_id, memory_quota); let observe_id = suite.endpoint.capture_regions[®ion_id].handle.id; let mut region = Region::default(); region.set_id(region_id); - suite.on_region_ready(observe_id, resolver, region); + suite + .capture_regions + .get_mut(®ion_id) + .unwrap() + .init_lock_tracker(); + suite.finish_scan_locks(observe_id, region, Default::default()); } } @@ -2665,7 +2592,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch_2.clone(), - 0, + RequestId(0), conn_id_a, ChangeDataRequestKvApi::TiDb, false, @@ -2674,7 +2601,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id: conn_id_a, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); let observe_id = suite.endpoint.capture_regions[&1].handle.id; @@ -2689,7 +2615,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch_1, - 0, + RequestId(0), conn_id_b, ChangeDataRequestKvApi::TiDb, false, @@ -2698,7 +2624,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id: conn_id_b, }); assert_eq!(suite.endpoint.capture_regions.len(), 1); @@ -2710,11 +2635,15 @@ mod tests { let mut region = Region::default(); region.id = 1; region.set_region_epoch(region_epoch_2); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - suite.run(Task::ResolverReady { + suite + .capture_regions + .get_mut(&1) + .unwrap() + .init_lock_tracker(); + suite.run(Task::FinishScanLocks { observe_id, region: region.clone(), - resolver: Resolver::new(1, memory_quota), + locks: Default::default(), }); // Deregister deletgate due to epoch not match for conn b. @@ -2780,14 +2709,6 @@ mod tests { assert_eq!(ts, 3.into()); assert_eq!(regions.len(), 1); assert!(regions.contains(&3)); - - heap1.reset_and_shrink_to(3); - assert_eq!(3, heap1.heap.capacity()); - assert!(heap1.heap.is_empty()); - - heap1.push(1, 1.into()); - heap1.clear(); - assert!(heap1.heap.is_empty()); } #[test] @@ -2823,7 +2744,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 0, + RequestId(0), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2834,22 +2755,26 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); - let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let mut resolver = Resolver::new(id, memory_quota); - resolver - .track_lock(TimeStamp::compose(0, id), vec![], None) - .unwrap(); + let mut locks = BTreeMap::::default(); + locks.insert( + Key::from_encoded(vec![]), + MiniLock::from_ts(TimeStamp::compose(0, id)), + ); let mut region = Region::default(); region.id = id; region.set_region_epoch(region_epoch); + suite + .capture_regions + .get_mut(&id) + .unwrap() + .init_lock_tracker(); let failed = suite .capture_regions .get_mut(&id) .unwrap() - .on_region_ready(resolver, region) + .finish_scan_locks(region, locks) .unwrap(); assert!(failed.is_empty()); } @@ -2912,7 +2837,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2921,7 +2846,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.connections[&conn_id].downstreams_count(), 1); @@ -2930,7 +2854,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 2, + RequestId(2), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2939,7 +2863,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.connections[&conn_id].downstreams_count(), 2); @@ -2948,7 +2871,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 2, + RequestId(2), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -2957,7 +2880,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.connections[&conn_id].downstreams_count(), 2); let cdc_event = channel::recv_timeout(&mut rx, Duration::from_millis(500)) @@ -2973,7 +2895,7 @@ mod tests { // Deregister an unexist downstream. suite.run(Task::Deregister(Deregister::Downstream { conn_id, - request_id: 1, + request_id: RequestId(1), region_id: 1, downstream_id: DownstreamId::new(), err: None, @@ -2989,10 +2911,10 @@ mod tests { assert_eq!(suite.connections[&conn_id].downstreams_count(), 2); // Deregister an exist downstream. - let downstream_id = suite.capture_regions[&1].downstreams()[0].get_id(); + let downstream_id = suite.capture_regions[&1].downstreams()[0].id; suite.run(Task::Deregister(Deregister::Downstream { conn_id, - request_id: 1, + request_id: RequestId(1), region_id: 1, downstream_id, err: Some(Error::Rocks("test error".to_owned())), @@ -3013,7 +2935,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -3022,7 +2944,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.connections[&conn_id].downstreams_count(), 2); @@ -3053,7 +2974,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - i as _, + RequestId(i), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -3062,20 +2983,19 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); - assert_eq!(suite.connections[&conn_id].downstreams_count(), i); + assert_eq!(suite.connections[&conn_id].downstreams_count(), i as usize); } // Deregister the request. suite.run(Task::Deregister(Deregister::Request { conn_id, - request_id: 1, + request_id: RequestId(1), })); assert_eq!(suite.connections[&conn_id].downstreams_count(), 1); suite.run(Task::Deregister(Deregister::Request { conn_id, - request_id: 2, + request_id: RequestId(2), })); assert_eq!(suite.connections[&conn_id].downstreams_count(), 0); assert_eq!(suite.capture_regions.len(), 0); @@ -3099,7 +3019,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -3108,7 +3028,6 @@ mod tests { suite.run(Task::Register { request: req.clone(), downstream, - conn_id, }); assert_eq!(suite.connections[&conn_id].downstreams_count(), i as usize); } @@ -3116,7 +3035,7 @@ mod tests { // Deregister regions one by one in the request. suite.run(Task::Deregister(Deregister::Region { conn_id, - request_id: 1, + request_id: RequestId(1), region_id: 1, })); assert_eq!(suite.connections[&conn_id].downstreams_count(), 1); @@ -3124,7 +3043,7 @@ mod tests { suite.run(Task::Deregister(Deregister::Region { conn_id, - request_id: 1, + request_id: RequestId(1), region_id: 2, })); assert_eq!(suite.connections[&conn_id].downstreams_count(), 0); @@ -3168,7 +3087,7 @@ mod tests { let downstream = Downstream::new( "".to_string(), region_epoch.clone(), - 1, + RequestId(1), conn_id, ChangeDataRequestKvApi::TiDb, false, @@ -3177,7 +3096,6 @@ mod tests { suite.run(Task::Register { request: req, downstream, - conn_id, }); assert!(suite.connections.is_empty()); } diff --git a/components/cdc/src/initializer.rs b/components/cdc/src/initializer.rs index ed8b0f9f5ca..0330e3fca56 100644 --- a/components/cdc/src/initializer.rs +++ b/components/cdc/src/initializer.rs @@ -1,5 +1,6 @@ // Copyright 2022 TiKV Project Authors. Licensed under Apache-2.0. use std::{ + collections::BTreeMap, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -22,27 +23,25 @@ use kvproto::{ metapb::{Region, RegionEpoch}, }; use raftstore::{ - coprocessor::ObserveId, + coprocessor::ObserveHandle, router::CdcHandle, store::{ fsm::ChangeObserver, msg::{Callback, ReadResponse}, }, }; -use resolved_ts::{Resolver, TsSource}; use tikv::storage::{ kv::Snapshot, - mvcc::{DeltaScanner, ScannerBuilder}, + mvcc::{DeltaScanner, MvccReader, ScannerBuilder}, raw::raw_mvcc::{RawMvccIterator, RawMvccSnapshot}, txn::{TxnEntry, TxnEntryScanner}, Statistics, }; -use tikv_kv::Iterator; +use tikv_kv::{Iterator, ScanMode}; use tikv_util::{ box_err, codec::number, debug, defer, error, info, - memory::MemoryQuota, sys::inspector::{self_thread_inspector, ThreadInspector}, time::{duration_to_sec, Instant, Limiter}, warn, @@ -50,19 +49,22 @@ use tikv_util::{ Either, }; use tokio::sync::Semaphore; -use txn_types::{Key, KvPair, Lock, LockType, OldValue, TimeStamp}; +use txn_types::{Key, KvPair, LockType, OldValue, TimeStamp}; use crate::{ channel::CdcEvent, - delegate::{post_init_downstream, Delegate, DownstreamId, DownstreamState, ObservedRange}, + delegate::{ + post_init_downstream, Delegate, DownstreamId, DownstreamState, MiniLock, ObservedRange, + }, endpoint::Deregister, metrics::*, old_value::{near_seek_old_value, OldValueCursors}, - service::ConnId, + service::{ConnId, RequestId}, Error, Result, Task, }; -struct ScanStat { +#[derive(Copy, Clone, Debug, Default)] +pub(crate) struct ScanStat { // Fetched bytes to the scanner. emit: usize, // Bytes from the device, `None` if not possible to get it. @@ -82,20 +84,29 @@ pub(crate) enum Scanner { } pub(crate) struct Initializer { - pub(crate) tablet: Option, - pub(crate) sched: Scheduler, - pub(crate) sink: crate::channel::Sink, - - pub(crate) observed_range: ObservedRange, pub(crate) region_id: u64, + pub(crate) conn_id: ConnId, + pub(crate) request_id: RequestId, + pub(crate) checkpoint_ts: TimeStamp, pub(crate) region_epoch: RegionEpoch, - pub(crate) observe_id: ObserveId, + + // `build_resolver` can only be determined after snapshot is acquired. + // If a region is subscribed more than one times, the downstream with the + // earliest snapshot will build the lock resolver. + // + // `build_resolver` won't be changed after set in `InitDownstream`. + pub(crate) build_resolver: Arc, + + pub(crate) observed_range: ObservedRange, + pub(crate) observe_handle: ObserveHandle, pub(crate) downstream_id: DownstreamId, pub(crate) downstream_state: Arc>, pub(crate) scan_truncated: Arc, - pub(crate) conn_id: ConnId, - pub(crate) request_id: u64, - pub(crate) checkpoint_ts: TimeStamp, + + pub(crate) tablet: Option, + pub(crate) sched: Scheduler, + pub(crate) sink: crate::channel::Sink, + pub(crate) concurrency_semaphore: Arc, pub(crate) scan_speed_limiter: Limiter, pub(crate) fetch_speed_limiter: Limiter, @@ -103,23 +114,18 @@ pub(crate) struct Initializer { pub(crate) max_scan_batch_bytes: usize, pub(crate) max_scan_batch_size: usize, - pub(crate) build_resolver: bool, pub(crate) ts_filter_ratio: f64, - pub(crate) kv_api: ChangeDataRequestKvApi, - pub(crate) filter_loop: bool, } impl Initializer { - pub(crate) async fn initialize>( - &mut self, - change_observer: ChangeObserver, - cdc_handle: T, - concurrency_semaphore: Arc, - memory_quota: Arc, - ) -> Result<()> { + pub(crate) async fn initialize(&mut self, cdc_handle: T) -> Result<()> + where + T: 'static + CdcHandle, + { fail_point!("cdc_before_initialize"); + let concurrency_semaphore = self.concurrency_semaphore.clone(); let _permit = concurrency_semaphore.acquire().await; // To avoid holding too many snapshots and holding them too long, @@ -127,23 +133,30 @@ impl Initializer { let sched = self.sched.clone(); let region_id = self.region_id; let region_epoch = self.region_epoch.clone(); + let observe_id = self.observe_handle.id; let downstream_id = self.downstream_id; let downstream_state = self.downstream_state.clone(); let (cb, fut) = tikv_util::future::paired_future_callback(); let sink = self.sink.clone(); + let build_resolver = self.build_resolver.clone(); let (incremental_scan_barrier_cb, incremental_scan_barrier_fut) = tikv_util::future::paired_future_callback(); let barrier = CdcEvent::Barrier(Some(incremental_scan_barrier_cb)); if let Err(e) = cdc_handle.capture_change( self.region_id, region_epoch, - change_observer, + ChangeObserver::from_cdc(self.region_id, self.observe_handle.clone()), + // NOTE: raftstore handles requests in serial for every region. + // That's why we can determine whether to build a lock resolver or not + // without check and compare snapshot sequence number. Callback::read(Box::new(move |resp| { if let Err(e) = sched.schedule(Task::InitDownstream { region_id, + observe_id, downstream_id, downstream_state, sink, + build_resolver, incremental_scan_barrier: barrier, cb: Box::new(move || cb(resp)), }) { @@ -164,21 +177,24 @@ impl Initializer { } match fut.await { - Ok(resp) => self.on_change_cmd_response(resp, memory_quota).await, + Ok(resp) => self.on_change_cmd_response(resp).await, Err(e) => Err(Error::Other(box_err!(e))), } } - pub(crate) async fn on_change_cmd_response( + pub(crate) async fn on_change_cmd_response( &mut self, - mut resp: ReadResponse, - memory_quota: Arc, - ) -> Result<()> { + mut resp: ReadResponse, + ) -> Result<()> + where + S: EngineSnapshot + 'static, + { if let Some(region_snapshot) = resp.snapshot { let region = region_snapshot.get_region().clone(); assert_eq!(self.region_id, region.get_id()); - self.async_incremental_scan(region_snapshot, region, memory_quota) + self.async_incremental_scan(region_snapshot, region) .await + .map(|_| ()) } else { assert!( resp.response.get_header().has_error(), @@ -190,26 +206,29 @@ impl Initializer { } } - pub(crate) async fn async_incremental_scan( + pub(crate) async fn async_incremental_scan( &mut self, snap: S, region: Region, - memory_quota: Arc, - ) -> Result<()> { + ) -> Result + where + S: Snapshot + 'static, + { CDC_SCAN_TASKS.with_label_values(&["ongoing"]).inc(); defer!(CDC_SCAN_TASKS.with_label_values(&["ongoing"]).dec()); - let region_id = region.get_id(); + let region_id = self.region_id; let downstream_id = self.downstream_id; - let observe_id = self.observe_id; + let observe_id = self.observe_handle.id; let conn_id = self.conn_id; - let kv_api = self.kv_api; - let on_cancel = || -> Result<()> { - info!("cdc async incremental scan canceled"; + let on_cancel = || -> Result { + info!( + "cdc async incremental scan canceled"; "region_id" => region_id, "downstream_id" => ?downstream_id, "observe_id" => ?observe_id, - "conn_id" => ?conn_id); + "conn_id" =>?conn_id, + ); Err(box_err!("scan canceled")) }; @@ -218,31 +237,69 @@ impl Initializer { } self.observed_range.update_region_key_range(®ion); - debug!("cdc async incremental scan"; + + // Be compatible with old TiCDC clients, which won't give `observed_range`. + let (start_key, end_key): (Key, Key); + if self.observed_range.start_key_encoded.as_encoded() <= ®ion.start_key { + start_key = Key::from_encoded_slice(®ion.start_key); + } else { + start_key = self.observed_range.start_key_encoded.clone(); + } + if self.observed_range.end_key_encoded.is_empty() + || self.observed_range.end_key_encoded.as_encoded() >= ®ion.end_key + && !region.end_key.is_empty() + { + end_key = Key::from_encoded_slice(®ion.end_key); + } else { + end_key = self.observed_range.end_key_encoded.clone(); + } + + debug!( + "cdc async incremental scan"; "region_id" => region_id, "downstream_id" => ?downstream_id, - "observe_id" => ?self.observe_id, + "observe_id" => ?observe_id, + "conn_id" => ?conn_id, "all_key_covered" => ?self.observed_range.all_key_covered, - "start_key" => log_wrappers::Value::key(snap.lower_bound().unwrap_or_default()), - "end_key" => log_wrappers::Value::key(snap.upper_bound().unwrap_or_default())); + "start_key" => log_wrappers::Value::key(start_key.as_encoded()), + "end_key" => log_wrappers::Value::key(end_key.as_encoded()) + ); - let mut resolver = if self.build_resolver { - Some(Resolver::new(region_id, memory_quota)) - } else { - None + if self.build_resolver.load(Ordering::Acquire) { + // Scan and collect locks if build_resolver is true. The range + // should be the whole region span instead of subscribed span, + // because those locks will be shared between multiple Downstreams. + let mut reader = MvccReader::new(snap.clone(), Some(ScanMode::Forward), false); + let (key_locks, has_remain) = + reader.scan_locks_from_storage(None, None, |_, _| true, 0)?; + assert!(!has_remain); + let mut locks = BTreeMap::::new(); + for (key, lock) in key_locks { + // When `decode_lock`, only consider `Put` and `Delete` + if matches!(lock.lock_type, LockType::Put | LockType::Delete) { + locks.insert(key, MiniLock::new(lock.ts, lock.txn_source)); + } + } + self.finish_scan_locks(region, locks); }; let (mut hint_min_ts, mut old_value_cursors) = (None, None); - let mut scanner = if kv_api == ChangeDataRequestKvApi::TiDb { - if self.ts_filter_is_helpful(&snap) { + let mut scanner = if self.kv_api == ChangeDataRequestKvApi::TiDb { + if self.ts_filter_is_helpful(&start_key, &end_key) { hint_min_ts = Some(self.checkpoint_ts); old_value_cursors = Some(OldValueCursors::new(&snap)); } + let upper_boundary = if end_key.as_encoded().is_empty() { + // Region upper boundary could be an empty slice. + None + } else { + Some(end_key) + }; // Time range: (checkpoint_ts, max] let txnkv_scanner = ScannerBuilder::new(snap, TimeStamp::max()) .fill_cache(false) - .range(None, None) + .range(Some(start_key), upper_boundary) .hint_min_ts(hint_min_ts) .build_delta_scanner(self.checkpoint_ts, TxnExtraOp::ReadOldValue) .unwrap(); @@ -273,8 +330,8 @@ impl Initializer { DownstreamState::Initializing | DownstreamState::Stopped )); + let mut scan_stat = ScanStat::default(); let scan_long_time = AtomicBool::new(false); - defer!(if scan_long_time.load(Ordering::SeqCst) { CDC_SCAN_LONG_DURATION_REGIONS.dec(); }); @@ -285,10 +342,11 @@ impl Initializer { && start.saturating_elapsed() > Duration::from_secs(60) { CDC_SCAN_LONG_DURATION_REGIONS.inc(); - scan_long_time.store(true, Ordering::SeqCst); - warn!("cdc incremental scan takes too long"; "region_id" => region_id, "conn_id" => ?self.conn_id, - "downstream_id" => ?self.downstream_id, "takes" => ?start.saturating_elapsed()); + warn!( + "cdc incremental scan takes too long"; "region_id" => region_id, "conn_id" => ?self.conn_id, + "downstream_id" => ?self.downstream_id, "takes" => ?start.saturating_elapsed() + ); } // When downstream_state is Stopped, it means the corresponding // delegate is stopped. The initialization can be safely canceled. @@ -296,8 +354,9 @@ impl Initializer { return on_cancel(); } let cursors = old_value_cursors.as_mut(); - let resolver = resolver.as_mut(); - let entries = self.scan_batch(&mut scanner, cursors, resolver).await?; + let entries = self + .scan_batch(&mut scanner, cursors, &mut scan_stat) + .await?; if let Some(None) = entries.last() { // If the last element is None, it means scanning is finished. done = true; @@ -315,19 +374,16 @@ impl Initializer { } let takes = start.saturating_elapsed(); info!("cdc async incremental scan finished"; - "region_id" => region.get_id(), - "conn_id" => ?self.conn_id, - "downstream_id" => ?self.downstream_id, + "region_id" => region_id, + "downstream_id" => ?downstream_id, + "observe_id" => ?observe_id, + "conn_id" => ?conn_id, "takes" => ?takes, ); - if let Some(resolver) = resolver { - self.finish_building_resolver(resolver, region); - } - CDC_SCAN_DURATION_HISTOGRAM.observe(takes.as_secs_f64()); CDC_SCAN_SINK_DURATION_HISTOGRAM.observe(duration_to_sec(sink_time)); - Ok(()) + Ok(scan_stat) } // It's extracted from `Initializer::scan_batch` to avoid becoming an @@ -414,40 +470,25 @@ impl Initializer { &self, scanner: &mut Scanner, old_value_cursors: Option<&mut OldValueCursors>, - resolver: Option<&mut Resolver>, + scan_stat: &mut ScanStat, ) -> Result>> { let mut entries = Vec::with_capacity(self.max_scan_batch_size); - let ScanStat { - emit, - disk_read, - perf_delta, - } = self.do_scan(scanner, old_value_cursors, &mut entries)?; + let delta = self.do_scan(scanner, old_value_cursors, &mut entries)?; + scan_stat.emit += delta.emit; + scan_stat.perf_delta += delta.perf_delta; + if let Some(disk_read) = delta.disk_read { + *scan_stat.disk_read.get_or_insert(0) += disk_read; + } - TLS_CDC_PERF_STATS.with(|x| *x.borrow_mut() += perf_delta); + TLS_CDC_PERF_STATS.with(|x| *x.borrow_mut() += delta.perf_delta); tls_flush_perf_stats(); - if let Some(bytes) = disk_read { + if let Some(bytes) = delta.disk_read { CDC_SCAN_DISK_READ_BYTES.inc_by(bytes as _); self.scan_speed_limiter.consume(bytes).await; } - CDC_SCAN_BYTES.inc_by(emit as _); - self.fetch_speed_limiter.consume(emit as _).await; - - if let Some(resolver) = resolver { - // Track the locks. - for entry in entries.iter().flatten() { - if let KvEntry::TxnEntry(TxnEntry::Prewrite { ref lock, .. }) = entry { - let (encoded_key, value) = lock; - let key = Key::from_encoded_slice(encoded_key).into_raw().unwrap(); - let lock = Lock::parse(value)?; - match lock.lock_type { - LockType::Put | LockType::Delete => { - resolver.track_lock(lock.ts, key, None)?; - } - _ => (), - }; - } - } - } + CDC_SCAN_BYTES.inc_by(delta.emit as _); + self.fetch_speed_limiter.consume(delta.emit as _).await; + Ok(entries) } @@ -484,24 +525,22 @@ impl Initializer { Ok(()) } - fn finish_building_resolver(&self, mut resolver: Resolver, region: Region) { - let observe_id = self.observe_id; - let rts = resolver.resolve(TimeStamp::zero(), None, TsSource::Cdc); + fn finish_scan_locks(&self, region: Region, locks: BTreeMap) { + let observe_id = self.observe_handle.id; info!( - "cdc resolver initialized and schedule resolver ready"; + "cdc has scanned all incremental scan locks"; "region_id" => region.get_id(), "conn_id" => ?self.conn_id, "downstream_id" => ?self.downstream_id, - "resolved_ts" => rts, - "lock_count" => resolver.locks().len(), + "lock_count" => locks.len(), "observe_id" => ?observe_id, ); fail_point!("before_schedule_resolver_ready"); - if let Err(e) = self.sched.schedule(Task::ResolverReady { + if let Err(e) = self.sched.schedule(Task::FinishScanLocks { observe_id, - resolver, region, + locks, }) { error!("cdc schedule task failed"; "error" => ?e); } @@ -509,7 +548,8 @@ impl Initializer { // Deregister downstream when the Initializer fails to initialize. pub(crate) fn deregister_downstream(&self, err: Error) { - let deregister = if self.build_resolver || err.has_region_error() { + let build_resolver = self.build_resolver.load(Ordering::Acquire); + let deregister = if build_resolver || err.has_region_error() { // Deregister delegate on the conditions, // * It fails to build a resolver. A delegate requires a resolver to advance // resolved ts. @@ -517,7 +557,7 @@ impl Initializer { // error and can not serve. Deregister::Delegate { region_id: self.region_id, - observe_id: self.observe_id, + observe_id: self.observe_handle.id, err, } } else { @@ -535,13 +575,13 @@ impl Initializer { } } - fn ts_filter_is_helpful(&self, snap: &S) -> bool { + fn ts_filter_is_helpful(&self, start_key: &Key, end_key: &Key) -> bool { if self.ts_filter_ratio < f64::EPSILON { return false; } + let start_key = data_key(start_key.as_encoded()); + let end_key = data_end_key(end_key.as_encoded()); - let start_key = data_key(snap.lower_bound().unwrap_or_default()); - let end_key = data_end_key(snap.upper_bound().unwrap_or_default()); let range = Range::new(&start_key, &end_key); let tablet = match self.tablet.as_ref() { Some(t) => t, @@ -593,6 +633,7 @@ mod tests { collections::BTreeMap, fmt::Display, sync::{ + atomic::AtomicBool, mpsc::{channel, sync_channel, Receiver, RecvTimeoutError, Sender}, Arc, }, @@ -606,8 +647,7 @@ mod tests { cdcpb::{EventLogType, Event_oneof_event}, errorpb::Error as ErrorHeader, }; - use raftstore::{coprocessor::ObserveHandle, router::CdcRaftRouter, store::RegionSnapshot}; - use resolved_ts::TxnLocks; + use raftstore::{coprocessor::ObserveHandle, router::CdcRaftRouter}; use test_raftstore::MockRaftStoreRouter; use tikv::{ config::DbConfig, @@ -677,6 +717,19 @@ mod tests { .unwrap(); let downstream_state = Arc::new(AtomicCell::new(DownstreamState::Initializing)); let initializer = Initializer { + region_id: 1, + conn_id: ConnId::new(), + request_id: RequestId(0), + checkpoint_ts: 1.into(), + region_epoch: RegionEpoch::default(), + + build_resolver: Arc::new(AtomicBool::new(true)), + observed_range: ObservedRange::default(), + observe_handle: ObserveHandle::new(), + downstream_id: DownstreamId::new(), + downstream_state, + scan_truncated: Arc::new(Default::default()), + tablet: engine.or_else(|| { TestEngineBuilder::new() .build_without_cache() @@ -685,21 +738,13 @@ mod tests { }), sched: receiver_worker.scheduler(), sink, - observed_range: ObservedRange::default(), - region_id: 1, - region_epoch: RegionEpoch::default(), - observe_id: ObserveId::new(), - downstream_id: DownstreamId::new(), - downstream_state, - scan_truncated: Arc::new(Default::default()), - conn_id: ConnId::new(), - request_id: 0, - checkpoint_ts: 1.into(), + concurrency_semaphore: Arc::new(Semaphore::new(1)), + scan_speed_limiter: Limiter::new(scan_limit as _), fetch_speed_limiter: Limiter::new(fetch_limit as _), max_scan_batch_bytes: 1024 * 1024, max_scan_batch_size: 1024, - build_resolver: true, + ts_filter_ratio: 1.0, // always enable it. kv_api, filter_loop, @@ -709,109 +754,77 @@ mod tests { } #[test] - fn test_initializer_build_resolver() { + fn test_initializer_scan_locks() { let mut engine = TestEngineBuilder::new().build_without_cache().unwrap(); - let mut expected_locks = BTreeMap::::new(); + let mut expected_locks = BTreeMap::::new(); - // Only observe ["", "b\0x90"] + // Only observe ["b\x00", "b\0x90"] let observed_range = ObservedRange::new( - Key::from_raw(&[]).into_encoded(), + Key::from_raw(&[b'k', 0]).into_encoded(), Key::from_raw(&[b'k', 90]).into_encoded(), ) .unwrap(); - let mut total_bytes = 0; + // Pessimistic locks should not be tracked for i in 0..10 { - let k = &[b'k', i]; - total_bytes += k.len(); - let ts = TimeStamp::new(i as _); + let (k, ts) = (&[b'k', i], TimeStamp::new(i as _)); must_acquire_pessimistic_lock(&mut engine, k, k, ts, ts); } for i in 10..100 { - let (k, v) = (&[b'k', i], &[b'v', i]); - total_bytes += k.len(); - total_bytes += v.len(); - let ts = TimeStamp::new(i as _); + let (k, v, ts) = (&[b'k', i], &[b'v', i], TimeStamp::new(i as _)); must_prewrite_put(&mut engine, k, v, k, ts); - let txn_locks = expected_locks.entry(ts).or_insert_with(|| { - let mut txn_locks = TxnLocks::default(); - txn_locks.sample_lock = Some(k.to_vec().into()); - txn_locks - }); - txn_locks.lock_count += 1; + expected_locks.insert(Key::from_raw(k), MiniLock::from_ts(ts)); } let region = Region::default(); let snap = engine.snapshot(Default::default()).unwrap(); - // Buffer must be large enough to unblock async incremental scan. - let buffer = 1000; let (mut worker, pool, mut initializer, rx, mut drain) = mock_initializer( - total_bytes, - total_bytes, - buffer, + usize::MAX, + usize::MAX, + 1000, engine.kv_engine(), ChangeDataRequestKvApi::TiDb, false, ); initializer.observed_range = observed_range.clone(); + initializer.build_resolver.store(true, Ordering::Release); + initializer + .downstream_state + .store(DownstreamState::Initializing); + let check_result = || { let task = rx.recv().unwrap(); match task { - Task::ResolverReady { resolver, .. } => { - assert_eq!(resolver.locks(), &expected_locks); - } + Task::FinishScanLocks { locks, .. } => assert_eq!(locks, expected_locks), t => panic!("unexpected task {} received", t), } }; - // To not block test by barrier. + pool.spawn(async move { let mut d = drain.drain(); while let Some((e, _)) = d.next().await { if let CdcEvent::Event(e) = e { for e in e.get_entries().get_entries() { - let key = Key::from_raw(&e.key).into_encoded(); - assert!(observed_range.contains_encoded_key(&key), "{:?}", e); + if e.r_type == EventLogType::Prewrite { + let key = Key::from_raw(&e.key).into_encoded(); + assert!(observed_range.contains_encoded_key(&key)); + } } } } }); - let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); - block_on(initializer.async_incremental_scan( - snap.clone(), - region.clone(), - memory_quota.clone(), - )) - .unwrap(); - check_result(); - - initializer - .downstream_state - .store(DownstreamState::Initializing); - initializer.max_scan_batch_bytes = total_bytes; - block_on(initializer.async_incremental_scan( - snap.clone(), - region.clone(), - memory_quota.clone(), - )) - .unwrap(); + block_on(initializer.async_incremental_scan(snap.clone(), region.clone())).unwrap(); check_result(); + initializer.build_resolver.store(false, Ordering::Release); initializer .downstream_state .store(DownstreamState::Initializing); - initializer.build_resolver = false; - block_on(initializer.async_incremental_scan( - snap.clone(), - region.clone(), - memory_quota.clone(), - )) - .unwrap(); - - let task = rx.recv_timeout(Duration::from_millis(100)); - match task { + block_on(initializer.async_incremental_scan(snap.clone(), region.clone())).unwrap(); + match rx.recv_timeout(Duration::from_millis(100)) { Ok(t) => panic!("unexpected task {} received", t), Err(RecvTimeoutError::Timeout) => (), Err(e) => panic!("unexpected err {:?}", e), @@ -819,28 +832,14 @@ mod tests { // Test cancellation. initializer.downstream_state.store(DownstreamState::Stopped); - block_on(initializer.async_incremental_scan(snap.clone(), region, memory_quota.clone())) - .unwrap_err(); - - // Cancel error should trigger a deregsiter. - let mut region = Region::default(); - region.set_id(initializer.region_id); - region.mut_peers().push(Default::default()); - let snapshot = Some(RegionSnapshot::from_snapshot(snap, Arc::new(region))); - let resp = ReadResponse { - snapshot, - response: Default::default(), - txn_extra_op: Default::default(), - }; - block_on(initializer.on_change_cmd_response(resp.clone(), memory_quota.clone())) - .unwrap_err(); + block_on(initializer.async_incremental_scan(snap.clone(), region.clone())).unwrap_err(); // Disconnect sink by dropping runtime (it also drops drain). - drop(pool); initializer .downstream_state .store(DownstreamState::Initializing); - block_on(initializer.on_change_cmd_response(resp, memory_quota)).unwrap_err(); + drop(pool); + block_on(initializer.async_incremental_scan(snap, region)).unwrap_err(); worker.stop(); } @@ -869,9 +868,8 @@ mod tests { filter_loop, ); let th = pool.spawn(async move { - let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); initializer - .async_incremental_scan(snap, Region::default(), memory_quota) + .async_incremental_scan(snap, Region::default()) .await .unwrap(); }); @@ -956,9 +954,8 @@ mod tests { let snap = engine.snapshot(Default::default()).unwrap(); let th = pool.spawn(async move { - let memory_qutoa = Arc::new(MemoryQuota::new(usize::MAX)); initializer - .async_incremental_scan(snap, Region::default(), memory_qutoa) + .async_incremental_scan(snap, Region::default()) .await .unwrap(); }); @@ -1009,7 +1006,7 @@ mod tests { fn test_initializer_deregister_downstream() { let total_bytes = 1; let buffer = 1; - let (mut worker, _pool, mut initializer, rx, _drain) = mock_initializer( + let (mut worker, _pool, initializer, rx, _drain) = mock_initializer( total_bytes, total_bytes, buffer, @@ -1019,7 +1016,7 @@ mod tests { ); // Errors reported by region should deregister region. - initializer.build_resolver = false; + initializer.build_resolver.store(false, Ordering::Release); initializer.deregister_downstream(Error::request(ErrorHeader::default())); let task = rx.recv_timeout(Duration::from_millis(100)); match task { @@ -1030,7 +1027,7 @@ mod tests { Err(e) => panic!("unexpected err {:?}", e), } - initializer.build_resolver = false; + initializer.build_resolver.store(false, Ordering::Release); initializer.deregister_downstream(Error::Other(box_err!("test"))); let task = rx.recv_timeout(Duration::from_millis(100)); match task { @@ -1042,7 +1039,7 @@ mod tests { } // Test deregister region when resolver fails to build. - initializer.build_resolver = true; + initializer.build_resolver.store(true, Ordering::Release); initializer.deregister_downstream(Error::Other(box_err!("test"))); let task = rx.recv_timeout(Duration::from_millis(100)); match task { @@ -1068,24 +1065,14 @@ mod tests { let (mut worker, pool, mut initializer, _rx, _drain) = mock_initializer(total_bytes, total_bytes, buffer, None, kv_api, false); - let change_cmd = ChangeObserver::from_cdc(1, ObserveHandle::new()); let raft_router = CdcRaftRouter(MockRaftStoreRouter::new()); - let concurrency_semaphore = Arc::new(Semaphore::new(1)); - let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); - initializer.downstream_state.store(DownstreamState::Stopped); - block_on(initializer.initialize( - change_cmd, - raft_router.clone(), - concurrency_semaphore.clone(), - memory_quota.clone(), - )) - .unwrap_err(); + block_on(initializer.initialize(raft_router.clone())).unwrap_err(); let (tx, rx) = sync_channel(1); - let concurrency_semaphore_ = concurrency_semaphore.clone(); + let concurrency_semaphore = initializer.concurrency_semaphore.clone(); pool.spawn(async move { - let _permit = concurrency_semaphore_.acquire().await; + let _permit = concurrency_semaphore.acquire().await; tx.send(()).unwrap(); tx.send(()).unwrap(); tx.send(()).unwrap(); @@ -1093,19 +1080,8 @@ mod tests { rx.recv_timeout(Duration::from_millis(200)).unwrap(); let (tx1, rx1) = sync_channel(1); - let change_cmd = ChangeObserver::from_cdc(1, ObserveHandle::new()); pool.spawn(async move { - // Migrated to 2021 migration. This let statement is probably not needed, see - // https://doc.rust-lang.org/edition-guide/rust-2021/disjoint-capture-in-closures.html - let _ = ( - &initializer, - &change_cmd, - &raft_router, - &concurrency_semaphore, - ); - let res = initializer - .initialize(change_cmd, raft_router, concurrency_semaphore, memory_quota) - .await; + let res = initializer.initialize(raft_router).await; tx1.send(res).unwrap(); }); // Must timeout because there is no enough permit. @@ -1154,9 +1130,8 @@ mod tests { let snap = engine.snapshot(Default::default()).unwrap(); let th = pool.spawn(async move { - let memory_quota = Arc::new(MemoryQuota::new(usize::MAX)); initializer - .async_incremental_scan(snap, Region::default(), memory_quota) + .async_incremental_scan(snap, Region::default()) .await .unwrap(); }); @@ -1171,4 +1146,67 @@ mod tests { block_on(th).unwrap(); worker.stop(); } + + #[test] + fn test_initialize_scan_range() { + let mut cfg = DbConfig::default(); + cfg.writecf.disable_auto_compactions = true; + let mut engine = TestEngineBuilder::new().build_with_cfg(&cfg).unwrap(); + + // Must start with 'z', otherwise table property collector doesn't work. + let ka = Key::from_raw(b"zaaa").into_encoded(); + let km = Key::from_raw(b"zmmm").into_encoded(); + let ky = Key::from_raw(b"zyyy").into_encoded(); + let kz = Key::from_raw(b"zzzz").into_encoded(); + + // Incremental scan iterator shouldn't access the key because it's out of range. + must_prewrite_put(&mut engine, &ka, b"value", &ka, 200); + must_commit(&mut engine, &ka, 200, 210); + for cf in &[CF_WRITE, CF_DEFAULT] { + let kv = engine.kv_engine().unwrap(); + kv.flush_cf(cf, true).unwrap(); + } + + // Incremental scan iterator shouldn't access the key because it's skiped by ts + // filter. + must_prewrite_put(&mut engine, &km, b"value", &km, 100); + must_commit(&mut engine, &km, 100, 110); + for cf in &[CF_WRITE, CF_DEFAULT] { + let kv = engine.kv_engine().unwrap(); + kv.flush_cf(cf, true).unwrap(); + } + + must_prewrite_put(&mut engine, &ky, b"value", &ky, 200); + must_commit(&mut engine, &ky, 200, 210); + for cf in &[CF_WRITE, CF_DEFAULT] { + let kv = engine.kv_engine().unwrap(); + kv.flush_cf(cf, true).unwrap(); + } + + let (mut _worker, pool, mut initializer, _rx, mut drain) = mock_initializer( + usize::MAX, + usize::MAX, + 1000, + engine.kv_engine(), + ChangeDataRequestKvApi::TiDb, + false, + ); + + initializer.observed_range = ObservedRange::new(km, kz).unwrap(); + initializer.checkpoint_ts = 150.into(); + + let th = pool.spawn(async move { + let snap = engine.snapshot(Default::default()).unwrap(); + let region = Region::default(); + let scan_stat = initializer + .async_incremental_scan(snap, region) + .await + .unwrap(); + let block_reads = scan_stat.perf_delta.block_read_count; + let block_gets = scan_stat.perf_delta.block_cache_hit_count; + assert_eq!(block_reads + block_gets, 1); + }); + while block_on(drain.drain().next()).is_some() {} + block_on(th).unwrap(); + } } diff --git a/components/cdc/src/observer.rs b/components/cdc/src/observer.rs index 965a31ac7ff..2e1a7f7734d 100644 --- a/components/cdc/src/observer.rs +++ b/components/cdc/src/observer.rs @@ -56,7 +56,7 @@ impl CdcObserver { .register_region_change_observer(100, BoxRegionChangeObserver::new(self.clone())); } - /// Subscribe an region, the observer will sink events of the region into + /// Subscribe a region, the observer will sink events of the region into /// its scheduler. /// /// Return previous ObserveId if there is one. diff --git a/components/cdc/src/service.rs b/components/cdc/src/service.rs index 4cb89d16394..d6c223d2ec7 100644 --- a/components/cdc/src/service.rs +++ b/components/cdc/src/service.rs @@ -35,6 +35,9 @@ pub fn validate_kv_api(kv_api: ChangeDataRequestKvApi, api_version: ApiVersion) #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub struct ConnId(usize); +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub struct RequestId(pub u64); + impl ConnId { pub fn new() -> ConnId { ConnId(CONNECTION_ID_ALLOC.fetch_add(1, Ordering::SeqCst)) @@ -89,7 +92,7 @@ pub struct Conn { #[derive(PartialEq, Eq, Hash)] struct DownstreamKey { - request_id: u64, + request_id: RequestId, region_id: u64, } @@ -143,7 +146,7 @@ impl Conn { &self.sink } - pub fn get_downstream(&self, request_id: u64, region_id: u64) -> Option { + pub fn get_downstream(&self, request_id: RequestId, region_id: u64) -> Option { let key = DownstreamKey { request_id, region_id, @@ -153,7 +156,7 @@ impl Conn { pub fn subscribe( &mut self, - request_id: u64, + request_id: RequestId, region_id: u64, downstream_id: DownstreamId, downstream_state: Arc>, @@ -174,7 +177,7 @@ impl Conn { } } - pub fn unsubscribe(&mut self, request_id: u64, region_id: u64) -> Option { + pub fn unsubscribe(&mut self, request_id: RequestId, region_id: u64) -> Option { let key = DownstreamKey { request_id, region_id, @@ -182,7 +185,7 @@ impl Conn { self.downstreams.remove(&key).map(|value| value.id) } - pub fn unsubscribe_request(&mut self, request_id: u64) -> Vec<(u64, DownstreamId)> { + pub fn unsubscribe_request(&mut self, request_id: RequestId) -> Vec<(u64, DownstreamId)> { let mut downstreams = Vec::new(); self.downstreams.retain(|key, value| -> bool { if key.request_id == request_id { @@ -196,7 +199,7 @@ impl Conn { pub fn iter_downstreams(&self, mut f: F) where - F: FnMut(u64, u64, DownstreamId, &Arc>), + F: FnMut(RequestId, u64, DownstreamId, &Arc>), { for (key, value) in &self.downstreams { f(key.request_id, key.region_id, value.id, &value.state); @@ -276,18 +279,15 @@ impl Service { peer: &str, ) -> semver::Version { let version_field = request.get_header().get_ticdc_version(); - match semver::Version::parse(version_field) { - Ok(v) => v, - Err(e) => { - warn!( - "empty or invalid TiCDC version, please upgrading TiCDC"; - "version" => version_field, - "downstream" => ?peer, "region_id" => request.region_id, - "error" => ?e, - ); - semver::Version::new(0, 0, 0) - } - } + semver::Version::parse(version_field).unwrap_or_else(|e| { + warn!( + "empty or invalid TiCDC version, please upgrading TiCDC"; + "version" => version_field, + "downstream" => ?peer, "region_id" => request.region_id, + "error" => ?e, + ); + semver::Version::new(0, 0, 0) + }) } fn set_conn_version( @@ -334,22 +334,19 @@ impl Service { request: ChangeDataRequest, conn_id: ConnId, ) -> Result<(), String> { - let observed_range = - match ObservedRange::new(request.start_key.clone(), request.end_key.clone()) { - Ok(observed_range) => observed_range, - Err(e) => { - warn!( - "cdc invalid observed start key or end key version"; - "downstream" => ?peer, "region_id" => request.region_id, - "error" => ?e, - ); - ObservedRange::default() - } - }; + let observed_range = ObservedRange::new(request.start_key.clone(), request.end_key.clone()) + .unwrap_or_else(|e| { + warn!( + "cdc invalid observed start key or end key version"; + "downstream" => ?peer, "region_id" => request.region_id, + "error" => ?e, + ); + ObservedRange::default() + }); let downstream = Downstream::new( peer.to_owned(), request.get_region_epoch().clone(), - request.request_id, + RequestId(request.request_id), conn_id, request.kv_api, request.filter_loop, @@ -358,7 +355,6 @@ impl Service { let task = Task::Register { request, downstream, - conn_id, }; scheduler.schedule(task).map_err(|e| format!("{:?}", e)) } @@ -371,13 +367,13 @@ impl Service { let task = if request.region_id != 0 { Task::Deregister(Deregister::Region { conn_id, - request_id: request.request_id, + request_id: RequestId(request.request_id), region_id: request.region_id, }) } else { Task::Deregister(Deregister::Request { conn_id, - request_id: request.request_id, + request_id: RequestId(request.request_id), }) }; scheduler.schedule(task).map_err(|e| format!("{:?}", e)) diff --git a/components/cdc/tests/failpoints/test_memory_quota.rs b/components/cdc/tests/failpoints/test_memory_quota.rs index 5b564ba61ec..bcc86d0b159 100644 --- a/components/cdc/tests/failpoints/test_memory_quota.rs +++ b/components/cdc/tests/failpoints/test_memory_quota.rs @@ -118,25 +118,13 @@ fn test_pending_on_region_ready_memory_quota_exceeded() { fail::cfg("cdc_event_size", "return(0)").unwrap(); // Trigger memory quota exceeded error. - fail::cfg("cdc_pending_on_region_ready", "return").unwrap(); + fail::cfg("cdc_finish_scan_locks_memory_quota_exceed", "return").unwrap(); let req = suite.new_changedata_request(1); let (mut req_tx, _event_feed_wrap, receive_event) = new_event_feed(suite.get_region_cdc_client(1)); block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); - let event = receive_event(false); - event.events.into_iter().for_each(|e| { - match e.event.unwrap() { - // Even if there is no write, - // it should always outputs an Initialized event. - Event_oneof_event::Entries(es) => { - assert!(es.entries.len() == 1, "{:?}", es); - let e = &es.entries[0]; - assert_eq!(e.get_type(), EventLogType::Initialized, "{:?}", es); - } - other => panic!("unknown event {:?}", other), - } - }); - // MemoryQuotaExceeded error is triggered on_region_ready. + + // MemoryQuotaExceeded error is triggered. let mut events = receive_event(false).events.to_vec(); assert_eq!(events.len(), 1, "{:?}", events); match events.pop().unwrap().event.unwrap() { @@ -164,7 +152,8 @@ fn test_pending_on_region_ready_memory_quota_exceeded() { "find unexpected delegate" ); - fail::remove("cdc_incremental_scan_start"); + fail::remove("cdc_event_size"); + fail::remove("cdc_finish_scan_locks_memory_quota_exceed"); suite.stop(); } @@ -227,6 +216,7 @@ fn test_pending_push_lock_memory_quota_exceeded() { "find unexpected delegate" ); + fail::remove("cdc_event_size"); fail::remove("cdc_incremental_scan_start"); suite.stop(); } @@ -285,5 +275,6 @@ fn test_scan_lock_memory_quota_exceeded() { "find unexpected delegate" ); + fail::remove("cdc_event_size"); suite.stop(); } diff --git a/components/cdc/tests/integrations/test_cdc.rs b/components/cdc/tests/integrations/test_cdc.rs index c1ac1706d52..c6ccfff0ad5 100644 --- a/components/cdc/tests/integrations/test_cdc.rs +++ b/components/cdc/tests/integrations/test_cdc.rs @@ -13,9 +13,9 @@ use raft::eraftpb::MessageType; use test_raftstore::*; use tikv::server::DEFAULT_CLUSTER_ID; use tikv_util::{config::ReadableDuration, HandyRwLock}; -use txn_types::{Key, Lock, LockType}; +use txn_types::{Key, Lock, LockType, TimeStamp}; -use crate::{new_event_feed, TestSuite, TestSuiteBuilder}; +use crate::{new_event_feed, new_event_feed_v2, TestSuite, TestSuiteBuilder}; #[test] fn test_cdc_basic() { @@ -934,12 +934,15 @@ fn test_cdc_batch_size_limit_impl() { let mut events = receive_event(false).events.to_vec(); assert_eq!(events.len(), 1, "{:?}", events); match events.pop().unwrap().event.unwrap() { - Event_oneof_event::Entries(es) => { - assert_eq!(es.entries.len(), 2); - let e = &es.entries[0]; + Event_oneof_event::Entries(mut es) => { + let mut entries = es.take_entries().into_vec(); + assert_eq!(entries.len(), 2); + entries.sort_by(|a, b| a.key.cmp(&b.key)); + + let e = &entries[0]; assert_eq!(e.get_type(), EventLogType::Prewrite, "{:?}", e.get_type()); assert_eq!(e.key, b"xk3", "{:?}", e.key); - let e = &es.entries[1]; + let e = &entries[1]; assert_eq!(e.get_type(), EventLogType::Prewrite, "{:?}", e.get_type()); assert_eq!(e.key, b"xk4", "{:?}", e.key); } @@ -1321,19 +1324,20 @@ fn test_cdc_1pc_impl() { let req = suite.new_changedata_request(1); let (mut req_tx, _, receive_event) = new_event_feed(suite.get_region_cdc_client(1)); block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + + // Wait until the region subscription is initialized. let event = receive_event(false); - event.events.into_iter().for_each(|e| { - match e.event.unwrap() { - // Even if there is no write, - // it should always outputs an Initialized event. + event + .events + .into_iter() + .for_each(|e| match e.event.unwrap() { Event_oneof_event::Entries(es) => { assert!(es.entries.len() == 1, "{:?}", es); let e = &es.entries[0]; assert_eq!(e.get_type(), EventLogType::Initialized, "{:?}", es); } other => panic!("unknown event {:?}", other), - } - }); + }); let (k1, v1) = (b"xk1", b"v1"); let (k2, v2) = (b"xk2", &[0u8; 512]); @@ -1377,16 +1381,19 @@ fn test_cdc_1pc_impl() { if !events.is_empty() { assert_eq!(events.len(), 1); match events.pop().unwrap().event.unwrap() { - Event_oneof_event::Entries(entries) => { - assert_eq!(entries.entries.len(), 2); - let (e0, e1) = (&entries.entries[0], &entries.entries[1]); + Event_oneof_event::Entries(mut es) => { + let mut entries = es.take_entries().into_vec(); + assert_eq!(entries.len(), 2); + entries.sort_by(|a, b| a.key.cmp(&b.key)); + + let (e0, e1) = (&entries[0], &entries[1]); assert_eq!(e0.get_type(), EventLogType::Committed); - assert_eq!(e0.get_key(), k2); - assert_eq!(e0.get_value(), v2); + assert_eq!(e0.get_key(), k1); + assert_eq!(e0.get_value(), v1); assert!(e0.commit_ts > resolved_ts); assert_eq!(e1.get_type(), EventLogType::Committed); - assert_eq!(e1.get_key(), k1); - assert_eq!(e1.get_value(), v1); + assert_eq!(e1.get_key(), k2); + assert_eq!(e1.get_value(), v2); assert!(e1.commit_ts > resolved_ts); break; } @@ -1906,18 +1913,17 @@ fn test_cdc_extract_rollback_if_gc_fence_set_impl() { let req = suite.new_changedata_request(1); let (mut req_tx, _, receive_event) = new_event_feed(suite.get_region_cdc_client(1)); block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); - let event = receive_event(false); - event - .events - .into_iter() - .for_each(|e| match e.event.unwrap() { + + for e in receive_event(false).events.into_vec() { + match e.event.unwrap() { Event_oneof_event::Entries(es) => { assert!(es.entries.len() == 1, "{:?}", es); let e = &es.entries[0]; assert_eq!(e.get_type(), EventLogType::Initialized, "{:?}", es); } other => panic!("unknown event {:?}", other), - }); + }; + } sleep_ms(1000); @@ -2208,7 +2214,7 @@ fn test_cdc_write_rollback_when_no_lock_impl() { let k1 = b"xk1".to_vec(); m1.set_op(Op::Put); m1.key = k1.clone(); - m1.value = b"v1".to_vec(); + m1.value = vec![b'x'; 16]; suite.must_kv_prewrite(1, vec![m1], k1.clone(), 10.into()); // Wait until resolved_ts advanced to 10 @@ -2732,3 +2738,171 @@ fn test_cdc_filter_key_range() { suite.stop(); } + +#[test] +fn test_cdc_partial_subscription() { + let mut cluster = new_server_cluster(0, 1); + configure_for_lease_read(&mut cluster.cfg, Some(100), Some(10)); + cluster.pd_client.disable_default_operator(); + let mut suite = TestSuiteBuilder::new().cluster(cluster).build(); + let region = suite.cluster.get_region(&[]); + let rid = region.id; + + let prewrite_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + let (k, v) = (b"key".to_vec(), vec![b'x'; 16]); + let mut mutation = Mutation::default(); + mutation.set_op(Op::Put); + mutation.key = k.clone(); + mutation.value = v; + suite.must_kv_prewrite(rid, vec![mutation], k.clone(), prewrite_tso); + + let cf_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + let (mut req_tx, _, receive_event) = new_event_feed_v2(suite.get_region_cdc_client(rid)); + let mut req = suite.new_changedata_request(rid); + req.request_id = 1; + req.checkpoint_ts = cf_tso.into_inner(); + req.set_start_key(Key::from_raw(b"x").into_encoded()); + req.set_end_key(Key::from_raw(b"z").into_encoded()); + block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + + let cdc_event = receive_event(false); + 'WaitInit: for event in cdc_event.get_events() { + for entry in event.get_entries().get_entries() { + match entry.get_type() { + EventLogType::Prewrite => {} + EventLogType::Initialized => break 'WaitInit, + _ => unreachable!(), + } + } + } + + for _ in 0..10 { + let cdc_event = receive_event(true); + if cdc_event.has_resolved_ts() { + let resolved_ts = cdc_event.get_resolved_ts(); + if resolved_ts.ts > prewrite_tso.into_inner() { + return; + } + } + } + panic!("resolved_ts should exceed prewrite_tso"); +} + +#[test] +fn test_cdc_rollback_prewrites_with_txn_source() { + let mut cluster = new_server_cluster(0, 1); + configure_for_lease_read(&mut cluster.cfg, Some(100), Some(10)); + cluster.pd_client.disable_default_operator(); + let mut suite = TestSuiteBuilder::new().cluster(cluster).build(); + let region = suite.cluster.get_region(&[]); + let rid = region.id; + let cf_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + + let (mut req_tx, _, receive_event) = new_event_feed_v2(suite.get_region_cdc_client(rid)); + let mut req = suite.new_changedata_request(rid); + req.request_id = 1; + req.checkpoint_ts = cf_tso.into_inner(); + req.filter_loop = true; + req.set_start_key(Key::from_raw(b"a").into_encoded()); + req.set_end_key(Key::from_raw(b"z").into_encoded()); + block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + + let cdc_event = receive_event(false); + 'WaitInit: for event in cdc_event.get_events() { + for entry in event.get_entries().get_entries() { + match entry.get_type() { + EventLogType::Prewrite => {} + EventLogType::Initialized => break 'WaitInit, + _ => unreachable!(), + } + } + } + + let start_tso = cf_tso.next(); + let k = b"key".to_vec(); + let v = vec![b'x'; 16 * 1024]; + let mut mutation = Mutation::default(); + mutation.set_op(Op::Put); + mutation.key = k.clone(); + mutation.value = v; + suite.must_kv_prewrite_with_source(rid, vec![mutation], k.clone(), start_tso, 1); + + loop { + let cdc_event = receive_event(true); + if cdc_event.has_resolved_ts() { + let resolved_ts = cdc_event.get_resolved_ts().get_ts(); + assert_eq!(resolved_ts, start_tso.into_inner()); + break; + } + } + + suite.must_kv_rollback(rid, vec![k.clone()], start_tso); + + // We can't receive the prewrite because it's with a txn_source, + // but we can receive the rollback. + let mut rollbacked = false; + for _ in 0..5 { + let cdc_event = receive_event(true); + if !rollbacked { + for event in cdc_event.get_events() { + for entry in event.get_entries().get_entries() { + match entry.get_type() { + EventLogType::Rollback => rollbacked = true, + _ => unreachable!(), + } + } + } + } else { + let resolved_ts = cdc_event.get_resolved_ts().get_ts(); + if resolved_ts > 5 { + return; + } + } + } + panic!("resolved ts must be advanced correctly"); +} + +#[test] +fn test_cdc_pessimistic_lock_unlock() { + let mut cluster = new_server_cluster(0, 1); + configure_for_lease_read(&mut cluster.cfg, Some(100), Some(10)); + cluster.pd_client.disable_default_operator(); + let mut suite = TestSuiteBuilder::new().cluster(cluster).build(); + let region = suite.cluster.get_region(&[]); + let rid = region.id; + let cf_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + + let (mut req_tx, _, receive_event) = new_event_feed_v2(suite.get_region_cdc_client(rid)); + let mut req = suite.new_changedata_request(rid); + req.request_id = 1; + req.checkpoint_ts = cf_tso.into_inner(); + req.filter_loop = true; + req.set_start_key(Key::from_raw(b"a").into_encoded()); + req.set_end_key(Key::from_raw(b"z").into_encoded()); + block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + + let cdc_event = receive_event(false); + 'WaitInit: for event in cdc_event.get_events() { + for entry in event.get_entries().get_entries() { + match entry.get_type() { + EventLogType::Prewrite => {} + EventLogType::Initialized => break 'WaitInit, + _ => unreachable!(), + } + } + } + + let start_tso = cf_tso.next(); + let k = b"key".to_vec(); + let v = vec![b'x'; 16 * 1024]; + let mut mutation = Mutation::default(); + mutation.set_op(Op::PessimisticLock); + mutation.key = k.clone(); + mutation.value = v; + let for_update_tso = TimeStamp::from(start_tso.into_inner() + 10); + suite.must_acquire_pessimistic_lock(rid, vec![mutation], k.clone(), start_tso, for_update_tso); + std::thread::sleep(Duration::from_millis(500)); + + suite.must_release_pessimistic_lock(rid, k.clone(), start_tso, for_update_tso); + std::thread::sleep(Duration::from_millis(500)); +} diff --git a/components/cdc/tests/mod.rs b/components/cdc/tests/mod.rs index b36cf46df93..ce52455a8af 100644 --- a/components/cdc/tests/mod.rs +++ b/components/cdc/tests/mod.rs @@ -475,6 +475,26 @@ impl TestSuite { ); } + pub fn must_release_pessimistic_lock( + &mut self, + region_id: u64, + pk: Vec, + start_ts: TimeStamp, + for_update_ts: TimeStamp, + ) { + let mut req = PessimisticRollbackRequest::default(); + req.set_context(self.get_context(region_id)); + req.start_version = start_ts.into_inner(); + req.for_update_ts = for_update_ts.into_inner(); + req.set_keys(vec![pk].into_iter().collect()); + let resp = self + .get_tikv_client(region_id) + .kv_pessimistic_rollback(&req) + .unwrap(); + assert!(!resp.has_region_error(), "{:?}", resp.get_region_error()); + assert!(resp.errors.is_empty(), "{:?}", resp.get_errors()); + } + pub fn must_kv_pessimistic_prewrite( &mut self, region_id: u64, @@ -509,6 +529,27 @@ impl TestSuite { ); } + pub fn must_kv_txn_heartbeat( + &mut self, + region_id: u64, + pk: Vec, + ts: TimeStamp, + advise_lock_ttl: TimeStamp, + ) { + let mut heartbeat_req = TxnHeartBeatRequest::default(); + heartbeat_req.set_context(self.get_context(region_id)); + heartbeat_req.primary_lock = pk; + heartbeat_req.start_version = ts.into_inner(); + heartbeat_req.advise_lock_ttl = advise_lock_ttl.into_inner(); + let heartbeat_resp = self + .get_tikv_client(region_id) + .kv_txn_heart_beat(&heartbeat_req) + .unwrap(); + assert!(!heartbeat_resp.has_region_error()); + assert!(!heartbeat_resp.has_error()); + assert_eq!(heartbeat_resp.lock_ttl, advise_lock_ttl.into_inner()); + } + pub fn async_kv_commit( &mut self, region_id: u64, @@ -526,6 +567,23 @@ impl TestSuite { .unwrap() } + pub fn async_kv_txn_heartbeat( + &mut self, + region_id: u64, + pk: Vec, + ts: TimeStamp, + advise_lock_ttl: TimeStamp, + ) -> ClientUnaryReceiver { + let mut heartbeat_req = TxnHeartBeatRequest::default(); + heartbeat_req.set_context(self.get_context(region_id)); + heartbeat_req.primary_lock = pk; + heartbeat_req.start_version = ts.into_inner(); + heartbeat_req.advise_lock_ttl = advise_lock_ttl.into_inner(); + self.get_tikv_client(region_id) + .kv_txn_heart_beat_async(&heartbeat_req) + .unwrap() + } + pub fn get_context(&mut self, region_id: u64) -> Context { let epoch = self.cluster.get_region_epoch(region_id); let leader = self.cluster.leader_of_region(region_id).unwrap(); diff --git a/components/txn_types/src/types.rs b/components/txn_types/src/types.rs index 6cbce2a4b6b..6e462beb577 100644 --- a/components/txn_types/src/types.rs +++ b/components/txn_types/src/types.rs @@ -247,6 +247,10 @@ impl Key { pub fn len(&self) -> usize { self.0.len() } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } } impl Clone for Key { From 92da45af32b85b271bd13bb2b9d177e2bff96640 Mon Sep 17 00:00:00 2001 From: mittalrishabh Date: Tue, 30 Jul 2024 01:47:49 -0700 Subject: [PATCH 014/144] TiKV : Stale reads.: add histogram of min safe ts. (#17308) close tikv/tikv#17307 Signed-off-by: rishabh_mittal Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/resolved_ts/src/endpoint.rs | 4 ++++ components/resolved_ts/src/metrics.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/components/resolved_ts/src/endpoint.rs b/components/resolved_ts/src/endpoint.rs index dfbafc0531f..7710f14b085 100644 --- a/components/resolved_ts/src/endpoint.rs +++ b/components/resolved_ts/src/endpoint.rs @@ -397,6 +397,7 @@ where let store_id = self.get_or_init_store_id(); let mut stats = Stats::default(); + let now = self.approximate_now_tso(); self.region_read_progress.with(|registry| { for (region_id, read_progress) in registry { let (leader_info, leader_store_id) = read_progress.dump_leader_info(); @@ -419,6 +420,9 @@ where } } else { // follower safe-ts + RTS_MIN_FOLLOWER_SAFE_TS_GAP_HISTOGRAM + .observe(now.saturating_sub(TimeStamp::from(safe_ts).physical()) as f64); + if safe_ts > 0 && safe_ts < stats.min_follower_safe_ts.safe_ts { stats.min_follower_safe_ts.set(*region_id, &core); } diff --git a/components/resolved_ts/src/metrics.rs b/components/resolved_ts/src/metrics.rs index fb751491d10..ed258580366 100644 --- a/components/resolved_ts/src/metrics.rs +++ b/components/resolved_ts/src/metrics.rs @@ -115,6 +115,12 @@ lazy_static! { &["type"] ) .unwrap(); + pub static ref RTS_MIN_FOLLOWER_SAFE_TS_GAP_HISTOGRAM: Histogram = register_histogram!( + "tikv_resolved_ts_min_follower_safe_ts_gap_millis_histogram", + "Bucketed histogram of the gap between now() and the minimal (non-zero) safe ts for followers", + exponential_buckets(50.0, 2.0, 20).unwrap(), + ) + .unwrap(); pub static ref RTS_CHECK_LEADER_DURATION_HISTOGRAM_VEC: HistogramVec = register_histogram_vec!( "tikv_resolved_ts_check_leader_duration_seconds", "Bucketed histogram of resolved-ts check leader duration", From 2253c93376ced0a214ab2b56a4b963a1a0522be5 Mon Sep 17 00:00:00 2001 From: Wenqi Mou Date: Tue, 30 Jul 2024 23:05:48 -0400 Subject: [PATCH 015/144] br: use dashmap for br router#tasks (#17301) close tikv/tikv#17300 Signed-off-by: Wenqi Mou Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/backup-stream/src/endpoint.rs | 8 +- components/backup-stream/src/router.rs | 95 +++++++++---------- .../backup-stream/tests/failpoints/mod.rs | 2 +- components/backup-stream/tests/suite.rs | 6 +- 4 files changed, 50 insertions(+), 61 deletions(-) diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index badb02c749c..bce6584ddbc 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -274,9 +274,7 @@ where fn on_fatal_error(&self, select: TaskSelector, err: Box) { err.report_fatal(); - let tasks = self - .pool - .block_on(self.range_router.select_task(select.reference())); + let tasks = self.range_router.select_task(select.reference()); warn!("fatal error reporting"; "selector" => ?select, "selected" => ?tasks, "err" => %err); for task in tasks { // Let's pause the task first. @@ -803,7 +801,7 @@ where // so simply clear all info would be fine. self.observer.ranges.wl().clear(); self.subs.clear(); - self.pool.block_on(router.unregister_task(task)) + router.unregister_task(task) } fn prepare_min_ts(&self) -> future![TimeStamp] { @@ -850,7 +848,7 @@ where pub fn on_force_flush(&self, task: String) { self.pool.block_on(async move { - let info = self.range_router.get_task_info(&task).await; + let info = self.range_router.get_task_info(&task); // This should only happen in testing, it would be to unwrap... let _ = info.unwrap().set_flushing_status_cas(false, true); let mts = self.prepare_min_ts().await; diff --git a/components/backup-stream/src/router.rs b/components/backup-stream/src/router.rs index d2a501ff995..b711cd88d4f 100644 --- a/components/backup-stream/src/router.rs +++ b/components/backup-stream/src/router.rs @@ -13,6 +13,7 @@ use std::{ time::Duration, }; +use dashmap::DashMap; use encryption::DataKeyManager; use engine_traits::{CfName, CF_DEFAULT, CF_LOCK, CF_WRITE}; use external_storage::{create_storage, BackendConfig, ExternalStorage, UnpinReader}; @@ -375,7 +376,7 @@ pub struct RouterInner { /// which range a point belongs to. ranges: SyncRwLock, String>>, /// The temporary files associated to some task. - tasks: Mutex>>, + tasks: DashMap>, /// The temporary directory for all tasks. prefix: PathBuf, @@ -404,7 +405,7 @@ impl RouterInner { pub fn new(scheduler: Scheduler, config: Config) -> Self { RouterInner { ranges: SyncRwLock::new(SegmentMap::default()), - tasks: Mutex::new(HashMap::default()), + tasks: DashMap::new(), prefix: config.prefix, scheduler, temp_file_size_limit: AtomicU64::new(config.temp_file_size_limit), @@ -420,9 +421,9 @@ impl RouterInner { .store(config.file_size_limit.0, Ordering::SeqCst); self.temp_file_memory_quota .store(config.temp_file_memory_quota.0, Ordering::SeqCst); - let tasks = self.tasks.blocking_lock(); - for task in tasks.values() { - task.temp_file_pool + for entry in self.tasks.iter() { + entry + .temp_file_pool .config() .cache_size .store(config.temp_file_memory_quota.0 as usize, Ordering::SeqCst); @@ -484,11 +485,9 @@ impl RouterInner { let cfg = self.tempfile_config_for_task(&task); let stream_task = StreamTaskInfo::new(task, ranges.clone(), merged_file_size_limit, cfg).await?; - frame!(self.tasks.lock()) - .await - .insert(task_name.clone(), Arc::new(stream_task)); + self.tasks.insert(task_name.clone(), Arc::new(stream_task)); - // register ragnes + // register ranges self.register_ranges(&task_name, ranges); Ok(()) @@ -511,14 +510,14 @@ impl RouterInner { } } - pub async fn unregister_task(&self, task_name: &str) -> Option { - frame!(self.tasks.lock()).await.remove(task_name).map(|t| { + pub fn unregister_task(&self, task_name: &str) -> Option { + self.tasks.remove(task_name).map(|t| { info!( "backup stream unregister task"; "task" => task_name, ); self.unregister_ranges(task_name); - t.task.info.clone() + t.1.task.info.clone() }) } @@ -528,11 +527,11 @@ impl RouterInner { r.get_value_by_point(key).cloned() } - #[instrument(skip(self))] - pub async fn select_task(&self, selector: TaskSelectorRef<'_>) -> Vec { - let s = frame!(self.tasks.lock()).await; - s.iter() - .filter(|(name, info)| { + pub fn select_task(&self, selector: TaskSelectorRef<'_>) -> Vec { + self.tasks + .iter() + .filter(|entry| { + let (name, info) = entry.pair(); selector.matches( name.as_str(), info.ranges @@ -540,25 +539,24 @@ impl RouterInner { .map(|(s, e)| (s.as_slice(), e.as_slice())), ) }) - .map(|(name, _)| name.to_owned()) + .map(|entry| entry.key().to_owned()) .collect() } #[cfg(test)] - pub(crate) async fn must_mut_task_info(&self, task_name: &str, mutator: F) + pub(crate) fn must_mut_task_info(&self, task_name: &str, mutator: F) where F: FnOnce(&mut StreamTaskInfo), { - let mut tasks = self.tasks.lock().await; - let t = tasks.remove(task_name); - let mut raw = Arc::try_unwrap(t.unwrap()).unwrap(); + let t = self.tasks.remove(task_name); + let mut raw = Arc::try_unwrap(t.unwrap().1).unwrap(); mutator(&mut raw); - tasks.insert(task_name.to_owned(), Arc::new(raw)); + self.tasks.insert(task_name.to_owned(), Arc::new(raw)); } #[instrument(skip(self))] - pub async fn get_task_info(&self, task_name: &str) -> Result> { - let task_info = match frame!(self.tasks.lock()).await.get(task_name) { + pub fn get_task_info(&self, task_name: &str) -> Result> { + let task_info = match self.tasks.get(task_name) { Some(t) => t.clone(), None => { info!("backup stream no task"; "task" => ?task_name); @@ -572,7 +570,7 @@ impl RouterInner { #[instrument(skip_all, fields(task))] async fn on_event(&self, task: String, events: ApplyEvents) -> Result<()> { - let task_info = self.get_task_info(&task).await?; + let task_info = self.get_task_info(&task)?; task_info.on_events(events).await?; let file_size_limit = self.temp_file_size_limit.load(Ordering::SeqCst); @@ -617,7 +615,7 @@ impl RouterInner { store_id: u64, resolve_to: TimeStamp, ) -> Option { - let task = self.tasks.lock().await.get(task_name).cloned(); + let task = self.tasks.get(task_name); match task { Some(task_info) => { let result = task_info.do_flush(store_id, resolve_to).await; @@ -654,8 +652,7 @@ impl RouterInner { global_checkpoint: u64, store_id: u64, ) -> Result { - self.get_task_info(task_name) - .await? + self.get_task_info(task_name)? .update_global_checkpoint(global_checkpoint, store_id) .await } @@ -665,7 +662,9 @@ impl RouterInner { pub async fn tick(&self) { let max_flush_interval = self.max_flush_interval.rl().to_owned(); - for (name, task_info) in self.tasks.lock().await.iter() { + for entry in self.tasks.iter() { + let name = entry.key(); + let task_info = entry.value(); if let Err(e) = self .scheduler .schedule(Task::UpdateGlobalCheckpoint(name.to_string())) @@ -1844,7 +1843,7 @@ mod tests { tokio::time::sleep(Duration::from_millis(200)).await; let end_ts = TimeStamp::physical_now(); - let files = router.tasks.lock().await.get("dummy").unwrap().clone(); + let files = router.tasks.get("dummy").unwrap().clone(); let mut meta = files .move_to_flushing_files() .await @@ -2089,11 +2088,9 @@ mod tests { )); let (task, _path) = task("error_prone".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; - router - .must_mut_task_info("error_prone", |i| { - i.storage = Arc::new(ErrorStorage::with_first_time_error(i.storage.clone())) - }) - .await; + router.must_mut_task_info("error_prone", |i| { + i.storage = Arc::new(ErrorStorage::with_first_time_error(i.storage.clone())) + }); check_on_events_result(&router.on_events(build_kv_event(0, 10)).await); assert!( router @@ -2102,7 +2099,7 @@ mod tests { .is_none() ); check_on_events_result(&router.on_events(build_kv_event(10, 10)).await); - let t = router.get_task_info("error_prone").await.unwrap(); + let t = router.get_task_info("error_prone").unwrap(); let _ = router.do_flush("error_prone", 42, TimeStamp::max()).await; assert_eq!(t.total_size() > 0, true); @@ -2141,7 +2138,7 @@ mod tests { ) .await .unwrap(); - let task = router.get_task_info("nothing").await.unwrap(); + let task = router.get_task_info("nothing").unwrap(); task.set_flushing_status_cas(false, true).unwrap(); let ts = TimeStamp::compose(TimeStamp::physical_now(), 42); let rts = router.do_flush("nothing", 1, ts).await.unwrap(); @@ -2167,13 +2164,11 @@ mod tests { write_simple_data(&router).await; let tempfiles = router .get_task_info("cleanup_test") - .await .unwrap() .temp_file_pool .clone(); router - .get_task_info("cleanup_test") - .await? + .get_task_info("cleanup_test")? .move_to_flushing_files() .await?; write_simple_data(&router).await; @@ -2221,11 +2216,9 @@ mod tests { )); let (task, _path) = task("flush_failure".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; - router - .must_mut_task_info("flush_failure", |i| { - i.storage = Arc::new(ErrorStorage::with_always_error(i.storage.clone())) - }) - .await; + router.must_mut_task_info("flush_failure", |i| { + i.storage = Arc::new(ErrorStorage::with_always_error(i.storage.clone())) + }); for i in 0..=FLUSH_FAILURE_BECOME_FATAL_THRESHOLD { check_on_events_result(&router.on_events(build_kv_event((i * 10) as _, 10)).await); assert_eq!( @@ -2541,11 +2534,9 @@ mod tests { let (task, _path) = task("race".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; - router - .must_mut_task_info("race", |i| { - i.storage = Arc::new(NoopStorage::default()); - }) - .await; + router.must_mut_task_info("race", |i| { + i.storage = Arc::new(NoopStorage::default()); + }); let mut b = KvEventsBuilder::new(42, 0); b.put_table(CF_DEFAULT, 1, b"k1", b"v1"); let events_before_flush = b.finish(); @@ -2562,7 +2553,7 @@ mod tests { let (fp_tx, fp_rx) = std::sync::mpsc::sync_channel(0); let fp_rx = std::sync::Mutex::new(fp_rx); - let t = router.get_task_info("race").await.unwrap(); + let t = router.get_task_info("race").unwrap(); let _ = router.on_events(events_before_flush).await; // make generate temp files ***happen after*** moving files to flushing_files diff --git a/components/backup-stream/tests/failpoints/mod.rs b/components/backup-stream/tests/failpoints/mod.rs index d1a9bc3a97b..006dfac1b87 100644 --- a/components/backup-stream/tests/failpoints/mod.rs +++ b/components/backup-stream/tests/failpoints/mod.rs @@ -254,7 +254,7 @@ mod all { .unwrap(); suite.sync(); - suite.wait_with_router(move |r| block_on(r.get_task_info("retry_abort")).is_ok()); + suite.wait_with_router(move |r| r.get_task_info("retry_abort").is_ok()); let items = run_async_test(suite.write_records(0, 128, 1)); suite.force_flush_files("retry_abort"); suite.wait_for_flush(); diff --git a/components/backup-stream/tests/suite.rs b/components/backup-stream/tests/suite.rs index 73462b0119f..dc80a1cba45 100644 --- a/components/backup-stream/tests/suite.rs +++ b/components/backup-stream/tests/suite.rs @@ -435,7 +435,7 @@ impl Suite { )) .unwrap(); let name = name.to_owned(); - self.wait_with_router(move |r| block_on(r.get_task_info(&name)).is_ok()) + self.wait_with_router(move |r| r.get_task_info(&name).is_ok()) } /// This function tries to calculate the global checkpoint from the flush @@ -926,9 +926,9 @@ impl Suite { pub fn wait_for_flush(&self) { self.wait_with_router(move |r| { - let task_names = block_on(r.select_task(TaskSelector::All.reference())); + let task_names = r.select_task(TaskSelector::All.reference()); for task_name in task_names { - let tsk = block_on(r.get_task_info(&task_name)); + let tsk = r.get_task_info(&task_name); if tsk.unwrap().is_flushing() { return false; } From e0199a038e74a52276a194c16fe545a8b08ad37d Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 1 Aug 2024 18:59:51 +0800 Subject: [PATCH 016/144] OWNERS: Auto Sync OWNERS files from community membership (#17343) Signed-off-by: Ti Chi Robot Co-authored-by: wuhuizuo --- OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS b/OWNERS index b0e73247005..e5d8ff9cf89 100644 --- a/OWNERS +++ b/OWNERS @@ -50,6 +50,7 @@ approvers: reviewers: - 3pointer - CalvinNeo + - crazycs520 - ethercflow - fredchenbj - Fullstop000 From 7c509085cbe59c82b51c853abf230cd7f188b5a0 Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 2 Aug 2024 14:44:51 +0800 Subject: [PATCH 017/144] batch-system: Reduce the memory usage of peers' message channel (#17326) close tikv/tikv#16229 Reduce the memory usage of peers' message channel Signed-off-by: Connor1996 --- components/raftstore/src/router.rs | 5 +- components/raftstore/src/store/fsm/apply.rs | 90 +++++++++---------- components/raftstore/src/store/fsm/peer.rs | 54 +++++------ components/raftstore/src/store/fsm/store.rs | 55 ++++++------ components/raftstore/src/store/msg.rs | 34 ++++--- .../raftstore/src/store/snapshot_backup.rs | 4 +- components/raftstore/src/store/transport.rs | 7 +- .../raftstore/src/store/unsafe_recovery.rs | 12 ++- .../src/store/worker/cleanup_snapshot.rs | 4 +- components/raftstore/src/store/worker/pd.rs | 8 +- components/snap_recovery/src/services.rs | 4 +- components/test_raftstore/src/router.rs | 5 +- src/server/server.rs | 10 ++- .../raftstore/test_snap_recovery.rs | 12 +-- 14 files changed, 165 insertions(+), 139 deletions(-) diff --git a/components/raftstore/src/router.rs b/components/raftstore/src/router.rs index 452616caf7e..18a33202eb3 100644 --- a/components/raftstore/src/router.rs +++ b/components/raftstore/src/router.rs @@ -92,7 +92,10 @@ where /// Report a `StoreResolved` event to all Raft groups. fn report_resolved(&self, store_id: u64, group_id: u64) { self.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::StoreResolved { store_id, group_id }) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::StoreResolved { + store_id, + group_id, + })) }) } } diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index dd3fde82110..857120ea601 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -930,7 +930,8 @@ where /// All of messages that need to continue to be handled after /// the source peer has applied its logs and pending entries /// are all handled. - pending_msgs: Vec>, + #[allow(clippy::vec_box)] + pending_msgs: Vec>>, /// Cache heap size for itself. heap_size: Option, @@ -2880,11 +2881,11 @@ where fail_point!("before_handle_catch_up_logs_for_merge"); // Sends message to the source peer fsm and pause `exec_commit_merge` process let logs_up_to_date = Arc::new(AtomicU64::new(0)); - let msg = SignificantMsg::CatchUpLogs(CatchUpLogs { + let msg = Box::new(SignificantMsg::CatchUpLogs(CatchUpLogs { target_region_id: self.region_id(), merge: merge.to_owned(), logs_up_to_date: logs_up_to_date.clone(), - }); + })); ctx.notifier .notify_one(source_region_id, PeerMsg::SignificantMsg(msg)); return Ok(( @@ -3795,13 +3796,13 @@ where }, } -impl ResourceMetered for Msg { +impl ResourceMetered for Box> { fn consume_resource(&self, resource_ctl: &Arc) -> Option { if !resource_ctl.is_customized() { return None; } - match self { - Msg::Apply { apply, .. } => { + match **self { + Msg::Apply { ref apply, .. } => { let mut dominant_group = "".to_owned(); let mut max_write_bytes = 0; for cached_entries in &apply.entries { @@ -3945,7 +3946,7 @@ where EK: KvEngine, { delegate: ApplyDelegate, - receiver: Receiver>, + receiver: Receiver>>, mailbox: Option>>, } @@ -3955,12 +3956,14 @@ where { fn from_peer( peer: &Peer, - ) -> (LooseBoundedSender>, Box>) { + ) -> (LooseBoundedSender>>, Box>) { let reg = Registration::new(peer); ApplyFsm::from_registration(reg) } - fn from_registration(reg: Registration) -> (LooseBoundedSender>, Box>) { + fn from_registration( + reg: Registration, + ) -> (LooseBoundedSender>>, Box>) { let (tx, rx) = loose_bounded(usize::MAX); let delegate = ApplyDelegate::from_registration(reg); ( @@ -4131,13 +4134,11 @@ where self.destroy(ctx); ctx.notifier.notify_one( self.delegate.region_id(), - PeerMsg::ApplyRes { - res: TaskRes::Destroy { - region_id: self.delegate.region_id(), - peer_id: self.delegate.id(), - merge_from_snapshot: d.merge_from_snapshot, - }, - }, + PeerMsg::ApplyRes(Box::new(TaskRes::Destroy { + region_id: self.delegate.region_id(), + peer_id: self.delegate.id(), + merge_from_snapshot: d.merge_from_snapshot, + })), ); } } @@ -4201,7 +4202,7 @@ where .store(region_id, Ordering::SeqCst); // To trigger the target apply fsm if let Some(mailbox) = ctx.router.mailbox(catch_up_logs.target_region_id) { - let _ = mailbox.force_send(Msg::Noop); + let _ = mailbox.force_send(Box::new(Msg::Noop)); } else { error!( "failed to get mailbox, are we shutting down?"; @@ -4412,7 +4413,8 @@ where ctx.finish_for(&mut self.delegate, result); } - fn handle_tasks(&mut self, apply_ctx: &mut ApplyContext, msgs: &mut Vec>) { + #[allow(clippy::vec_box)] + fn handle_tasks(&mut self, apply_ctx: &mut ApplyContext, msgs: &mut Vec>>) { let mut drainer = msgs.drain(..); let mut batch_apply = None; loop { @@ -4427,7 +4429,7 @@ where }; if batch_apply.is_some() { - match &msg { + match *msg { Msg::Apply { .. } => (), _ => { self.handle_apply(apply_ctx, batch_apply.take().unwrap()); @@ -4440,7 +4442,7 @@ where } } - match msg { + match *msg { Msg::Apply { start, mut apply } => { let apply_wait = start.saturating_elapsed(); apply_ctx.apply_wait.observe(apply_wait.as_secs_f64()); @@ -4461,7 +4463,9 @@ where } else { self.handle_apply(apply_ctx, batch_apply.take().unwrap()); if let Some(ref mut state) = self.delegate.yield_state { - state.pending_msgs.push(Msg::Apply { start, apply }); + state + .pending_msgs + .push(Box::new(Msg::Apply { start, apply })); state.pending_msgs.extend(drainer); break; } @@ -4514,7 +4518,7 @@ impl Fsm for ApplyFsm where EK: KvEngine, { - type Message = Msg; + type Message = Box>; #[inline] fn is_stopped(&self) -> bool { @@ -4621,7 +4625,8 @@ pub struct ApplyPoller where EK: KvEngine, { - msg_buf: Vec>, + #[allow(clippy::vec_box)] + msg_buf: Vec>>, apply_ctx: ApplyContext, messages_per_tick: usize, cfg_tracker: Tracker, @@ -4853,9 +4858,9 @@ where EK: KvEngine, { pub fn schedule_task(&self, region_id: u64, msg: Msg) { - let reg = match self.try_send(region_id, msg) { + let reg = match self.try_send(region_id, Box::new(msg)) { Either::Left(Ok(())) => return, - Either::Left(Err(TrySendError::Disconnected(msg))) | Either::Right(msg) => match msg { + Either::Left(Err(TrySendError::Disconnected(msg))) | Either::Right(msg) => match *msg { Msg::Registration(reg) => reg, Msg::Apply { mut apply, .. } => { info!( @@ -5193,8 +5198,8 @@ mod tests { impl Notifier for TestNotifier { fn notify(&self, apply_res: Vec>) { for r in apply_res { - let res = TaskRes::Apply(r); - let _ = self.tx.send(PeerMsg::ApplyRes { res }); + let res = Box::new(TaskRes::Apply(r)); + let _ = self.tx.send(PeerMsg::ApplyRes(res)); } } fn notify_one(&self, _: u64, msg: PeerMsg) { @@ -5401,10 +5406,7 @@ mod tests { E: KvEngine, { match receiver.recv_timeout(Duration::from_secs(3)) { - Ok(PeerMsg::ApplyRes { - res: TaskRes::Apply(res), - .. - }) => res, + Ok(PeerMsg::ApplyRes(box TaskRes::Apply(res))) => res, e => panic!("unexpected res {:?}", e), } } @@ -5552,10 +5554,7 @@ mod tests { ], ); let apply_res = match rx.recv_timeout(Duration::from_secs(3)) { - Ok(PeerMsg::ApplyRes { - res: TaskRes::Apply(res), - .. - }) => res, + Ok(PeerMsg::ApplyRes(box TaskRes::Apply(res))) => res, e => panic!("unexpected apply result: {:?}", e), }; let apply_state_key = keys::apply_state_key(2); @@ -5586,12 +5585,9 @@ mod tests { router.schedule_task(2, Msg::destroy(2, false)); let (region_id, peer_id) = match rx.recv_timeout(Duration::from_secs(3)) { - Ok(PeerMsg::ApplyRes { - res: TaskRes::Destroy { - region_id, peer_id, .. - }, - .. - }) => (region_id, peer_id), + Ok(PeerMsg::ApplyRes(box TaskRes::Destroy { + region_id, peer_id, .. + })) => (region_id, peer_id), e => panic!("expected destroy result, but got {:?}", e), }; assert_eq!(peer_id, 1); @@ -7854,9 +7850,9 @@ mod tests { .unwrap(); assert_ne!(initial_state.get_applied_index(), 0); match apply_res_rx.recv_timeout(Duration::from_secs(3)) { - Ok(PeerMsg::ApplyRes { - res: TaskRes::Apply(apply_res), - }) => assert_eq!(apply_res.apply_state, initial_state), + Ok(PeerMsg::ApplyRes(box TaskRes::Apply(apply_res))) => { + assert_eq!(apply_res.apply_state, initial_state) + } e => panic!("unexpected result: {:?}", e), } index_id += 1; @@ -7888,9 +7884,9 @@ mod tests { .unwrap() .unwrap(); match apply_res_rx.recv_timeout(Duration::from_secs(3)) { - Ok(PeerMsg::ApplyRes { - res: TaskRes::Apply(apply_res), - }) => assert_eq!(apply_res.apply_state, apply_state), + Ok(PeerMsg::ApplyRes(box TaskRes::Apply(apply_res))) => { + assert_eq!(apply_res.apply_state, apply_state) + } e => panic!("unexpected result: {:?}", e), } assert!( diff --git a/components/raftstore/src/store/fsm/peer.rs b/components/raftstore/src/store/fsm/peer.rs index 9abc1c39945..999d23c46a4 100644 --- a/components/raftstore/src/store/fsm/peer.rs +++ b/components/raftstore/src/store/fsm/peer.rs @@ -210,7 +210,7 @@ where while let Ok(msg) = self.receiver.try_recv() { let callback = match msg { PeerMsg::RaftCommand(cmd) => cmd.callback, - PeerMsg::CasualMessage(CasualMessage::SplitRegion { callback, .. }) => callback, + PeerMsg::CasualMessage(box CasualMessage::SplitRegion { callback, .. }) => callback, PeerMsg::RaftMessage(im, _) => { raft_messages_size += im.heap_size; continue; @@ -684,7 +684,7 @@ where && !self.fsm.peer.disk_full_peers.majority()) || cmd.extra_opts.disk_full_opt == DiskFullOpt::NotAllowedOnFull) { - self.fsm.batch_req_builder.add(cmd, req_size); + self.fsm.batch_req_builder.add(*cmd, req_size); if self.fsm.batch_req_builder.should_finish(&self.ctx.cfg) { self.propose_pending_batch_raft_command(); } @@ -697,7 +697,7 @@ where } } PeerMsg::Tick(tick) => self.on_tick(tick), - PeerMsg::ApplyRes { res } => { + PeerMsg::ApplyRes(res) => { self.on_apply_res(res); } PeerMsg::SignificantMsg(msg) => self.on_significant_msg(msg), @@ -1129,8 +1129,8 @@ where } } - fn on_casual_msg(&mut self, msg: CasualMessage) { - match msg { + fn on_casual_msg(&mut self, msg: Box>) { + match *msg { CasualMessage::SplitRegion { region_epoch, split_keys, @@ -1491,8 +1491,8 @@ where ); } - fn on_significant_msg(&mut self, msg: SignificantMsg) { - match msg { + fn on_significant_msg(&mut self, msg: Box>) { + match *msg { SignificantMsg::SnapshotStatus { to_peer_id, status, .. } => { @@ -1873,7 +1873,7 @@ where // follower state let _ = self.ctx.router.send( self.region_id(), - PeerMsg::CasualMessage(CasualMessage::Campaign), + PeerMsg::CasualMessage(Box::new(CasualMessage::Campaign)), ); } self.fsm.has_ready = true; @@ -2440,9 +2440,9 @@ where } } - fn on_apply_res(&mut self, res: ApplyTaskRes) { + fn on_apply_res(&mut self, res: Box>) { fail_point!("on_apply_res", |_| {}); - match res { + match *res { ApplyTaskRes::Apply(mut res) => { debug!( "async apply finish"; @@ -2613,8 +2613,8 @@ where } } - fn on_raft_message(&mut self, msg: InspectedRaftMessage) -> Result<()> { - let InspectedRaftMessage { heap_size, mut msg } = msg; + fn on_raft_message(&mut self, m: Box) -> Result<()> { + let InspectedRaftMessage { heap_size, mut msg } = *m; let peer_disk_usage = msg.disk_usage; let stepped = Cell::new(false); let memtrace_raft_entries = &mut self.fsm.peer.memtrace_raft_entries as *mut usize; @@ -3199,10 +3199,10 @@ where ); if self.handle_destroy_peer(job) { // It's not frequent, so use 0 as `heap_size` is ok. - let store_msg = StoreMsg::RaftMessage(InspectedRaftMessage { + let store_msg = StoreMsg::RaftMessage(Box::new(InspectedRaftMessage { heap_size: 0, msg: msg.clone(), - }); + })); if let Err(e) = self.ctx.router.send_control(store_msg) { info!( "failed to send back store message, are we shutting down?"; @@ -3537,7 +3537,7 @@ where // may has been merged/splitted already. let _ = self.ctx.router.force_send( exist_region.get_id(), - PeerMsg::CasualMessage(CasualMessage::RegionOverlapped), + PeerMsg::CasualMessage(Box::new(CasualMessage::RegionOverlapped)), ); } } @@ -3615,11 +3615,11 @@ where .router .force_send( source_region_id, - PeerMsg::SignificantMsg(SignificantMsg::MergeResult { + PeerMsg::SignificantMsg(Box::new(SignificantMsg::MergeResult { target_region_id: self.fsm.region_id(), target: self.fsm.peer.peer.clone(), result, - }), + })), ) .unwrap(); } @@ -3847,9 +3847,9 @@ where ) .flush() .when_done(move || { - if let Err(e) = - mb.force_send(PeerMsg::SignificantMsg(SignificantMsg::RaftLogGcFlushed)) - { + if let Err(e) = mb.force_send(PeerMsg::SignificantMsg(Box::new( + SignificantMsg::RaftLogGcFlushed, + ))) { if tikv_util::thread_group::is_shutdown(!cfg!(test)) { return; } @@ -4534,7 +4534,7 @@ where .swap_remove_front(|m| m.get_to_peer() == &meta_peer) { let peer_msg = PeerMsg::RaftMessage( - InspectedRaftMessage { heap_size: 0, msg }, + Box::new(InspectedRaftMessage { heap_size: 0, msg }), Some(TiInstant::now()), ); if let Err(e) = self.ctx.router.force_send(new_region_id, peer_msg) { @@ -4765,14 +4765,14 @@ where .router .force_send( target_id, - PeerMsg::RaftCommand(RaftCommand::new_ext( + PeerMsg::RaftCommand(Box::new(RaftCommand::new_ext( request, Callback::None, RaftCmdExtraOpts { deadline: None, disk_full_opt: DiskFullOpt::AllowedOnAlmostFull, }, - )), + ))), ) .map_err(|_| Error::RegionNotFound(target_id)) } @@ -5029,11 +5029,11 @@ where } if let Err(e) = self.ctx.router.force_send( source.get_id(), - PeerMsg::SignificantMsg(SignificantMsg::MergeResult { + PeerMsg::SignificantMsg(Box::new(SignificantMsg::MergeResult { target_region_id: self.fsm.region_id(), target: self.fsm.peer.peer.clone(), result: MergeResultKind::FromTargetLog, - }), + })), ) { panic!( "{} failed to send merge result(FromTargetLog) to source region {}, err {}", @@ -5307,11 +5307,11 @@ where for r in &persist_res.destroy_regions { if let Err(e) = self.ctx.router.force_send( r.get_id(), - PeerMsg::SignificantMsg(SignificantMsg::MergeResult { + PeerMsg::SignificantMsg(Box::new(SignificantMsg::MergeResult { target_region_id: self.fsm.region_id(), target: self.fsm.peer.peer.clone(), result: MergeResultKind::FromTargetSnapshotStep2, - }), + })), ) { panic!( "{} failed to send merge result(FromTargetSnapshotStep2) to source region {}, err {}", diff --git a/components/raftstore/src/store/fsm/store.rs b/components/raftstore/src/store/fsm/store.rs index 08955f07187..8da5743fecb 100644 --- a/components/raftstore/src/store/fsm/store.rs +++ b/components/raftstore/src/store/fsm/store.rs @@ -384,9 +384,7 @@ where let region_id = r.region_id; if let Err(e) = self.router.force_send( region_id, - PeerMsg::ApplyRes { - res: ApplyTaskRes::Apply(r), - }, + PeerMsg::ApplyRes(Box::new(ApplyTaskRes::Apply(r))), ) { error!("failed to send apply result"; "region_id" => region_id, "err" => ?e); } @@ -423,7 +421,7 @@ where heap_size += bytes_capacity(&e.data) + bytes_capacity(&e.context); } let peer_msg = PeerMsg::RaftMessage( - InspectedRaftMessage { heap_size, msg }, + Box::new(InspectedRaftMessage { heap_size, msg }), Some(TiInstant::now()), ); let event = TraceEvent::Add(heap_size); @@ -468,10 +466,10 @@ where cmd: RaftCommand, ) -> std::result::Result<(), TrySendError>> { let region_id = cmd.request.get_header().get_region_id(); - match self.send(region_id, PeerMsg::RaftCommand(cmd)) { + match self.send(region_id, PeerMsg::RaftCommand(Box::new(cmd))) { Ok(()) => Ok(()), - Err(TrySendError::Full(PeerMsg::RaftCommand(cmd))) => Err(TrySendError::Full(cmd)), - Err(TrySendError::Disconnected(PeerMsg::RaftCommand(cmd))) => { + Err(TrySendError::Full(PeerMsg::RaftCommand(box cmd))) => Err(TrySendError::Full(cmd)), + Err(TrySendError::Disconnected(PeerMsg::RaftCommand(box cmd))) => { Err(TrySendError::Disconnected(cmd)) } _ => unreachable!(), @@ -480,7 +478,7 @@ where fn report_unreachable(&self, store_id: u64) { self.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::StoreUnreachable { store_id }) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::StoreUnreachable { store_id })) }); } @@ -491,7 +489,10 @@ where /// Broadcasts resolved result to all regions. pub fn report_resolved(&self, store_id: u64, group_id: u64) { self.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::StoreResolved { store_id, group_id }) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::StoreResolved { + store_id, + group_id, + })) }) } @@ -1074,12 +1075,7 @@ impl PollHandler, St fail_point!( "pause_on_peer_destroy_res", peer.peer_id() == 1 - && matches!( - msg, - PeerMsg::ApplyRes { - res: ApplyTaskRes::Destroy { .. }, - } - ), + && matches!(msg, PeerMsg::ApplyRes(box ApplyTaskRes::Destroy { .. })), |_| unreachable!() ); self.peer_msg_buf.push(msg); @@ -1679,7 +1675,9 @@ impl RaftBatchSystem { for region_id in regions { let _ = router_clone.send( region_id, - PeerMsg::CasualMessage(CasualMessage::ForceCompactRaftLogs), + PeerMsg::CasualMessage(Box::new( + CasualMessage::ForceCompactRaftLogs, + )), ); } } @@ -2143,7 +2141,7 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER Ok(CheckMsgStatus::NewPeer) } - fn on_raft_message(&mut self, msg: InspectedRaftMessage) -> Result<()> { + fn on_raft_message(&mut self, msg: Box) -> Result<()> { let (heap_size, forwarded) = (msg.heap_size, Cell::new(false)); defer!(if !forwarded.get() { MEMTRACE_RAFT_MESSAGES.trace(TraceEvent::Sub(heap_size)); @@ -2234,8 +2232,10 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER check_msg_status == CheckMsgStatus::NewPeerFirst, )? { // Peer created, send the message again. - let peer_msg = - PeerMsg::RaftMessage(InspectedRaftMessage { heap_size, msg }, None); + let peer_msg = PeerMsg::RaftMessage( + Box::new(InspectedRaftMessage { heap_size, msg }), + None, + ); if self.ctx.router.send(region_id, peer_msg).is_ok() { forwarded.set(true); } @@ -2258,7 +2258,8 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER store_meta.pending_msgs.push(msg); } else { drop(store_meta); - let peer_msg = PeerMsg::RaftMessage(InspectedRaftMessage { heap_size, msg }, None); + let peer_msg = + PeerMsg::RaftMessage(Box::new(InspectedRaftMessage { heap_size, msg }), None); if let Err(e) = self.ctx.router.force_send(region_id, peer_msg) { warn!("handle first request failed"; "region_id" => region_id, "error" => ?e); } else { @@ -2423,7 +2424,7 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER // region may has been merged/splitted already. let _ = self.ctx.router.force_send( exist_region.get_id(), - PeerMsg::CasualMessage(CasualMessage::RegionOverlapped), + PeerMsg::CasualMessage(Box::new(CasualMessage::RegionOverlapped)), ); } } @@ -2438,11 +2439,11 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER .router .force_send( id, - PeerMsg::SignificantMsg(SignificantMsg::MergeResult { + PeerMsg::SignificantMsg(Box::new(SignificantMsg::MergeResult { target_region_id: region_id, target: target.clone(), result: MergeResultKind::Stale, - }), + })), ) .unwrap(); } @@ -2510,9 +2511,9 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER for (region_id, declined_bytes) in region_declined_bytes.drain(..) { let _ = self.ctx.router.send( region_id, - PeerMsg::CasualMessage(CasualMessage::CompactionDeclinedBytes { + PeerMsg::CasualMessage(Box::new(CasualMessage::CompactionDeclinedBytes { bytes: declined_bytes, - }), + })), ); } } @@ -3201,7 +3202,7 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER let _ = self.ctx.router.send( target_region_id, - PeerMsg::RaftCommand(RaftCommand::new(request, Callback::None)), + PeerMsg::RaftCommand(Box::new(RaftCommand::new(request, Callback::None))), ); } @@ -3239,7 +3240,7 @@ impl<'a, EK: KvEngine, ER: RaftEngine, T: Transport> StoreFsmDelegate<'a, EK, ER for region_id in regions { let _ = self.ctx.router.send( region_id, - PeerMsg::CasualMessage(CasualMessage::ClearRegionSize), + PeerMsg::CasualMessage(Box::new(CasualMessage::ClearRegionSize)), ); } } diff --git a/components/raftstore/src/store/msg.rs b/components/raftstore/src/store/msg.rs index a947790e6db..b8e37e1d973 100644 --- a/components/raftstore/src/store/msg.rs +++ b/components/raftstore/src/store/msg.rs @@ -809,28 +809,25 @@ impl fmt::Debug for InspectedRaftMessage { } /// Message that can be sent to a peer. -#[allow(clippy::large_enum_variant)] #[derive(EnumCount, EnumVariantNames)] pub enum PeerMsg { /// Raft message is the message sent between raft nodes in the same /// raft group. Messages need to be redirected to raftstore if target /// peer doesn't exist. - RaftMessage(InspectedRaftMessage, Option), + RaftMessage(Box, Option), /// Raft command is the command that is expected to be proposed by the /// leader of the target raft group. If it's failed to be sent, callback /// usually needs to be called before dropping in case of resource leak. - RaftCommand(RaftCommand), + RaftCommand(Box>), /// Tick is periodical task. If target peer doesn't exist there is a /// potential that the raft node will not work anymore. Tick(PeerTick), /// Result of applying committed entries. The message can't be lost. - ApplyRes { - res: ApplyTaskRes, - }, + ApplyRes(Box>), /// Message that can't be lost but rarely created. If they are lost, real /// bad things happen like some peers will be considered dead in the /// group. - SignificantMsg(SignificantMsg), + SignificantMsg(Box>), /// Start the FSM. Start, /// A message only used to notify a peer. @@ -840,7 +837,7 @@ pub enum PeerMsg { ready_number: u64, }, /// Message that is not important and can be dropped occasionally. - CasualMessage(CasualMessage), + CasualMessage(Box>), /// Ask region to report a heartbeat to PD. HeartbeatPd, /// Asks region to change replication mode. @@ -863,7 +860,7 @@ impl fmt::Debug for PeerMsg { tick }, PeerMsg::SignificantMsg(msg) => write!(fmt, "{:?}", msg), - PeerMsg::ApplyRes { res } => write!(fmt, "ApplyRes {:?}", res), + PeerMsg::ApplyRes(res) => write!(fmt, "ApplyRes {:?}", res), PeerMsg::Start => write!(fmt, "Startup"), PeerMsg::Noop => write!(fmt, "Noop"), PeerMsg::Persisted { @@ -906,7 +903,7 @@ impl PeerMsg { pub fn is_send_failure_ignorable(&self) -> bool { matches!( self, - PeerMsg::SignificantMsg(SignificantMsg::CaptureChange { .. }) + PeerMsg::SignificantMsg(box SignificantMsg::CaptureChange { .. }) ) } } @@ -916,7 +913,7 @@ pub enum StoreMsg where EK: KvEngine, { - RaftMessage(InspectedRaftMessage), + RaftMessage(Box), // Clear region size and keys for all regions in the range, so we can force them to // re-calculate their size later. @@ -1017,3 +1014,18 @@ impl StoreMsg { } } } + +#[cfg(test)] +mod tests { + #[test] + fn test_msg_size() { + use std::mem; + + use engine_rocks::RocksEngine; + + use super::*; + + // make sure the msg is small enough + assert_eq!(mem::size_of::>(), 32); + } +} diff --git a/components/raftstore/src/store/snapshot_backup.rs b/components/raftstore/src/store/snapshot_backup.rs index 9168e974fc2..710ac281e8a 100644 --- a/components/raftstore/src/store/snapshot_backup.rs +++ b/components/raftstore/src/store/snapshot_backup.rs @@ -75,7 +75,7 @@ impl SnapshotBrHandle for Arc crate::Result<()> { let msg_gen = || { metrics::SNAP_BR_WAIT_APPLY_EVENT.sent.inc(); - PeerMsg::SignificantMsg(SignificantMsg::SnapshotBrWaitApply(req.clone())) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::SnapshotBrWaitApply(req.clone()))) }; self.lock().unwrap().broadcast_normal(msg_gen); Ok(()) @@ -86,7 +86,7 @@ impl SnapshotBrHandle for Arc, ) -> crate::Result<()> { self.lock().unwrap().broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::CheckPendingAdmin(tx.clone())) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::CheckPendingAdmin(tx.clone()))) }); Ok(()) } diff --git a/components/raftstore/src/store/transport.rs b/components/raftstore/src/store/transport.rs index 2ca19fbe5fe..35761aa5d18 100644 --- a/components/raftstore/src/store/transport.rs +++ b/components/raftstore/src/store/transport.rs @@ -78,7 +78,10 @@ where { #[inline] fn send(&self, region_id: u64, msg: CasualMessage) -> Result<()> { - match self.router.send(region_id, PeerMsg::CasualMessage(msg)) { + match self + .router + .send(region_id, PeerMsg::CasualMessage(Box::new(msg))) + { Ok(()) => Ok(()), Err(TrySendError::Full(_)) => Err(Error::Transport(DiscardReason::Full)), Err(TrySendError::Disconnected(_)) => Err(Error::RegionNotFound(region_id)), @@ -102,7 +105,7 @@ where fn significant_send(&self, region_id: u64, msg: SignificantMsg) -> Result<()> { if let Err(SendError(msg)) = self .router - .force_send(region_id, PeerMsg::SignificantMsg(msg)) + .force_send(region_id, PeerMsg::SignificantMsg(Box::new(msg))) { // TODO: panic here once we can detect system is shutting down reliably. diff --git a/components/raftstore/src/store/unsafe_recovery.rs b/components/raftstore/src/store/unsafe_recovery.rs index fd750f54278..876f181807b 100644 --- a/components/raftstore/src/store/unsafe_recovery.rs +++ b/components/raftstore/src/store/unsafe_recovery.rs @@ -80,7 +80,9 @@ impl UnsafeRecoveryHandle for Mutex UnsafeRecoveryHandle for Mutex region_id, ); - let gc_snap = PeerMsg::CasualMessage(CasualMessage::GcSnap { snaps }); + let gc_snap = PeerMsg::CasualMessage(Box::new(CasualMessage::GcSnap { snaps })); match (*self.router).send(region_id, gc_snap) { Ok(()) => Ok(()), Err(TrySendError::Disconnected(_)) if self.router.is_shutdown() => Ok(()), Err(TrySendError::Disconnected(PeerMsg::CasualMessage( - CasualMessage::GcSnap { snaps }, + box CasualMessage::GcSnap { snaps }, ))) => { // The snapshot exists because MsgAppend has been rejected. So the // peer must have been exist. But now it's disconnected, so the peer diff --git a/components/raftstore/src/store/worker/pd.rs b/components/raftstore/src/store/worker/pd.rs index d6f644ee00a..000e3310e4e 100644 --- a/components/raftstore/src/store/worker/pd.rs +++ b/components/raftstore/src/store/worker/pd.rs @@ -1547,7 +1547,7 @@ where cb: Callback::None, } }; - if let Err(e) = router.send(region_id, PeerMsg::CasualMessage(msg)) { + if let Err(e) = router.send(region_id, PeerMsg::CasualMessage(Box::new(msg))) { error!("send halfsplit request failed"; "region_id" => region_id, "err" => ?e); } } else if resp.has_merge() { @@ -1737,7 +1737,7 @@ where match resp.await { Ok(Some((region, leader))) => { if leader.get_store_id() != 0 { - let msg = CasualMessage::QueryRegionLeaderResp { region, leader }; + let msg = Box::new(CasualMessage::QueryRegionLeaderResp { region, leader }); if let Err(e) = router.send(region_id, PeerMsg::CasualMessage(msg)) { error!("send region info message failed"; "region_id" => region_id, "err" => ?e); } @@ -1991,14 +1991,14 @@ where let start_key = split_info.start_key.unwrap(); let end_key = split_info.end_key.unwrap(); let region_id = region.get_id(); - let msg = CasualMessage::HalfSplitRegion { + let msg = Box::new(CasualMessage::HalfSplitRegion { region_epoch: region.get_region_epoch().clone(), start_key: Some(start_key.clone()), end_key: Some(end_key.clone()), policy: pdpb::CheckPolicy::Scan, source: "auto_split", cb: Callback::None, - }; + }); if let Err(e) = router.send(region_id, PeerMsg::CasualMessage(msg)) { error!("send auto half split request failed"; "region_id" => region_id, diff --git a/components/snap_recovery/src/services.rs b/components/snap_recovery/src/services.rs index ff83db76bf2..931870a8ae4 100644 --- a/components/snap_recovery/src/services.rs +++ b/components/snap_recovery/src/services.rs @@ -228,9 +228,9 @@ where pub fn wait_apply_last(router: RaftRouter, sender: Sender) { let wait_apply = SnapshotBrWaitApplySyncer::new(0, sender); router.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::SnapshotBrWaitApply( + PeerMsg::SignificantMsg(Box::new(SignificantMsg::SnapshotBrWaitApply( SnapshotBrWaitApplyRequest::relaxed(wait_apply.clone()), - )) + ))) }); } } diff --git a/components/test_raftstore/src/router.rs b/components/test_raftstore/src/router.rs index 3b6b1e962c3..d6a135c9f9a 100644 --- a/components/test_raftstore/src/router.rs +++ b/components/test_raftstore/src/router.rs @@ -60,7 +60,7 @@ impl CasualRouter for MockRaftStoreRouter { fn send(&self, region_id: u64, msg: CasualMessage) -> RaftStoreResult<()> { let mut senders = self.senders.lock().unwrap(); if let Some(tx) = senders.get_mut(®ion_id) { - tx.try_send(PeerMsg::CasualMessage(msg)) + tx.try_send(PeerMsg::CasualMessage(Box::new(msg))) .map_err(|e| handle_send_error(region_id, e)) } else { Err(RaftStoreError::RegionNotFound(region_id)) @@ -76,7 +76,8 @@ impl SignificantRouter for MockRaftStoreRouter { ) -> RaftStoreResult<()> { let mut senders = self.senders.lock().unwrap(); if let Some(tx) = senders.get_mut(®ion_id) { - tx.force_send(PeerMsg::SignificantMsg(msg)).unwrap(); + tx.force_send(PeerMsg::SignificantMsg(Box::new(msg))) + .unwrap(); Ok(()) } else { error!("failed to send significant msg"; "msg" => ?msg); diff --git a/src/server/server.rs b/src/server/server.rs index e5326a651a9..bc83cf19ba3 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -481,14 +481,18 @@ pub mod test_router { cmd: RaftCommand, ) -> std::result::Result<(), crossbeam::channel::TrySendError>> { - let _ = self.tx.send(Either::Left(PeerMsg::RaftCommand(cmd))); + let _ = self + .tx + .send(Either::Left(PeerMsg::RaftCommand(Box::new(cmd)))); Ok(()) } } impl CasualRouter for TestRaftStoreRouter { fn send(&self, _: u64, msg: CasualMessage) -> RaftStoreResult<()> { - let _ = self.tx.send(Either::Left(PeerMsg::CasualMessage(msg))); + let _ = self + .tx + .send(Either::Left(PeerMsg::CasualMessage(Box::new(msg)))); Ok(()) } } @@ -507,7 +511,7 @@ pub mod test_router { impl RaftStoreRouter for TestRaftStoreRouter { fn send_raft_msg(&self, msg: RaftMessage) -> RaftStoreResult<()> { let _ = self.tx.send(Either::Left(PeerMsg::RaftMessage( - InspectedRaftMessage { heap_size: 0, msg }, + Box::new(InspectedRaftMessage { heap_size: 0, msg }), Some(TiInstant::now()), ))); Ok(()) diff --git a/tests/integrations/raftstore/test_snap_recovery.rs b/tests/integrations/raftstore/test_snap_recovery.rs index 5411e8ec75b..e0f150576ed 100644 --- a/tests/integrations/raftstore/test_snap_recovery.rs +++ b/tests/integrations/raftstore/test_snap_recovery.rs @@ -45,7 +45,7 @@ fn test_check_pending_admin() { let (tx, mut rx) = futures::channel::mpsc::unbounded(); router.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::CheckPendingAdmin(tx.clone())) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::CheckPendingAdmin(tx.clone()))) }); futures::executor::block_on(async { let r = rx.next().await; @@ -61,7 +61,7 @@ fn test_check_pending_admin() { let (tx, mut rx) = futures::channel::mpsc::unbounded(); router.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::CheckPendingAdmin(tx.clone())) + PeerMsg::SignificantMsg(Box::new(SignificantMsg::CheckPendingAdmin(tx.clone()))) }); futures::executor::block_on(async { let r = rx.next().await; @@ -101,9 +101,9 @@ fn test_snap_wait_apply() { let (tx, rx) = oneshot::channel(); let syncer = SnapshotBrWaitApplySyncer::new(1, tx); router.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::SnapshotBrWaitApply( + PeerMsg::SignificantMsg(Box::new(SignificantMsg::SnapshotBrWaitApply( SnapshotBrWaitApplyRequest::relaxed(syncer.clone()), - )) + ))) }); // we expect recv timeout because the leader peer on store 1 cannot finished the @@ -119,9 +119,9 @@ fn test_snap_wait_apply() { let (tx, rx) = oneshot::channel(); let syncer = SnapshotBrWaitApplySyncer::new(1, tx); router.broadcast_normal(|| { - PeerMsg::SignificantMsg(SignificantMsg::SnapshotBrWaitApply( + PeerMsg::SignificantMsg(Box::new(SignificantMsg::SnapshotBrWaitApply( SnapshotBrWaitApplyRequest::relaxed(syncer.clone()), - )) + ))) }); drop(syncer); From f1ff5e2e65f2d092b45774bf665009596d7ed516 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:44:11 +0800 Subject: [PATCH 018/144] In-memory engine: show index/select_by_range_cache_engine in handle/wait duration in cop detail (#17324) ref tikv/tikv#16141 show index/select-by-range-cache-engine in handle/wait duration in cop detail Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/engine_traits/src/snapshot.rs | 6 ++++++ components/hybrid_engine/src/snapshot.rs | 3 +++ components/tikv_kv/src/lib.rs | 7 +++++++ components/tikv_kv/src/raftstore_impls.rs | 4 ++++ metrics/grafana/tikv_details.dashboard.py | 12 ++++++------ metrics/grafana/tikv_details.json | 22 +++++++++++----------- metrics/grafana/tikv_details.json.sha256 | 2 +- src/coprocessor/endpoint.rs | 3 +++ src/coprocessor/metrics.rs | 2 ++ src/coprocessor/tracker.rs | 22 ++++++++++++++++++++-- 10 files changed, 63 insertions(+), 20 deletions(-) diff --git a/components/engine_traits/src/snapshot.rs b/components/engine_traits/src/snapshot.rs index 6ab2bb78af1..9f35640fa72 100644 --- a/components/engine_traits/src/snapshot.rs +++ b/components/engine_traits/src/snapshot.rs @@ -13,4 +13,10 @@ where Self: 'static + Peekable + Iterable + CfNamesExt + SnapshotMiscExt + Send + Sync + Sized + Debug, { + /// Whether the snapshot acquired hit the cached range in the range cache + /// engine. It always returns false if the range cahce engine is not + /// enabled. + fn range_cache_engine_hit(&self) -> bool { + false + } } diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index a4ed06bd91a..ea831368eb6 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -48,6 +48,9 @@ where EK: KvEngine, EC: RangeCacheEngine, { + fn range_cache_engine_hit(&self) -> bool { + self.range_cache_snap.is_some() + } } impl Debug for HybridEngineSnapshot diff --git a/components/tikv_kv/src/lib.rs b/components/tikv_kv/src/lib.rs index 9b3402704b7..1590eee2e53 100644 --- a/components/tikv_kv/src/lib.rs +++ b/components/tikv_kv/src/lib.rs @@ -532,6 +532,13 @@ pub trait SnapshotExt { fn get_buckets(&self) -> Option> { None } + + /// Whether the snapshot acquired hit the cached range in the range cache + /// engine. It always returns false if the range cahce engine is not + /// enabled. + fn range_cache_engine_hit(&self) -> bool { + false + } } pub struct DummySnapshotExt; diff --git a/components/tikv_kv/src/raftstore_impls.rs b/components/tikv_kv/src/raftstore_impls.rs index 977c34254f6..7247da3d14b 100644 --- a/components/tikv_kv/src/raftstore_impls.rs +++ b/components/tikv_kv/src/raftstore_impls.rs @@ -61,6 +61,10 @@ impl<'a, S: Snapshot> SnapshotExt for RegionSnapshotExt<'a, S> { fn get_buckets(&self) -> Option> { self.snapshot.bucket_meta.clone() } + + fn range_cache_engine_hit(&self) -> bool { + self.snapshot.get_snapshot().range_cache_engine_hit() + } } impl EngineSnapshot for RegionSnapshot { diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index 3fefd74714c..b0475bd1f1e 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -4084,7 +4084,7 @@ def CoprocessorDetail() -> RowPanel: target( expr=expr_sum_rate( "tikv_coprocessor_scan_details", - label_selectors=['req="select"'], + label_selectors=['req=~"select|select_by_range_cache"'], by_labels=["tag"], ), ), @@ -4097,7 +4097,7 @@ def CoprocessorDetail() -> RowPanel: target( expr=expr_sum_rate( "tikv_coprocessor_scan_details", - label_selectors=['req="index"'], + label_selectors=['req=~"index|index_by_range_cache"'], by_labels=["tag"], ), ), @@ -4114,7 +4114,7 @@ def CoprocessorDetail() -> RowPanel: target( expr=expr_sum_rate( "tikv_coprocessor_scan_details", - label_selectors=['req="select"'], + label_selectors=['req=~"select|select_by_range_cache"'], by_labels=["cf", "tag"], ), ), @@ -4127,7 +4127,7 @@ def CoprocessorDetail() -> RowPanel: target( expr=expr_sum_rate( "tikv_coprocessor_scan_details", - label_selectors=['req="index"'], + label_selectors=['req=~"index|index_by_range_cache"'], by_labels=["cf", "tag"], ), ), @@ -4268,10 +4268,10 @@ def RangeCacheMemoryEngine() -> RowPanel: targets=[ target( expr=expr_sum_rate( - "tikv_range_load_duration_secs_count", + "tikv_range_eviction_duration_secs_count", by_labels=["instance"], ), - legend_format="{{instance}}--loading2", + legend_format="{{instance}}", ), ], ), diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index b16c8426f5d..f14a06f6219 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -38199,15 +38199,15 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "expr": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "format": "time_series", "hide": false, "instant": false, "interval": "", "intervalFactor": 1, - "legendFormat": "{{instance}}--loading2", + "legendFormat": "{{instance}}", "metric": "", - "query": "sum(rate(\n tikv_range_load_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "query": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", "refId": "", "step": 10, "target": "" @@ -46039,7 +46039,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"select\"}\n [$__rate_interval]\n)) by (tag) ", + "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"select|select_by_range_cache\"}\n [$__rate_interval]\n)) by (tag) ", "format": "time_series", "hide": false, "instant": false, @@ -46047,7 +46047,7 @@ "intervalFactor": 1, "legendFormat": "{{tag}}", "metric": "", - "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"select\"}\n [$__rate_interval]\n)) by (tag) ", + "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"select|select_by_range_cache\"}\n [$__rate_interval]\n)) by (tag) ", "refId": "", "step": 10, "target": "" @@ -46172,7 +46172,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"index\"}\n [$__rate_interval]\n)) by (tag) ", + "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"index|index_by_range_cache\"}\n [$__rate_interval]\n)) by (tag) ", "format": "time_series", "hide": false, "instant": false, @@ -46180,7 +46180,7 @@ "intervalFactor": 1, "legendFormat": "{{tag}}", "metric": "", - "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"index\"}\n [$__rate_interval]\n)) by (tag) ", + "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"index|index_by_range_cache\"}\n [$__rate_interval]\n)) by (tag) ", "refId": "", "step": 10, "target": "" @@ -46305,7 +46305,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"select\"}\n [$__rate_interval]\n)) by (cf, tag) ", + "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"select|select_by_range_cache\"}\n [$__rate_interval]\n)) by (cf, tag) ", "format": "time_series", "hide": false, "instant": false, @@ -46313,7 +46313,7 @@ "intervalFactor": 1, "legendFormat": "{{cf}}-{{tag}}", "metric": "", - "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"select\"}\n [$__rate_interval]\n)) by (cf, tag) ", + "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"select|select_by_range_cache\"}\n [$__rate_interval]\n)) by (cf, tag) ", "refId": "", "step": 10, "target": "" @@ -46438,7 +46438,7 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"index\"}\n [$__rate_interval]\n)) by (cf, tag) ", + "expr": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"index|index_by_range_cache\"}\n [$__rate_interval]\n)) by (cf, tag) ", "format": "time_series", "hide": false, "instant": false, @@ -46446,7 +46446,7 @@ "intervalFactor": 1, "legendFormat": "{{cf}}-{{tag}}", "metric": "", - "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=\"index\"}\n [$__rate_interval]\n)) by (cf, tag) ", + "query": "sum(rate(\n tikv_coprocessor_scan_details\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",req=~\"index|index_by_range_cache\"}\n [$__rate_interval]\n)) by (cf, tag) ", "refId": "", "step": 10, "target": "" diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index db599173fe6..6384c6863e9 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -1c5a149c9ff8753b505e48e5ad0d1a6008eb36820b0a512ef8c8a550a08106cf ./metrics/grafana/tikv_details.json +aac4c44b48b6bf54aab2f24392975d24ff53a999748a5f2dca4d3b9d2bd77c6f ./metrics/grafana/tikv_details.json diff --git a/src/coprocessor/endpoint.rs b/src/coprocessor/endpoint.rs index cd06fc5f24b..14a6d3cda8e 100644 --- a/src/coprocessor/endpoint.rs +++ b/src/coprocessor/endpoint.rs @@ -441,6 +441,9 @@ impl Endpoint { .await?; let latest_buckets = snapshot.ext().get_buckets(); + let range_cache_snap = snapshot.ext().range_cache_engine_hit(); + tracker.adjust_snapshot_type(range_cache_snap); + // Check if the buckets version is latest. // skip if request don't carry this bucket version. if let Some(ref buckets) = latest_buckets diff --git a/src/coprocessor/metrics.rs b/src/coprocessor/metrics.rs index 402ed02408c..e06d4007ab9 100644 --- a/src/coprocessor/metrics.rs +++ b/src/coprocessor/metrics.rs @@ -18,7 +18,9 @@ use crate::{ make_auto_flush_static_metric! { pub label_enum ReqTag { select, + select_by_range_cache, index, + index_by_range_cache, // For AnalyzeType::{TypeColumn,TypeMixed}. analyze_table, // For AnalyzeType::{TypeIndex,TypeCommonHandle}. diff --git a/src/coprocessor/tracker.rs b/src/coprocessor/tracker.rs index a005984dc74..60a6b742646 100644 --- a/src/coprocessor/tracker.rs +++ b/src/coprocessor/tracker.rs @@ -109,6 +109,16 @@ impl Tracker { } } + pub fn adjust_snapshot_type(&mut self, range_cache_engine: bool) { + if range_cache_engine { + if self.req_ctx.tag == ReqTag::select { + self.req_ctx.tag = ReqTag::select_by_range_cache; + } else if self.req_ctx.tag == ReqTag::index { + self.req_ctx.tag = ReqTag::index_by_range_cache; + } + } + } + pub fn on_scheduled(&mut self) { assert_eq!(self.current_stage, TrackerState::Initialized); let now = Instant::now(); @@ -365,7 +375,11 @@ impl Tracker { // only collect metrics for select and index, exclude transient read flow such // like analyze and checksum. - if self.req_ctx.tag == ReqTag::select || self.req_ctx.tag == ReqTag::index { + if self.req_ctx.tag == ReqTag::select + || self.req_ctx.tag == ReqTag::index + || self.req_ctx.tag == ReqTag::select_by_range_cache + || self.req_ctx.tag == ReqTag::index_by_range_cache + { tls_collect_query( region_id, peer, @@ -390,7 +404,9 @@ impl Tracker { { thread_local! { static SELECT: RefCell>> = RefCell::new(None); + static SELECT_BY_RANGE_CACHE: RefCell>> = RefCell::new(None); static INDEX: RefCell>> = RefCell::new(None); + static INDEX_BY_RANGE_CACHE: RefCell>> = RefCell::new(None); static ANALYZE_TABLE: RefCell>> = RefCell::new(None); static ANALYZE_INDEX: RefCell>> = RefCell::new(None); static ANALYZE_FULL_SAMPLING: RefCell>> = RefCell::new(None); @@ -400,7 +416,9 @@ impl Tracker { } let tls_cell = match self.req_ctx.tag { ReqTag::select => &SELECT, + ReqTag::select_by_range_cache => &SELECT_BY_RANGE_CACHE, ReqTag::index => &INDEX, + ReqTag::index_by_range_cache => &INDEX_BY_RANGE_CACHE, ReqTag::analyze_table => &ANALYZE_TABLE, ReqTag::analyze_index => &ANALYZE_INDEX, ReqTag::analyze_full_sampling => &ANALYZE_FULL_SAMPLING, @@ -410,7 +428,7 @@ impl Tracker { }; tls_cell.with(|c| { let mut c = c.borrow_mut(); - let perf_context = c.get_or_insert_with(|| { + let perf_context: &mut Box = c.get_or_insert_with(|| { Box::new(E::Local::get_perf_context( PerfLevel::Uninitialized, PerfContextKind::Coprocessor(self.req_ctx.tag.get_str()), From 74a760fd7e15eb5a40ebcfdb5c663e5afaa36c8f Mon Sep 17 00:00:00 2001 From: lucasliang Date: Mon, 5 Aug 2024 15:06:40 +0800 Subject: [PATCH 019/144] *: enlarge the default region-size. (#17311) ref tikv/tikv#17309 This pr make the default setting of `coprocessor.region-split-size` larger, from `96MB` to `256MB` by default. The new setting for `region-split-size` is compatible to the larger cluster. Signed-off-by: lucasliang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> Co-authored-by: Bisheng Huang --- components/raftstore/src/coprocessor/config.rs | 6 ++++-- etc/config-template.toml | 17 +++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/components/raftstore/src/coprocessor/config.rs b/components/raftstore/src/coprocessor/config.rs index 8abfe38bb51..7eb13210ee1 100644 --- a/components/raftstore/src/coprocessor/config.rs +++ b/components/raftstore/src/coprocessor/config.rs @@ -69,8 +69,10 @@ pub enum ConsistencyCheckMethod { Mvcc = 1, } -/// Default region split size. -pub const SPLIT_SIZE: ReadableSize = ReadableSize::mb(96); +/// Default region split size. In version < 8.3.0, the default split size is +/// 96MB. In version >= 8.3.0, the default split size is increased to 256MB to +/// allow for larger region size in TiKV. +pub const SPLIT_SIZE: ReadableSize = ReadableSize::mb(256); pub const RAFTSTORE_V2_SPLIT_SIZE: ReadableSize = ReadableSize::gb(10); /// Default batch split limit. diff --git a/etc/config-template.toml b/etc/config-template.toml index 95b2853fd1e..767a91e575e 100644 --- a/etc/config-template.toml +++ b/etc/config-template.toml @@ -405,7 +405,8 @@ ## When Region size change exceeds this config, TiKV will check whether the Region should be split ## or not. To reduce the cost of scanning data in the checking process, you can set the value to ## 32MB during checking and set it back to the default value in normal operations. -# region-split-check-diff = "6MB" +## It's recommanded to set it to 1/16 of `region-split-size`. +# region-split-check-diff = "16MB" ## The interval of triggering Region split check. # split-region-check-tick-interval = "10s" @@ -423,11 +424,11 @@ # raft-log-gc-threshold = 50 ## When the entry count exceeds this value, GC will be forced to trigger. -# raft-log-gc-count-limit = 73728 +# raft-log-gc-count-limit = 196608 ## When the approximate size of Raft log entries exceeds this value, GC will be forced trigger. ## It's recommanded to set it to 3/4 of `region-split-size`. -# raft-log-gc-size-limit = "72MB" +# raft-log-gc-size-limit = "192MB" ## Old Raft logs could be reserved if `raft_log_gc_threshold` is not reached. ## GC them after ticks `raft_log_reserve_max_ticks` times. @@ -506,14 +507,14 @@ ## When Region [a,e) size exceeds `region_max_size`, it will be split into several Regions [a,b), ## [b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be `region_split_size` (or a ## little larger). -# region-max-size = "144MB" -# region-split-size = "96MB" +# region-max-size = "384MB" +# region-split-size = "256MB" ## When the number of keys in Region [a,e) exceeds the `region_max_keys`, it will be split into ## several Regions [a,b), [b,c), [c,d), [d,e) and the number of keys in [a,b), [b,c), [c,d) will be ## `region_split_keys`. -# region-max-keys = 1440000 -# region-split-keys = 960000 +# region-max-keys = 3840000 +# region-split-keys = 2560000 ## Set to "mvcc" to do consistency check for MVCC data, or "raw" for raw data. # consistency-check-method = "mvcc" @@ -1295,7 +1296,7 @@ ## When Backup region [a,e) size exceeds `sst-max-size`, it will be backuped into several Files [a,b), ## [b,c), [c,d), [d,e) and the size of [a,b), [b,c), [c,d) will be `sst-max-size` (or a ## little larger). -# sst-max-size = "144MB" +# sst-max-size = "384MB" ## Automatically reduce the number of backup threads when the current workload is high, ## in order to reduce impact on the cluster's performance during back up. From 0a7fb7cdb61bb8731c4eba9404cc877c336d0b5e Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:20:08 +0800 Subject: [PATCH 020/144] In-memory engine: show eviction reasons in metrics (#17345) ref tikv/tikv#16141 show eviction reasons in metrics Signed-off-by: SpadeA-Tang --- .../engine_panic/src/range_cache_engine.rs | 4 +- .../engine_rocks/src/range_cache_engine.rs | 4 +- .../engine_traits/src/range_cache_engine.rs | 15 ++++- components/hybrid_engine/src/misc.rs | 10 ++- components/hybrid_engine/src/observer.rs | 20 ++++-- .../hybrid_engine/src/range_cache_engine.rs | 6 +- .../src/background.rs | 41 ++++++++---- .../range_cache_memory_engine/src/engine.rs | 12 ++-- .../range_cache_memory_engine/src/metrics.rs | 44 ++++++++++++- .../src/range_manager.rs | 66 ++++++++++++------- .../range_cache_memory_engine/src/read.rs | 12 ++-- .../src/write_batch.rs | 11 ++-- .../tests/failpoints/test_memory_engine.rs | 14 ++-- metrics/grafana/tikv_details.dashboard.py | 4 +- metrics/grafana/tikv_details.json | 6 +- metrics/grafana/tikv_details.json.sha256 | 2 +- .../cases/test_range_cache_engine.rs | 6 +- 17 files changed, 189 insertions(+), 88 deletions(-) diff --git a/components/engine_panic/src/range_cache_engine.rs b/components/engine_panic/src/range_cache_engine.rs index 5ef60d9e65d..00891c04510 100644 --- a/components/engine_panic/src/range_cache_engine.rs +++ b/components/engine_panic/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::RangeCacheEngineExt; +use engine_traits::{EvictReason, RangeCacheEngineExt}; use crate::PanicEngine; @@ -9,7 +9,7 @@ impl RangeCacheEngineExt for PanicEngine { panic!() } - fn evict_range(&self, range: &engine_traits::CacheRange) { + fn evict_range(&self, range: &engine_traits::CacheRange, evict_range: EvictReason) { panic!() } } diff --git a/components/engine_rocks/src/range_cache_engine.rs b/components/engine_rocks/src/range_cache_engine.rs index 1275b00a6fc..509d32edf26 100644 --- a/components/engine_rocks/src/range_cache_engine.rs +++ b/components/engine_rocks/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::RangeCacheEngineExt; +use engine_traits::{EvictReason, RangeCacheEngineExt}; use crate::RocksEngine; @@ -10,5 +10,5 @@ impl RangeCacheEngineExt for RocksEngine { } #[inline] - fn evict_range(&self, _: &engine_traits::CacheRange) {} + fn evict_range(&self, _: &engine_traits::CacheRange, _: EvictReason) {} } diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 8b5c10bd354..0f081ff8700 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -17,6 +17,17 @@ pub enum FailedReason { TooOldRead, } +#[derive(Debug, Clone, Copy)] +pub enum EvictReason { + LoadFailed, + LoadFailedWithoutStart, + MemoryLimitReached, + BecomeFollower, + AutoEvict, + DeleteRange, + Merge, +} + /// RangeCacheEngine works as a range cache caching some ranges (in Memory or /// NVME for instance) to improve the read performance. pub trait RangeCacheEngine: @@ -48,7 +59,7 @@ pub trait RangeCacheEngine: false } - fn evict_range(&self, range: &CacheRange); + fn evict_range(&self, range: &CacheRange, evict_reason: EvictReason); } pub trait RangeCacheEngineExt { @@ -56,7 +67,7 @@ pub trait RangeCacheEngineExt { // TODO(SpadeA): try to find a better way to reduce coupling degree of range // cache engine and kv engine - fn evict_range(&self, range: &CacheRange); + fn evict_range(&self, range: &CacheRange, evict_range: EvictReason); } /// A service that should run in the background to retrieve and apply cache diff --git a/components/hybrid_engine/src/misc.rs b/components/hybrid_engine/src/misc.rs index 777637d8d77..5d8043160b5 100644 --- a/components/hybrid_engine/src/misc.rs +++ b/components/hybrid_engine/src/misc.rs @@ -1,6 +1,8 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{CacheRange, KvEngine, MiscExt, RangeCacheEngine, Result, WriteBatchExt}; +use engine_traits::{ + CacheRange, EvictReason, KvEngine, MiscExt, RangeCacheEngine, Result, WriteBatchExt, +}; use crate::{engine::HybridEngine, hybrid_metrics::HybridEngineStatisticsReporter}; @@ -36,8 +38,10 @@ where ranges: &[engine_traits::Range<'_>], ) -> Result { for r in ranges { - self.range_cache_engine() - .evict_range(&CacheRange::new(r.start_key.to_vec(), r.end_key.to_vec())); + self.range_cache_engine().evict_range( + &CacheRange::new(r.start_key.to_vec(), r.end_key.to_vec()), + EvictReason::DeleteRange, + ); } self.disk_engine() .delete_ranges_cf(wopts, cf, strategy, ranges) diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer.rs index acf8eb990bf..4fd0bcddcc9 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; -use engine_traits::{CacheRange, KvEngine, RangeCacheEngineExt}; +use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngineExt}; use kvproto::{metapb::Region, raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; use raft::StateRole; use raftstore::coprocessor::{ @@ -13,7 +13,7 @@ use raftstore::coprocessor::{ #[derive(Clone)] pub struct Observer { - pending_evict: Arc>>, + pending_evict: Arc>>, cache_engine: Arc, } @@ -82,7 +82,10 @@ impl Observer { "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), "range" => ?range, ); - self.pending_evict.lock().unwrap().push(range); + self.pending_evict + .lock() + .unwrap() + .push((range, EvictReason::Merge)); } } @@ -95,8 +98,8 @@ impl Observer { let mut ranges = self.pending_evict.lock().unwrap(); std::mem::take(&mut *ranges) }; - for range in ranges { - self.cache_engine.evict_range(&range); + for (range, evict_reason) in ranges { + self.cache_engine.evict_range(&range, evict_reason); } } @@ -111,7 +114,10 @@ impl Observer { "region_id" => region.get_id(), "range" => ?range, ); - self.pending_evict.lock().unwrap().push(range); + self.pending_evict + .lock() + .unwrap() + .push((range, EvictReason::BecomeFollower)); } } @@ -197,7 +203,7 @@ mod tests { fn range_cache_engine_enabled(&self) -> bool { self.enabled.load(Ordering::Relaxed) } - fn evict_range(&self, range: &CacheRange) { + fn evict_range(&self, range: &CacheRange, _: EvictReason) { self.evicted_ranges.lock().unwrap().push(range.clone()); } } diff --git a/components/hybrid_engine/src/range_cache_engine.rs b/components/hybrid_engine/src/range_cache_engine.rs index 2c87abdcada..fb54ad80c04 100644 --- a/components/hybrid_engine/src/range_cache_engine.rs +++ b/components/hybrid_engine/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{CacheRange, KvEngine, RangeCacheEngine, RangeCacheEngineExt}; +use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngine, RangeCacheEngineExt}; use crate::HybridEngine; @@ -14,7 +14,7 @@ where } #[inline] - fn evict_range(&self, range: &CacheRange) { - self.range_cache_engine().evict_range(range); + fn evict_range(&self, range: &CacheRange, evict_range: EvictReason) { + self.range_cache_engine().evict_range(range, evict_range); } } diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 14cc96d103f..737405a1cee 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -9,8 +9,8 @@ use crossbeam::{ }; use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_traits::{ - CacheRange, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, SnapshotMiscExt, - CF_DEFAULT, CF_WRITE, DATA_CFS, + CacheRange, EvictReason, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, + SnapshotMiscExt, CF_DEFAULT, CF_WRITE, DATA_CFS, }; use parking_lot::RwLock; use pd_client::{PdClient, RpcClient}; @@ -492,7 +492,7 @@ impl BackgroundRunnerCore { assert_eq!(r, range); core.mut_range_manager() .ranges_being_deleted - .insert(r.clone(), (true, Instant::now())); + .insert(r.clone(), (true, Instant::now(), EvictReason::LoadFailed)); core.remove_cached_write_batch(&range); drop(core); fail::fail_point!("in_memory_engine_snapshot_load_canceled"); @@ -542,10 +542,12 @@ impl BackgroundRunnerCore { true } - fn on_snapshot_load_canceled( + // `start` means whether to start to load keys + fn on_snapshot_load_failed( &mut self, range: CacheRange, delete_range_scheduler: &Scheduler, + started: bool, ) { let mut core = self.engine.write(); let (r, ..) = core @@ -555,9 +557,18 @@ impl BackgroundRunnerCore { .unwrap(); assert_eq!(r, range); core.remove_cached_write_batch(&range); - core.mut_range_manager() - .ranges_being_deleted - .insert(r.clone(), (true, Instant::now())); + core.mut_range_manager().ranges_being_deleted.insert( + r.clone(), + ( + true, + Instant::now(), + if !started { + EvictReason::LoadFailedWithoutStart + } else { + EvictReason::LoadFailed + }, + ), + ); if let Err(e) = delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(vec![r])) { @@ -606,7 +617,9 @@ impl BackgroundRunnerCore { } let evicted_range = { let mut engine_wr = self.engine.write(); - let mut ranges = engine_wr.mut_range_manager().evict_range(range); + let mut ranges = engine_wr + .mut_range_manager() + .evict_range(range, EvictReason::MemoryLimitReached); if !ranges.is_empty() { info!( "evict on soft limit reached"; @@ -675,7 +688,9 @@ impl BackgroundRunnerCore { for evict_range in ranges_to_remove { if self.memory_controller.reached_soft_limit() { let mut core = self.engine.write(); - let mut ranges = core.mut_range_manager().evict_range(&evict_range); + let mut ranges = core + .mut_range_manager() + .evict_range(&evict_range, EvictReason::AutoEvict); info!( "load_evict: soft limit reached"; "range_to_evict" => ?&evict_range, @@ -905,7 +920,7 @@ impl Runnable for BackgroundRunner { "snapshot load canceled due to memory reaching soft limit"; "range" => ?range, ); - core.on_snapshot_load_canceled(range, &delete_range_scheduler); + core.on_snapshot_load_failed(range, &delete_range_scheduler, false); continue; } @@ -969,7 +984,7 @@ impl Runnable for BackgroundRunner { "snapshot load failed"; "range" => ?range, ); - core.on_snapshot_load_canceled(range, &delete_range_scheduler); + core.on_snapshot_load_failed(range, &delete_range_scheduler, true); continue; } @@ -1166,7 +1181,7 @@ impl Runnable for DeleteRangeRunner { for r in ranges { // Check whether range exists in `ranges_being_deleted` and it's scheduled if !core.range_manager.ranges_being_deleted.iter().any( - |(range_being_delete, &(scheduled, _))| { + |(range_being_delete, &(scheduled, ..))| { if range_being_delete == &r && !scheduled { panic!("range to delete with scheduled false; range={:?}", r,); }; @@ -2310,7 +2325,7 @@ pub mod tests { let _snap3 = engine.snapshot(range.clone(), 60, 1000).unwrap(); let range2 = CacheRange::new(b"key5".to_vec(), b"key8".to_vec()); - engine.evict_range(&range2); + engine.evict_range(&range2, EvictReason::AutoEvict); assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index a73f738073c..e7176250ae8 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -18,8 +18,8 @@ use crossbeam_skiplist::{ }; use engine_rocks::RocksEngine; use engine_traits::{ - CacheRange, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, Result, - CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + CacheRange, EvictReason, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, + Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use parking_lot::{lock_api::RwLockUpgradableReadGuard, RwLock, RwLockWriteGuard}; use raftstore::coprocessor::RegionInfoProvider; @@ -367,9 +367,9 @@ impl RangeCacheMemoryEngine { /// Evict a range from the in-memory engine. After this call, the range will /// not be readable, but the data of the range may not be deleted /// immediately due to some ongoing snapshots. - pub fn evict_range(&self, range: &CacheRange) { + pub fn evict_range(&self, range: &CacheRange, evict_reason: EvictReason) { let mut core = self.core.write(); - let mut ranges_to_delete = core.range_manager.evict_range(range); + let mut ranges_to_delete = core.range_manager.evict_range(range, evict_reason); core.mut_range_manager() .mark_delete_ranges_scheduled(&mut ranges_to_delete); if !ranges_to_delete.is_empty() { @@ -596,8 +596,8 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { self.config.value().enabled } - fn evict_range(&self, range: &CacheRange) { - self.evict_range(range) + fn evict_range(&self, range: &CacheRange, evict_range: EvictReason) { + self.evict_range(range, evict_range) } } diff --git a/components/range_cache_memory_engine/src/metrics.rs b/components/range_cache_memory_engine/src/metrics.rs index 4436c639ea0..187d2359f4b 100644 --- a/components/range_cache_memory_engine/src/metrics.rs +++ b/components/range_cache_memory_engine/src/metrics.rs @@ -2,6 +2,7 @@ use std::sync::Arc; +use engine_traits::EvictReason; use lazy_static::lazy_static; use prometheus::*; use prometheus_static_metric::*; @@ -30,6 +31,16 @@ make_auto_flush_static_metric! { number_db_prev_found, } + pub label_enum EvictReasonType { + merge, + auto_evict, + load_failed, + load_failed_without_start, + delete_range, + become_follower, + memory_limit_reached, + } + pub struct GcFilteredCountVec: LocalIntCounter { "type" => KeyCountType, } @@ -37,6 +48,10 @@ make_auto_flush_static_metric! { pub struct InMemoryEngineTickerMetrics: LocalIntCounter { "type" => TickerEnum, } + + pub struct EvictionDurationVec: LocalHistogram { + "type" => EvictReasonType, + } } lazy_static! { @@ -63,9 +78,10 @@ lazy_static! { exponential_buckets(0.001, 2.0, 20).unwrap() ) .unwrap(); - pub static ref RANGE_EVICTION_DURATION_HISTOGRAM: Histogram = register_histogram!( + pub static ref RANGE_EVICTION_DURATION_HISTOGRAM: HistogramVec = register_histogram_vec!( "tikv_range_eviction_duration_secs", "Bucketed histogram of range eviction time duration.", + &["type"], exponential_buckets(0.001, 2.0, 20).unwrap() ) .unwrap(); @@ -114,6 +130,8 @@ lazy_static! { auto_flush_from!(IN_MEMORY_ENGINE_FLOW, InMemoryEngineTickerMetrics); pub static ref IN_MEMORY_ENGINE_LOCATE_STATIC: InMemoryEngineTickerMetrics = auto_flush_from!(IN_MEMORY_ENGINE_LOCATE, InMemoryEngineTickerMetrics); + pub static ref RANGE_EVICTION_DURATION_HISTOGRAM_STATIC: EvictionDurationVec = + auto_flush_from!(RANGE_EVICTION_DURATION_HISTOGRAM, EvictionDurationVec); } pub fn flush_range_cache_engine_statistics(statistics: &Arc) { @@ -160,3 +178,27 @@ fn flush_engine_ticker_metrics(t: Tickers, value: u64) { } } } + +pub(crate) fn observe_eviction_duration(secs: f64, evict_reason: EvictReason) { + match evict_reason { + EvictReason::AutoEvict => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .auto_evict + .observe(secs), + EvictReason::BecomeFollower => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .become_follower + .observe(secs), + EvictReason::DeleteRange => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .delete_range + .observe(secs), + EvictReason::LoadFailed => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .load_failed + .observe(secs), + EvictReason::LoadFailedWithoutStart => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .load_failed_without_start + .observe(secs), + EvictReason::MemoryLimitReached => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .memory_limit_reached + .observe(secs), + EvictReason::Merge => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC.merge.observe(secs), + } +} diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 0de5a315573..8e29dafc2d1 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -8,10 +8,10 @@ use std::{ use collections::HashMap; use engine_rocks::RocksSnapshot; -use engine_traits::{CacheRange, FailedReason}; +use engine_traits::{CacheRange, EvictReason, FailedReason}; use tikv_util::{info, time::Instant}; -use crate::{metrics::RANGE_EVICTION_DURATION_HISTOGRAM, read::RangeCacheSnapshotMeta}; +use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; // read_ts -> ref_count #[derive(Default, Debug)] @@ -116,7 +116,7 @@ pub struct RangeManager { // `ranges_being_deleted` contains ranges that are evicted but not finished the delete (or even // not start to delete due to ongoing snapshot) // `bool` means whether the range has been scheduled to the delete range worker - pub(crate) ranges_being_deleted: BTreeMap, + pub(crate) ranges_being_deleted: BTreeMap, // ranges that are cached now ranges: BTreeMap, @@ -329,7 +329,11 @@ impl RangeManager { // // For 2, this is caused by some special operations such as merge and delete // range. So, conservatively, we evict all ranges overlap with it. - pub(crate) fn evict_range(&mut self, evict_range: &CacheRange) -> Vec { + pub(crate) fn evict_range( + &mut self, + evict_range: &CacheRange, + evict_reason: EvictReason, + ) -> Vec { info!( "try to evict range"; "evict_range" => ?evict_range, @@ -352,7 +356,7 @@ impl RangeManager { let mut overlapped_ranges = vec![]; for r in self.ranges.keys() { if r.contains_range(evict_range) { - if self.evict_within_range(evict_range, &r.clone()) { + if self.evict_within_range(evict_range, &r.clone(), evict_reason) { return vec![evict_range.clone()]; } else { return vec![]; @@ -372,13 +376,18 @@ impl RangeManager { overlapped_ranges .into_iter() - .filter(|r| self.evict_within_range(r, r)) + .filter(|r| self.evict_within_range(r, r, evict_reason)) .collect() } // Return true means there is no ongoing snapshot, the evicted_range can be // deleted now. - fn evict_within_range(&mut self, evict_range: &CacheRange, cached_range: &CacheRange) -> bool { + fn evict_within_range( + &mut self, + evict_range: &CacheRange, + cached_range: &CacheRange, + evict_reason: EvictReason, + ) -> bool { assert!(cached_range.contains_range(evict_range)); info!( "evict range in cache range engine"; @@ -400,7 +409,7 @@ impl RangeManager { } self.ranges_being_deleted - .insert(evict_range.clone(), (false, Instant::now())); + .insert(evict_range.clone(), (false, Instant::now(), evict_reason)); if !meta.range_snapshot_list.is_empty() { self.historical_ranges.insert(cached_range.clone(), meta); @@ -420,8 +429,8 @@ impl RangeManager { pub fn on_delete_ranges(&mut self, ranges: &[CacheRange]) { for r in ranges { - let (_, t) = self.ranges_being_deleted.remove(r).unwrap(); - RANGE_EVICTION_DURATION_HISTOGRAM.observe(t.saturating_elapsed_secs()); + let (_, t, evict_reason) = self.ranges_being_deleted.remove(r).unwrap(); + observe_eviction_duration(t.saturating_elapsed_secs(), evict_reason); info!( "range eviction done"; "range" => ?r, @@ -487,7 +496,7 @@ impl RangeManager { // Only ranges that have not been scheduled will be retained in `ranges` pub fn mark_delete_ranges_scheduled(&mut self, ranges: &mut Vec) { ranges.retain(|r| { - let (ref mut scheduled, _) = self.ranges_being_deleted.get_mut(r).unwrap(); + let (ref mut scheduled, ..) = self.ranges_being_deleted.get_mut(r).unwrap(); let has_scheduled = *scheduled; *scheduled = true; !has_scheduled @@ -513,7 +522,7 @@ pub enum RangeCacheStatus { mod tests { use std::collections::BTreeSet; - use engine_traits::{CacheRange, FailedReason}; + use engine_traits::{CacheRange, EvictReason, FailedReason}; use super::RangeManager; use crate::range_manager::LoadFailedReason; @@ -545,7 +554,7 @@ mod tests { let r_evict = CacheRange::new(b"k03".to_vec(), b"k06".to_vec()); let r_left = CacheRange::new(b"k00".to_vec(), b"k03".to_vec()); let r_right = CacheRange::new(b"k06".to_vec(), b"k10".to_vec()); - range_mgr.evict_range(&r_evict); + range_mgr.evict_range(&r_evict, EvictReason::AutoEvict); let meta1 = range_mgr.historical_ranges.get(&r1).unwrap(); assert!(range_mgr.ranges_being_deleted.get(&r_evict).is_some()); assert!(range_mgr.ranges.get(&r1).is_none()); @@ -555,12 +564,16 @@ mod tests { // evict a range with accurate match let _ = range_mgr.range_snapshot(&r_left, 10); - range_mgr.evict_range(&r_left); + range_mgr.evict_range(&r_left, EvictReason::AutoEvict); assert!(range_mgr.historical_ranges.get(&r_left).is_some()); assert!(range_mgr.ranges_being_deleted.get(&r_left).is_some()); assert!(range_mgr.ranges.get(&r_left).is_none()); - assert!(range_mgr.evict_range(&r_right).is_empty()); + assert!( + range_mgr + .evict_range(&r_right, EvictReason::AutoEvict) + .is_empty() + ); assert!(range_mgr.historical_ranges.get(&r_right).is_none()); } @@ -573,7 +586,7 @@ mod tests { let r4 = CacheRange::new(b"k25".to_vec(), b"k35".to_vec()); range_mgr.new_range(r1.clone()); range_mgr.new_range(r3.clone()); - range_mgr.evict_range(&r1); + range_mgr.evict_range(&r1, EvictReason::AutoEvict); let mut gced = BTreeSet::default(); gced.insert(r2.clone()); @@ -602,7 +615,7 @@ mod tests { let r2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); let r3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); range_mgr.new_range(r1.clone()); - range_mgr.evict_range(&r1); + range_mgr.evict_range(&r1, EvictReason::AutoEvict); let mut gced = BTreeSet::default(); gced.insert(r2); @@ -654,7 +667,7 @@ mod tests { let r4 = CacheRange::new(b"k00".to_vec(), b"k05".to_vec()); let r5 = CacheRange::new(b"k05".to_vec(), b"k10".to_vec()); - assert_eq!(range_mgr.evict_range(&r4), vec![r4]); + assert_eq!(range_mgr.evict_range(&r4, EvictReason::AutoEvict), vec![r4]); assert_eq!( range_mgr.ranges().keys().collect::>(), vec![&r5, &r2, &r3] @@ -663,7 +676,7 @@ mod tests { let r6 = CacheRange::new(b"k24".to_vec(), b"k27".to_vec()); let r7 = CacheRange::new(b"k20".to_vec(), b"k24".to_vec()); let r8 = CacheRange::new(b"k27".to_vec(), b"k30".to_vec()); - assert_eq!(range_mgr.evict_range(&r6), vec![r6]); + assert_eq!(range_mgr.evict_range(&r6, EvictReason::AutoEvict), vec![r6]); assert_eq!( range_mgr.ranges().keys().collect::>(), vec![&r5, &r7, &r8, &r3] @@ -683,7 +696,10 @@ mod tests { range_mgr.contains_range(&r3); let r4 = CacheRange::new(b"k".to_vec(), b"k51".to_vec()); - assert_eq!(range_mgr.evict_range(&r4), vec![r1, r2, r3]); + assert_eq!( + range_mgr.evict_range(&r4, EvictReason::AutoEvict), + vec![r1, r2, r3] + ); assert!(range_mgr.ranges().is_empty()); } @@ -697,7 +713,10 @@ mod tests { range_mgr.new_range(r3.clone()); let r4 = CacheRange::new(b"k25".to_vec(), b"k55".to_vec()); - assert_eq!(range_mgr.evict_range(&r4), vec![r2, r3]); + assert_eq!( + range_mgr.evict_range(&r4, EvictReason::AutoEvict), + vec![r2, r3] + ); assert_eq!(range_mgr.ranges().len(), 1); } @@ -711,7 +730,10 @@ mod tests { range_mgr.new_range(r3.clone()); let r4 = CacheRange::new(b"k25".to_vec(), b"k75".to_vec()); - assert_eq!(range_mgr.evict_range(&r4), vec![r2, r3]); + assert_eq!( + range_mgr.evict_range(&r4, EvictReason::AutoEvict), + vec![r2, r3] + ); assert_eq!(range_mgr.ranges().len(), 1); } } diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index fdcb24374ad..fd5bbf73a5f 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -671,9 +671,9 @@ mod tests { raw::DBStatisticsTickerType, util::new_engine_opt, RocksDbOptions, RocksStatistics, }; use engine_traits::{ - CacheRange, FailedReason, IterMetricsCollector, IterOptions, Iterable, Iterator, - MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, WriteBatch, WriteBatchExt, - CF_DEFAULT, CF_LOCK, CF_WRITE, + CacheRange, EvictReason, FailedReason, IterMetricsCollector, IterOptions, Iterable, + Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, WriteBatch, + WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, }; use tempfile::Builder; use tikv_util::config::VersionTrack; @@ -1798,7 +1798,7 @@ mod tests { } } - engine.evict_range(&evict_range); + engine.evict_range(&evict_range, EvictReason::AutoEvict); assert_eq!( engine.snapshot(range.clone(), 10, 200).unwrap_err(), FailedReason::NotCached @@ -1863,7 +1863,7 @@ mod tests { let s1 = engine.snapshot(range.clone(), 10, 10); let s2 = engine.snapshot(range, 20, 20); - engine.evict_range(&evict_range); + engine.evict_range(&evict_range, EvictReason::AutoEvict); let range_left = CacheRange::new(construct_user_key(0), construct_user_key(10)); let s3 = engine.snapshot(range_left, 20, 20).unwrap(); let range_right = CacheRange::new(construct_user_key(20), construct_user_key(30)); @@ -1871,7 +1871,7 @@ mod tests { drop(s3); let range_left_eviction = CacheRange::new(construct_user_key(0), construct_user_key(5)); - engine.evict_range(&range_left_eviction); + engine.evict_range(&range_left_eviction, EvictReason::AutoEvict); // todo(SpadeA): memory limiter { diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index f018564f016..a9e4abcff24 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -7,7 +7,7 @@ use std::{ use bytes::Bytes; use crossbeam::epoch; use engine_traits::{ - CacheRange, MiscExt, Mutable, RangeCacheEngine, Result, WriteBatch, WriteBatchExt, + CacheRange, EvictReason, MiscExt, Mutable, RangeCacheEngine, Result, WriteBatch, WriteBatchExt, WriteOptions, CF_DEFAULT, }; use tikv_util::{box_err, config::ReadableSize, error, info, time::Instant, warn}; @@ -243,7 +243,8 @@ impl RangeCacheWriteBatch { let mut ranges = vec![]; let range_manager = core.mut_range_manager(); for r in std::mem::take(&mut self.ranges_to_evict) { - let mut ranges_to_delete = range_manager.evict_range(&r); + let mut ranges_to_delete = + range_manager.evict_range(&r, EvictReason::MemoryLimitReached); if !ranges_to_delete.is_empty() { ranges.append(&mut ranges_to_delete); continue; @@ -613,13 +614,13 @@ impl Mutable for RangeCacheWriteBatch { // them directly fn delete_range(&mut self, begin_key: &[u8], end_key: &[u8]) -> Result<()> { let range = CacheRange::new(begin_key.to_vec(), end_key.to_vec()); - self.engine.evict_range(&range); + self.engine.evict_range(&range, EvictReason::DeleteRange); Ok(()) } fn delete_range_cf(&mut self, _: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()> { let range = CacheRange::new(begin_key.to_vec(), end_key.to_vec()); - self.engine.evict_range(&range); + self.engine.evict_range(&range, EvictReason::DeleteRange); Ok(()) } } @@ -958,7 +959,7 @@ mod tests { assert_eq!(822, memory_controller.mem_usage()); drop(snap1); - engine.evict_range(&range1); + engine.evict_range(&range1, EvictReason::AutoEvict); flush_epoch(); wait_evict_done(&engine); assert_eq!(548, memory_controller.mem_usage()); diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 91ce612defd..de9479a50d0 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -8,8 +8,8 @@ use std::{ use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, - CF_WRITE, DATA_CFS, + CacheRange, EvictReason, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, + CF_LOCK, CF_WRITE, DATA_CFS, }; use range_cache_memory_engine::{ decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, test_util::put_data, @@ -253,7 +253,7 @@ fn test_evict_with_loading_range() { let engine_clone = engine.clone(); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); - engine_clone.evict_range(&r); + engine_clone.evict_range(&r, EvictReason::AutoEvict); }) .unwrap(); @@ -431,8 +431,8 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { // Now, three ranges are in write status, delete range will not be performed // until they leave the write status - engine.evict_range(&range1); - engine.evict_range(&range2); + engine.evict_range(&range1, EvictReason::AutoEvict); + engine.evict_range(&range2, EvictReason::AutoEvict); let verify_data = |range, expected_num: u64| { let handle = engine.core().write().engine().cf_handle(CF_LOCK); @@ -479,7 +479,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { snapshot_load_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - engine.evict_range(&range3); + engine.evict_range(&range3, EvictReason::AutoEvict); fail::cfg("before_clear_ranges_in_being_written", "pause").unwrap(); write_batch_consume_rx @@ -520,7 +520,7 @@ fn test_double_delete_range_schedule() { let _ = snapshot_load_tx.send(true); // evict all ranges. So the loading ranges will also be evicted and a delete // range task will be scheduled. - engine_clone.evict_range(&r); + engine_clone.evict_range(&r, EvictReason::AutoEvict); }) .unwrap(); diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index b0475bd1f1e..584fd37746f 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -4269,9 +4269,9 @@ def RangeCacheMemoryEngine() -> RowPanel: target( expr=expr_sum_rate( "tikv_range_eviction_duration_secs_count", - by_labels=["instance"], + by_labels=["type"], ), - legend_format="{{instance}}", + legend_format="{{type}}", ), ], ), diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index f14a06f6219..984604b6ac4 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -38199,15 +38199,15 @@ "targets": [ { "datasource": "${DS_TEST-CLUSTER}", - "expr": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "expr": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (type) ", "format": "time_series", "hide": false, "instant": false, "interval": "", "intervalFactor": 1, - "legendFormat": "{{instance}}", + "legendFormat": "{{type}}", "metric": "", - "query": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (instance) ", + "query": "sum(rate(\n tikv_range_eviction_duration_secs_count\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\"}\n [$__rate_interval]\n)) by (type) ", "refId": "", "step": 10, "target": "" diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index 6384c6863e9..e34ded46ab7 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -aac4c44b48b6bf54aab2f24392975d24ff53a999748a5f2dca4d3b9d2bd77c6f ./metrics/grafana/tikv_details.json +623607982360b0eb9e6df493d0fb821428fa97c08280fe558e004256114c7752 ./metrics/grafana/tikv_details.json diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index 1392a302bcd..c52127c16fd 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -7,8 +7,8 @@ use std::{ use engine_rocks::RocksSstWriterBuilder; use engine_traits::{ - CacheRange, RangeCacheEngine, SnapshotContext, SstWriter, SstWriterBuilder, CF_DEFAULT, - CF_WRITE, + CacheRange, EvictReason, RangeCacheEngine, SnapshotContext, SstWriter, SstWriterBuilder, + CF_DEFAULT, CF_WRITE, }; use file_system::calc_crc32_bytes; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; @@ -518,7 +518,7 @@ fn test_load_with_eviction() { } // Now, the range (DATA_MIN_KEY, DATA_MAX_KEY) should be cached let range = CacheRange::new(data_key(b"k10"), DATA_MAX_KEY.to_vec()); - range_cache_engine.evict_range(&range); + range_cache_engine.evict_range(&range, EvictReason::AutoEvict); } fail::remove("on_write_impl"); From 78d53dc561d38179d35b48ad9ec94c61584b1ae6 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:14:08 +0800 Subject: [PATCH 021/144] In-memory engine: gc the range immediately after load (#17298) close tikv/tikv#17299 gc the range immediately after load Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 184 +++++++++++++----- .../range_cache_memory_engine/src/engine.rs | 3 +- .../src/range_manager.rs | 7 + .../src/test_util.rs | 40 ++++ .../tests/failpoints/test_memory_engine.rs | 75 ++++++- 5 files changed, 249 insertions(+), 60 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 737405a1cee..5dcf5dcc832 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -45,6 +45,9 @@ use crate::{ write_batch::RangeCacheWriteBatchEntry, }; +// 5 seconds should be long enough for getting a TSO from PD. +const TIMTOUT_FOR_TSO: Duration = Duration::from_secs(5); + /// Try to extract the key and `u64` timestamp from `encoded_key`. /// /// See also: [`txn_types::Key::split_on_ts_for`] @@ -218,6 +221,8 @@ impl BgWorkManager { memory_controller, region_info_provider, expected_region_size, + gc_interval, + pd_client.clone(), ); let scheduler = worker.start_with_timer("range-cache-engine-background", runner); @@ -270,8 +275,7 @@ impl BgWorkManager { let h = std::thread::spawn(move || { let gc_ticker = tick(gc_interval); let load_evict_ticker = tick(load_evict_interval); // TODO (afeinberg): Use a real value. - // 5 seconds should be long enough for getting a TSO from PD. - let tso_timeout = std::cmp::min(gc_interval, Duration::from_secs(5)); + let tso_timeout = std::cmp::min(gc_interval, TIMTOUT_FOR_TSO); 'LOOP: loop { select! { recv(gc_ticker) -> _ => { @@ -351,7 +355,7 @@ impl BackgroundRunnerCore { } fn gc_range(&self, range: &CacheRange, safe_point: u64, oldest_seqno: u64) -> FilterMetrics { - let (skiplist_engine, safe_ts) = { + let (skiplist_engine, safe_point) = { let mut core = self.engine.write(); // We should also consider the ongoing snapshot of the historical ranges (ranges // that have been evicted). @@ -398,30 +402,13 @@ impl BackgroundRunnerCore { }; let start = Instant::now(); - let write_cf_handle = skiplist_engine.cf_handle(CF_WRITE); - let default_cf_handle = skiplist_engine.cf_handle(CF_DEFAULT); let mut filter = Filter::new( - safe_ts, + safe_point, oldest_seqno, - default_cf_handle, - write_cf_handle.clone(), + skiplist_engine.cf_handle(CF_DEFAULT), + skiplist_engine.cf_handle(CF_WRITE), ); - - let mut iter = write_cf_handle.iterator(); - let guard = &epoch::pin(); - let (start_key, end_key) = encode_key_for_boundary_with_mvcc(range); - iter.seek(&start_key, guard); - while iter.valid() && iter.key() < &end_key { - let k = iter.key(); - let v = iter.value(); - if let Err(e) = filter.filter(k.as_bytes(), v.as_bytes()) { - warn!( - "Something Wrong in memory engine GC"; - "error" => ?e, - ); - } - iter.next(guard); - } + filter.filter_keys_in_range(range); let duration = start.saturating_elapsed(); RANGE_GC_TIME_HISTOGRAM.observe(duration.as_secs_f64()); @@ -434,7 +421,7 @@ impl BackgroundRunnerCore { "below_safe_point_unique_keys" => filter.metrics.unique_key, "below_safe_point_version" => filter.metrics.versions, "below_safe_point_delete_version" => filter.metrics.delete_versions, - "current_safe_point" => safe_ts, + "current_safe_point" => safe_point, ); let mut metrics = std::mem::take(&mut filter.metrics); @@ -470,6 +457,7 @@ impl BackgroundRunnerCore { &mut self, range: CacheRange, delete_range_scheduler: &Scheduler, + safe_point: u64, ) -> bool { fail::fail_point!("on_snapshot_load_finished"); fail::fail_point!("on_snapshot_load_finished2"); @@ -532,7 +520,9 @@ impl BackgroundRunnerCore { fail::fail_point!("on_cached_write_batch_consumed"); } else { core.remove_cached_write_batch(&range); - RangeCacheMemoryEngineCore::pending_range_completes_loading(&mut core, &range); + RangeCacheMemoryEngineCore::pending_range_completes_loading( + &mut core, &range, safe_point, + ); drop(core); fail::fail_point!("pending_range_completes_loading"); @@ -745,6 +735,9 @@ pub(crate) fn flush_epoch() { pub struct BackgroundRunner { core: BackgroundRunnerCore, + pd_client: Arc, + gc_interval: Duration, + // We have following four separate workers so that each type of task would not block each // others range_load_remote: Remote, @@ -786,6 +779,8 @@ impl BackgroundRunner { memory_controller: Arc, region_info_provider: Option>, expected_region_size: usize, + gc_interval: Duration, + pd_client: Arc, ) -> (Self, Scheduler) { let range_load_worker = Builder::new("background-range-load-worker") // Range load now is implemented sequentially, so we must use exactly one thread to handle it. @@ -827,6 +822,8 @@ impl BackgroundRunner { memory_controller, range_stats_manager, }, + pd_client, + gc_interval, range_load_worker, range_load_remote, delete_range_worker, @@ -898,6 +895,8 @@ impl Runnable for BackgroundRunner { BackgroundTask::LoadRange => { let mut core = self.core.clone(); let delete_range_scheduler = self.delete_range_scheduler.clone(); + let pd_client = self.pd_client.clone(); + let gc_interval = self.gc_interval; let f = async move { let skiplist_engine = { let core = core.engine.read(); @@ -924,7 +923,7 @@ impl Runnable for BackgroundRunner { continue; } - let snapshot_load = || -> bool { + let snapshot_load = || -> Option { for &cf in DATA_CFS { let handle = skiplist_engine.cf_handle(cf); let seq = snap.sequence_number(); @@ -956,7 +955,7 @@ impl Runnable for BackgroundRunner { "range" => ?range, "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), ); - return false; + return None; } encoded_key.set_memory_controller( @@ -971,15 +970,66 @@ impl Runnable for BackgroundRunner { } Err(e) => { error!("creating rocksdb iterator failed"; "cf" => cf, "err" => %e); - return false; + return None; } } } - true + + // gc the range + let tso_timeout = std::cmp::min(gc_interval, TIMTOUT_FOR_TSO); + let now = match block_on_timeout(pd_client.get_tso(), tso_timeout) { + Ok(Ok(ts)) => ts, + err => { + error!( + "get timestamp failed, skip gc loaded range"; + "timeout_duration" => ?tso_timeout, + "error" => ?err, + ); + // Get timestamp fail so don't do gc. + return Some(0); + } + }; + + let safe_point = (|| { + fail::fail_point!("in_memory_engine_safe_point_in_loading", |t| { + t.unwrap().parse::().unwrap() + }); + + let safe_point = now + .physical() + .saturating_sub(gc_interval.as_millis() as u64); + TimeStamp::compose(safe_point, 0).into_inner() + })(); + + let mut filter = Filter::new( + safe_point, + u64::MAX, + skiplist_engine.cf_handle(CF_DEFAULT), + skiplist_engine.cf_handle(CF_WRITE), + ); + filter.filter_keys_in_range(&range); + + Some(safe_point) }; let start = Instant::now(); - if !snapshot_load() { + if let Some(safe_point) = snapshot_load() { + if core.on_snapshot_load_finished( + range.clone(), + &delete_range_scheduler, + safe_point, + ) { + let duration = start.saturating_elapsed(); + RANGE_LOAD_TIME_HISTOGRAM.observe(duration.as_secs_f64()); + info!( + "Loading range finished"; + "range" => ?range, + "duration(sec)" => ?duration, + ); + } else { + info!("Loading range canceled";"range" => ?range); + } + } else { info!( "snapshot load failed"; "range" => ?range, @@ -987,18 +1037,6 @@ impl Runnable for BackgroundRunner { core.on_snapshot_load_failed(range, &delete_range_scheduler, true); continue; } - - if core.on_snapshot_load_finished(range.clone(), &delete_range_scheduler) { - let duration = start.saturating_elapsed(); - RANGE_LOAD_TIME_HISTOGRAM.observe(duration.as_secs_f64()); - info!( - "Loading range finished"; - "range" => ?range, - "duration(sec)" => ?duration, - ); - } else { - info!("Loading range canceled";"range" => ?range); - } } }; self.range_load_remote.spawn(f); @@ -1315,7 +1353,25 @@ impl Filter { } } - fn filter(&mut self, key: &Bytes, value: &Bytes) -> Result<(), String> { + fn filter_keys_in_range(&mut self, range: &CacheRange) { + let mut iter = self.write_cf_handle.iterator(); + let guard = &epoch::pin(); + let (start_key, end_key) = encode_key_for_boundary_with_mvcc(range); + iter.seek(&start_key, guard); + while iter.valid() && iter.key() < &end_key { + let k = iter.key(); + let v = iter.value(); + if let Err(e) = self.filter_key(k.as_bytes(), v.as_bytes()) { + warn!( + "Something Wrong in memory engine GC"; + "error" => ?e, + ); + } + iter.next(guard); + } + } + + fn filter_key(&mut self, key: &Bytes, value: &Bytes) -> Result<(), String> { self.metrics.total += 1; let InternalKey { user_key, @@ -1425,16 +1481,12 @@ impl Filter { self.metrics.filtered += 1; self.write_cf_handle .remove(&InternalBytes::from_bytes(key.clone()), guard); - self.handle_filtered_write(write, guard)?; + self.handle_filtered_write(write, guard); Ok(()) } - fn handle_filtered_write( - &mut self, - write: WriteRef<'_>, - guard: &epoch::Guard, - ) -> std::result::Result<(), String> { + fn handle_filtered_write(&mut self, write: WriteRef<'_>, guard: &epoch::Guard) { if write.short_value.is_none() && write.write_type == WriteType::Put { // todo(SpadeA): We don't know the sequence number of the key in the skiplist so // we cannot delete it directly. So we encoding a key with MAX sequence number @@ -1450,7 +1502,6 @@ impl Filter { iter.next(guard); } } - Ok(()) } } @@ -1597,6 +1648,13 @@ pub mod tests { encoding_for_filter(key.as_encoded(), ts) } + struct MockPdClient {} + impl PdClient for MockPdClient { + fn get_tso(&self) -> pd_client::PdFuture { + Box::pin(ready(Ok(TimeStamp::compose(TimeStamp::physical_now(), 0)))) + } + } + #[test] fn test_filter() { let skiplist_engine = SkiplistEngine::new(); @@ -1695,7 +1753,7 @@ pub mod tests { while iter.valid() { let k = iter.key(); let v = iter.value(); - filter.filter(k.as_bytes(), v.as_bytes()).unwrap(); + filter.filter_key(k.as_bytes(), v.as_bytes()).unwrap(); count += 1; iter.next(guard); } @@ -1809,6 +1867,8 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); worker.core.gc_range(&range, 40, 100); @@ -1883,6 +1943,8 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); // gc should not hanlde keys with larger seqno than oldest seqno @@ -2045,6 +2107,8 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); let filter = worker.core.gc_range(&range1, 100, 100); assert_eq!(2, filter.filtered); @@ -2060,6 +2124,8 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); worker.core.gc_range(&range2, 100, 100); assert_eq!(2, filter.filtered); @@ -2108,6 +2174,8 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); let filter = worker.core.gc_range(&range, 20, 200); @@ -2206,6 +2274,8 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); let s1 = engine.snapshot(range.clone(), 10, u64::MAX); let s2 = engine.snapshot(range.clone(), 11, u64::MAX); @@ -2335,6 +2405,8 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); let ranges: Vec<_> = engine @@ -2469,6 +2541,8 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + Duration::from_secs(100), + Arc::new(MockPdClient {}), ); let ranges = runner.core.ranges_for_gc().unwrap(); assert_eq!(2, ranges.len()); @@ -2647,7 +2721,8 @@ pub mod tests { let verify = |range: CacheRange, exist, expect_count| { if exist { - let snap = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); + let snap = engine.snapshot(range.clone(), read_ts, u64::MAX).unwrap(); let mut count = 0; for cf in DATA_CFS { let mut iter = IterOptions::default(); @@ -2749,7 +2824,8 @@ pub mod tests { let verify = |range: CacheRange, exist, expect_count| { if exist { - let snap = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); + let snap = engine.snapshot(range.clone(), read_ts, u64::MAX).unwrap(); let mut count = 0; for cf in DATA_CFS { let mut iter = IterOptions::default(); diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index e7176250ae8..6912f9ab232 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -255,6 +255,7 @@ impl RangeCacheMemoryEngineCore { pub(crate) fn pending_range_completes_loading( core: &mut RwLockWriteGuard<'_, Self>, range: &CacheRange, + safe_point: u64, ) { assert!(!core.has_cached_write_batch(range)); let range_manager = core.mut_range_manager(); @@ -264,7 +265,7 @@ impl RangeCacheMemoryEngineCore { .unwrap(); assert_eq!(&r, range); assert!(!canceled); - range_manager.new_range(r); + range_manager.new_range_with_safe_point(r, safe_point); } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 8e29dafc2d1..89eaa35ef56 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -176,6 +176,13 @@ impl RangeManager { self.ranges.insert(range, range_meta); } + pub fn new_range_with_safe_point(&mut self, range: CacheRange, safe_point: u64) { + assert!(!self.overlap_with_range(&range)); + let mut range_meta = RangeMeta::new(self.id_allocator.allocate_id()); + range_meta.set_safe_point(safe_point); + self.ranges.insert(range, range_meta); + } + pub fn mut_range_meta(&mut self, range: &CacheRange) -> Option<&mut RangeMeta> { self.ranges.get_mut(range) } diff --git a/components/range_cache_memory_engine/src/test_util.rs b/components/range_cache_memory_engine/src/test_util.rs index f9f353903b2..1a68ea3fb84 100644 --- a/components/range_cache_memory_engine/src/test_util.rs +++ b/components/range_cache_memory_engine/src/test_util.rs @@ -3,6 +3,8 @@ use std::sync::Arc; use crossbeam::epoch; +use engine_rocks::RocksEngine; +use engine_traits::{SyncMutable, CF_WRITE}; use txn_types::{Key, TimeStamp, Write, WriteType}; use crate::{ @@ -124,3 +126,41 @@ fn put_data_impl( default_cf.insert(default_k, val, guard); } } + +pub fn put_data_in_rocks( + key: &[u8], + value: &[u8], + commit_ts: u64, + start_ts: u64, + short_value: bool, + rocks_engine: &RocksEngine, + write_type: WriteType, +) { + let raw_write_k = Key::from_raw(key) + .append_ts(TimeStamp::new(commit_ts)) + .into_encoded(); + let write_v = Write::new( + write_type, + TimeStamp::new(start_ts), + if short_value { + Some(value.to_vec()) + } else { + None + }, + ); + + rocks_engine + .put_cf(CF_WRITE, &raw_write_k, &write_v.as_ref().to_bytes()) + .unwrap(); + + if write_type == WriteType::Delete { + return; + } + + if !short_value { + let raw_default_k = Key::from_raw(key) + .append_ts(TimeStamp::new(start_ts)) + .into_encoded(); + rocks_engine.put(&raw_default_k, value).unwrap(); + } +} diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index de9479a50d0..987a2a74de1 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -12,13 +12,14 @@ use engine_traits::{ CF_LOCK, CF_WRITE, DATA_CFS, }; use range_cache_memory_engine::{ - decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, test_util::put_data, + decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, + test_util::{put_data, put_data_in_rocks}, BackgroundTask, InternalBytes, InternalKey, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, SkiplistHandle, ValueType, }; use tempfile::Builder; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; -use txn_types::{Key, TimeStamp}; +use txn_types::{Key, TimeStamp, WriteType}; #[test] fn test_set_disk_engine() { @@ -286,9 +287,10 @@ fn test_evict_with_loading_range() { .recv_timeout(Duration::from_secs(5)) .unwrap(); - engine.snapshot(range1, 100, 100).unwrap_err(); - engine.snapshot(range2, 100, 100).unwrap_err(); - engine.snapshot(range3, 100, 100).unwrap(); + let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); + engine.snapshot(range1, read_ts, 100).unwrap_err(); + engine.snapshot(range2, read_ts, 100).unwrap_err(); + engine.snapshot(range3, read_ts, 100).unwrap(); } #[test] @@ -565,3 +567,66 @@ fn test_double_delete_range_schedule() { .recv_timeout(Duration::from_secs(2)) .unwrap_err(); } + +#[test] +fn test_load_with_gc() { + let path = Builder::new().prefix("test").tempdir().unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + + let mut config = RangeCacheEngineConfig::config_for_test(); + config.gc_interval = ReadableDuration(Duration::from_secs(1)); + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(config), + ))); + engine.set_disk_engine(rocks_engine.clone()); + + // safe_point: 6 + // Rocks: [k1-5, k1-3, k2-4-d, k2-3, k3-7, k3-4, k3-1, k4-6-d, k4-5] + // After load + // IME: [k1-5, k3-7, k3-4] + put_data_in_rocks(b"k1", b"val", 5, 4, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k1", b"val", 3, 2, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k2", b"val", 4, 3, false, &rocks_engine, WriteType::Delete); + put_data_in_rocks(b"k2", b"val", 3, 2, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k3", b"val", 7, 5, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k3", b"val", 4, 3, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k3", b"val", 1, 0, false, &rocks_engine, WriteType::Put); + put_data_in_rocks(b"k4", b"val", 6, 0, false, &rocks_engine, WriteType::Delete); + put_data_in_rocks(b"k4", b"val", 5, 0, false, &rocks_engine, WriteType::Put); + + fail::cfg("in_memory_engine_safe_point_in_loading", "return(6)").unwrap(); + let (load_tx, load_rx) = sync_channel(0); + fail::cfg_callback("pending_range_completes_loading", move || { + let _ = load_tx.send(true); + }) + .unwrap(); + + let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); + engine.load_range(range.clone()).unwrap(); + let mut wb = engine.write_batch(); + wb.prepare_for_range(range.clone()); + wb.set_sequence_number(100).unwrap(); + wb.write().unwrap(); + + load_rx.recv_timeout(Duration::from_secs(5)).unwrap(); + + let expects = vec![(b"k1", 5), (b"k3", 7), (b"k3", 4)]; + let write_handle = engine.core().read().engine().cf_handle(CF_WRITE); + + let mut iter = write_handle.iterator(); + let guard = &epoch::pin(); + iter.seek_to_first(guard); + for (key, commit_ts) in expects { + let expect_key = Key::from_raw(key).into_encoded(); + let InternalKey { user_key, .. } = decode_key(iter.key().as_bytes()); + let (mem_key, ts) = Key::split_on_ts_for(user_key).unwrap(); + assert_eq!(expect_key, mem_key); + assert_eq!(commit_ts, ts.into_inner()); + iter.next(guard); + } + + // ensure the safe point of the engine + engine.snapshot(range.clone(), 6, 100).unwrap_err(); + engine.snapshot(range, 7, 100).unwrap(); +} From 050f1a6de647a2b364d23270aa7b32517e2f222e Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Mon, 5 Aug 2024 23:14:09 -0700 Subject: [PATCH 022/144] RocksDB: Fix bloom filter incompatible issue (#17361) close tikv/tikv#17272 TiKV no longer names bloom filter blocks with suffix like "FullBloom" or "Ribbon". Signed-off-by: Yang Zhang --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76131c4f90f..cd466d6f7d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2914,7 +2914,7 @@ dependencies = [ [[package]] name = "librocksdb_sys" version = "0.1.0" -source = "git+https://github.com/tikv/rust-rocksdb.git#224bed6ffa29ba3bbe9a91ef6bda7186200c59a8" +source = "git+https://github.com/tikv/rust-rocksdb.git#c92c467a3ab0b60484a0db83fcf89366791716cd" dependencies = [ "bindgen 0.65.1", "bzip2-sys", @@ -2933,7 +2933,7 @@ dependencies = [ [[package]] name = "libtitan_sys" version = "0.0.1" -source = "git+https://github.com/tikv/rust-rocksdb.git#224bed6ffa29ba3bbe9a91ef6bda7186200c59a8" +source = "git+https://github.com/tikv/rust-rocksdb.git#c92c467a3ab0b60484a0db83fcf89366791716cd" dependencies = [ "bzip2-sys", "cc", @@ -4816,7 +4816,7 @@ dependencies = [ [[package]] name = "rocksdb" version = "0.3.0" -source = "git+https://github.com/tikv/rust-rocksdb.git#224bed6ffa29ba3bbe9a91ef6bda7186200c59a8" +source = "git+https://github.com/tikv/rust-rocksdb.git#c92c467a3ab0b60484a0db83fcf89366791716cd" dependencies = [ "libc 0.2.151", "librocksdb_sys", From 0e3806935c11be6bf9a75d8666a183520d3c4556 Mon Sep 17 00:00:00 2001 From: lucasliang Date: Thu, 8 Aug 2024 19:18:40 +0800 Subject: [PATCH 023/144] *: fix compatibility to `raft-engine.spill-dir` (#17358) close tikv/tikv#17356 Make the diskfull check mechanism compatible to the configuration `raft-engine.spill-dir`. Signed-off-by: lucasliang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- .../raftstore-v2/src/worker/pd/store.rs | 9 +- components/raftstore/src/store/worker/pd.rs | 9 +- components/server/Cargo.toml | 22 +- components/server/src/common.rs | 363 +++++++++++++++++- components/server/src/server.rs | 114 ++---- components/server/src/server2.rs | 115 ++---- components/tikv_util/Cargo.toml | 6 +- components/tikv_util/src/sys/disk.rs | 18 +- components/tikv_util/src/sys/mod.rs | 14 +- 10 files changed, 475 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd466d6f7d7..b9b6556a67f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5304,7 +5304,6 @@ dependencies = [ "error_code", "fail", "file_system", - "fs2", "futures 0.3.15", "grpcio", "grpcio-health", @@ -6753,6 +6752,7 @@ dependencies = [ "derive_more", "error_code", "fail", + "fs2", "futures 0.3.15", "futures-util", "gag", diff --git a/components/raftstore-v2/src/worker/pd/store.rs b/components/raftstore-v2/src/worker/pd/store.rs index 926ad307cf0..226fef08d11 100644 --- a/components/raftstore-v2/src/worker/pd/store.rs +++ b/components/raftstore-v2/src/worker/pd/store.rs @@ -23,6 +23,7 @@ use slog::{error, info, warn}; use tikv_util::{ metrics::RecordPairVec, store::QueryStats, + sys::disk::get_disk_space_stats, time::{Duration, Instant as TiInstant, UnixSecs}, topn::TopN, }; @@ -442,7 +443,8 @@ where /// Returns (capacity, used, available). fn collect_engine_size(&self) -> Option<(u64, u64, u64)> { - let disk_stats = match fs2::statvfs(self.tablet_registry.tablet_root()) { + let (disk_cap, disk_avail) = match get_disk_space_stats(self.tablet_registry.tablet_root()) + { Err(e) => { error!( self.logger, @@ -452,9 +454,8 @@ where ); return None; } - Ok(stats) => stats, + Ok((total_size, available_size)) => (total_size, available_size), }; - let disk_cap = disk_stats.total_space(); let capacity = if self.cfg.value().capacity.0 == 0 { disk_cap } else { @@ -481,7 +482,7 @@ where let mut available = capacity.checked_sub(used_size).unwrap_or_default(); // We only care about rocksdb SST file size, so we should check disk available // here. - available = cmp::min(available, disk_stats.available_space()); + available = cmp::min(available, disk_avail); Some((capacity, used_size, available)) } } diff --git a/components/raftstore/src/store/worker/pd.rs b/components/raftstore/src/store/worker/pd.rs index 000e3310e4e..e95ac635ba4 100644 --- a/components/raftstore/src/store/worker/pd.rs +++ b/components/raftstore/src/store/worker/pd.rs @@ -44,7 +44,7 @@ use tikv_util::{ box_err, debug, error, info, metrics::ThreadInfoStatistics, store::QueryStats, - sys::{thread::StdThreadBuildWrapper, SysQuota}, + sys::{disk::get_disk_space_stats, thread::StdThreadBuildWrapper, SysQuota}, thd_name, time::{Instant as TiInstant, UnixSecs}, timer::GLOBAL_TIMER_HANDLE, @@ -2433,7 +2433,7 @@ fn collect_engine_size( return Some((engine_size.capacity, engine_size.used, engine_size.avail)); } let store_info = store_info.unwrap(); - let disk_stats = match fs2::statvfs(store_info.kv_engine.path()) { + let (disk_cap, disk_avail) = match get_disk_space_stats(store_info.kv_engine.path()) { Err(e) => { error!( "get disk stat for rocksdb failed"; @@ -2442,9 +2442,8 @@ fn collect_engine_size( ); return None; } - Ok(stats) => stats, + Ok((total_size, available_size)) => (total_size, available_size), }; - let disk_cap = disk_stats.total_space(); let capacity = if store_info.capacity == 0 || disk_cap < store_info.capacity { disk_cap } else { @@ -2468,7 +2467,7 @@ fn collect_engine_size( let mut available = capacity.checked_sub(used_size).unwrap_or_default(); // We only care about rocksdb SST file size, so we should check disk available // here. - available = cmp::min(available, disk_stats.available_space()); + available = cmp::min(available, disk_avail); Some((capacity, used_size, available)) } diff --git a/components/server/Cargo.toml b/components/server/Cargo.toml index 61e53af9805..cb071d2b796 100644 --- a/components/server/Cargo.toml +++ b/components/server/Cargo.toml @@ -15,18 +15,10 @@ sse = ["tikv/sse"] memory-engine = [] mem-profiling = ["tikv/mem-profiling"] failpoints = ["tikv/failpoints"] -test-engine-kv-rocksdb = [ - "tikv/test-engine-kv-rocksdb" -] -test-engine-raft-raft-engine = [ - "tikv/test-engine-raft-raft-engine" -] -test-engines-rocksdb = [ - "tikv/test-engines-rocksdb", -] -test-engines-panic = [ - "tikv/test-engines-panic", -] +test-engine-kv-rocksdb = ["tikv/test-engine-kv-rocksdb"] +test-engine-raft-raft-engine = ["tikv/test-engine-raft-raft-engine"] +test-engines-rocksdb = ["tikv/test-engines-rocksdb"] +test-engines-panic = ["tikv/test-engines-panic"] nortcheck = ["engine_rocks/nortcheck"] backup-stream-debug = ["backup-stream/backup-stream-debug"] @@ -49,7 +41,6 @@ engine_traits = { workspace = true } error_code = { workspace = true } fail = "0.5" file_system = { workspace = true } -fs2 = "0.4" futures = "0.3" grpcio = { workspace = true } grpcio-health = { workspace = true } @@ -59,7 +50,10 @@ hybrid_engine = { workspace = true } keys = { workspace = true } kvproto = { workspace = true } libc = "0.2" -log = { version = "0.4", features = ["max_level_trace", "release_max_level_debug"] } +log = { version = "0.4", features = [ + "max_level_trace", + "release_max_level_debug", +] } log_wrappers = { workspace = true } pd_client = { workspace = true } prometheus = { version = "0.13", features = ["nightly"] } diff --git a/components/server/src/common.rs b/components/server/src/common.rs index b3449bfa42f..8d48a3ece12 100644 --- a/components/server/src/common.rs +++ b/components/server/src/common.rs @@ -220,8 +220,9 @@ impl TikvServerCore { } } - let disk_stats = fs2::statvfs(&self.config.storage.data_dir).unwrap(); - let mut capacity = disk_stats.total_space(); + let (disk_cap, disk_avail) = + disk::get_disk_space_stats(&self.config.storage.data_dir).unwrap(); + let mut capacity = disk_cap; if self.config.raft_store.capacity.0 > 0 { capacity = cmp::min(capacity, self.config.raft_store.capacity.0); } @@ -229,11 +230,7 @@ impl TikvServerCore { let kv_reserved_size = calculate_reserved_space(capacity, self.config.storage.reserve_space.0); disk::set_disk_reserved_space(kv_reserved_size); - reserve_physical_space( - &self.config.storage.data_dir, - disk_stats.available_space(), - kv_reserved_size, - ); + reserve_physical_space(&self.config.storage.data_dir, disk_avail, kv_reserved_size); let raft_data_dir = if self.config.raft_engine.enable { self.config.raft_engine.config().dir @@ -244,18 +241,13 @@ impl TikvServerCore { let separated_raft_mount_path = path_in_diff_mount_point(&self.config.storage.data_dir, &raft_data_dir); if separated_raft_mount_path { - let raft_disk_stats = fs2::statvfs(&raft_data_dir).unwrap(); + let (raft_disk_cap, raft_disk_avail) = + disk::get_disk_space_stats(&raft_data_dir).unwrap(); // reserve space for raft engine if raft engine is deployed separately - let raft_reserved_size = calculate_reserved_space( - raft_disk_stats.total_space(), - self.config.storage.reserve_raft_space.0, - ); + let raft_reserved_size = + calculate_reserved_space(raft_disk_cap, self.config.storage.reserve_raft_space.0); disk::set_raft_disk_reserved_space(raft_reserved_size); - reserve_physical_space( - &raft_data_dir, - raft_disk_stats.available_space(), - raft_reserved_size, - ); + reserve_physical_space(&raft_data_dir, raft_disk_avail, raft_reserved_size); } } @@ -924,3 +916,340 @@ impl EngineMetricsManager { } } } + +fn calculate_disk_usage(a: disk::DiskUsage, b: disk::DiskUsage) -> disk::DiskUsage { + match (a, b) { + (disk::DiskUsage::AlreadyFull, _) => disk::DiskUsage::AlreadyFull, + (_, disk::DiskUsage::AlreadyFull) => disk::DiskUsage::AlreadyFull, + (disk::DiskUsage::AlmostFull, _) => disk::DiskUsage::AlmostFull, + (_, disk::DiskUsage::AlmostFull) => disk::DiskUsage::AlmostFull, + (disk::DiskUsage::Normal, disk::DiskUsage::Normal) => disk::DiskUsage::Normal, + } +} + +/// A checker to inspect the disk usage of kv engine and raft engine. +/// The caller should call `inspect` periodically to get the disk usage status +/// manually. +#[derive(Clone)] +pub struct DiskUsageChecker { + /// The path of kv engine. + kvdb_path: String, + /// The path of raft engine. + raft_path: String, + /// The path of auxiliary directory of raft engine if specified. + raft_auxiliary_path: Option, + /// Whether the main directory of raft engine is separated from kv engine. + separated_raft_mount_path: bool, + /// Whether the auxiliary directory of raft engine is separated from kv + /// engine. + separated_raft_auxiliary_mount_path: bool, + /// Whether the auxiliary directory of raft engine is both separated from + /// the main directory of raft engine and kv engine. + separated_raft_auxiliary_and_kvdb_mount_path: bool, + /// The threshold of disk usage of kv engine to trigger the almost full + /// status. + kvdb_almost_full_thd: u64, + /// The threshold of disk usage of raft engine to trigger the almost full + /// status. + raft_almost_full_thd: u64, + /// The specified disk capacity for the whole disk. + config_disk_capacity: u64, +} + +impl DiskUsageChecker { + pub fn new( + kvdb_path: String, + raft_path: String, + raft_auxiliary_path: Option, + separated_raft_mount_path: bool, + separated_raft_auxiliary_mount_path: bool, + separated_raft_auxiliary_and_kvdb_mount_path: bool, + kvdb_almost_full_thd: u64, + raft_almost_full_thd: u64, + config_disk_capacity: u64, + ) -> Self { + DiskUsageChecker { + kvdb_path, + raft_path, + raft_auxiliary_path, + separated_raft_mount_path, + separated_raft_auxiliary_mount_path, + separated_raft_auxiliary_and_kvdb_mount_path, + kvdb_almost_full_thd, + raft_almost_full_thd, + config_disk_capacity, + } + } + + /// Inspect the disk usage of kv engine and raft engine. + /// The `kvdb_used_size` is the used size of kv engine, and the + /// `raft_used_size` is the used size of raft engine. + /// + /// Returns the disk usage status of the whole disk, kv engine and raft + /// engine, the whole disk capacity and available size. + pub fn inspect( + &self, + kvdb_used_size: u64, + raft_used_size: u64, + ) -> ( + disk::DiskUsage, // whole disk status + disk::DiskUsage, // kvdb disk status + disk::DiskUsage, // raft disk status + u64, // whole capacity + u64, // whole available + ) { + // By default, the almost full threshold of kv engine is half of the + // configured value. + let kvdb_already_full_thd = self.kvdb_almost_full_thd / 2; + let raft_already_full_thd = self.raft_almost_full_thd / 2; + // Check the disk space of raft engine. + let raft_disk_status = { + if !self.separated_raft_mount_path || self.raft_almost_full_thd == 0 { + disk::DiskUsage::Normal + } else { + let (raft_disk_cap, raft_disk_avail) = match disk::get_disk_space_stats( + &self.raft_path, + ) { + Err(e) => { + error!( + "get disk stat for raft engine failed"; + "raft_engine_path" => &self.raft_path, + "err" => ?e + ); + return ( + disk::DiskUsage::Normal, + disk::DiskUsage::Normal, + disk::DiskUsage::Normal, + 0, + 0, + ); + } + Ok((cap, avail)) => { + if !self.separated_raft_auxiliary_mount_path { + // If the auxiliary directory of raft engine is not separated from + // kv engine, returns u64::MAX to indicate that the disk space of + // the raft engine should not be checked. + (std::u64::MAX, std::u64::MAX) + } else if self.separated_raft_auxiliary_and_kvdb_mount_path { + // If the auxiliary directory of raft engine is separated from kv + // engine and the main directory of + // raft engine, the disk space of + // the auxiliary directory should be + // checked. + assert!(self.raft_auxiliary_path.is_some()); + let (auxiliary_disk_cap, auxiliary_disk_avail) = + match disk::get_disk_space_stats( + self.raft_auxiliary_path.as_ref().unwrap(), + ) { + Err(e) => { + error!( + "get auxiliary disk stat for raft engine failed"; + "raft_engine_path" => self.raft_auxiliary_path.as_ref().unwrap(), + "err" => ?e + ); + (0_u64, 0_u64) + } + Ok((total, avail)) => (total, avail), + }; + (cap + auxiliary_disk_cap, avail + auxiliary_disk_avail) + } else { + (cap, avail) + } + } + }; + let raft_disk_available = cmp::min( + raft_disk_cap + .checked_sub(raft_used_size) + .unwrap_or_default(), + raft_disk_avail, + ); + if raft_disk_available <= raft_already_full_thd { + disk::DiskUsage::AlreadyFull + } else if raft_disk_available <= self.raft_almost_full_thd { + disk::DiskUsage::AlmostFull + } else { + disk::DiskUsage::Normal + } + } + }; + // Check the disk space of kv engine. + let (disk_cap, disk_avail) = match disk::get_disk_space_stats(&self.kvdb_path) { + Err(e) => { + error!( + "get disk stat for kv store failed"; + "kv_path" => &self.kvdb_path, + "err" => ?e + ); + return ( + disk::DiskUsage::Normal, + disk::DiskUsage::Normal, + disk::DiskUsage::Normal, + 0, + 0, + ); + } + Ok((total, avail)) => (total, avail), + }; + let capacity = if self.config_disk_capacity == 0 || disk_cap < self.config_disk_capacity { + disk_cap + } else { + self.config_disk_capacity + }; + let available = cmp::min( + capacity.checked_sub(kvdb_used_size).unwrap_or_default(), + disk_avail, + ); + let cur_kv_disk_status = if available <= kvdb_already_full_thd { + disk::DiskUsage::AlreadyFull + } else if available <= self.kvdb_almost_full_thd { + disk::DiskUsage::AlmostFull + } else { + disk::DiskUsage::Normal + }; + let cur_disk_status = calculate_disk_usage(raft_disk_status, cur_kv_disk_status); + ( + cur_disk_status, + cur_kv_disk_status, + raft_disk_status, + capacity, + available, + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_disk_usage_checker() { + let kvdb_path = "/tmp/tikv-kvdb".to_owned(); + let raft_path = "/tmp/tikv-raft".to_owned(); + let raft_spill_path = "/tmp/tikv-raft/spill".to_owned(); + + // Case 1: mock the kvdb and raft engine are not separated. + fail::cfg("mock_disk_space_stats", "return(10000,5000)").unwrap(); + let disk_usage_checker = DiskUsageChecker::new( + kvdb_path.clone(), + raft_path.clone(), + Some(raft_spill_path.clone()), + false, + true, + false, + 100, + 100, + 1000, + ); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 1000); + assert_eq!(disk_status, disk::DiskUsage::AlreadyFull); + assert_eq!(kvdb_status, disk::DiskUsage::AlreadyFull); + assert_eq!(raft_status, disk::DiskUsage::Normal); + + let disk_usage_checker = DiskUsageChecker::new( + kvdb_path.clone(), + raft_path.clone(), + Some(raft_spill_path.clone()), + false, + true, + false, + 100, + 100, + 4100, + ); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 1000); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::AlmostFull); + assert_eq!(disk_status, disk::DiskUsage::AlmostFull); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(3999, 1000); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::Normal); + fail::remove("mock_disk_space_stats"); + + // Case 2: mock the kvdb and raft engine are separated. + fail::cfg( + "mock_disk_space_stats", + "1*return(500,200)->1*return(5000,2000)->1*return(500,200)->1*return(5000,2000)->1*return(500,200)->1*return(5000,2000)", + ) + .unwrap(); + let disk_usage_checker = DiskUsageChecker::new( + kvdb_path.clone(), + raft_path.clone(), + Some(raft_spill_path.clone()), + true, + true, + false, + 100, + 100, + 6000, + ); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 450); + assert_eq!(raft_status, disk::DiskUsage::AlreadyFull); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::AlreadyFull); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 400); + assert_eq!(raft_status, disk::DiskUsage::AlmostFull); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::AlmostFull); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 399); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::Normal); + fail::remove("mock_disk_space_stats"); + + fail::cfg( + "mock_disk_space_stats", + "1*return(500,200)->1*return(5000,2000)->1*return(500,200)->1*return(5000,2000)->1*return(500,200)->1*return(5000,2000)", + ) + .unwrap(); + let disk_usage_checker = DiskUsageChecker::new( + kvdb_path.clone(), + raft_path.clone(), + Some(raft_spill_path.clone()), + true, + false, + false, + 100, + 100, + 6000, + ); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 450); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::Normal); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 500); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::Normal); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4900, 500); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::AlmostFull); + assert_eq!(disk_status, disk::DiskUsage::AlmostFull); + fail::remove("mock_disk_space_stats"); + + // Case 3: mock the kvdb and raft engine are separated and the auxiliary + // directory of raft engine is separated from the main directory of + // raft. + fail::cfg( + "mock_disk_space_stats", + "1*return(500,200)->1*return(100,20)->1*return(5000,2000)", + ) + .unwrap(); + let disk_usage_checker = DiskUsageChecker::new( + kvdb_path.clone(), + raft_path.clone(), + Some(raft_spill_path.clone()), + true, + true, + true, + 100, + 100, + 6000, + ); + let (disk_status, kvdb_status, raft_status, ..) = disk_usage_checker.inspect(4000, 450); + assert_eq!(raft_status, disk::DiskUsage::Normal); + assert_eq!(kvdb_status, disk::DiskUsage::Normal); + assert_eq!(disk_status, disk::DiskUsage::Normal); + fail::remove("mock_disk_space_stats"); + } +} diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 8712d38338f..9f6e124570e 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -12,7 +12,6 @@ //! explicitly stopped. We keep these components in the `TikvServer` struct. use std::{ - cmp, collections::HashMap, convert::TryFrom, path::{Path, PathBuf}, @@ -134,8 +133,8 @@ use tokio::runtime::Builder; use crate::{ common::{ - ConfiguredRaftEngine, EngineMetricsManager, EnginesResourceInfo, KvEngineBuilder, - TikvServerCore, + ConfiguredRaftEngine, DiskUsageChecker, EngineMetricsManager, EnginesResourceInfo, + KvEngineBuilder, TikvServerCore, }, memory::*, setup::*, @@ -1398,77 +1397,53 @@ where let raft_path = engines.raft.get_engine_path().to_string(); let separated_raft_mount_path = path_in_diff_mount_point(raft_path.as_str(), engines.kv.path()); - let raft_almost_full_threshold = reserve_raft_space; - let raft_already_full_threshold = reserve_raft_space / 2; - - let almost_full_threshold = reserve_space; - let already_full_threshold = reserve_space / 2; - fn calculate_disk_usage(a: disk::DiskUsage, b: disk::DiskUsage) -> disk::DiskUsage { - match (a, b) { - (disk::DiskUsage::AlreadyFull, _) => disk::DiskUsage::AlreadyFull, - (_, disk::DiskUsage::AlreadyFull) => disk::DiskUsage::AlreadyFull, - (disk::DiskUsage::AlmostFull, _) => disk::DiskUsage::AlmostFull, - (_, disk::DiskUsage::AlmostFull) => disk::DiskUsage::AlmostFull, - (disk::DiskUsage::Normal, disk::DiskUsage::Normal) => disk::DiskUsage::Normal, - } - } + // If the auxiliary directory of raft engine is specified, it's needed to be + // checked. Otherwise, it's not needed to be checked. And as the configuration + // is static, it's safe to check it only once. + let raft_auxiliay_path = if self.core.config.raft_engine.enable { + self.core.config.raft_engine.config().spill_dir.clone() + } else { + None + }; + let (separated_raft_auxillay_mount_path, separated_raft_auxiliary_with_kvdb) = + raft_auxiliay_path + .as_ref() + .map(|path| { + let seperated_with_kvdb = + path_in_diff_mount_point(path.as_str(), engines.kv.path()); + let seperated_with_raft = + path_in_diff_mount_point(path.as_str(), raft_path.as_str()); + ( + seperated_with_kvdb && seperated_with_raft, + seperated_with_kvdb, + ) + }) + .unwrap_or((false, false)); + let disk_usage_checker = DiskUsageChecker::new( + store_path.as_path().to_str().unwrap().to_string(), + raft_path, + raft_auxiliay_path, + separated_raft_mount_path, + separated_raft_auxillay_mount_path, + separated_raft_auxiliary_with_kvdb, + reserve_space, + reserve_raft_space, + config_disk_capacity, + ); self.core.background_worker .spawn_interval_task(DEFAULT_STORAGE_STATS_INTERVAL, move || { - let disk_stats = match fs2::statvfs(&store_path) { - Err(e) => { - error!( - "get disk stat for kv store failed"; - "kv_path" => store_path.to_str(), - "err" => ?e - ); - return; - } - Ok(stats) => stats, - }; - let disk_cap = disk_stats.total_space(); let snap_size = snap_mgr.get_total_snap_size().unwrap(); - let kv_size = engines .kv .get_engine_used_size() .expect("get kv engine size"); - let raft_size = engines .raft .get_engine_size() .expect("get raft engine size"); - - let mut raft_disk_status = disk::DiskUsage::Normal; - if separated_raft_mount_path && reserve_raft_space != 0 { - let raft_disk_stats = match fs2::statvfs(&raft_path) { - Err(e) => { - error!( - "get disk stat for raft engine failed"; - "raft_engine_path" => raft_path.clone(), - "err" => ?e - ); - return; - } - Ok(stats) => stats, - }; - let raft_disk_cap = raft_disk_stats.total_space(); - let mut raft_disk_available = - raft_disk_cap.checked_sub(raft_size).unwrap_or_default(); - raft_disk_available = cmp::min(raft_disk_available, raft_disk_stats.available_space()); - raft_disk_status = if raft_disk_available <= raft_already_full_threshold - { - disk::DiskUsage::AlreadyFull - } else if raft_disk_available <= raft_almost_full_threshold - { - disk::DiskUsage::AlmostFull - } else { - disk::DiskUsage::Normal - }; - } let placeholer_file_path = PathBuf::from_str(&data_dir) .unwrap() .join(Path::new(file_system::SPACE_PLACEHOLDER_FILE)); - let placeholder_size: u64 = file_system::get_file_size(placeholer_file_path).unwrap_or(0); @@ -1477,24 +1452,9 @@ where } else { snap_size + kv_size + placeholder_size }; - let capacity = if config_disk_capacity == 0 || disk_cap < config_disk_capacity { - disk_cap - } else { - config_disk_capacity - }; - - let mut available = capacity.checked_sub(used_size).unwrap_or_default(); - available = cmp::min(available, disk_stats.available_space()); - + // Check the disk usage and update the disk usage status. + let (cur_disk_status, cur_kv_disk_status, raft_disk_status, capacity, available) = disk_usage_checker.inspect(used_size, raft_size); let prev_disk_status = disk::get_disk_status(0); //0 no need care about failpoint. - let cur_kv_disk_status = if available <= already_full_threshold { - disk::DiskUsage::AlreadyFull - } else if available <= almost_full_threshold { - disk::DiskUsage::AlmostFull - } else { - disk::DiskUsage::Normal - }; - let cur_disk_status = calculate_disk_usage(raft_disk_status, cur_kv_disk_status); if prev_disk_status != cur_disk_status { warn!( "disk usage {:?}->{:?} (raft engine usage: {:?}, kv engine usage: {:?}), seperated raft mount={}, kv available={}, snap={}, kv={}, raft={}, capacity={}", diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index 7613ae18def..8723eed37d8 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -12,7 +12,6 @@ //! explicitly stopped. We keep these components in the `TikvServer` struct. use std::{ - cmp, collections::HashMap, marker::PhantomData, path::{Path, PathBuf}, @@ -123,7 +122,10 @@ use tikv_util::{ use tokio::runtime::Builder; use crate::{ - common::{ConfiguredRaftEngine, EngineMetricsManager, EnginesResourceInfo, TikvServerCore}, + common::{ + ConfiguredRaftEngine, DiskUsageChecker, EngineMetricsManager, EnginesResourceInfo, + TikvServerCore, + }, memory::*, setup::*, signal_handler, @@ -1158,36 +1160,42 @@ where let raft_path = raft_engine.get_engine_path().to_string(); let separated_raft_mount_path = path_in_diff_mount_point(raft_path.as_str(), tablet_registry.tablet_root()); - let raft_almost_full_threshold = reserve_raft_space; - let raft_already_full_threshold = reserve_raft_space / 2; - - let almost_full_threshold = reserve_space; - let already_full_threshold = reserve_space / 2; - fn calculate_disk_usage(a: disk::DiskUsage, b: disk::DiskUsage) -> disk::DiskUsage { - match (a, b) { - (disk::DiskUsage::AlreadyFull, _) => disk::DiskUsage::AlreadyFull, - (_, disk::DiskUsage::AlreadyFull) => disk::DiskUsage::AlreadyFull, - (disk::DiskUsage::AlmostFull, _) => disk::DiskUsage::AlmostFull, - (_, disk::DiskUsage::AlmostFull) => disk::DiskUsage::AlmostFull, - (disk::DiskUsage::Normal, disk::DiskUsage::Normal) => disk::DiskUsage::Normal, - } - } + // If the auxiliary directory of raft engine is specified, it's needed to be + // checked. Otherwise, it's not needed to be checked. And as the configuration + // is static, it's safe to check it only once. + let raft_auxiliay_path = if self.core.config.raft_engine.enable { + self.core.config.raft_engine.config().spill_dir.clone() + } else { + None + }; + let (separated_raft_auxillay_mount_path, separated_raft_auxiliary_with_kvdb) = + raft_auxiliay_path + .as_ref() + .map(|path| { + let seperated_with_kvdb = + path_in_diff_mount_point(path.as_str(), tablet_registry.tablet_root()); + let seperated_with_raft = + path_in_diff_mount_point(path.as_str(), raft_path.as_str()); + ( + seperated_with_kvdb && seperated_with_raft, + seperated_with_kvdb, + ) + }) + .unwrap_or((false, false)); + let disk_usage_checker = DiskUsageChecker::new( + store_path.as_path().to_str().unwrap().to_string(), + raft_path, + raft_auxiliay_path, + separated_raft_mount_path, + separated_raft_auxillay_mount_path, + separated_raft_auxiliary_with_kvdb, + reserve_space, + reserve_raft_space, + config_disk_capacity, + ); self.core.background_worker .spawn_interval_task(DEFAULT_STORAGE_STATS_INTERVAL, move || { - let disk_stats = match fs2::statvfs(&store_path) { - Err(e) => { - error!( - "get disk stat for kv store failed"; - "kv_path" => store_path.to_str(), - "err" => ?e - ); - return; - } - Ok(stats) => stats, - }; - let disk_cap = disk_stats.total_space(); let snap_size = snap_mgr.total_snap_size().unwrap(); - let mut kv_size = 0; tablet_registry.for_each_opened_tablet(|_, cached| { if let Some(tablet) = cached.latest() { @@ -1195,42 +1203,12 @@ where } true }); - let raft_size = raft_engine .get_engine_size() .expect("get raft engine size"); - - let mut raft_disk_status = disk::DiskUsage::Normal; - if separated_raft_mount_path && reserve_raft_space != 0 { - let raft_disk_stats = match fs2::statvfs(&raft_path) { - Err(e) => { - error!( - "get disk stat for raft engine failed"; - "raft_engine_path" => raft_path.clone(), - "err" => ?e - ); - return; - } - Ok(stats) => stats, - }; - let raft_disk_cap = raft_disk_stats.total_space(); - let mut raft_disk_available = - raft_disk_cap.checked_sub(raft_size).unwrap_or_default(); - raft_disk_available = cmp::min(raft_disk_available, raft_disk_stats.available_space()); - raft_disk_status = if raft_disk_available <= raft_already_full_threshold - { - disk::DiskUsage::AlreadyFull - } else if raft_disk_available <= raft_almost_full_threshold - { - disk::DiskUsage::AlmostFull - } else { - disk::DiskUsage::Normal - }; - } let placeholer_file_path = PathBuf::from_str(&data_dir) .unwrap() .join(Path::new(file_system::SPACE_PLACEHOLDER_FILE)); - let placeholder_size: u64 = file_system::get_file_size(placeholer_file_path).unwrap_or(0); @@ -1239,24 +1217,9 @@ where } else { snap_size + kv_size + placeholder_size }; - let capacity = if config_disk_capacity == 0 || disk_cap < config_disk_capacity { - disk_cap - } else { - config_disk_capacity - }; - - let mut available = capacity.checked_sub(used_size).unwrap_or_default(); - available = cmp::min(available, disk_stats.available_space()); - + // Check the disk usage and update the disk usage status. + let (cur_disk_status, cur_kv_disk_status, raft_disk_status, capacity, available) = disk_usage_checker.inspect(used_size, raft_size); let prev_disk_status = disk::get_disk_status(0); //0 no need care about failpoint. - let cur_kv_disk_status = if available <= already_full_threshold { - disk::DiskUsage::AlreadyFull - } else if available <= almost_full_threshold { - disk::DiskUsage::AlmostFull - } else { - disk::DiskUsage::Normal - }; - let cur_disk_status = calculate_disk_usage(raft_disk_status, cur_kv_disk_status); if prev_disk_status != cur_disk_status { warn!( "disk usage {:?}->{:?} (raft engine usage: {:?}, kv engine usage: {:?}), seperated raft mount={}, kv available={}, snap={}, kv={}, raft={}, capacity={}", diff --git a/components/tikv_util/Cargo.toml b/components/tikv_util/Cargo.toml index d2d7b87d672..9aba80be396 100644 --- a/components/tikv_util/Cargo.toml +++ b/components/tikv_util/Cargo.toml @@ -24,6 +24,7 @@ crossbeam-skiplist = { workspace = true } derive_more = "0.99.3" error_code = { workspace = true } fail = "0.5" +fs2 = "0.4" futures = { version = "0.3", features = ["compat", "thread-pool"] } futures-util = { version = "0.3", default-features = false, features = ["io"] } grpcio = { workspace = true } @@ -32,7 +33,10 @@ http = "0.2.0" kvproto = { workspace = true } lazy_static = "1.3" libc = "0.2" -log = { version = "0.4", features = ["max_level_trace", "release_max_level_debug"] } +log = { version = "0.4", features = [ + "max_level_trace", + "release_max_level_debug", +] } log_wrappers = { workspace = true } nix = "0.24" num-traits = "0.2" diff --git a/components/tikv_util/src/sys/disk.rs b/components/tikv_util/src/sys/disk.rs index c8fe87a56b0..5918bdd8e3b 100644 --- a/components/tikv_util/src/sys/disk.rs +++ b/components/tikv_util/src/sys/disk.rs @@ -1,5 +1,8 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. -use std::sync::atomic::{AtomicI32, AtomicU64, Ordering}; +use std::{ + path::Path, + sync::atomic::{AtomicI32, AtomicU64, Ordering}, +}; use fail::fail_point; pub use kvproto::disk_usage::DiskUsage; @@ -78,3 +81,16 @@ pub fn get_disk_status(_store_id: u64) -> DiskUsage { _ => panic!("Disk Status Value not meet expectations"), } } + +pub fn get_disk_space_stats>(path: P) -> std::io::Result<(u64, u64)> { + fail_point!("mock_disk_space_stats", |stats| { + let stats = stats.unwrap(); + let values = stats.split(',').collect::>(); + Ok(( + values[0].parse::().unwrap(), + values[1].parse::().unwrap(), + )) + }); + let disk_stats = fs2::statvfs(path)?; + Ok((disk_stats.total_space(), disk_stats.available_space())) +} diff --git a/components/tikv_util/src/sys/mod.rs b/components/tikv_util/src/sys/mod.rs index 8e0334fb171..028a70ce181 100644 --- a/components/tikv_util/src/sys/mod.rs +++ b/components/tikv_util/src/sys/mod.rs @@ -281,10 +281,11 @@ pub fn path_in_diff_mount_point(_path1: impl AsRef, _path2: impl AsRef 0); + assert!(available > 0); + assert!(capacity >= available); + + disk::get_disk_space_stats("/non-exist-path").unwrap_err(); + } } From 819eefe53afc28cb06f20b5ac53efbce26b11278 Mon Sep 17 00:00:00 2001 From: cfzjywxk Date: Tue, 13 Aug 2024 19:01:32 +0800 Subject: [PATCH 024/144] raftstore: debug print write info details (#17348) ref tikv/tikv#14474 Signed-off-by: cfzjywxk --- Cargo.lock | 1 + .../raftstore/src/store/async_io/write.rs | 3 ++ components/raftstore/src/store/fsm/apply.rs | 15 +++++++- components/raftstore/src/store/peer.rs | 9 ++++- components/tracker/Cargo.toml | 1 + components/tracker/src/lib.rs | 2 +- components/tracker/src/slab.rs | 29 ++++++++++++++++ components/txn_types/src/types.rs | 20 +++++------ src/storage/txn/scheduler.rs | 34 ++++++++++++++++--- src/storage/txn/task.rs | 1 + 10 files changed, 97 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9b6556a67f..21313cf6d4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7061,6 +7061,7 @@ dependencies = [ "pin-project", "prometheus", "slab", + "slog", ] [[package]] diff --git a/components/raftstore/src/store/async_io/write.rs b/components/raftstore/src/store/async_io/write.rs index 1fc99993ab1..7f32b1aaf71 100644 --- a/components/raftstore/src/store/async_io/write.rs +++ b/components/raftstore/src/store/async_io/write.rs @@ -43,6 +43,7 @@ use tikv_util::{ time::{duration_to_sec, setup_for_spin_interval, spin_at_least, Duration, Instant}, warn, }; +use tracker::TrackerTokenArray; use super::write_router::{SharedSenders, WriteSenders}; use crate::{ @@ -925,6 +926,8 @@ where self.perf_context.report_metrics(&trackers); write_raft_time = duration_to_sec(now.saturating_elapsed()); STORE_WRITE_RAFTDB_DURATION_HISTOGRAM.observe(write_raft_time); + debug!("raft log is persisted"; + "req_info" => TrackerTokenArray::new(trackers.as_slice())); } fail_point!("raft_after_save"); diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index 857120ea601..2726e705308 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -70,7 +70,7 @@ use tikv_util::{ Either, MustConsumeVec, }; use time::Timespec; -use tracker::GLOBAL_TRACKERS; +use tracker::{TrackerToken, TrackerTokenArray, GLOBAL_TRACKERS}; use uuid::Builder as UuidBuilder; use self::memtrace::*; @@ -644,6 +644,19 @@ where } = mem::replace(&mut self.applied_batch, ApplyCallbackBatch::new()); // Call it before invoking callback for preventing Commit is executed before // Prewrite is observed. + debug!("raft log is applied to the kv db"; + "req_info" => TrackerTokenArray::new( + &cb_batch.iter().fold(vec![], |mut acc: Vec, cb| { + acc.extend( + cb.0.write_trackers().into_iter(). + filter_map(|time_tracker| time_tracker.as_tracker_token()) + .collect::>().as_slice() + ); + acc + }) + ), + "cmd_batch" => ?cmd_batch.len(), + ); self.host .on_flush_applied_cmd_batch(batch_max_level, cmd_batch, &self.engine); // Invoke callbacks diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index ca702525d15..41e2c3b72aa 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -66,7 +66,7 @@ use tikv_util::{ Either, }; use time::{Duration as TimeDuration, Timespec}; -use tracker::GLOBAL_TRACKERS; +use tracker::{TrackerTokenArray, GLOBAL_TRACKERS}; use txn_types::{TimeStamp, WriteBatchFlags}; use uuid::Uuid; @@ -3085,6 +3085,13 @@ where // In this case the apply can be guaranteed to be successful. Invoke the // on_committed callback if necessary. p.cb.invoke_committed(); + + debug!("raft log is committed"; + "req_info" => TrackerTokenArray::new(p.cb.write_trackers() + .into_iter() + .filter_map(|time_tracker| time_tracker.as_tracker_token()) + .collect::>().as_slice()) + ); } p }) diff --git a/components/tracker/Cargo.toml b/components/tracker/Cargo.toml index 0b03d1ba1fc..9d05d61ded7 100644 --- a/components/tracker/Cargo.toml +++ b/components/tracker/Cargo.toml @@ -14,3 +14,4 @@ parking_lot = "0.12" pin-project = "1" prometheus = "0.13" slab = "0.4" +slog = { workspace = true } diff --git a/components/tracker/src/lib.rs b/components/tracker/src/lib.rs index db748c94d4b..d03cd9502b2 100644 --- a/components/tracker/src/lib.rs +++ b/components/tracker/src/lib.rs @@ -9,7 +9,7 @@ use std::time::Instant; use kvproto::kvrpcpb as pb; pub use self::{ - slab::{TrackerToken, GLOBAL_TRACKERS, INVALID_TRACKER_TOKEN}, + slab::{TrackerToken, TrackerTokenArray, GLOBAL_TRACKERS, INVALID_TRACKER_TOKEN}, tls::*, }; diff --git a/components/tracker/src/slab.rs b/components/tracker/src/slab.rs index 3ba4ca5953f..b8946989f84 100644 --- a/components/tracker/src/slab.rs +++ b/components/tracker/src/slab.rs @@ -188,6 +188,35 @@ impl Default for TrackerToken { } } +pub struct TrackerTokenArray<'a>(&'a [TrackerToken]); +impl<'a> slog::Value for TrackerTokenArray<'a> { + fn serialize( + &self, + _record: &slog::Record<'_>, + key: slog::Key, + serializer: &mut dyn slog::Serializer, + ) -> slog::Result { + let trackers_str = self + .0 + .iter() + .map(|tracker_token| { + format!( + "{:?}", + GLOBAL_TRACKERS.with_tracker(*tracker_token, |t| t.req_info.clone()) + ) + }) + .collect::>() + .join(", "); + serializer.emit_str(key, &trackers_str) + } +} + +impl<'a> TrackerTokenArray<'a> { + pub fn new(tokens: &'a [TrackerToken]) -> Self { + TrackerTokenArray(tokens) + } +} + #[cfg(test)] mod tests { use std::{sync::Arc, thread}; diff --git a/components/txn_types/src/types.rs b/components/txn_types/src/types.rs index 6e462beb577..0deece96e3e 100644 --- a/components/txn_types/src/types.rs +++ b/components/txn_types/src/types.rs @@ -335,12 +335,12 @@ impl Debug for Mutation { impl Display for Mutation { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Mutation::Put((key, value), assertion) => write!( + // TODO: find a proper way to print values, debug printing them in the log + // may result in large files. + Mutation::Put((key, _), assertion) => write!( f, - "Put key:{:?} value:{:?} assertion:{:?}", - key, - &log_wrappers::Value::value(value), - assertion + "Put key:{:?} value:skipped assertion:{:?}", + key, assertion ), Mutation::Delete(key, assertion) => { write!(f, "Delete key:{:?} assertion:{:?}", key, assertion) @@ -348,12 +348,12 @@ impl Display for Mutation { Mutation::Lock(key, assertion) => { write!(f, "Lock key:{:?} assertion:{:?}", key, assertion) } - Mutation::Insert((key, value), assertion) => write!( + // TODO: find a proper way to print values, debug printing them in the log + // may result in large files. + Mutation::Insert((key, _), assertion) => write!( f, - "Put key:{:?} value:{:?} assertion:{:?}", - key, - &log_wrappers::Value::value(value), - assertion + "Put key:{:?} value:skipped assertion:{:?}", + key, assertion ), Mutation::CheckNotExists(key, assertion) => { write!(f, "CheckNotExists key:{:?} assertion:{:?}", key, assertion) diff --git a/src/storage/txn/scheduler.rs b/src/storage/txn/scheduler.rs index cf75a0fed54..536a2c3fc8a 100644 --- a/src/storage/txn/scheduler.rs +++ b/src/storage/txn/scheduler.rs @@ -55,7 +55,7 @@ use tikv_kv::{Modify, Snapshot, SnapshotExt, WriteData, WriteEvent}; use tikv_util::{ memory::MemoryQuota, quota_limiter::QuotaLimiter, time::Instant, timer::GLOBAL_TIMER_HANDLE, }; -use tracker::{set_tls_tracker_token, TrackerToken, GLOBAL_TRACKERS}; +use tracker::{set_tls_tracker_token, TrackerToken, TrackerTokenArray, GLOBAL_TRACKERS}; use txn_types::TimeStamp; use super::task::Task; @@ -764,7 +764,7 @@ impl TxnScheduler { debug!( "process cmd with snapshot"; "cid" => task.cid(), "term" => ?term, "extra_op" => ?extra_op, - "tracker" => ?task.tracker_token() + "task" => ?&task, ); sched.process(snapshot, task).await; } @@ -809,14 +809,16 @@ impl TxnScheduler { err: StorageError::from(err), }; if let Some(details) = sched_details { - GLOBAL_TRACKERS.with_tracker(details.tracker, |tracker| { + let req_info = GLOBAL_TRACKERS.with_tracker(details.tracker, |tracker| { tracker.metrics.scheduler_process_nanos = details .start_process_instant .saturating_elapsed() .as_nanos() as u64; tracker.metrics.scheduler_throttle_nanos = details.flow_control_nanos + details.quota_limit_delay_nanos; + tracker.req_info.clone() }); + debug!("write command finished with error"; "cid" => cid, "pr" => ?&pr, "req_info" => ?req_info); } if let Some(cb) = tctx.cb { cb.execute(pr); @@ -878,8 +880,12 @@ impl TxnScheduler { SCHED_STAGE_COUNTER_VEC.get(tag).write_finish.inc(); } - debug!("write command finished"; - "cid" => cid, "pipelined" => pipelined, "async_apply_prewrite" => async_apply_prewrite); + debug!("write_command_finished"; + "req_info" => TrackerTokenArray::new(&[sched_details.tracker]), + "cid" => ?cid, + "pipelined" => ?pipelined, + "async_apply_prewrite" => ?async_apply_prewrite + ); drop(lock_guards); if result.is_ok() && !known_txn_status.is_empty() { @@ -1459,6 +1465,11 @@ impl TxnScheduler { &ctx, ) { + debug!("pessimistic locks to be written in-memory"; + "req_info" => TrackerTokenArray::new(&[tracker_token]), + "locks" => ?&to_be_write.modifies, + "cid" => ?cid + ); // Safety: `self.sched_pool` ensures a TLS engine exists. unsafe { with_tls_engine(|engine: &mut E| { @@ -1570,6 +1581,7 @@ impl TxnScheduler { txn_scheduler: TxnScheduler, cid: u64, tag: CommandKind, + tracker_token: TrackerToken, pipelined: bool, txn_ext: Option>, sched_details: &mut SchedulerDetails, @@ -1631,6 +1643,12 @@ impl TxnScheduler { } _ => vec![], }; + debug!( + "to be removed pessimistic_locks"; + "req_info" => TrackerTokenArray::new(&[tracker_token]), + "removed_locks" => ?&removed_pessimistic_locks, + "cid" => ?cid + ); // Keep the read lock guard of the pessimistic lock table until the request is // sent to the raftstore. // @@ -1814,6 +1832,11 @@ impl TxnScheduler { Ok(res) => res, }; SCHED_STAGE_COUNTER_VEC.get(tag).write.inc(); + debug!("process_write task handle result"; + "req_info" => TrackerTokenArray::new(&[tracker_token]), + "cid" => ?cid, + "process_result" => ?&write_result.pr + ); // Continue to process if there is data to be persisted in the `WriteResult`, or // return. @@ -1844,6 +1867,7 @@ impl TxnScheduler { self.clone(), cid, tag, + tracker_token, pipelined, txn_ext, sched_details, diff --git a/src/storage/txn/task.rs b/src/storage/txn/task.rs index 0defc77afd0..d0c66eb616d 100644 --- a/src/storage/txn/task.rs +++ b/src/storage/txn/task.rs @@ -17,6 +17,7 @@ use crate::storage::{ }, }; +#[derive(Debug)] pub(super) struct Task { cid: u64, tracker_token: TrackerToken, From 26c20c7923fb868cd3976fb8d36d738d4fff4abb Mon Sep 17 00:00:00 2001 From: Jianjun Liao <36503113+Leavrth@users.noreply.github.com> Date: Tue, 13 Aug 2024 20:52:32 +0800 Subject: [PATCH 025/144] raftstore: remove the behavior - immediately persist when the command's priority is different from that of apply poller. (#17338) close tikv/tikv#17278 remove the behavior - immediately persist when the command's priority is different from that of apply poller. Signed-off-by: Jianjun Liao Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/raftstore/src/store/fsm/apply.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index 2726e705308..4fb90d9ebc9 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -1262,7 +1262,7 @@ where // just return Yield return ApplyResult::Yield; } - let mut has_unflushed_data = + let has_unflushed_data = self.last_flush_applied_index != self.apply_state.get_applied_index(); if (has_unflushed_data && should_write_to_engine(!apply_ctx.kv_wb().is_empty(), &cmd) @@ -1279,12 +1279,8 @@ where { return ApplyResult::Yield; } - has_unflushed_data = false; } if self.priority != apply_ctx.priority { - if has_unflushed_data { - apply_ctx.commit(self); - } return ApplyResult::Yield; } From 918a9bc5478f22f09ce1504312946e0640f76381 Mon Sep 17 00:00:00 2001 From: Wenqi Mou Date: Wed, 14 Aug 2024 20:34:10 -0400 Subject: [PATCH 026/144] br: some code cleanup in router (#17347) close tikv/tikv#17360 remove scheduler.schedule(Task::MarkFailover(Instant::now()))?; as not needed anymore rename load_task to register_stream_task so can be more explicit of what the method is doing rename Service to BackupStreamGrpcService to be more explicit rename StreamTaskInfo to StreamTaskHandler as it contains methods acting as reactors on stream task events. It's more like a handler rather than read-only info. remove unused metrics tikv_backup_request_duration_seconds remove unused code handle_fatal_error Signed-off-by: Wenqi Mou --- components/backup-stream/src/endpoint.rs | 65 ++-------- components/backup-stream/src/lib.rs | 2 +- components/backup-stream/src/metrics.rs | 2 + components/backup-stream/src/router.rs | 118 ++++++++++-------- components/backup-stream/src/service.rs | 14 +-- .../backup-stream/src/subscription_manager.rs | 27 +--- .../backup-stream/tests/failpoints/mod.rs | 2 +- components/backup-stream/tests/suite.rs | 10 +- components/backup/src/metrics.rs | 7 +- components/server/src/server.rs | 2 +- components/server/src/server2.rs | 2 +- 11 files changed, 98 insertions(+), 153 deletions(-) diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index bce6584ddbc..ed58d63352b 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -321,8 +321,6 @@ where if task.is_paused { continue; } - // We have meet task upon store start, we must in a failover. - scheduler.schedule(Task::MarkFailover(Instant::now()))?; // move task to schedule scheduler.schedule(Task::WatchTask(TaskOp::AddTask(task)))?; } @@ -668,15 +666,16 @@ where pub fn on_register(&self, task: StreamTask) { let name = task.info.name.clone(); let start_ts = task.info.start_ts; - self.load_task(task); + self.register_stream_task(task); metrics::STORE_CHECKPOINT_TS .with_label_values(&[name.as_str()]) .set(start_ts as _); } - /// Load the task into memory: this would make the endpint start to observe. - fn load_task(&self, task: StreamTask) { + /// Load the task into memory: this would make the endpoint start to + /// observe. + fn register_stream_task(&self, task: StreamTask) { let cli = self.meta_client.clone(); let range_router = self.range_router.clone(); @@ -699,10 +698,9 @@ where }) )); self.pool.block_on(async move { - let task_clone = task.clone(); + let task_name_clone = task.info.get_name().to_owned(); let run = async move { - let task_name = task.info.get_name(); - let ranges = cli.ranges_of_task(task_name).await?; + let ranges = cli.ranges_of_task(task.info.get_name()).await?; fail::fail_point!("load_task::error_when_fetching_ranges", |_| { Err(Error::Other("what range? no such thing, go away.".into())) }); @@ -730,10 +728,10 @@ where "finish register backup stream ranges"; "task" => ?task, ); - Result::Ok(()) + Ok(()) }; if let Err(e) = run.await { - self.on_fatal_error_of_task(&task_clone.info.name, &Box::new(e)) + self.on_fatal_error_of_task(&task_name_clone, &Box::new(e)) .await; } }); @@ -757,7 +755,7 @@ where pub fn on_resume(&self, task_name: String) { let task = self.pool.block_on(self.meta_client.get_task(&task_name)); match task { - Ok(Some(stream_task)) => self.load_task(stream_task), + Ok(Some(stream_task)) => self.register_stream_task(stream_task), Ok(None) => { info!("backup stream task not existed"; "task" => %task_name); } @@ -848,9 +846,9 @@ where pub fn on_force_flush(&self, task: String) { self.pool.block_on(async move { - let info = self.range_router.get_task_info(&task); + let handler_res = self.range_router.get_task_handler(&task); // This should only happen in testing, it would be to unwrap... - let _ = info.unwrap().set_flushing_status_cas(false, true); + let _ = handler_res.unwrap().set_flushing_status_cas(false, true); let mts = self.prepare_min_ts().await; let sched = self.scheduler.clone(); self.region_op(ObserveOp::ResolveRegions { @@ -1439,44 +1437,3 @@ where self.run_task(task) } } - -#[cfg(test)] -mod test { - use engine_rocks::RocksEngine; - use raftstore::coprocessor::region_info_accessor::MockRegionInfoProvider; - use tikv_util::worker::dummy_scheduler; - - use crate::{ - checkpoint_manager::tests::MockPdClient, endpoint, endpoint::Endpoint, metadata::test, Task, - }; - - #[tokio::test] - async fn test_start() { - let cli = test::test_meta_cli(); - let (sched, mut rx) = dummy_scheduler(); - let task = test::simple_task("simple_3"); - cli.insert_task_with_range(&task, &[]).await.unwrap(); - - fail::cfg("failed_to_get_tasks", "1*return").unwrap(); - Endpoint::<_, MockRegionInfoProvider, RocksEngine, MockPdClient>::start_and_watch_tasks( - cli, sched, - ) - .await - .unwrap(); - fail::remove("failed_to_get_tasks"); - - let _t1 = rx.recv().unwrap(); - let t2 = rx.recv().unwrap(); - - match t2 { - Task::WatchTask(t) => match t { - endpoint::TaskOp::AddTask(t) => { - assert_eq!(t.info, task.info); - assert!(!t.is_paused); - } - _ => panic!("not match TaskOp type"), - }, - _ => panic!("not match Task type {:?}", t2), - } - } -} diff --git a/components/backup-stream/src/lib.rs b/components/backup-stream/src/lib.rs index 0402e5d2ee3..407c45bcaa3 100644 --- a/components/backup-stream/src/lib.rs +++ b/components/backup-stream/src/lib.rs @@ -25,4 +25,4 @@ pub use checkpoint_manager::GetCheckpointResult; pub use endpoint::{ BackupStreamResolver, Endpoint, ObserveOp, RegionCheckpointOperation, RegionSet, Task, }; -pub use service::Service; +pub use service::BackupStreamGrpcService; diff --git a/components/backup-stream/src/metrics.rs b/components/backup-stream/src/metrics.rs index 3a2fc1d119d..7b03c482774 100644 --- a/components/backup-stream/src/metrics.rs +++ b/components/backup-stream/src/metrics.rs @@ -30,6 +30,8 @@ pub fn remove_task_status_metric(task: &str) -> Result<()> { TASK_STATUS.remove_label_values(&[task]) } +// When adding new metrics, remember to update in the grafana dashboard, for +// example update the tikv_details.dashboard.py. lazy_static! { pub static ref INTERNAL_ACTOR_MESSAGE_HANDLE_DURATION: HistogramVec = register_histogram_vec!( "tikv_log_backup_interal_actor_acting_duration_sec", diff --git a/components/backup-stream/src/router.rs b/components/backup-stream/src/router.rs index b711cd88d4f..fbdd3158057 100644 --- a/components/backup-stream/src/router.rs +++ b/components/backup-stream/src/router.rs @@ -330,8 +330,8 @@ pub struct Config { pub data_key_manager: Option>, } -impl From for Config { - fn from(value: tikv::config::BackupStreamConfig) -> Self { +impl From for Config { + fn from(value: BackupStreamConfig) -> Self { let prefix = PathBuf::from(value.temp_path); let temp_file_size_limit = value.file_size_limit.0; let temp_file_memory_quota = value.temp_file_memory_quota.0; @@ -376,7 +376,7 @@ pub struct RouterInner { /// which range a point belongs to. ranges: SyncRwLock, String>>, /// The temporary files associated to some task. - tasks: DashMap>, + tasks: DashMap>, /// The temporary directory for all tasks. prefix: PathBuf, @@ -483,9 +483,10 @@ impl RouterInner { // register task info let cfg = self.tempfile_config_for_task(&task); - let stream_task = - StreamTaskInfo::new(task, ranges.clone(), merged_file_size_limit, cfg).await?; - self.tasks.insert(task_name.clone(), Arc::new(stream_task)); + let stream_task_handler = + StreamTaskHandler::new(task, ranges.clone(), merged_file_size_limit, cfg).await?; + self.tasks + .insert(task_name.clone(), Arc::new(stream_task_handler)); // register ranges self.register_ranges(&task_name, ranges); @@ -546,7 +547,7 @@ impl RouterInner { #[cfg(test)] pub(crate) fn must_mut_task_info(&self, task_name: &str, mutator: F) where - F: FnOnce(&mut StreamTaskInfo), + F: FnOnce(&mut StreamTaskHandler), { let t = self.tasks.remove(task_name); let mut raw = Arc::try_unwrap(t.unwrap().1).unwrap(); @@ -555,8 +556,8 @@ impl RouterInner { } #[instrument(skip(self))] - pub fn get_task_info(&self, task_name: &str) -> Result> { - let task_info = match self.tasks.get(task_name) { + pub fn get_task_handler(&self, task_name: &str) -> Result> { + let task_handler = match self.tasks.get(task_name) { Some(t) => t.clone(), None => { info!("backup stream no task"; "task" => ?task_name); @@ -565,13 +566,13 @@ impl RouterInner { }); } }; - Ok(task_info) + Ok(task_handler) } #[instrument(skip_all, fields(task))] - async fn on_event(&self, task: String, events: ApplyEvents) -> Result<()> { - let task_info = self.get_task_info(&task)?; - task_info.on_events(events).await?; + async fn on_events_by_task(&self, task: String, events: ApplyEvents) -> Result<()> { + let task_handler = self.get_task_handler(&task)?; + task_handler.on_events(events).await?; let file_size_limit = self.temp_file_size_limit.load(Ordering::SeqCst); // When this event make the size of temporary files exceeds the size limit, make @@ -580,16 +581,16 @@ impl RouterInner { debug!( "backup stream statics size"; "task" => ?task, - "next_size" => task_info.total_size(), + "next_size" => task_handler.total_size(), "size_limit" => file_size_limit, ); - let cur_size = task_info.total_size(); - if cur_size > file_size_limit && !task_info.is_flushing() { + let cur_size = task_handler.total_size(); + if cur_size > file_size_limit && !task_handler.is_flushing() { info!("try flushing task"; "task" => %task, "size" => %cur_size); - if task_info.set_flushing_status_cas(false, true).is_ok() { + if task_handler.set_flushing_status_cas(false, true).is_ok() { if let Err(e) = self.scheduler.schedule(Task::Flush(task)) { error!("backup stream schedule task failed"; "error" => ?e); - task_info.set_flushing_status(false); + task_handler.set_flushing_status(false); } } } @@ -600,13 +601,14 @@ impl RouterInner { use futures::FutureExt; HANDLE_KV_HISTOGRAM.observe(kv.len() as _); let partitioned_events = kv.partition_by_range(&self.ranges.rl()); - let tasks = partitioned_events - .into_iter() - .map(|(task, events)| self.on_event(task.clone(), events).map(move |r| (task, r))); + let tasks = partitioned_events.into_iter().map(|(task, events)| { + self.on_events_by_task(task.clone(), events) + .map(move |r| (task, r)) + }); futures::future::join_all(tasks).await } - /// flush the specified task, once once success, return the min resolved ts + /// flush the specified task, once success, return the min resolved ts /// of this flush. returns `None` if failed. #[instrument(skip(self, resolve_to))] pub async fn do_flush( @@ -617,15 +619,15 @@ impl RouterInner { ) -> Option { let task = self.tasks.get(task_name); match task { - Some(task_info) => { - let result = task_info.do_flush(store_id, resolve_to).await; + Some(task_handler) => { + let result = task_handler.do_flush(store_id, resolve_to).await; // set false to flushing whether success or fail - task_info.set_flushing_status(false); + task_handler.set_flushing_status(false); if let Err(e) = result { e.report("failed to flush task."); warn!("backup steam do flush fail"; "err" => ?e); - if task_info.flush_failure_count() > FLUSH_FAILURE_BECOME_FATAL_THRESHOLD { + if task_handler.flush_failure_count() > FLUSH_FAILURE_BECOME_FATAL_THRESHOLD { // NOTE: Maybe we'd better record all errors and send them to the client? try_send!( self.scheduler, @@ -638,7 +640,7 @@ impl RouterInner { return None; } // if succeed in flushing, update flush_time. Or retry do_flush immediately. - task_info.update_flush_time(); + task_handler.update_flush_time(); result.ok().flatten() } _ => None, @@ -652,7 +654,7 @@ impl RouterInner { global_checkpoint: u64, store_id: u64, ) -> Result { - self.get_task_info(task_name)? + self.get_task_handler(task_name)? .update_global_checkpoint(global_checkpoint, store_id) .await } @@ -823,7 +825,10 @@ impl TempFileKey { } } -pub struct StreamTaskInfo { +/// StreamTaskHandler acts on the events for the backup stream task. +/// It writes the key value pair changes from raft store to local temp files and +/// flushes it to the external storage. +pub struct StreamTaskHandler { pub(crate) task: StreamTask, /// support external storage. eg local/s3. pub(crate) storage: Arc, @@ -859,7 +864,7 @@ pub struct StreamTaskInfo { temp_file_pool: Arc, } -impl Drop for StreamTaskInfo { +impl Drop for StreamTaskHandler { fn drop(&mut self) { let (success, failed): (Vec<_>, Vec<_>) = self .flushing_files @@ -869,7 +874,7 @@ impl Drop for StreamTaskInfo { .map(|(_, f, _)| f.inner.path().to_owned()) .map(|p| self.temp_file_pool.remove(&p)) .partition(|r| *r); - info!("stream task info dropped[1/2], removing flushing_temp files"; "success" => %success.len(), "failure" => %failed.len()); + info!("stream task handler dropped[1/2], removing flushing_temp files"; "success" => %success.len(), "failure" => %failed.len()); let (success, failed): (Vec<_>, Vec<_>) = self .files .get_mut() @@ -877,13 +882,13 @@ impl Drop for StreamTaskInfo { .map(|(_, f)| f.into_inner().inner.path().to_owned()) .map(|p| self.temp_file_pool.remove(&p)) .partition(|r| *r); - info!("stream task info dropped[2/2], removing temp files"; "success" => %success.len(), "failure" => %failed.len()); + info!("stream task handler dropped[2/2], removing temp files"; "success" => %success.len(), "failure" => %failed.len()); } } -impl std::fmt::Debug for StreamTaskInfo { +impl std::fmt::Debug for StreamTaskHandler { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("StreamTaskInfo") + f.debug_struct("StreamTaskHandler") .field("task", &self.task.info.name) .field("min_resolved_ts", &self.min_resolved_ts) .field("total_size", &self.total_size) @@ -892,7 +897,7 @@ impl std::fmt::Debug for StreamTaskInfo { } } -impl StreamTaskInfo { +impl StreamTaskHandler { /// Create a new temporary file set at the `temp_dir`. pub async fn new( task: StreamTask, @@ -1956,7 +1961,7 @@ mod tests { is_paused: false, }; let merged_file_size_limit = 0x10000; - let task = StreamTaskInfo::new( + let task_handler = StreamTaskHandler::new( stream_task, vec![(vec![], vec![])], merged_file_size_limit, @@ -1969,14 +1974,14 @@ mod tests { let region_count = merged_file_size_limit / (4 * 1024); // 2 merged log files for i in 1..=region_count { let kv_events = mock_build_large_kv_events(i as _, i as _, i as _); - task.on_events(kv_events).await.unwrap(); + task_handler.on_events(kv_events).await.unwrap(); } // do_flush - task.set_flushing_status(true); - task.do_flush(1, TimeStamp::new(1)).await.unwrap(); - assert_eq!(task.flush_failure_count(), 0); - assert_eq!(task.files.read().await.is_empty(), true); - assert_eq!(task.flushing_files.read().await.is_empty(), true); + task_handler.set_flushing_status(true); + task_handler.do_flush(1, TimeStamp::new(1)).await.unwrap(); + assert_eq!(task_handler.flush_failure_count(), 0); + assert_eq!(task_handler.files.read().await.is_empty(), true); + assert_eq!(task_handler.flushing_files.read().await.is_empty(), true); // assert backup log files let mut meta_count = 0; @@ -2099,7 +2104,7 @@ mod tests { .is_none() ); check_on_events_result(&router.on_events(build_kv_event(10, 10)).await); - let t = router.get_task_info("error_prone").unwrap(); + let t = router.get_task_handler("error_prone").unwrap(); let _ = router.do_flush("error_prone", 42, TimeStamp::max()).await; assert_eq!(t.total_size() > 0, true); @@ -2138,7 +2143,7 @@ mod tests { ) .await .unwrap(); - let task = router.get_task_info("nothing").unwrap(); + let task = router.get_task_handler("nothing").unwrap(); task.set_flushing_status_cas(false, true).unwrap(); let ts = TimeStamp::compose(TimeStamp::physical_now(), 42); let rts = router.do_flush("nothing", 1, ts).await.unwrap(); @@ -2163,12 +2168,12 @@ mod tests { must_register_table(&router, task, 1).await; write_simple_data(&router).await; let tempfiles = router - .get_task_info("cleanup_test") + .get_task_handler("cleanup_test") .unwrap() .temp_file_pool .clone(); router - .get_task_info("cleanup_test")? + .get_task_handler("cleanup_test")? .move_to_flushing_files() .await?; write_simple_data(&router).await; @@ -2340,7 +2345,7 @@ mod tests { info: task_info, is_paused: false, }; - let task = StreamTaskInfo::new( + let task_handler = StreamTaskHandler::new( stream_task, vec![(vec![], vec![])], 0x100000, @@ -2348,25 +2353,30 @@ mod tests { ) .await .unwrap(); - task.global_checkpoint_ts.store(10001, Ordering::SeqCst); + task_handler + .global_checkpoint_ts + .store(10001, Ordering::SeqCst); // test no need to update global checkpoint let store_id = 3; let mut global_checkpoint = 10000; - let is_updated = task + let is_updated = task_handler .update_global_checkpoint(global_checkpoint, store_id) .await?; assert_eq!(is_updated, false); - assert_eq!(task.global_checkpoint_ts.load(Ordering::SeqCst), 10001); + assert_eq!( + task_handler.global_checkpoint_ts.load(Ordering::SeqCst), + 10001 + ); // test update global checkpoint global_checkpoint = 10002; - let is_updated = task + let is_updated = task_handler .update_global_checkpoint(global_checkpoint, store_id) .await?; assert_eq!(is_updated, true); assert_eq!( - task.global_checkpoint_ts.load(Ordering::SeqCst), + task_handler.global_checkpoint_ts.load(Ordering::SeqCst), global_checkpoint ); @@ -2448,7 +2458,7 @@ mod tests { let tmp_key = TempFileKey::of(&kv_event.events[0], 1); data_file.inner.done().await?; let mut files = vec![(tmp_key, data_file, info)]; - let result = StreamTaskInfo::merge_and_flush_log_files_to( + let result = StreamTaskHandler::merge_and_flush_log_files_to( Arc::new(ms), &mut files[0..], &mut meta, @@ -2553,7 +2563,7 @@ mod tests { let (fp_tx, fp_rx) = std::sync::mpsc::sync_channel(0); let fp_rx = std::sync::Mutex::new(fp_rx); - let t = router.get_task_info("race").unwrap(); + let t = router.get_task_handler("race").unwrap(); let _ = router.on_events(events_before_flush).await; // make generate temp files ***happen after*** moving files to flushing_files diff --git a/components/backup-stream/src/service.rs b/components/backup-stream/src/service.rs index 43d4ede2f27..e639f44a731 100644 --- a/components/backup-stream/src/service.rs +++ b/components/backup-stream/src/service.rs @@ -13,11 +13,11 @@ use crate::{ }; #[derive(Clone)] -pub struct Service { +pub struct BackupStreamGrpcService { endpoint: Scheduler, } -impl Service { +impl BackupStreamGrpcService { pub fn new(endpoint: Scheduler) -> Self { Self { endpoint } } @@ -39,7 +39,7 @@ impl From for RegionIdentity { } } -impl LogBackup for Service { +impl LogBackup for BackupStreamGrpcService { fn get_last_flush_ts_of_region( &mut self, _ctx: RpcContext<'_>, @@ -92,11 +92,9 @@ impl LogBackup for Service { fn subscribe_flush_event( &mut self, - _ctx: grpcio::RpcContext<'_>, - _req: kvproto::logbackuppb::SubscribeFlushEventRequest, - #[allow(unused_variables)] sink: grpcio::ServerStreamingSink< - kvproto::logbackuppb::SubscribeFlushEventResponse, - >, + _ctx: RpcContext<'_>, + _req: SubscribeFlushEventRequest, + #[allow(unused_variables)] sink: grpcio::ServerStreamingSink, ) { #[cfg(test)] panic!("Service should not be used in an unit test"); diff --git a/components/backup-stream/src/subscription_manager.rs b/components/backup-stream/src/subscription_manager.rs index 232a292e571..7e8d2c89de2 100644 --- a/components/backup-stream/src/subscription_manager.rs +++ b/components/backup-stream/src/subscription_manager.rs @@ -141,8 +141,6 @@ trait InitialScan: Clone + Sync + Send + 'static { start_ts: TimeStamp, handle: ObserveHandle, ) -> Result; - - fn handle_fatal_error(&self, region: &Region, err: Error); } #[async_trait::async_trait] @@ -171,19 +169,6 @@ where let stat = self.do_initial_scan(region, h, start_ts, snap).await?; Ok(stat) } - - fn handle_fatal_error(&self, region: &Region, err: Error) { - try_send!( - self.scheduler, - Task::FatalError( - TaskSelector::ByRange( - region.get_start_key().to_owned(), - region.get_end_key().to_owned() - ), - Box::new(err), - ) - ); - } } impl ScanCmd { @@ -897,15 +882,11 @@ mod test { async fn do_initial_scan( &self, region: &Region, - start_ts: txn_types::TimeStamp, - handle: raftstore::coprocessor::ObserveHandle, - ) -> crate::errors::Result { + start_ts: TimeStamp, + handle: ObserveHandle, + ) -> crate::errors::Result { (self.0)(region, start_ts, handle) } - - fn handle_fatal_error(&self, region: &Region, err: crate::errors::Error) { - panic!("fatal {:?} {}", region, err) - } } #[test] @@ -918,7 +899,7 @@ mod test { use super::ScanCmd; use crate::{subscription_manager::spawn_executors, utils::FutureWaitGroup}; - fn should_finish_in(f: impl FnOnce() + Send + 'static, d: std::time::Duration) { + fn should_finish_in(f: impl FnOnce() + Send + 'static, d: Duration) { let (tx, rx) = futures::channel::oneshot::channel(); std::thread::spawn(move || { f(); diff --git a/components/backup-stream/tests/failpoints/mod.rs b/components/backup-stream/tests/failpoints/mod.rs index 006dfac1b87..2499a679e38 100644 --- a/components/backup-stream/tests/failpoints/mod.rs +++ b/components/backup-stream/tests/failpoints/mod.rs @@ -254,7 +254,7 @@ mod all { .unwrap(); suite.sync(); - suite.wait_with_router(move |r| r.get_task_info("retry_abort").is_ok()); + suite.wait_with_router(move |r| r.get_task_handler("retry_abort").is_ok()); let items = run_async_test(suite.write_records(0, 128, 1)); suite.force_flush_files("retry_abort"); suite.wait_for_flush(); diff --git a/components/backup-stream/tests/suite.rs b/components/backup-stream/tests/suite.rs index dc80a1cba45..ba6c350ccd6 100644 --- a/components/backup-stream/tests/suite.rs +++ b/components/backup-stream/tests/suite.rs @@ -18,8 +18,8 @@ use backup_stream::{ }, observer::BackupStreamObserver, router::{Router, TaskSelector}, - utils, BackupStreamResolver, Endpoint, GetCheckpointResult, RegionCheckpointOperation, - RegionSet, Service, Task, + utils, BackupStreamGrpcService, BackupStreamResolver, Endpoint, GetCheckpointResult, + RegionCheckpointOperation, RegionSet, Task, }; use engine_rocks::RocksEngine; use futures::{executor::block_on, AsyncWriteExt, Future, Stream, StreamExt}; @@ -357,7 +357,7 @@ impl Suite { .get(&id) .expect("must register endpoint first"); - let serv = Service::new(endpoint.scheduler()); + let serv = BackupStreamGrpcService::new(endpoint.scheduler()); let builder = ServerBuilder::new(self.env.clone()).register_service(create_log_backup(serv)); let mut server = builder.bind("127.0.0.1", 0).build().unwrap(); @@ -435,7 +435,7 @@ impl Suite { )) .unwrap(); let name = name.to_owned(); - self.wait_with_router(move |r| r.get_task_info(&name).is_ok()) + self.wait_with_router(move |r| r.get_task_handler(&name).is_ok()) } /// This function tries to calculate the global checkpoint from the flush @@ -928,7 +928,7 @@ impl Suite { self.wait_with_router(move |r| { let task_names = r.select_task(TaskSelector::All.reference()); for task_name in task_names { - let tsk = r.get_task_info(&task_name); + let tsk = r.get_task_handler(&task_name); if tsk.unwrap().is_flushing() { return false; } diff --git a/components/backup/src/metrics.rs b/components/backup/src/metrics.rs index a24a1593e9f..352092619bc 100644 --- a/components/backup/src/metrics.rs +++ b/components/backup/src/metrics.rs @@ -3,12 +3,9 @@ use lazy_static::*; use prometheus::*; +// When adding new metrics, remember to update in the grafana dashboard, for +// example update the tikv_details.dashboard.py. lazy_static! { - pub static ref BACKUP_REQUEST_HISTOGRAM: Histogram = register_histogram!( - "tikv_backup_request_duration_seconds", - "Bucketed histogram of backup requests duration" - ) - .unwrap(); pub static ref BACKUP_RANGE_HISTOGRAM_VEC: HistogramVec = register_histogram_vec!( "tikv_backup_range_duration_seconds", "Bucketed histogram of backup range duration", diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 9f6e124570e..017e6192f14 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -1311,7 +1311,7 @@ where } if let Some(sched) = servers.backup_stream_scheduler.take() { - let pitr_service = backup_stream::Service::new(sched); + let pitr_service = backup_stream::BackupStreamGrpcService::new(sched); if servers .server .register_service(create_log_backup(pitr_service)) diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index 8723eed37d8..f91e20f5687 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -986,7 +986,7 @@ where } if let Some(sched) = self.backup_stream_scheduler.take() { - let pitr_service = backup_stream::Service::new(sched); + let pitr_service = backup_stream::BackupStreamGrpcService::new(sched); if servers .server .register_service(create_log_backup(pitr_service)) From 0f03af51a1e0d780a2c5a483a310e745428c8e5b Mon Sep 17 00:00:00 2001 From: Connor Date: Thu, 15 Aug 2024 20:56:40 +0800 Subject: [PATCH 027/144] server: Fix io flow stat for snapshot sending (#17384) ref tikv/tikv#15990 Fix io flow stat for snapshot sending. Its io flow is not taken into account previously because the io flow is recorded only when using `file_system::File` which is a wrapper of `std::fs::File`. Signed-off-by: Connor1996 --- components/raftstore/src/store/snap/io.rs | 2 +- src/server/snap.rs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/raftstore/src/store/snap/io.rs b/components/raftstore/src/store/snap/io.rs index 641afb3ad36..ad2c687c9fa 100644 --- a/components/raftstore/src/store/snap/io.rs +++ b/components/raftstore/src/store/snap/io.rs @@ -2,7 +2,6 @@ use std::{ cell::RefCell, fs, - fs::{File, OpenOptions}, io::{self, BufReader, Read, Write}, sync::Arc, usize, @@ -14,6 +13,7 @@ use engine_traits::{ SstWriter, SstWriterBuilder, WriteBatch, }; use fail::fail_point; +use file_system::{File, OpenOptions}; use kvproto::encryptionpb::EncryptionMethod; use tikv_util::{ box_try, diff --git a/src/server/snap.rs b/src/server/snap.rs index 3e06fcecae3..3db888da843 100644 --- a/src/server/snap.rs +++ b/src/server/snap.rs @@ -110,6 +110,7 @@ struct SnapChunk { first: Option, snap: Box, remain_bytes: usize, + io_type: IoType, } pub const SNAP_CHUNK_LEN: usize = 1024 * 1024; @@ -128,6 +129,7 @@ impl Stream for SnapChunk { n if n > SNAP_CHUNK_LEN => vec![0; SNAP_CHUNK_LEN], n => vec![0; n], }; + let _with_io_type = WithIoType::new(self.io_type); let result = self.snap.read_exact(buf.as_mut_slice()); match result { Ok(_) => { @@ -164,7 +166,7 @@ pub fn send_snap( let send_timer = SEND_SNAP_HISTOGRAM.start_coarse_timer(); - let (key, snap_start, generate_duration_sec) = { + let (key, snap_start, generate_duration_sec, io_type) = { let snap = msg.get_message().get_snapshot(); let mut snap_data = RaftSnapshotData::default(); if let Err(e) = snap_data.merge_from_bytes(snap.get_data()) { @@ -173,7 +175,12 @@ pub fn send_snap( let key = SnapKey::from_region_snap(msg.get_region_id(), snap); let snap_start = snap_data.get_meta().get_start(); let generate_duration_sec = snap_data.get_meta().get_generate_duration_sec(); - (key, snap_start, generate_duration_sec) + let io_type = if snap_data.get_meta().get_for_balance() { + IoType::LoadBalance + } else { + IoType::Replication + }; + (key, snap_start, generate_duration_sec, io_type) }; mgr.register(key.clone(), SnapEntry::Sending); @@ -198,6 +205,7 @@ pub fn send_snap( first: Some(first_chunk), snap: s, remain_bytes: total_size as usize, + io_type, } }; From 2577ecfee311d4335c5e415a13ed95be78eeed24 Mon Sep 17 00:00:00 2001 From: glorv Date: Fri, 16 Aug 2024 16:11:41 +0800 Subject: [PATCH 028/144] In-Memory-Engine: move from range-base to region-base (#17331) ref tikv/tikv#16141, close tikv/tikv#17147 Move range cache engine's range manager for range-base to region-base Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 3 + components/backup-stream/src/tempfiles.rs | 4 +- .../engine_panic/src/range_cache_engine.rs | 4 +- .../engine_rocks/src/range_cache_engine.rs | 4 +- components/engine_traits/src/engine.rs | 4 + components/engine_traits/src/flush.rs | 2 +- .../engine_traits/src/range_cache_engine.rs | 150 +- components/engine_traits/src/write_batch.rs | 8 +- components/hybrid_engine/Cargo.toml | 2 + components/hybrid_engine/src/engine.rs | 89 +- components/hybrid_engine/src/metrics.rs | 1 + components/hybrid_engine/src/misc.rs | 60 +- components/hybrid_engine/src/observer.rs | 82 +- .../hybrid_engine/src/range_cache_engine.rs | 6 +- components/hybrid_engine/src/snapshot.rs | 23 +- components/hybrid_engine/src/util.rs | 14 +- components/hybrid_engine/src/write_batch.rs | 113 +- .../tests/failpoints/test_write_batch.rs | 90 +- components/raftstore/src/coprocessor/mod.rs | 1 + .../src/coprocessor/region_info_accessor.rs | 2 +- components/raftstore/src/store/fsm/apply.rs | 35 +- components/raftstore/src/store/fsm/peer.rs | 4 +- components/raftstore/src/store/peer.rs | 2 + components/raftstore/src/store/util.rs | 4 +- components/raftstore/src/store/worker/read.rs | 15 +- .../src/background.rs | 1274 +++++++++-------- .../range_cache_memory_engine/src/engine.rs | 353 ++--- .../range_cache_memory_engine/src/keys.rs | 31 +- .../range_cache_memory_engine/src/lib.rs | 9 +- .../src/memory_controller.rs | 5 +- .../range_cache_memory_engine/src/metrics.rs | 4 + .../src/range_manager.rs | 1239 ++++++++++------ .../src/range_stats.rs | 125 +- .../range_cache_memory_engine/src/read.rs | 480 ++++--- .../src/test_util.rs | 20 +- .../src/write_batch.rs | 692 +++++---- .../tests/failpoints/test_memory_engine.rs | 201 +-- components/test_pd_client/src/pd.rs | 36 + components/test_raftstore/src/cluster.rs | 14 +- .../test_raftstore/src/range_cache_engine.rs | 16 +- components/test_raftstore/src/server.rs | 7 + metrics/grafana/tikv_details.dashboard.py | 2 +- metrics/grafana/tikv_details.json | 2 +- metrics/grafana/tikv_details.json.sha256 | 2 +- src/server/raftkv/mod.rs | 2 + tests/Cargo.toml | 1 + tests/failpoints/cases/test_early_apply.rs | 2 +- .../cases/test_range_cache_engine.rs | 322 ++--- tests/failpoints/cases/test_stale_read.rs | 2 +- 49 files changed, 3000 insertions(+), 2563 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21313cf6d4e..e0255c05042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2542,6 +2542,7 @@ dependencies = [ "fail", "kvproto", "lazy_static", + "log_wrappers", "online_config", "prometheus", "prometheus-static-metric", @@ -2551,6 +2552,7 @@ dependencies = [ "slog", "slog-global", "tempfile", + "test_util", "tikv_util", "txn_types", ] @@ -6202,6 +6204,7 @@ dependencies = [ "raftstore-v2", "rand 0.8.5", "rand_xorshift", + "range_cache_memory_engine", "resource_control", "resource_metering", "security", diff --git a/components/backup-stream/src/tempfiles.rs b/components/backup-stream/src/tempfiles.rs index def8342a606..21a07798cea 100644 --- a/components/backup-stream/src/tempfiles.rs +++ b/components/backup-stream/src/tempfiles.rs @@ -59,7 +59,7 @@ pub struct Config { /// Prevent files with size less than this being swapped out. /// We perfer to swap larger files for reducing IOps. pub minimal_swap_out_file_size: usize, - /// The buffer size for writting swap files. + /// The buffer size for writing swap files. /// Even some of files has been swapped out, when new content appended, /// those content would be kept in memory before they reach a threshold. /// This would help us to reduce the I/O system calls. @@ -334,7 +334,7 @@ impl TempFilePool { self.current.load(Ordering::Acquire) } - /// Create a file for writting. + /// Create a file for writing. /// This function is synchronous so we can call it easier in the polling /// context. (Anyway, it is really hard to call an async function in the /// polling context.) diff --git a/components/engine_panic/src/range_cache_engine.rs b/components/engine_panic/src/range_cache_engine.rs index 00891c04510..1b5e3cc61df 100644 --- a/components/engine_panic/src/range_cache_engine.rs +++ b/components/engine_panic/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{EvictReason, RangeCacheEngineExt}; +use engine_traits::{EvictReason, RangeCacheEngineExt, RegionEvent}; use crate::PanicEngine; @@ -9,7 +9,7 @@ impl RangeCacheEngineExt for PanicEngine { panic!() } - fn evict_range(&self, range: &engine_traits::CacheRange, evict_range: EvictReason) { + fn on_region_event(&self, event: RegionEvent) { panic!() } } diff --git a/components/engine_rocks/src/range_cache_engine.rs b/components/engine_rocks/src/range_cache_engine.rs index 509d32edf26..cce2498126b 100644 --- a/components/engine_rocks/src/range_cache_engine.rs +++ b/components/engine_rocks/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{EvictReason, RangeCacheEngineExt}; +use engine_traits::{RangeCacheEngineExt, RegionEvent}; use crate::RocksEngine; @@ -10,5 +10,5 @@ impl RangeCacheEngineExt for RocksEngine { } #[inline] - fn evict_range(&self, _: &engine_traits::CacheRange, _: EvictReason) {} + fn on_region_event(&self, _: RegionEvent) {} } diff --git a/components/engine_traits/src/engine.rs b/components/engine_traits/src/engine.rs index 7e20201e231..3d8240650f4 100644 --- a/components/engine_traits/src/engine.rs +++ b/components/engine_traits/src/engine.rs @@ -86,6 +86,10 @@ pub trait KvEngine: #[derive(Debug, Clone)] pub struct SnapshotContext { pub range: Option, + pub region_id: u64, + // the version of region epoch. + pub epoch_version: u64, + pub read_ts: u64, } diff --git a/components/engine_traits/src/flush.rs b/components/engine_traits/src/flush.rs index 46b1877a703..2a98c69bc8b 100644 --- a/components/engine_traits/src/flush.rs +++ b/components/engine_traits/src/flush.rs @@ -217,7 +217,7 @@ impl PersistenceListener { }) })(); // The correctness relies on the assumption that there will be only one - // thread writting to the DB and increasing apply index. + // thread writing to the DB and increasing apply index. // Apply index will be set within DB lock, so it's correct even with manual // flush. let offset = data_cf_offset(&cf); diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 0f081ff8700..fa632f3d0f8 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -1,13 +1,12 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - cmp, fmt::{self, Debug}, result, }; use keys::{enc_end_key, enc_start_key}; -use kvproto::metapb; +use kvproto::metapb::Region; use crate::{Iterable, KvEngine, Snapshot, WriteBatchExt}; @@ -15,9 +14,33 @@ use crate::{Iterable, KvEngine, Snapshot, WriteBatchExt}; pub enum FailedReason { NotCached, TooOldRead, + // while we always get rocksdb's snapshot first and then get IME's snapshot. + // epoch is first checked in get rocksdb's snaphsot by raftstore. + // But because we update IME's epoch in apply batch, and update raft local reader's + // epoch after ApplyRes is returned, so it's possible that IME's region epoch is + // newer than raftstore's, so we still need to check epoch again in IME snapshot. + EpochNotMatch, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, PartialEq)] +pub enum RegionEvent { + Split { + source: Region, + new_regions: Vec, + }, + Eviction { + region: Region, + reason: EvictReason, + }, + // range eviction triggered by delete_range + // we should evict all cache regions that overlaps with this range + EvictByRange { + range: CacheRange, + reason: EvictReason, + }, +} + +#[derive(Debug, Clone, Copy, PartialEq)] pub enum EvictReason { LoadFailed, LoadFailedWithoutStart, @@ -26,6 +49,7 @@ pub enum EvictReason { AutoEvict, DeleteRange, Merge, + Disabled, } /// RangeCacheEngine works as a range cache caching some ranges (in Memory or @@ -41,6 +65,8 @@ pub trait RangeCacheEngine: // provide atomic write fn snapshot( &self, + region_id: u64, + region_epoch: u64, range: CacheRange, read_ts: u64, seq_num: u64, @@ -49,8 +75,8 @@ pub trait RangeCacheEngine: type DiskEngine: KvEngine; fn set_disk_engine(&mut self, disk_engine: Self::DiskEngine); - // return the range containing the key - fn get_range_for_key(&self, key: &[u8]) -> Option; + // return the region containing the key + fn get_region_for_key(&self, key: &[u8]) -> Option; type RangeHintService: RangeHintService; fn start_hint_service(&self, range_hint_service: Self::RangeHintService); @@ -59,7 +85,7 @@ pub trait RangeCacheEngine: false } - fn evict_range(&self, range: &CacheRange, evict_reason: EvictReason); + fn on_region_event(&self, event: RegionEvent); } pub trait RangeCacheEngineExt { @@ -67,7 +93,7 @@ pub trait RangeCacheEngineExt { // TODO(SpadeA): try to find a better way to reduce coupling degree of range // cache engine and kv engine - fn evict_range(&self, range: &CacheRange, evict_range: EvictReason); + fn on_region_event(&self, event: RegionEvent); } /// A service that should run in the background to retrieve and apply cache @@ -78,25 +104,15 @@ pub trait RangeCacheEngineExt { /// as it continues to evolve to handle eviction, using stats. pub trait RangeHintService: Send + Sync {} -#[derive(Clone, Eq)] +#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct CacheRange { pub start: Vec, pub end: Vec, - // Note: tag may not be accurate due decouple of region split and range split. It's only for - // debug purpose. - pub tag: String, -} - -impl PartialEq for CacheRange { - fn eq(&self, other: &Self) -> bool { - self.start == other.start && self.end == other.end - } } impl Debug for CacheRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CacheRange") - .field("tag", &self.tag) .field("range_start", &log_wrappers::Value(&self.start)) .field("range_end", &log_wrappers::Value(&self.end)) .finish() @@ -105,47 +121,14 @@ impl Debug for CacheRange { impl CacheRange { pub fn new(start: Vec, end: Vec) -> Self { - Self { - start, - end, - tag: "".to_owned(), - } + Self { start, end } } - pub fn from_region(region: &metapb::Region) -> Self { + pub fn from_region(region: &Region) -> Self { Self { start: enc_start_key(region), end: enc_end_key(region), - tag: format!("[region_id={}]", region.get_id()), - } - } -} - -impl PartialOrd for CacheRange { - fn partial_cmp(&self, other: &Self) -> Option { - if self.end <= other.start { - return Some(cmp::Ordering::Less); - } - - if other.end <= self.start { - return Some(cmp::Ordering::Greater); - } - - if self == other { - return Some(cmp::Ordering::Equal); - } - - None - } -} - -impl Ord for CacheRange { - fn cmp(&self, other: &Self) -> cmp::Ordering { - let c = self.start.cmp(&other.start); - if !c.is_eq() { - return c; } - self.end.cmp(&other.end) } } @@ -163,70 +146,11 @@ impl CacheRange { pub fn overlaps(&self, other: &CacheRange) -> bool { self.start < other.end && other.start < self.end } - - pub fn split_off(&self, range: &CacheRange) -> (Option, Option) { - assert!(self.contains_range(range)); - let left = if self.start != range.start { - Some(CacheRange { - start: self.start.clone(), - end: range.start.clone(), - tag: "".to_owned(), - }) - } else { - None - }; - let right = if self.end != range.end { - Some(CacheRange { - start: range.end.clone(), - end: self.end.clone(), - tag: "".to_owned(), - }) - } else { - None - }; - - (left, right) - } } #[cfg(test)] mod tests { - use std::cmp::Ordering; - - use crate::CacheRange; - - #[test] - fn test_cache_range_eq() { - let r1 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - let mut r2 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - r2.tag = "Something".to_string(); - assert_eq!(r1, r2); - } - - #[test] - fn test_cache_range_partial_cmp() { - let r1 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k3".to_vec()); - let r3 = CacheRange::new(b"k2".to_vec(), b"k4".to_vec()); - assert_eq!(r1.partial_cmp(&r2).unwrap(), Ordering::Less); - assert_eq!(r2.partial_cmp(&r1).unwrap(), Ordering::Greater); - assert!(r2.partial_cmp(&r3).is_none()); - } - - #[test] - fn test_split_off() { - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k4".to_vec()); - - let r3 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - let r4 = CacheRange::new(b"k4".to_vec(), b"k6".to_vec()); - - let (left, right) = r1.split_off(&r1); - assert!(left.is_none() && right.is_none()); - let (left, right) = r1.split_off(&r2); - assert_eq!(left.unwrap(), r3); - assert_eq!(right.unwrap(), r4); - } + use super::CacheRange; #[test] fn test_overlap() { diff --git a/components/engine_traits/src/write_batch.rs b/components/engine_traits/src/write_batch.rs index e04cb498fb6..7a2a222178e 100644 --- a/components/engine_traits/src/write_batch.rs +++ b/components/engine_traits/src/write_batch.rs @@ -1,6 +1,8 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{errors::Result, options::WriteOptions, CacheRange}; +use kvproto::metapb::Region; + +use crate::{errors::Result, options::WriteOptions}; /// Engines that can create write batches pub trait WriteBatchExt: Sized { @@ -125,6 +127,6 @@ pub trait WriteBatch: Mutable { fn merge(&mut self, src: Self) -> Result<()>; /// It declares that the following consecutive write will be within this - /// range. - fn prepare_for_range(&mut self, _: CacheRange) {} + /// region. + fn prepare_for_region(&mut self, _: &Region) {} } diff --git a/components/hybrid_engine/Cargo.toml b/components/hybrid_engine/Cargo.toml index f14eff7f10e..d49c06e4568 100644 --- a/components/hybrid_engine/Cargo.toml +++ b/components/hybrid_engine/Cargo.toml @@ -19,6 +19,7 @@ engine_traits = { workspace = true } txn_types = { workspace = true } tikv_util = { workspace = true } engine_rocks = { workspace = true } +log_wrappers = { workspace = true } online_config = { workspace = true } range_cache_memory_engine = { workspace = true } slog = { workspace = true } @@ -35,3 +36,4 @@ kvproto = { workspace = true } [dev-dependencies] tempfile = "3.0" +test_util = { workspace = true } diff --git a/components/hybrid_engine/src/engine.rs b/components/hybrid_engine/src/engine.rs index e3591098cb4..dd82f02d728 100644 --- a/components/hybrid_engine/src/engine.rs +++ b/components/hybrid_engine/src/engine.rs @@ -63,6 +63,26 @@ where } } +impl HybridEngine +where + EK: KvEngine, + EC: RangeCacheEngine, + HybridEngine: WriteBatchExt, +{ + fn sync_write(&self, key: &[u8], f: F) -> Result<()> + where + F: FnOnce(&mut ::WriteBatch) -> Result<()>, + { + let mut batch = self.write_batch(); + if let Some(region) = self.range_cache_engine.get_region_for_key(key) { + batch.prepare_for_region(®ion); + } + f(&mut batch)?; + let _ = batch.write()?; + Ok(()) + } +} + // todo: implement KvEngine methods as well as it's super traits. impl KvEngine for HybridEngine where @@ -78,6 +98,8 @@ where None } else if let Some(ctx) = ctx { match self.range_cache_engine.snapshot( + ctx.region_id, + ctx.epoch_version, ctx.range.unwrap(), ctx.read_ts, disk_snap.sequence_number(), @@ -98,6 +120,12 @@ where .inc(); None } + Err(FailedReason::EpochNotMatch) => { + RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC + .epoch_not_match + .inc(); + None + } } } else { RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC @@ -155,63 +183,27 @@ where HybridEngine: WriteBatchExt, { fn put(&self, key: &[u8], value: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(key) { - batch.prepare_for_range(range); - } - batch.put(key, value)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(key, |b| b.put(key, value)) } fn put_cf(&self, cf: &str, key: &[u8], value: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(key) { - batch.prepare_for_range(range); - } - batch.put_cf(cf, key, value)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(key, |b| b.put_cf(cf, key, value)) } fn delete(&self, key: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(key) { - batch.prepare_for_range(range); - } - batch.delete(key)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(key, |b| b.delete(key)) } fn delete_cf(&self, cf: &str, key: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(key) { - batch.prepare_for_range(range); - } - batch.delete_cf(cf, key)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(key, |b| b.delete_cf(cf, key)) } fn delete_range(&self, begin_key: &[u8], end_key: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(begin_key) { - batch.prepare_for_range(range); - } - batch.delete_range(begin_key, end_key)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(begin_key, |b| b.delete_range(begin_key, end_key)) } fn delete_range_cf(&self, cf: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()> { - let mut batch = self.write_batch(); - if let Some(range) = self.range_cache_engine.get_range_for_key(begin_key) { - batch.prepare_for_range(range); - } - batch.delete_range_cf(cf, begin_key, end_key)?; - let _ = batch.write()?; - Ok(()) + self.sync_write(begin_key, |b| b.delete_range_cf(cf, begin_key, end_key)) } } @@ -224,8 +216,8 @@ mod tests { use engine_traits::{CacheRange, KvEngine, SnapshotContext, CF_DEFAULT, CF_LOCK, CF_WRITE}; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use range_cache_memory_engine::{ - config::RangeCacheConfigManager, RangeCacheEngineConfig, RangeCacheEngineContext, - RangeCacheMemoryEngine, + config::RangeCacheConfigManager, test_util::new_region, RangeCacheEngineConfig, + RangeCacheEngineContext, RangeCacheMemoryEngine, }; use tempfile::Builder; use tikv_util::config::VersionTrack; @@ -244,11 +236,12 @@ mod tests { let memory_engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config.clone())); - let range = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - memory_engine.new_range(range.clone()); + let region = new_region(1, b"k00", b"k10"); + let range = CacheRange::from_region(®ion); + memory_engine.new_region(region.clone()); { let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range, 10); + core.mut_range_manager().set_safe_point(region.id, 10); } let hybrid_engine = HybridEngine::new(disk_engine, memory_engine.clone()); @@ -256,6 +249,8 @@ mod tests { assert!(!s.range_cache_snapshot_available()); let mut snap_ctx = SnapshotContext { + region_id: 1, + epoch_version: 0, read_ts: 15, range: Some(range.clone()), }; diff --git a/components/hybrid_engine/src/metrics.rs b/components/hybrid_engine/src/metrics.rs index 9c31cead88e..81a1b54b96b 100644 --- a/components/hybrid_engine/src/metrics.rs +++ b/components/hybrid_engine/src/metrics.rs @@ -18,6 +18,7 @@ make_auto_flush_static_metric! { no_read_ts, not_cached, too_old_read, + epoch_not_match, } pub struct FailedReasonCountVec: LocalIntCounter { diff --git a/components/hybrid_engine/src/misc.rs b/components/hybrid_engine/src/misc.rs index 5d8043160b5..dcecdae1a7b 100644 --- a/components/hybrid_engine/src/misc.rs +++ b/components/hybrid_engine/src/misc.rs @@ -1,7 +1,8 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. use engine_traits::{ - CacheRange, EvictReason, KvEngine, MiscExt, RangeCacheEngine, Result, WriteBatchExt, + CacheRange, EvictReason, KvEngine, MiscExt, RangeCacheEngine, RegionEvent, Result, + WriteBatchExt, }; use crate::{engine::HybridEngine, hybrid_metrics::HybridEngineStatisticsReporter}; @@ -38,10 +39,11 @@ where ranges: &[engine_traits::Range<'_>], ) -> Result { for r in ranges { - self.range_cache_engine().evict_range( - &CacheRange::new(r.start_key.to_vec(), r.end_key.to_vec()), - EvictReason::DeleteRange, - ); + self.range_cache_engine() + .on_region_event(RegionEvent::EvictByRange { + range: CacheRange::new(r.start_key.to_vec(), r.end_key.to_vec()), + reason: EvictReason::DeleteRange, + }); } self.disk_engine() .delete_ranges_cf(wopts, cf, strategy, ranges) @@ -151,43 +153,43 @@ where } #[cfg(test)] -mod tests { +pub mod tests { use engine_traits::{ CacheRange, DeleteStrategy, MiscExt, Mutable, Range, RangeCacheEngine, WriteBatch, WriteBatchExt, WriteOptions, CF_DEFAULT, }; - use range_cache_memory_engine::RangeCacheEngineConfig; + use range_cache_memory_engine::{test_util::new_region, RangeCacheEngineConfig}; use crate::util::hybrid_engine_for_tests; #[test] fn test_delete_range() { - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let range3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); - let range1_clone = range1.clone(); - let range2_clone = range2.clone(); - let range3_clone = range3.clone(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); + let r1_clone = r1.clone(); + let r2_clone = r2.clone(); + let r3_clone = r3.clone(); let (_path, hybrid_engine) = hybrid_engine_for_tests( "temp", RangeCacheEngineConfig::config_for_test(), move |memory_engine| { - memory_engine.new_range(range1_clone); - memory_engine.new_range(range2_clone); - memory_engine.new_range(range3_clone); + memory_engine.new_region(r1_clone); + memory_engine.new_region(r2_clone); + memory_engine.new_region(r3_clone); }, ) .unwrap(); let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_range(range1.clone()); - write_batch.put(b"k02", b"val").unwrap(); - write_batch.put(b"k03", b"val").unwrap(); - write_batch.prepare_for_range(range2.clone()); - write_batch.put(b"k22", b"val").unwrap(); - write_batch.put(b"k23", b"val").unwrap(); - write_batch.prepare_for_range(range3.clone()); - write_batch.put(b"k42", b"val").unwrap(); - write_batch.put(b"k42", b"val").unwrap(); + write_batch.prepare_for_region(&r1); + write_batch.put(b"zk02", b"val").unwrap(); + write_batch.put(b"zk03", b"val").unwrap(); + write_batch.prepare_for_region(&r2); + write_batch.put(b"zk22", b"val").unwrap(); + write_batch.put(b"zk23", b"val").unwrap(); + write_batch.prepare_for_region(&r3); + write_batch.put(b"zk42", b"val").unwrap(); + write_batch.put(b"zk42", b"val").unwrap(); write_batch.write().unwrap(); hybrid_engine @@ -195,21 +197,21 @@ mod tests { &WriteOptions::default(), CF_DEFAULT, DeleteStrategy::DeleteByRange, - &[Range::new(b"k00", b"k15"), Range::new(b"k22", b"k27")], + &[Range::new(b"zk00", b"zk15"), Range::new(b"zk22", b"zk27")], ) .unwrap(); hybrid_engine .range_cache_engine() - .snapshot(range1.clone(), 1000, 1000) + .snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(range2.clone(), 1000, 1000) + .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(range3.clone(), 1000, 1000) + .snapshot(r3.id, 0, CacheRange::from_region(&r3), 1000, 1000) .unwrap(); } } diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer.rs index 4fd0bcddcc9..8a2c837f17d 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; -use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngineExt}; +use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngineExt, RegionEvent}; use kvproto::{metapb::Region, raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; use raft::StateRole; use raftstore::coprocessor::{ @@ -13,14 +13,18 @@ use raftstore::coprocessor::{ #[derive(Clone)] pub struct Observer { - pending_evict: Arc>>, + // observer is per thread so there is no need to use mutex here, + // but current inteface only provides `&self` but not `&mut self`, + // so we use mutex to workaround this restriction. + // TODO: change Observer's interface to `&mut self`. + pending_events: Arc>>, cache_engine: Arc, } impl Observer { pub fn new(cache_engine: Arc) -> Self { Observer { - pending_evict: Arc::default(), + pending_events: Arc::default(), cache_engine, } } @@ -80,12 +84,36 @@ impl Observer { "region_id" => ctx.region().get_id(), "is_ingest_sst" => apply.pending_handle_ssts.is_some(), "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), - "range" => ?range, + "start_key" => ?log_wrappers::Value(&ctx.region().start_key), + "end_key" => ?log_wrappers::Value(&ctx.region().end_key), ); - self.pending_evict + self.pending_events .lock() .unwrap() - .push((range, EvictReason::Merge)); + .push(RegionEvent::Eviction { + region: ctx.region().clone(), + reason: EvictReason::Merge, + }); + } + // there are new_regions, this must be a split event. + if !state.new_regions.is_empty() { + let cmd_type = cmd.request.get_admin_request().get_cmd_type(); + assert!(cmd_type == AdminCmdType::BatchSplit || cmd_type == AdminCmdType::Split); + tikv_util::info!( + "in-memory-engine handle region split"; + "region_id" => ctx.region().get_id(), + "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), + "region" => ?state.modified_region.as_ref().unwrap(), + "new_regions" => ?state.new_regions, + ); + + self.pending_events + .lock() + .unwrap() + .push(RegionEvent::Split { + source: ctx.region().clone(), + new_regions: state.new_regions.clone(), + }); } } @@ -94,12 +122,9 @@ impl Observer { return; } - let ranges = { - let mut ranges = self.pending_evict.lock().unwrap(); - std::mem::take(&mut *ranges) - }; - for (range, evict_reason) in ranges { - self.cache_engine.evict_range(&range, evict_reason); + let events = std::mem::take(&mut *self.pending_events.lock().unwrap()); + for e in events { + self.cache_engine.on_region_event(e); } } @@ -110,14 +135,19 @@ impl Observer { let range = CacheRange::from_region(region); tikv_util::info!( - "evict range due to leader step down"; - "region_id" => region.get_id(), - "range" => ?range, + "evict region due to leader step down"; + "region_id" => region.get_id(), + "epoch" => ?region.get_region_epoch(), + "start_key" => ?log_wrappers::Value(®ion.start_key), + "end_key" => ?log_wrappers::Value(®ion.end_key), ); - self.pending_evict + self.pending_events .lock() .unwrap() - .push((range, EvictReason::BecomeFollower)); + .push(RegionEvent::Eviction { + region: region.clone(), + reason: EvictReason::BecomeFollower, + }); } } @@ -185,7 +215,7 @@ impl CmdObserver for Observer { mod tests { use std::sync::atomic::{AtomicBool, Ordering}; - use engine_traits::SstMetaInfo; + use engine_traits::{RegionEvent, SstMetaInfo}; use kvproto::{ import_sstpb::SstMeta, metapb::Peer, @@ -197,14 +227,14 @@ mod tests { #[derive(Default)] struct MockRangeCacheEngine { enabled: AtomicBool, - evicted_ranges: Arc>>, + region_events: Arc>>, } impl RangeCacheEngineExt for MockRangeCacheEngine { fn range_cache_engine_enabled(&self) -> bool { self.enabled.load(Ordering::Relaxed) } - fn evict_range(&self, range: &CacheRange, _: EvictReason) { - self.evicted_ranges.lock().unwrap().push(range.clone()); + fn on_region_event(&self, event: RegionEvent) { + self.region_events.lock().unwrap().push(event); } } @@ -246,7 +276,7 @@ mod tests { observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); let expected = CacheRange::from_region(®ion); - assert!(&cache_engine.evicted_ranges.lock().unwrap().is_empty()); + assert!(&cache_engine.region_events.lock().unwrap().is_empty()); } #[test] @@ -282,13 +312,17 @@ mod tests { // Must not evict range when range cache engine is disabled. observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); - assert!(cache_engine.evicted_ranges.lock().unwrap().is_empty()); + assert!(cache_engine.region_events.lock().unwrap().is_empty()); // Enable range cache engine. cache_engine.enabled.store(true, Ordering::Relaxed); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); let expected = CacheRange::from_region(®ion); - assert_eq!(&cache_engine.evicted_ranges.lock().unwrap()[0], &expected); + let expected = RegionEvent::Eviction { + region, + reason: EvictReason::Merge, + }; + assert_eq!(&cache_engine.region_events.lock().unwrap()[0], &expected); } } diff --git a/components/hybrid_engine/src/range_cache_engine.rs b/components/hybrid_engine/src/range_cache_engine.rs index fb54ad80c04..1fabcfee5ac 100644 --- a/components/hybrid_engine/src/range_cache_engine.rs +++ b/components/hybrid_engine/src/range_cache_engine.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngine, RangeCacheEngineExt}; +use engine_traits::{KvEngine, RangeCacheEngine, RangeCacheEngineExt, RegionEvent}; use crate::HybridEngine; @@ -14,7 +14,7 @@ where } #[inline] - fn evict_range(&self, range: &CacheRange, evict_range: EvictReason) { - self.range_cache_engine().evict_range(range, evict_range); + fn on_region_event(&self, event: RegionEvent) { + self.range_cache_engine().on_region_event(event); } } diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index ea831368eb6..b69837278ba 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -135,26 +135,29 @@ mod tests { CacheRange, IterOptions, Iterable, Iterator, KvEngine, Mutable, SnapshotContext, WriteBatch, WriteBatchExt, CF_DEFAULT, }; - use range_cache_memory_engine::{RangeCacheEngineConfig, RangeCacheStatus}; + use range_cache_memory_engine::{ + test_util::new_region, RangeCacheEngineConfig, RangeCacheStatus, + }; use crate::util::hybrid_engine_for_tests; #[test] fn test_iterator() { - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); - let range_clone = range.clone(); + let region_clone = region.clone(); let (_path, hybrid_engine) = hybrid_engine_for_tests( "temp", RangeCacheEngineConfig::config_for_test(), move |memory_engine| { - memory_engine.new_range(range_clone.clone()); + memory_engine.new_region(region_clone); { let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range_clone, 5); + core.mut_range_manager().set_safe_point(1, 5); } }, ) @@ -165,15 +168,17 @@ mod tests { assert!(!iter.seek_to_first().unwrap()); } let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_range(range.clone()); + write_batch.prepare_for_region(®ion); write_batch .cache_write_batch .set_range_cache_status(RangeCacheStatus::Cached); - write_batch.put(b"hello", b"world").unwrap(); + write_batch.put(b"zhello", b"world").unwrap(); let seq = write_batch.write().unwrap(); assert!(seq > 0); let ctx = SnapshotContext { - range: Some(range.clone()), + region_id: 1, + epoch_version: 0, + range: Some(CacheRange::from_region(®ion)), read_ts: 10, }; let snap = hybrid_engine.snapshot(Some(ctx)); @@ -182,7 +187,7 @@ mod tests { assert!(iter.seek_to_first().unwrap()); let actual_key = iter.key(); let actual_value = iter.value(); - assert_eq!(actual_key, b"hello"); + assert_eq!(actual_key, b"zhello"); assert_eq!(actual_value, b"world"); } } diff --git a/components/hybrid_engine/src/util.rs b/components/hybrid_engine/src/util.rs index 4d8a614a36d..cab4f2d82bb 100644 --- a/components/hybrid_engine/src/util.rs +++ b/components/hybrid_engine/src/util.rs @@ -19,14 +19,12 @@ use crate::HybridEngine; /// /// ``` /// use hybrid_engine::util::hybrid_engine_for_tests; -/// let (_path, _hybrid_engine) = hybrid_engine_for_tests("temp", |memory_engine| { -/// let range = engine_traits::CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); -/// memory_engine.new_range(range.clone()); -/// { -/// let mut core = memory_engine.core().write().unwrap(); -/// core.mut_range_manager().set_range_readable(&range, true); -/// core.mut_range_manager().set_safe_ts(&range, 10); -/// } +/// use range_cache_memory_engine::{test_util::new_region, RangeCacheEngineConfig}; +/// let mut config = RangeCacheEngineConfig::default(); +/// config.enabled = true; +/// let (_path, _hybrid_engine) = hybrid_engine_for_tests("temp", config, |memory_engine| { +/// let region = new_region(1, b"", b"z"); +/// memory_engine.new_region(region); /// }) /// .unwrap(); /// ``` diff --git a/components/hybrid_engine/src/write_batch.rs b/components/hybrid_engine/src/write_batch.rs index 136f99c0ce5..b8753bd89bc 100644 --- a/components/hybrid_engine/src/write_batch.rs +++ b/components/hybrid_engine/src/write_batch.rs @@ -3,8 +3,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use engine_traits::{ - is_data_cf, CacheRange, KvEngine, Mutable, Result, WriteBatch, WriteBatchExt, WriteOptions, + is_data_cf, KvEngine, Mutable, Result, WriteBatch, WriteBatchExt, WriteOptions, }; +use kvproto::metapb::Region; use range_cache_memory_engine::{RangeCacheMemoryEngine, RangeCacheWriteBatch}; use crate::engine::HybridEngine; @@ -100,8 +101,8 @@ impl WriteBatch for HybridEngineWriteBatch { self.cache_write_batch.merge(other.cache_write_batch) } - fn prepare_for_range(&mut self, range: CacheRange) { - self.cache_write_batch.prepare_for_range(range); + fn prepare_for_region(&mut self, r: &Region) { + self.cache_write_batch.prepare_for_region(r); } } @@ -155,49 +156,55 @@ mod tests { CacheRange, KvEngine, Mutable, Peekable, RangeCacheEngine, SnapshotContext, WriteBatch, WriteBatchExt, }; - use range_cache_memory_engine::{RangeCacheEngineConfig, RangeCacheStatus}; + use range_cache_memory_engine::{ + test_util::new_region, RangeCacheEngineConfig, RangeCacheStatus, + }; use crate::util::hybrid_engine_for_tests; #[test] fn test_write_to_both_engines() { - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - let range_clone = range.clone(); + let region = new_region(1, b"", b"z"); + let region_clone = region.clone(); let (_path, hybrid_engine) = hybrid_engine_for_tests( "temp", RangeCacheEngineConfig::config_for_test(), move |memory_engine| { - memory_engine.new_range(range_clone.clone()); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range_clone, 5); - } + let id = region_clone.id; + memory_engine.new_region(region_clone); + memory_engine + .core() + .write() + .mut_range_manager() + .set_safe_point(id, 5); }, ) .unwrap(); let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_range(range.clone()); + write_batch.prepare_for_region(®ion); write_batch .cache_write_batch .set_range_cache_status(RangeCacheStatus::Cached); - write_batch.put(b"hello", b"world").unwrap(); + write_batch.put(b"zhello", b"world").unwrap(); let seq = write_batch.write().unwrap(); assert!(seq > 0); - let actual: &[u8] = &hybrid_engine.get_value(b"hello").unwrap().unwrap(); + let actual: &[u8] = &hybrid_engine.get_value(b"zhello").unwrap().unwrap(); assert_eq!(b"world", &actual); let ctx = SnapshotContext { - range: Some(range.clone()), + region_id: 1, + epoch_version: 0, + range: Some(CacheRange::from_region(®ion)), read_ts: 10, }; let snap = hybrid_engine.snapshot(Some(ctx)); - let actual: &[u8] = &snap.get_value(b"hello").unwrap().unwrap(); + let actual: &[u8] = &snap.get_value(b"zhello").unwrap().unwrap(); assert_eq!(b"world", &actual); - let actual: &[u8] = &snap.disk_snap().get_value(b"hello").unwrap().unwrap(); + let actual: &[u8] = &snap.disk_snap().get_value(b"zhello").unwrap().unwrap(); assert_eq!(b"world", &actual); let actual: &[u8] = &snap .range_cache_snap() .unwrap() - .get_value(b"hello") + .get_value(b"zhello") .unwrap() .unwrap(); assert_eq!(b"world", &actual); @@ -209,11 +216,11 @@ mod tests { "temp", RangeCacheEngineConfig::config_for_test(), |memory_engine| { - let range = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - memory_engine.new_range(range.clone()); + let region = new_region(1, b"k00", b"k10"); + memory_engine.new_region(region); { let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range, 10); + core.mut_range_manager().set_safe_point(1, 10); } }, ) @@ -234,37 +241,37 @@ mod tests { #[test] fn test_delete_range() { - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); + let region1 = new_region(1, b"k00", b"k10"); + let region2 = new_region(2, b"k20", b"k30"); - let range1_clone = range1.clone(); - let range2_clone = range2.clone(); + let region1_clone = region1.clone(); + let region2_clone = region2.clone(); let (_path, hybrid_engine) = hybrid_engine_for_tests( "temp", RangeCacheEngineConfig::config_for_test(), move |memory_engine| { - memory_engine.new_range(range1_clone); - memory_engine.new_range(range2_clone); + memory_engine.new_region(region1_clone); + memory_engine.new_region(region2_clone); }, ) .unwrap(); let mut wb = hybrid_engine.write_batch(); - wb.prepare_for_range(range1.clone()); - wb.put(b"k05", b"val").unwrap(); - wb.put(b"k08", b"val2").unwrap(); - wb.prepare_for_range(range2.clone()); - wb.put(b"k25", b"val3").unwrap(); - wb.put(b"k27", b"val4").unwrap(); + wb.prepare_for_region(®ion1); + wb.put(b"zk05", b"val").unwrap(); + wb.put(b"zk08", b"val2").unwrap(); + wb.prepare_for_region(®ion2); + wb.put(b"zk25", b"val3").unwrap(); + wb.put(b"zk27", b"val4").unwrap(); wb.write().unwrap(); hybrid_engine .range_cache_engine() - .snapshot(range1.clone(), 1000, 1000) + .snapshot(region1.id, 0, CacheRange::from_region(®ion1), 1000, 1000) .unwrap(); hybrid_engine .range_cache_engine() - .snapshot(range2.clone(), 1000, 1000) + .snapshot(region2.id, 0, CacheRange::from_region(®ion2), 1000, 1000) .unwrap(); assert_eq!( 4, @@ -279,33 +286,33 @@ mod tests { let mut wb = hybrid_engine.write_batch(); // all ranges overlapped with it will be evicted - wb.delete_range(b"k05", b"k21").unwrap(); + wb.prepare_for_region(®ion1); + wb.delete_range(b"zk05", b"zk08").unwrap(); + wb.prepare_for_region(®ion2); + wb.delete_range(b"zk20", b"zk21").unwrap(); wb.write().unwrap(); hybrid_engine .range_cache_engine() - .snapshot(range1, 1000, 1000) + .snapshot(region1.id, 0, CacheRange::from_region(®ion1), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(range2, 1000, 1000) + .snapshot(region2.id, 0, CacheRange::from_region(®ion2), 1000, 1000) .unwrap_err(); let m_engine = hybrid_engine.range_cache_engine(); - let mut times = 0; - while times < 10 { - if m_engine - .core() - .read() - .engine() - .cf_handle("default") - .is_empty() - { - return; - } - times += 1; - std::thread::sleep(Duration::from_millis(200)); - } - panic!("data is not empty"); + test_util::eventually( + Duration::from_millis(100), + Duration::from_millis(2000), + || { + m_engine + .core() + .read() + .engine() + .cf_handle("default") + .is_empty() + }, + ); } } diff --git a/components/hybrid_engine/tests/failpoints/test_write_batch.rs b/components/hybrid_engine/tests/failpoints/test_write_batch.rs index 2a28a80dc9b..227c95b0db3 100644 --- a/components/hybrid_engine/tests/failpoints/test_write_batch.rs +++ b/components/hybrid_engine/tests/failpoints/test_write_batch.rs @@ -3,9 +3,11 @@ use std::sync::mpsc::sync_channel; use crossbeam::epoch; -use engine_traits::{CacheRange, Mutable, WriteBatch, WriteBatchExt}; +use engine_traits::{Mutable, WriteBatch, WriteBatchExt}; use hybrid_engine::util::hybrid_engine_for_tests; -use range_cache_memory_engine::{decode_key, InternalKey, RangeCacheEngineConfig, ValueType}; +use range_cache_memory_engine::{ + decode_key, test_util::new_region, InternalKey, RangeCacheEngineConfig, ValueType, +}; #[test] fn test_sequence_number_unique() { @@ -13,49 +15,54 @@ fn test_sequence_number_unique() { hybrid_engine_for_tests("temp", RangeCacheEngineConfig::config_for_test(), |_| {}).unwrap(); let (tx, rx) = sync_channel(0); - fail::cfg_callback("pending_range_completes_loading", move || { - fail::cfg("on_snapshot_load_finished", "pause").unwrap(); + fail::cfg_callback("on_completes_batch_loading", move || { + fail::cfg("on_start_loading_region", "pause").unwrap(); tx.send(true).unwrap(); }) .unwrap(); + // first write some data, these data should be handled by batch loading. + let mut wb = hybrid_engine.write_batch(); + wb.put(b"zk5", b"val").unwrap(); // seq 1 + wb.put(b"zk7", b"val").unwrap(); // seq 2 + let engine = hybrid_engine.range_cache_engine().clone(); - let r = CacheRange::new(b"k".to_vec(), b"k5".to_vec()); - engine.new_range(r.clone()); + let r = new_region(1, b"k", b"k5"); + engine.new_region(r.clone()); + wb.write().unwrap(); // Mock that we have a loading range, and there are some keys written in it // during the load - let r2 = CacheRange::new(b"k5".to_vec(), b"k7".to_vec()); - let r3 = CacheRange::new(b"k7".to_vec(), b"k9".to_vec()); + let r2 = new_region(2, b"k5", b"k7"); + let r3 = new_region(3, b"k7", b"k9"); - engine.load_range(r2.clone()).unwrap(); - engine.load_range(r3.clone()).unwrap(); + engine.load_region(r2.clone()).unwrap(); + engine.load_region(r3.clone()).unwrap(); // The sequence number of write batch should be increased one by one, otherwise // if a delete and a put of the same key occurs in the same write batch, // the delete will be hidden by the put even the delete is performed // after the put. + // while we block the batch loading of region3, it's new KVs are still directly + // written into the skiplist. let mut wb = hybrid_engine.write_batch(); - wb.prepare_for_range(r.clone()); - wb.put(b"k", b"val").unwrap(); // seq 6 - wb.delete(b"k").unwrap(); // seq 7 - wb.put(b"k2", b"val").unwrap(); // seq 8 + wb.prepare_for_region(&r); + wb.put(b"zk", b"val").unwrap(); // seq 3 + wb.delete(b"zk").unwrap(); // seq 4 + wb.put(b"zk2", b"val").unwrap(); // seq 5 - wb.prepare_for_range(r2.clone()); - wb.put(b"k6", b"val").unwrap(); // seq 3 - wb.put(b"k5", b"val").unwrap(); // seq 4 - wb.delete(b"k5").unwrap(); // seq 5 + wb.prepare_for_region(&r2); + wb.put(b"zk6", b"val").unwrap(); // seq 6 + wb.delete(b"zk5").unwrap(); // seq 7 + wb.put(b"zk5", b"val2").unwrap(); // seq 8 - wb.prepare_for_range(r3.clone()); - wb.put(b"k8", b"val").unwrap(); // seq 1 - wb.put(b"k7", b"val").unwrap(); // seq 2 + wb.prepare_for_region(&r3); + wb.put(b"zk8", b"val").unwrap(); // seq 9 + wb.put(b"zk7", b"val2").unwrap(); // seq 10 rx.recv().unwrap(); wb.write().unwrap(); - // For sequence number increment, the loading range get increment first, the - // loading range that completes the loading before consuming the write batch get - // increment second, and the cached range get increment last. let mut iter = engine .core() .read() @@ -66,13 +73,19 @@ fn test_sequence_number_unique() { let mut first = true; - for (k, seq, ty) in [ - (b"k".to_vec(), 7, ValueType::Deletion), - (b"k".to_vec(), 6, ValueType::Value), - (b"k2".to_vec(), 8, ValueType::Value), - (b"k5".to_vec(), 5, ValueType::Deletion), - (b"k5".to_vec(), 4, ValueType::Value), - (b"k6".to_vec(), 3, ValueType::Value), + for (k, sequence, v_type) in [ + (b"zk".to_vec(), 4, ValueType::Deletion), + (b"zk".to_vec(), 3, ValueType::Value), + (b"zk2".to_vec(), 5, ValueType::Value), + (b"zk5".to_vec(), 8, ValueType::Value), + (b"zk5".to_vec(), 7, ValueType::Deletion), + // NOTE: for batch loading, we always use the current seq number + // to write all the keys. + (b"zk5".to_vec(), 2, ValueType::Value), + (b"zk6".to_vec(), 6, ValueType::Value), + (b"zk7".to_vec(), 10, ValueType::Value), + // "zk7" with seq 2 is block, so invisible here. + (b"zk8".to_vec(), 9, ValueType::Value), ] { if first { iter.seek_to_first(guard); @@ -81,14 +94,13 @@ fn test_sequence_number_unique() { iter.next(guard); } - let key = iter.key(); - let InternalKey { - user_key, - sequence, + let expected_key = InternalKey { + user_key: k.as_slice(), v_type, - } = decode_key(key.as_bytes()); - assert_eq!(sequence, seq); - assert_eq!(user_key, &k); - assert_eq!(v_type, ty); + sequence, + }; + let key = iter.key(); + let got_key = decode_key(key.as_bytes()); + assert_eq!(expected_key, got_key); } } diff --git a/components/raftstore/src/coprocessor/mod.rs b/components/raftstore/src/coprocessor/mod.rs index c62ae409470..1cbbdab5ab5 100644 --- a/components/raftstore/src/coprocessor/mod.rs +++ b/components/raftstore/src/coprocessor/mod.rs @@ -87,6 +87,7 @@ pub struct RegionState { pub peer_id: u64, pub pending_remove: bool, pub modified_region: Option, + pub new_regions: Vec, } /// Context for exec observers of mutation to be applied to ApplyContext. diff --git a/components/raftstore/src/coprocessor/region_info_accessor.rs b/components/raftstore/src/coprocessor/region_info_accessor.rs index 81032a87230..60d1239f453 100644 --- a/components/raftstore/src/coprocessor/region_info_accessor.rs +++ b/components/raftstore/src/coprocessor/region_info_accessor.rs @@ -817,7 +817,7 @@ pub trait RegionInfoProvider: Send + Sync { fn find_region_by_id( &self, - _reigon_id: u64, + _region_id: u64, _callback: Callback>, ) -> Result<()> { unimplemented!() diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index 4fb90d9ebc9..d1ef08909ad 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -29,9 +29,9 @@ use batch_system::{ use collections::{HashMap, HashMapEntry, HashSet}; use crossbeam::channel::{TryRecvError, TrySendError}; use engine_traits::{ - util::SequenceNumber, CacheRange, DeleteStrategy, KvEngine, Mutable, PerfContext, - PerfContextKind, RaftEngine, RaftEngineReadOnly, Range as EngineRange, Snapshot, SstMetaInfo, - WriteBatch, WriteOptions, ALL_CFS, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, + util::SequenceNumber, DeleteStrategy, KvEngine, Mutable, PerfContext, PerfContextKind, + RaftEngine, RaftEngineReadOnly, Range as EngineRange, Snapshot, SstMetaInfo, WriteBatch, + WriteOptions, ALL_CFS, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, }; use fail::fail_point; use health_controller::types::LatencyInspector; @@ -542,8 +542,7 @@ where pub fn prepare_for(&mut self, delegate: &mut ApplyDelegate) { self.applied_batch .push_batch(&delegate.observe_info, delegate.region.get_id()); - let range = CacheRange::from_region(&delegate.region); - self.kv_wb.prepare_for_range(range); + self.kv_wb.prepare_for_region(&delegate.region); } /// Commits all changes have done for delegate. `persistent` indicates @@ -1520,17 +1519,19 @@ where self.apply_state.set_applied_index(index); self.applied_term = term; - let (modified_region, mut pending_handle_ssts) = match exec_result { - ApplyResult::Res(ref e) => match e { - ExecResult::SplitRegion { ref derived, .. } => (Some(derived.clone()), None), - ExecResult::PrepareMerge { ref region, .. } => (Some(region.clone()), None), - ExecResult::CommitMerge { ref region, .. } => (Some(region.clone()), None), - ExecResult::RollbackMerge { ref region, .. } => (Some(region.clone()), None), - ExecResult::IngestSst { ref ssts } => (None, Some(ssts.clone())), - ExecResult::Flashback { ref region } => (Some(region.clone()), None), - _ => (None, None), + let (modified_region, new_regions, mut pending_handle_ssts) = match &exec_result { + ApplyResult::Res(e) => match e { + ExecResult::SplitRegion { regions, .. } => { + (Some(self.region.clone()), regions.clone(), None) + } + ExecResult::PrepareMerge { region, .. } => (Some(region.clone()), vec![], None), + ExecResult::CommitMerge { region, .. } => (Some(region.clone()), vec![], None), + ExecResult::RollbackMerge { region, .. } => (Some(region.clone()), vec![], None), + ExecResult::IngestSst { ssts } => (None, vec![], Some(ssts.clone())), + ExecResult::Flashback { region } => (Some(region.clone()), vec![], None), + _ => (None, vec![], None), }, - _ => (None, None), + _ => (None, vec![], None), }; let mut apply_ctx_info = ApplyCtxInfo { pending_handle_ssts: &mut pending_handle_ssts, @@ -1545,9 +1546,11 @@ where peer_id: self.id(), pending_remove: self.pending_remove, modified_region, + new_regions, }, &mut apply_ctx_info, ); + match pending_handle_ssts { None => (), Some(mut v) => { @@ -7429,7 +7432,7 @@ mod tests { let cmd_batch = cmdbatch_rx.recv_timeout(Duration::from_secs(3)).unwrap(); assert_eq!(2, cmd_batch.len()); - // Stop observer regoin 1. + // Stop observer region 1. observe_handle.stop_observing(); let observe_handle = ObserveHandle::new(); diff --git a/components/raftstore/src/store/fsm/peer.rs b/components/raftstore/src/store/fsm/peer.rs index 999d23c46a4..4131dcae60e 100644 --- a/components/raftstore/src/store/fsm/peer.rs +++ b/components/raftstore/src/store/fsm/peer.rs @@ -2627,7 +2627,7 @@ where MEMTRACE_RAFT_MESSAGES.trace(TraceEvent::Sub(heap_size)); if stepped.get() { unsafe { - // It could be less than exact for entry overwritting. + // It could be less than exact for entry overwriting. *memtrace_raft_entries += heap_size; MEMTRACE_RAFT_ENTRIES.trace(TraceEvent::Add(heap_size)); } @@ -3806,7 +3806,7 @@ where if self.fsm.peer.has_unpersisted_ready() { assert!(self.ctx.sync_write_worker.is_none()); // The destroy must be delayed if there are some unpersisted readies. - // Otherwise there is a race of writting kv db and raft db between here + // Otherwise there is a race of writing kv db and raft db between here // and write worker. return Some(DelayReason::UnPersistedReady); } diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index 41e2c3b72aa..8649384e6a5 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -5016,6 +5016,8 @@ where let snap_ctx = if let Ok(read_ts) = decode_u64(&mut req.get_header().get_flag_data()) { Some(SnapshotContext { range: Some(CacheRange::from_region(®ion)), + region_id: region.id, + epoch_version: region.get_region_epoch().version, read_ts, }) } else { diff --git a/components/raftstore/src/store/util.rs b/components/raftstore/src/store/util.rs index 856cfb12885..53884a13ba6 100644 --- a/components/raftstore/src/store/util.rs +++ b/components/raftstore/src/store/util.rs @@ -424,7 +424,7 @@ pub fn check_term(header: &RaftRequestHeader, term: u64) -> Result<()> { if header.get_term() == 0 || term <= header.get_term() + 1 { Ok(()) } else { - // If header's term is 2 verions behind current term, + // If header's term is 2 versions behind current term, // leadership may have been changed away. Err(Error::StaleCommand) } @@ -2304,7 +2304,7 @@ mod tests { header.set_term(7); check_term(&header, 7).unwrap(); check_term(&header, 8).unwrap(); - // If header's term is 2 verions behind current term, + // If header's term is 2 versions behind current term, // leadership may have been changed away. check_term(&header, 9).unwrap_err(); check_term(&header, 10).unwrap_err(); diff --git a/components/raftstore/src/store/worker/read.rs b/components/raftstore/src/store/worker/read.rs index a1893bf8d93..4983694df52 100644 --- a/components/raftstore/src/store/worker/read.rs +++ b/components/raftstore/src/store/worker/read.rs @@ -1071,6 +1071,8 @@ where match self.pre_propose_raft_command(&req) { Ok(Some((mut delegate, policy))) => { if let Some(ref mut ctx) = snap_ctx { + ctx.region_id = delegate.region.id; + ctx.epoch_version = delegate.region.get_region_epoch().version; ctx.set_range(CacheRange::from_region(&delegate.region)) } @@ -1298,7 +1300,7 @@ mod tests { use crossbeam::channel::TrySendError; use engine_test::kv::{KvTestEngine, KvTestSnapshot}; - use engine_traits::{CacheRange, MiscExt, Peekable, SyncMutable, ALL_CFS}; + use engine_traits::{MiscExt, Peekable, SyncMutable, ALL_CFS}; use hybrid_engine::{HybridEngine, HybridEngineSnapshot}; use keys::DATA_PREFIX; use kvproto::{metapb::RegionEpoch, raft_cmdpb::*}; @@ -2546,11 +2548,10 @@ mod tests { }; let leader2 = prs[0].clone(); region1.set_region_epoch(epoch13.clone()); - let range = CacheRange::from_region(®ion1); - memory_engine.new_range(range.clone()); + memory_engine.new_region(region1.clone()); { let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range, 1); + core.mut_range_manager().set_safe_point(region1.id, 1); } let kv = (&[DATA_PREFIX, b'a'], b"b"); reader.kv_engine.put(kv.0, kv.1).unwrap(); @@ -2597,10 +2598,12 @@ mod tests { { let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(&range, 10); + core.mut_range_manager().set_safe_point(region1.id, 10); } let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: 15, range: None, }; @@ -2683,6 +2686,8 @@ mod tests { let snap_ctx = SnapshotContext { read_ts: 15, range: None, + region_id: 0, + epoch_version: 0, }; reader.propose_raft_command(Some(snap_ctx), read_id, task.request, task.callback); assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 5dcf5dcc832..f5996e72226 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::BTreeSet, fmt::Display, sync::Arc, thread::JoinHandle, time::Duration}; +use std::{collections::HashMap, fmt::Display, sync::Arc, thread::JoinHandle, time::Duration}; use bytes::Bytes; use crossbeam::{ @@ -12,6 +12,8 @@ use engine_traits::{ CacheRange, EvictReason, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, SnapshotMiscExt, CF_DEFAULT, CF_WRITE, DATA_CFS, }; +use hex::FromHexError; +use kvproto::metapb::Region; use parking_lot::RwLock; use pd_client::{PdClient, RpcClient}; use raftstore::coprocessor::RegionInfoProvider; @@ -37,10 +39,11 @@ use crate::{ GC_FILTERED_STATIC, RANGE_CACHE_COUNT, RANGE_CACHE_MEMORY_USAGE, RANGE_GC_TIME_HISTOGRAM, RANGE_LOAD_TIME_HISTOGRAM, }, - range_manager::LoadFailedReason, + range_manager::{RangeMeta, RegionState}, range_stats::{RangeStatsManager, DEFAULT_EVICT_MIN_DURATION}, region_label::{ - LabelRule, RegionLabelAddedCb, RegionLabelRulesManager, RegionLabelServiceBuilder, + KeyRangeRule, LabelRule, RegionLabelAddedCb, RegionLabelRulesManager, + RegionLabelServiceBuilder, }, write_batch::RangeCacheWriteBatchEntry, }; @@ -74,9 +77,9 @@ fn parse_write(value: &[u8]) -> Result, String> { #[derive(Debug)] pub enum BackgroundTask { Gc(GcTask), - LoadRange, + LoadRegion(Region, Arc), MemoryCheckAndEvict, - DeleteRange(Vec), + DeleteRegions(Vec), TopRegionsLoadEvict, CleanLockTombstone(u64), SetRocksEngine(RocksEngine), @@ -84,15 +87,15 @@ pub enum BackgroundTask { impl Display for BackgroundTask { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - BackgroundTask::Gc(ref t) => t.fmt(f), - BackgroundTask::LoadRange => f.debug_struct("LoadTask").finish(), + match &self { + BackgroundTask::Gc(t) => t.fmt(f), + BackgroundTask::LoadRegion(..) => f.debug_struct("LoadTask").finish(), BackgroundTask::MemoryCheckAndEvict => f.debug_struct("MemoryCheckAndEvict").finish(), - BackgroundTask::DeleteRange(ref r) => { - f.debug_struct("DeleteRange").field("range", r).finish() + BackgroundTask::DeleteRegions(r) => { + f.debug_struct("DeleteRegions").field("region", r).finish() } BackgroundTask::TopRegionsLoadEvict => f.debug_struct("CheckTopRegions").finish(), - BackgroundTask::CleanLockTombstone(ref r) => f + BackgroundTask::CleanLockTombstone(r) => f .debug_struct("CleanLockTombstone") .field("seqno", r) .finish(), @@ -121,9 +124,10 @@ impl Display for GcTask { pub struct BgWorkManager { worker: Worker, scheduler: Scheduler, - delete_range_scheduler: Scheduler, + delete_region_scheduler: Scheduler, tick_stopper: Option<(JoinHandle<()>, Sender)>, core: Arc>, + region_info_provider: Option>, } impl Drop for BgWorkManager { @@ -160,8 +164,14 @@ impl PdRangeHintService { /// label is removed or no longer set to always. pub fn start(&self, remote: Remote, range_manager_load_cb: F) where - F: Fn(&CacheRange) -> Result<(), LoadFailedReason> + Send + Sync + 'static, + F: Fn(&[u8], &[u8]) + Send + Sync + 'static, { + let parse_range = |key_range: &KeyRangeRule| { + let start = hex::decode(&key_range.start_key)?; + let end = hex::decode(&key_range.end_key)?; + Ok::<_, FromHexError>((start, end)) + }; + let pd_client = self.0.clone(); let region_label_added_cb: RegionLabelAddedCb = Arc::new(move |label_rule: &LabelRule| { if !label_rule @@ -173,12 +183,12 @@ impl PdRangeHintService { return; } for key_range in &label_rule.data { - match CacheRange::try_from(key_range) { - Ok(cache_range) => { - info!("Requested to cache range"; "cache_range" => ?&cache_range); - if let Err(reason) = range_manager_load_cb(&cache_range) { - error!("Cache range load failed"; "range" => ?&cache_range, "reason" => ?reason); - } + match parse_range(key_range) { + Ok((start, end)) => { + info!("Requested to cache range"; + "start" => ?log_wrappers::Value(&start), + "end" => ?log_wrappers::Value(&end)); + range_manager_load_cb(&start, &end); } Err(e) => { error!("Unable to convert key_range rule to cache range"; "err" => ?e); @@ -219,7 +229,7 @@ impl BgWorkManager { let (runner, delete_range_scheduler) = BackgroundRunner::new( core.clone(), memory_controller, - region_info_provider, + region_info_provider.clone(), expected_region_size, gc_interval, pd_client.clone(), @@ -236,16 +246,17 @@ impl BgWorkManager { Self { worker, scheduler, - delete_range_scheduler, + delete_region_scheduler: delete_range_scheduler, tick_stopper: Some((h, tx)), core, + region_info_provider, } } pub fn schedule_task(&self, task: BackgroundTask) -> Result<(), ScheduleError> { match task { - task @ BackgroundTask::DeleteRange(_) => { - self.delete_range_scheduler.schedule_force(task) + task @ BackgroundTask::DeleteRegions(_) => { + self.delete_region_scheduler.schedule_force(task) } task => self.scheduler.schedule_force(task), } @@ -253,13 +264,39 @@ impl BgWorkManager { pub fn start_bg_hint_service(&self, range_hint_service: PdRangeHintService) { let core = self.core.clone(); - range_hint_service.start(self.worker.remote(), move |cache_range: &CacheRange| { + let region_info_provider = self.region_info_provider.clone(); + range_hint_service.start(self.worker.remote(), move |start: &[u8], end: &[u8]| { + let Some(ref info_provider) = region_info_provider else { + warn!("[IME] region info provider is none, skip load pinned range."); + return; + }; + + let regions = match info_provider.get_regions_in_range(start, end) { + Ok(r) => r, + Err(e) => { + warn!( + "get regions in range failed"; "err" => ?e, + "start" => ?log_wrappers::Value(start), + "end" => ?log_wrappers::Value(end) + ); + return; + } + }; + + if regions.is_empty() { + return; + } + let mut engine = core.write(); - engine.mut_range_manager().load_range(cache_range.clone())?; - // TODO (afeinberg): This does not actually load the range. The load happens - // the apply thread begins to apply raft entries. To force this (for read-only - // use-cases) we should propose a No-Op command. - Ok(()) + for r in regions { + if let Err(e) = engine.mut_range_manager().load_region(r.clone()) { + warn!("load region by label failed"; "err" => ?e, "region" => ?r); + } + } + // TODO (afeinberg): This does not actually load the range. The load + // happens the apply thread begins to apply raft + // entries. To force this (for read-only use-cases) we + // should propose a No-Op command. }); } @@ -333,58 +370,63 @@ struct BackgroundRunnerCore { impl BackgroundRunnerCore { /// Returns the ranges that are eligible for garbage collection. /// - /// Returns `None` if there are no ranges cached or the previous gc is not - /// finished. - fn ranges_for_gc(&self) -> Option> { - let ranges: BTreeSet = { - let core = self.engine.read(); - if core.range_manager().has_ranges_in_gc() { - return None; - } - core.range_manager().ranges().keys().cloned().collect() - }; - let ranges_clone = ranges.clone(); - if ranges_clone.is_empty() { - return None; - } - { - let mut core = self.engine.write(); - core.mut_range_manager().set_ranges_in_gc(ranges_clone); + /// Returns empty vector if there are no ranges cached or the previous gc is + /// not finished. + fn regions_for_gc(&self) -> Vec { + let core = self.engine.read(); + // another gc task is running, skipped. + if !core.range_manager().try_set_regions_in_gc(true) { + return vec![]; } - Some(ranges) + + core.range_manager() + .regions() + .values() + .filter_map(|m| { + if m.get_state() == RegionState::Active { + Some(m.region().clone()) + } else { + None + } + }) + .collect() } - fn gc_range(&self, range: &CacheRange, safe_point: u64, oldest_seqno: u64) -> FilterMetrics { + pub(crate) fn gc_region( + &self, + region: &Region, + safe_point: u64, + oldest_seqno: u64, + ) -> FilterMetrics { + let range = CacheRange::from_region(region); let (skiplist_engine, safe_point) = { let mut core = self.engine.write(); // We should also consider the ongoing snapshot of the historical ranges (ranges // that have been evicted). let historical_safe_point = core .range_manager() - .historical_ranges() - .iter() - .find_map(|(r, m)| { - if r.contains_range(range) { - m.range_snapshot_list().min_snapshot_ts() - } else { - None - } - }) + .get_history_regions_min_ts(&range) .unwrap_or(u64::MAX); - let Some(range_meta) = core.mut_range_manager().mut_range_meta(range) else { + + let Some(region_meta) = core.mut_range_manager().mut_region_meta(region.id) else { return FilterMetrics::default(); }; - let min_snapshot = range_meta - .range_snapshot_list() + + if region_meta.get_state() != RegionState::Active + || !range.contains_range(region_meta.get_range()) + { + return FilterMetrics::default(); + } + + let min_snapshot = region_meta + .region_snapshot_list() .min_snapshot_ts() .unwrap_or(u64::MAX); - let safe_point = u64::min(safe_point, min_snapshot); - let safe_point = u64::min(safe_point, historical_safe_point); - - if safe_point <= range_meta.safe_point() { + let safe_point = safe_point.min(min_snapshot).min(historical_safe_point); + if safe_point <= region_meta.safe_point() { info!( "safe point not large enough"; - "prev" => range_meta.safe_point(), + "prev" => region_meta.safe_point(), "current" => safe_point, ); return FilterMetrics::default(); @@ -393,11 +435,12 @@ impl BackgroundRunnerCore { // todo: change it to debug! info!( "safe point update"; - "prev" => range_meta.safe_point(), + "prev" => region_meta.safe_point(), "current" => safe_point, "range" => ?range, ); - range_meta.set_safe_point(safe_point); + region_meta.set_safe_point(safe_point); + region_meta.set_in_gc(true); (core.engine(), safe_point) }; @@ -408,7 +451,12 @@ impl BackgroundRunnerCore { skiplist_engine.cf_handle(CF_DEFAULT), skiplist_engine.cf_handle(CF_WRITE), ); - filter.filter_keys_in_range(range); + filter.filter_keys_in_range(&range); + + { + let mut engine = self.engine.write(); + engine.mut_range_manager().on_gc_region_finished(region); + } let duration = start.saturating_elapsed(); RANGE_GC_TIME_HISTOGRAM.observe(duration.as_secs_f64()); @@ -434,133 +482,117 @@ impl BackgroundRunnerCore { metrics } - fn on_gc_finished(&mut self, ranges: BTreeSet) { - let mut core = self.engine.write(); - core.mut_range_manager().on_gc_finished(ranges); - } - - /// Returns the first range to load with RocksDB snapshot. The `bool` - /// returned indicates whether the task has been canceled due to memory - /// issue. - /// - /// Returns `None` if there are no ranges to load. - fn get_range_to_load(&self) -> Option<(CacheRange, Arc, bool)> { - let core = self.engine.read(); - core.range_manager() - .pending_ranges_loading_data - .front() - .cloned() + fn on_gc_finished(&self) { + let success = self + .engine + .read() + .range_manager() + .try_set_regions_in_gc(false); + assert!(success); } // if `false` is returned, the load is canceled fn on_snapshot_load_finished( - &mut self, - range: CacheRange, + &self, + region: &Region, delete_range_scheduler: &Scheduler, safe_point: u64, ) -> bool { fail::fail_point!("on_snapshot_load_finished"); fail::fail_point!("on_snapshot_load_finished2"); - loop { - // Consume the cached write batch after the snapshot is acquired. - let mut core = self.engine.write(); - // We still need to check whether the snapshot is canceled during the load - let canceled = core - .range_manager() - .pending_ranges_loading_data - .front() - .unwrap() - .2; - if canceled { - let (r, ..) = core - .mut_range_manager() - .pending_ranges_loading_data - .pop_front() - .unwrap(); - assert_eq!(r, range); - core.mut_range_manager() - .ranges_being_deleted - .insert(r.clone(), (true, Instant::now(), EvictReason::LoadFailed)); - core.remove_cached_write_batch(&range); - drop(core); - fail::fail_point!("in_memory_engine_snapshot_load_canceled"); - - if let Err(e) = - delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(vec![r])) - { - error!( - "schedule delete range failed"; - "err" => ?e, - ); - assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); - } - - return false; + // Consume the cached write batch after the snapshot is acquired. + let mut core = self.engine.write(); + // We still need to check whether the snapshot is canceled during the load + let region_meta = core.mut_range_manager().mut_region_meta(region.id).unwrap(); + let mut remove_regions = vec![]; + let mut on_region_meta = |meta: &mut RangeMeta| { + assert!( + meta.get_state() == RegionState::Loading + || meta.get_state() == RegionState::LoadingCanceled, + "region meta: {:?}", + meta, + ); + if meta.get_state() == RegionState::Loading { + meta.set_state(RegionState::Active); + meta.set_safe_point(safe_point); + } else { + assert_eq!(meta.get_state(), RegionState::LoadingCanceled); + meta.mark_evict(RegionState::Evicting, EvictReason::LoadFailed); + remove_regions.push(meta.region().clone()); } + }; - if core.has_cached_write_batch(&range) { - let (cache_batch, skiplist_engine) = { - ( - core.take_cached_write_batch_entries(&range), - core.engine().clone(), - ) - }; - drop(core); - let guard = &epoch::pin(); - for (seq, entry) in cache_batch { - entry - .write_to_memory( - seq, - &skiplist_engine, - self.memory_controller.clone(), - guard, - ) - .unwrap(); - } - fail::fail_point!("on_cached_write_batch_consumed"); - } else { - core.remove_cached_write_batch(&range); - RangeCacheMemoryEngineCore::pending_range_completes_loading( - &mut core, &range, safe_point, - ); - drop(core); + if region_meta.region().get_region_epoch().version == region.get_region_epoch().version { + on_region_meta(region_meta); + } else { + // epoch version changed, should use scan to find all overlapped regions + let range = CacheRange::from_region(region); + core.range_manager + .iter_overlapped_regions_mut(&range, |meta| { + assert!(range.contains_range(meta.get_range())); + on_region_meta(meta); + }); + } + drop(core); - fail::fail_point!("pending_range_completes_loading"); - break; + if !remove_regions.is_empty() { + fail::fail_point!("in_memory_engine_snapshot_load_canceled"); + + if let Err(e) = + delete_range_scheduler.schedule_force(BackgroundTask::DeleteRegions(remove_regions)) + { + error!( + "schedule delete range failed"; + "err" => ?e, + ); + assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } + + return false; } + + fail::fail_point!("on_completes_batch_loading"); true } - // `start` means whether to start to load keys fn on_snapshot_load_failed( - &mut self, - range: CacheRange, + &self, + region: &Region, delete_range_scheduler: &Scheduler, started: bool, ) { let mut core = self.engine.write(); - let (r, ..) = core - .mut_range_manager() - .pending_ranges_loading_data - .pop_front() - .unwrap(); - assert_eq!(r, range); - core.remove_cached_write_batch(&range); - core.mut_range_manager().ranges_being_deleted.insert( - r.clone(), - ( - true, - Instant::now(), - if !started { - EvictReason::LoadFailedWithoutStart - } else { - EvictReason::LoadFailed - }, - ), - ); + let region_meta = core.range_manager.mut_region_meta(region.id).unwrap(); + let mut remove_regions = vec![]; + + let mut mark_region_evicted = |meta: &mut RangeMeta| { + assert!( + meta.get_state() == RegionState::Loading + || meta.get_state() == RegionState::LoadingCanceled + ); + let reason = if started { + EvictReason::LoadFailed + } else { + EvictReason::LoadFailedWithoutStart + }; + meta.mark_evict(RegionState::Evicting, reason); + remove_regions.push(meta.region().clone()); + }; - if let Err(e) = delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(vec![r])) + if region_meta.region().get_region_epoch().version == region.get_region_epoch().version { + mark_region_evicted(region_meta); + } else { + // epoch version changed, should use scan to find all overlap regions + let range = CacheRange::from_region(region); + core.range_manager + .iter_overlapped_regions_mut(&range, |meta| { + assert!(range.contains_range(meta.get_range())); + mark_region_evicted(meta); + }); + } + + if let Err(e) = + delete_range_scheduler.schedule_force(BackgroundTask::DeleteRegions(remove_regions)) { error!( "schedule delete range failed"; @@ -582,63 +614,53 @@ impl BackgroundRunnerCore { return; } let range_stats_manager = self.range_stats_manager.as_ref().unwrap(); - let to_shrink_by = self + let mut remaining = self .memory_controller .mem_usage() - .checked_sub(self.memory_controller.soft_limit_threshold()); - if to_shrink_by.is_none() { + .saturating_sub(self.memory_controller.soft_limit_threshold()); + if remaining == 0 { return; } - let mut remaining = to_shrink_by.unwrap(); - let mut ranges_to_evict = Vec::<(CacheRange, u64)>::with_capacity(256); + + let mut regions_to_evict = Vec::with_capacity(256); // TODO (afeinberg, low): consider returning just an iterator and using scan // below for cleaner code. - range_stats_manager.collect_candidates_for_eviction(&mut ranges_to_evict, |range| { - self.engine.read().range_manager().contains_range(range) + range_stats_manager.collect_candidates_for_eviction(&mut regions_to_evict, |region| { + self.engine + .read() + .range_manager() + .contains_region(region.id) }); - let mut ranges_to_delete = vec![]; + let mut regions_to_delete = vec![]; // TODO (afeinberg): approximate size may differ from size in in-memory cache, // consider taking the actual size into account. - for (range, approx_size) in &ranges_to_evict { + for (region, approx_size) in regions_to_evict { if remaining == 0 { break; } - let evicted_range = { - let mut engine_wr = self.engine.write(); - let mut ranges = engine_wr - .mut_range_manager() - .evict_range(range, EvictReason::MemoryLimitReached); - if !ranges.is_empty() { - info!( - "evict on soft limit reached"; - "range_to_evict" => ?&range, - "ranges_evicted" => ?ranges, - "approx_size" => approx_size, - "remaining" => remaining - ); - remaining = remaining - .checked_sub(*approx_size as usize) - .unwrap_or_default(); - ranges_to_delete.append(&mut ranges); - true - } else { - false - } - }; - if evicted_range { - range_stats_manager.handle_range_evicted(range); + let mut engine_wr = self.engine.write(); + let deleteable_regions = engine_wr + .mut_range_manager() + .evict_region(®ion, EvictReason::MemoryLimitReached); + if !deleteable_regions.is_empty() { + info!( + "evict on soft limit reached"; + "region_to_evict" => ?region, + "regions_evicted" => ?&deleteable_regions, + "approx_size" => approx_size, + "remaining" => remaining + ); + remaining = remaining.saturating_sub(approx_size as usize); + range_stats_manager.handle_region_evicted(®ion); + regions_to_delete.extend(deleteable_regions); } } - self.engine - .write() - .mut_range_manager() - .mark_delete_ranges_scheduled(&mut ranges_to_delete); - if !ranges_to_delete.is_empty() { - if let Err(e) = - delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(ranges_to_delete)) + if !regions_to_delete.is_empty() { + if let Err(e) = delete_range_scheduler + .schedule_force(BackgroundTask::DeleteRegions(regions_to_delete)) { error!( "schedule deletet range failed"; @@ -657,47 +679,43 @@ impl BackgroundRunnerCore { /// See: [`RangeStatsManager::collect_changes_ranges`] for /// algorithm details. fn top_regions_load_evict(&self, delete_range_scheduler: &Scheduler) { - if self.range_stats_manager.is_none() { - return; - } - let range_stats_manager: &RangeStatsManager = self.range_stats_manager.as_ref().unwrap(); - if range_stats_manager.checking_top_regions() { + let range_stats_manager = match &self.range_stats_manager { + Some(m) => m, + None => { + return; + } + }; + if range_stats_manager.set_checking_top_regions(true) { return; } - range_stats_manager.set_checking_top_regions(true); let curr_memory_usage = self.memory_controller.mem_usage(); let threshold = self.memory_controller.soft_limit_threshold(); range_stats_manager.adjust_max_num_regions(curr_memory_usage, threshold); - let mut ranges_to_add = Vec::::with_capacity(256); - let mut ranges_to_remove = Vec::::with_capacity(256); - range_stats_manager.collect_changed_ranges(&mut ranges_to_add, &mut ranges_to_remove); - let mut ranges_to_delete = vec![]; - info!("load_evict"; "ranges_to_add" => ?&ranges_to_add, "may_evict" => ?&ranges_to_remove); - for evict_range in ranges_to_remove { + let mut regions_to_add = Vec::with_capacity(256); + let mut regions_to_remove = Vec::with_capacity(256); + range_stats_manager.collect_changed_ranges(&mut regions_to_add, &mut regions_to_remove); + let mut regions_to_delete = Vec::with_capacity(regions_to_remove.len()); + info!("load_evict"; "ranges_to_add" => ?®ions_to_add, "may_evict" => ?®ions_to_remove); + for evict_region in regions_to_remove { if self.memory_controller.reached_soft_limit() { let mut core = self.engine.write(); - let mut ranges = core + let deleteable_regions = core .mut_range_manager() - .evict_range(&evict_range, EvictReason::AutoEvict); + .evict_region(&evict_region, EvictReason::AutoEvict); info!( "load_evict: soft limit reached"; - "range_to_evict" => ?&evict_range, - "ranges_evicted" => ?ranges + "region_to_evict" => ?&evict_region, + "evicted_regions" => ?&deleteable_regions, ); - ranges_to_delete.append(&mut ranges); + regions_to_delete.extend(deleteable_regions); } } - self.engine - .write() - .mut_range_manager() - .mark_delete_ranges_scheduled(&mut ranges_to_delete); - - if !ranges_to_delete.is_empty() { - if let Err(e) = - delete_range_scheduler.schedule_force(BackgroundTask::DeleteRange(ranges_to_delete)) + if !regions_to_delete.is_empty() { + if let Err(e) = delete_range_scheduler + .schedule_force(BackgroundTask::DeleteRegions(regions_to_delete)) { error!( "schedule deletet range failed"; @@ -706,10 +724,10 @@ impl BackgroundRunnerCore { assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } } - for cache_range in ranges_to_add { + for region in regions_to_add { let mut core = self.engine.write(); - if let Err(e) = core.mut_range_manager().load_range(cache_range.clone()) { - error!("error loading range"; "cache_range" => ?&cache_range, "err" => ?e); + if let Err(e) = core.mut_range_manager().load_region(region.clone()) { + error!("error loading range"; "cache_range" => ?region, "err" => ?e); } } range_stats_manager.set_checking_top_regions(false); @@ -877,166 +895,182 @@ impl Runnable for BackgroundRunner { "safe_point" => t.safe_point, "oldest_sequence" => seqno, ); - let mut core = self.core.clone(); - if let Some(ranges) = core.ranges_for_gc() { + let core = self.core.clone(); + let regions = core.regions_for_gc(); + if !regions.is_empty() { let f = async move { let mut metrics = FilterMetrics::default(); - for range in &ranges { - let m = core.gc_range(range, t.safe_point, seqno); + for region in ®ions { + let m = core.gc_region(region, t.safe_point, seqno); metrics.merge(&m); } - core.on_gc_finished(ranges); + core.on_gc_finished(); metrics.flush(); fail::fail_point!("in_memory_engine_gc_finish"); }; self.gc_range_remote.spawn(f); + } else { + core.on_gc_finished(); } } - BackgroundTask::LoadRange => { - let mut core = self.core.clone(); + BackgroundTask::LoadRegion(region, snapshot) => { + let core = self.core.clone(); let delete_range_scheduler = self.delete_range_scheduler.clone(); let pd_client = self.pd_client.clone(); let gc_interval = self.gc_interval; let f = async move { + fail::fail_point!("on_start_loading_region"); + let mut is_canceled = false; + let region_range = CacheRange::from_region(®ion); let skiplist_engine = { - let core = core.engine.read(); - core.engine().clone() + let mut engine = core.engine.write(); + let region_meta = engine + .mut_range_manager() + .mut_region_meta(region.id) + .unwrap(); + // if loading is canceled, we skip the batch load. + // NOTE: here we don't check the region epoch version change, + // We will handle possible region split and partial cancelation + // in `on_snapshot_load_canceled` and `on_snapshot_load_finished`. + if region_meta.get_state() != RegionState::ReadyToLoad { + assert_eq!(region_meta.get_state(), RegionState::LoadingCanceled); + is_canceled = true; + } else { + region_meta.set_state(RegionState::Loading); + } + + engine.engine.clone() }; - while let Some((range, snap, mut canceled)) = core.get_range_to_load() { - info!("Loading range"; "range" => ?&range); - let iter_opt = IterOptions::new( - Some(KeyBuilder::from_vec(range.start.clone(), 0, 0)), - Some(KeyBuilder::from_vec(range.end.clone(), 0, 0)), - false, + + if core.memory_controller.reached_soft_limit() { + // We are running out of memory, so cancel the load. + is_canceled = true; + } + + if is_canceled { + info!( + "snapshot load canceled"; + "region" => ?region, ); - if core.memory_controller.reached_soft_limit() { - // We are running out of memory, so cancel the load. - canceled = true; - } + core.on_snapshot_load_failed(®ion, &delete_range_scheduler, false); + return; + } - if canceled { - info!( - "snapshot load canceled due to memory reaching soft limit"; - "range" => ?range, - ); - core.on_snapshot_load_failed(range, &delete_range_scheduler, false); - continue; - } + info!("Loading region"; "region" => ?®ion); + let start = Instant::now(); + let iter_opt = IterOptions::new( + Some(KeyBuilder::from_slice(®ion_range.start, 0, 0)), + Some(KeyBuilder::from_slice(®ion_range.end, 0, 0)), + false, + ); - let snapshot_load = || -> Option { - for &cf in DATA_CFS { - let handle = skiplist_engine.cf_handle(cf); - let seq = snap.sequence_number(); - let guard = &epoch::pin(); - match snap.iterator_opt(cf, iter_opt.clone()) { - Ok(mut iter) => { - iter.seek_to_first().unwrap(); - while iter.valid().unwrap() { - // use the sequence number from RocksDB snapshot here as - // the kv is clearly visible - let mut encoded_key = - encode_key(iter.key(), seq, ValueType::Value); - let mut val = - InternalBytes::from_vec(iter.value().to_vec()); - - let mem_size = - RangeCacheWriteBatchEntry::calc_put_entry_size( - iter.key(), - val.as_bytes(), - ); - - // todo(SpadeA): we can batch acquire the memory size - // here. - if let MemoryUsage::HardLimitReached(n) = - core.memory_controller.acquire(mem_size) - { - warn!( - "stop loading snapshot due to memory reaching hard limit"; - "range" => ?range, - "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), - ); - return None; - } - - encoded_key.set_memory_controller( - core.memory_controller.clone(), + let safe_point = 'load_snapshot: { + for &cf in DATA_CFS { + let handle = skiplist_engine.cf_handle(cf); + let seq = snapshot.sequence_number(); + let guard = &epoch::pin(); + match snapshot.iterator_opt(cf, iter_opt.clone()) { + Ok(mut iter) => { + iter.seek_to_first().unwrap(); + while iter.valid().unwrap() { + // use the sequence number from RocksDB snapshot here as + // the kv is clearly visible + let mut encoded_key = + encode_key(iter.key(), seq, ValueType::Value); + let mut val = + InternalBytes::from_vec(iter.value().to_vec()); + + let mem_size = + RangeCacheWriteBatchEntry::calc_put_entry_size( + iter.key(), + val.as_bytes(), ); - val.set_memory_controller( - core.memory_controller.clone(), + + // todo(SpadeA): we can batch acquire the memory size + // here. + if let MemoryUsage::HardLimitReached(n) = + core.memory_controller.acquire(mem_size) + { + warn!( + "stop loading snapshot due to memory reaching hard limit"; + "region" => ?region, + "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), ); - handle.insert(encoded_key, val, guard); - iter.next().unwrap(); + break 'load_snapshot None; } - } - Err(e) => { - error!("creating rocksdb iterator failed"; "cf" => cf, "err" => %e); - return None; + + encoded_key + .set_memory_controller(core.memory_controller.clone()); + val.set_memory_controller(core.memory_controller.clone()); + handle.insert(encoded_key, val, guard); + iter.next().unwrap(); } } + Err(e) => { + error!("creating rocksdb iterator failed"; "cf" => cf, "err" => %e); + break 'load_snapshot None; + } + } + } + // gc the range + let tso_timeout = std::cmp::min(gc_interval, TIMTOUT_FOR_TSO); + let now = match block_on_timeout(pd_client.get_tso(), tso_timeout) { + Ok(Ok(ts)) => ts, + err => { + error!( + "get timestamp failed, skip gc loaded range"; + "timeout_duration" => ?tso_timeout, + "error" => ?err, + ); + // Get timestamp fail so don't do gc. + break 'load_snapshot Some(0); } + }; - // gc the range - let tso_timeout = std::cmp::min(gc_interval, TIMTOUT_FOR_TSO); - let now = match block_on_timeout(pd_client.get_tso(), tso_timeout) { - Ok(Ok(ts)) => ts, - err => { - error!( - "get timestamp failed, skip gc loaded range"; - "timeout_duration" => ?tso_timeout, - "error" => ?err, - ); - // Get timestamp fail so don't do gc. - return Some(0); - } - }; - - let safe_point = (|| { - fail::fail_point!("in_memory_engine_safe_point_in_loading", |t| { - t.unwrap().parse::().unwrap() - }); - - let safe_point = now - .physical() - .saturating_sub(gc_interval.as_millis() as u64); - TimeStamp::compose(safe_point, 0).into_inner() - })(); - - let mut filter = Filter::new( - safe_point, - u64::MAX, - skiplist_engine.cf_handle(CF_DEFAULT), - skiplist_engine.cf_handle(CF_WRITE), - ); - filter.filter_keys_in_range(&range); + let safe_point = (|| { + fail::fail_point!("in_memory_engine_safe_point_in_loading", |t| { + t.unwrap().parse::().unwrap() + }); + + let safe_point = now + .physical() + .saturating_sub(gc_interval.as_millis() as u64); + TimeStamp::compose(safe_point, 0).into_inner() + })(); + + let mut filter = Filter::new( + safe_point, + u64::MAX, + skiplist_engine.cf_handle(CF_DEFAULT), + skiplist_engine.cf_handle(CF_WRITE), + ); + filter.filter_keys_in_range(®ion_range); - Some(safe_point) - }; + Some(safe_point) + }; - let start = Instant::now(); - if let Some(safe_point) = snapshot_load() { - if core.on_snapshot_load_finished( - range.clone(), - &delete_range_scheduler, - safe_point, - ) { - let duration = start.saturating_elapsed(); - RANGE_LOAD_TIME_HISTOGRAM.observe(duration.as_secs_f64()); - info!( - "Loading range finished"; - "range" => ?range, - "duration(sec)" => ?duration, - ); - } else { - info!("Loading range canceled";"range" => ?range); - } - } else { + if let Some(safe_point) = safe_point { + if core.on_snapshot_load_finished( + ®ion, + &delete_range_scheduler, + safe_point, + ) { + let duration = start.saturating_elapsed(); + RANGE_LOAD_TIME_HISTOGRAM.observe(duration.as_secs_f64()); info!( - "snapshot load failed"; - "range" => ?range, + "Loading region finished"; + "region" => ?region, + "duration(sec)" => ?duration, ); - core.on_snapshot_load_failed(range, &delete_range_scheduler, true); - continue; + } else { + info!("Loading region canceled";"region" => ?region); } + } else { + info!( + "snapshot load failed"; + "region" => ?region, + ); + core.on_snapshot_load_failed(®ion, &delete_range_scheduler, true); } }; self.range_load_remote.spawn(f); @@ -1061,7 +1095,7 @@ impl Runnable for BackgroundRunner { } // DeleteRange task is executed by `DeleteRangeRunner` with a different scheduler so // that the task will not be scheduled to here. - BackgroundTask::DeleteRange(_) => unreachable!(), + BackgroundTask::DeleteRegions(_) => unreachable!(), BackgroundTask::TopRegionsLoadEvict => { let delete_range_scheduler = self.delete_range_scheduler.clone(); let core = self.core.clone(); @@ -1156,15 +1190,16 @@ impl RunnableWithTimer for BackgroundRunner { RANGE_CACHE_MEMORY_USAGE.set(mem_usage as i64); let core = self.core.engine.read(); - let pending = core.range_manager.pending_ranges.len(); - let cached = core.range_manager.ranges().len(); + let mut count_by_state = HashMap::new(); + for m in core.range_manager.regions().values() { + *count_by_state.entry(m.get_state()).or_default() += 1; + } drop(core); - RANGE_CACHE_COUNT - .with_label_values(&["pending_range"]) - .set(pending as i64); - RANGE_CACHE_COUNT - .with_label_values(&["cached_range"]) - .set(cached as i64); + for (state, count) in count_by_state { + RANGE_CACHE_COUNT + .with_label_values(&[state.as_str()]) + .set(count); + } } fn get_interval(&self) -> Duration { @@ -1178,26 +1213,27 @@ pub struct DeleteRangeRunner { // written by apply threads. In that case, we have to delay the delete range task to avoid race // condition between them. Periodically, these delayed ranges will be checked to see if it is // ready to be deleted. - delay_ranges: Vec, + delay_regions: Vec, } impl DeleteRangeRunner { fn new(engine: Arc>) -> Self { Self { engine, - delay_ranges: vec![], + delay_regions: vec![], } } - fn delete_ranges(&mut self, ranges: &[CacheRange]) { + fn delete_regions(&mut self, regions: &[Region]) { let skiplist_engine = self.engine.read().engine(); - for r in ranges { - skiplist_engine.delete_range(r); + for r in regions { + let range = CacheRange::from_region(r); + skiplist_engine.delete_range(&range); } self.engine .write() .mut_range_manager() - .on_delete_ranges(ranges); + .on_delete_regions(regions); fail::fail_point!("in_memory_engine_delete_range_done"); @@ -1210,41 +1246,36 @@ impl Runnable for DeleteRangeRunner { type Task = BackgroundTask; fn run(&mut self, task: Self::Task) { match task { - BackgroundTask::DeleteRange(ranges) => { + BackgroundTask::DeleteRegions(regions) => { fail::fail_point!("on_in_memory_engine_delete_range"); - let (mut ranges_to_delay, ranges_to_delete) = { - let core = self.engine.read(); - let mut ranges_to_delay = vec![]; - let mut ranges_to_delete = vec![]; - for r in ranges { - // Check whether range exists in `ranges_being_deleted` and it's scheduled - if !core.range_manager.ranges_being_deleted.iter().any( - |(range_being_delete, &(scheduled, ..))| { - if range_being_delete == &r && !scheduled { - panic!("range to delete with scheduled false; range={:?}", r,); - }; - range_being_delete == &r - }, - ) { - panic!("range to delete not in ranges_being_deleted; range={:?}", r,); - } - + let (mut regions_to_delay, regions_to_delete) = { + let core = self.engine.write(); + let mut regions_to_delay = vec![]; + let mut regions_to_delete = vec![]; + for r in regions { + let region_meta = core.range_manager.region_meta(r.id).unwrap(); + assert_eq!( + region_meta.region().get_region_epoch().version, + r.get_region_epoch().version + ); + assert_eq!(region_meta.get_state(), RegionState::Evicting); // If the range is overlapped with ranges in `ranges_being_written`, the // range has to be delayed to delete. See comment on `delay_ranges`. - if core - .range_manager - .is_overlapped_with_ranges_being_written(&r) + if region_meta.is_in_gc() + || core + .range_manager + .is_overlapped_with_regions_being_written(region_meta.get_range()) { - ranges_to_delay.push(r); + regions_to_delay.push(r); } else { - ranges_to_delete.push(r); + regions_to_delete.push(r); } } - (ranges_to_delay, ranges_to_delete) + (regions_to_delay, regions_to_delete) }; - self.delay_ranges.append(&mut ranges_to_delay); - if !ranges_to_delete.is_empty() { - self.delete_ranges(&ranges_to_delete); + self.delay_regions.append(&mut regions_to_delay); + if !regions_to_delete.is_empty() { + self.delete_regions(®ions_to_delete); } } _ => unreachable!(), @@ -1254,11 +1285,11 @@ impl Runnable for DeleteRangeRunner { impl RunnableWithTimer for DeleteRangeRunner { fn on_timeout(&mut self) { - if self.delay_ranges.is_empty() { + if self.delay_regions.is_empty() { return; } - let ranges = std::mem::take(&mut self.delay_ranges); - self.run(BackgroundTask::DeleteRange(ranges)); + let regions = std::mem::take(&mut self.delay_regions); + self.run(BackgroundTask::DeleteRegions(regions)); } fn get_interval(&self) -> Duration { @@ -1518,8 +1549,8 @@ pub mod tests { use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, IterOptions, Iterable, Iterator, RangeCacheEngine, SyncMutable, CF_DEFAULT, - CF_LOCK, CF_WRITE, DATA_CFS, + CacheRange, IterOptions, Iterable, Iterator, RangeCacheEngine, RegionEvent, SyncMutable, + CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use futures::future::ready; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; @@ -1538,15 +1569,16 @@ pub mod tests { config::RangeCacheConfigManager, engine::{SkiplistEngine, SkiplistHandle}, keys::{ - construct_key, construct_user_key, construct_value, encode_key, encode_seek_key, + construct_key, construct_region_key, construct_value, encode_key, encode_seek_key, encoding_for_filter, InternalBytes, ValueType, }, memory_controller::MemoryController, + range_manager::RegionState::*, region_label::{ region_label_meta_client, tests::{add_region_label_rule, new_region_label_rule, new_test_server_and_client}, }, - test_util::{put_data, put_data_with_overwrite}, + test_util::{new_region, put_data, put_data_with_overwrite}, write_batch::RangeCacheWriteBatchEntry, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, }; @@ -1558,7 +1590,8 @@ pub mod tests { write_cf: &SkiplistHandle, mem_controller: Arc, ) { - let raw_write_k = Key::from_raw(key) + let key = data_key(key); + let raw_write_k = Key::from_raw(&key) .append_ts(TimeStamp::new(ts)) .into_encoded(); let mut write_k = encode_key(&raw_write_k, seq_num, ValueType::Value); @@ -1581,7 +1614,8 @@ pub mod tests { write_cf: &SkiplistHandle, mem_controller: Arc, ) { - let raw_write_k = Key::from_raw(key) + let key = data_key(key); + let raw_write_k = Key::from_raw(&key) .append_ts(TimeStamp::new(ts)) .into_encoded(); let mut write_k = encode_key(&raw_write_k, seq_num, ValueType::Value); @@ -1644,7 +1678,8 @@ pub mod tests { } fn encode_raw_key_for_filter(key: &[u8], ts: TimeStamp) -> InternalBytes { - let key = Key::from_raw(key); + let key = data_key(key); + let key = Key::from_raw(&key); encoding_for_filter(key.as_encoded(), ts) } @@ -1789,8 +1824,10 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); + let (write, default) = { let skiplist_engine = engine.core().write().engine(); ( @@ -1813,7 +1850,7 @@ pub mod tests { // Delete the above key let guard = &epoch::pin(); - let raw_write_k = Key::from_raw(b"key1") + let raw_write_k = Key::from_raw(&data_key(b"key1")) .append_ts(TimeStamp::new(15)) .into_encoded(); let mut write_k = encode_key(&raw_write_k, 15, ValueType::Deletion); @@ -1835,7 +1872,7 @@ pub mod tests { ); // Delete the above key - let raw_write_k = Key::from_raw(b"key2") + let raw_write_k = Key::from_raw(&data_key(b"key2")) .append_ts(TimeStamp::new(25)) .into_encoded(); let mut write_k = encode_key(&raw_write_k, 15, ValueType::Deletion); @@ -1857,7 +1894,9 @@ pub mod tests { ); delete_data(b"key2", 40, 18, &write, memory_controller.clone()); - let snap = engine.snapshot(range.clone(), u64::MAX, u64::MAX).unwrap(); + let snap = engine + .snapshot(1, 0, range.clone(), u64::MAX, u64::MAX) + .unwrap(); let mut iter_opts = IterOptions::default(); iter_opts.set_lower_bound(&range.start, 0); iter_opts.set_upper_bound(&range.end, 0); @@ -1870,7 +1909,7 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - worker.core.gc_range(&range, 40, 100); + worker.core.gc_region(®ion, 40, 100); let mut iter = snap.iterator_opt("write", iter_opts).unwrap(); iter.seek_to_first().unwrap(); @@ -1887,8 +1926,8 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + engine.new_region(region.clone()); let (write, default) = { let skiplist_engine = engine.core().write().engine(); ( @@ -1898,7 +1937,8 @@ pub mod tests { }; let encode_key = |key, ts| { - let key = Key::from_raw(key); + let data_key = data_key(key); + let key = Key::from_raw(&data_key); encoding_for_filter(key.as_encoded(), ts) }; @@ -1948,22 +1988,22 @@ pub mod tests { ); // gc should not hanlde keys with larger seqno than oldest seqno - worker.core.gc_range(&range, 13, 10); + worker.core.gc_region(®ion, 13, 10); assert_eq!(3, element_count(&default)); assert_eq!(3, element_count(&write)); // gc will not remove the latest mvcc put below safe point - worker.core.gc_range(&range, 14, 100); + worker.core.gc_region(®ion, 14, 100); assert_eq!(2, element_count(&default)); assert_eq!(2, element_count(&write)); - worker.core.gc_range(&range, 16, 100); + worker.core.gc_region(®ion, 16, 100); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); // rollback will not make the first older version be filtered rollback_data(b"key1", 17, 16, &write, memory_controller.clone()); - worker.core.gc_range(&range, 17, 100); + worker.core.gc_region(®ion, 17, 100); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); let key = encode_key(b"key1", TimeStamp::new(15)); @@ -1975,7 +2015,7 @@ pub mod tests { // unlike in WriteCompactionFilter, the latest mvcc delete below safe point will // be filtered delete_data(b"key1", 19, 18, &write, memory_controller.clone()); - worker.core.gc_range(&range, 19, 100); + worker.core.gc_region(®ion, 19, 100); assert_eq!(0, element_count(&write)); assert_eq!(0, element_count(&default)); } @@ -1988,25 +2028,21 @@ pub mod tests { VersionTrack::new(config), ))); let memory_controller = engine.memory_controller(); - let (write, default, range1, range2) = { + let (write, default, region1, region2) = { let mut core = engine.core().write(); - let start1 = Key::from_raw(b"k00").into_encoded(); - let end1 = Key::from_raw(b"k10").into_encoded(); - let range1 = CacheRange::new(start1, end1); - core.mut_range_manager().new_range(range1.clone()); + let region1 = new_region(1, b"k00", b"k10"); + core.mut_range_manager().new_region(region1.clone()); - let start2 = Key::from_raw(b"k30").into_encoded(); - let end2 = Key::from_raw(b"k40").into_encoded(); - let range2 = CacheRange::new(start2, end2); - core.mut_range_manager().new_range(range2.clone()); + let region2 = new_region(2, b"k30", b"k40"); + core.mut_range_manager().new_region(region2.clone()); let engine = core.engine(); ( engine.cf_handle(CF_WRITE), engine.cf_handle(CF_DEFAULT), - range1, - range2, + region1, + region2, ) }; @@ -2083,7 +2119,8 @@ pub mod tests { ); let encode_key = |key, commit_ts, seq_num| -> InternalBytes { - let raw_write_k = Key::from_raw(key) + let data_key = data_key(key); + let raw_write_k = Key::from_raw(&data_key) .append_ts(TimeStamp::new(commit_ts)) .into_encoded(); encode_key(&raw_write_k, seq_num, ValueType::Value) @@ -2110,7 +2147,7 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - let filter = worker.core.gc_range(&range1, 100, 100); + let filter = worker.core.gc_region(®ion1, 100, 100); assert_eq!(2, filter.filtered); verify(b"k05", 15, 18, &write); @@ -2127,7 +2164,7 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - worker.core.gc_range(&range2, 100, 100); + worker.core.gc_region(®ion2, 100, 100); assert_eq!(2, filter.filtered); verify(b"k35", 15, 20, &write); @@ -2143,8 +2180,8 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + engine.new_region(region.clone()); let (write, default) = { let skiplist_engine = engine.core().write().engine(); ( @@ -2178,7 +2215,7 @@ pub mod tests { Arc::new(MockPdClient {}), ); - let filter = worker.core.gc_range(&range, 20, 200); + let filter = worker.core.gc_region(®ion, 20, 200); assert_eq!(1, filter.filtered); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); @@ -2190,8 +2227,8 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + engine.new_region(region.clone()); let (write, default) = { let skiplist_engine = engine.core().write().engine(); ( @@ -2277,43 +2314,44 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - let s1 = engine.snapshot(range.clone(), 10, u64::MAX); - let s2 = engine.snapshot(range.clone(), 11, u64::MAX); - let s3 = engine.snapshot(range.clone(), 20, u64::MAX); + let range = CacheRange::from_region(®ion); + let s1 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX); + let s2 = engine.snapshot(1, 0, range.clone(), 11, u64::MAX); + let s3 = engine.snapshot(1, 0, range.clone(), 20, u64::MAX); // nothing will be removed due to snapshot 5 - let filter = worker.core.gc_range(&range, 30, 100); + let filter = worker.core.gc_region(®ion, 30, 100); assert_eq!(0, filter.filtered); assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); drop(s1); - let filter = worker.core.gc_range(&range, 30, 100); + let filter = worker.core.gc_region(®ion, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(5, element_count(&default)); assert_eq!(5, element_count(&write)); drop(s2); - let filter = worker.core.gc_range(&range, 30, 100); + let filter = worker.core.gc_region(®ion, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(4, element_count(&default)); assert_eq!(4, element_count(&write)); drop(s3); - let filter = worker.core.gc_range(&range, 30, 100); + let filter = worker.core.gc_region(®ion, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(3, element_count(&default)); assert_eq!(3, element_count(&write)); } #[test] - fn test_gc_range_contained_in_historical_range() { + fn test_gc_region_contained_in_historical_range() { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + engine.new_region(region.clone()); let (write, default) = { let skiplist_engine = engine.core().write().engine(); ( @@ -2390,13 +2428,27 @@ pub mod tests { memory_controller.clone(), ); - let snap1 = engine.snapshot(range.clone(), 20, 1000).unwrap(); - let snap2 = engine.snapshot(range.clone(), 22, 1000).unwrap(); - let _snap3 = engine.snapshot(range.clone(), 60, 1000).unwrap(); - - let range2 = CacheRange::new(b"key5".to_vec(), b"key8".to_vec()); - engine.evict_range(&range2, EvictReason::AutoEvict); + let range = CacheRange::from_region(®ion); + let snap1 = engine.snapshot(1, 0, range.clone(), 20, 1000).unwrap(); + let snap2 = engine.snapshot(1, 0, range.clone(), 22, 1000).unwrap(); + let _snap3 = engine.snapshot(1, 0, range.clone(), 60, 1000).unwrap(); + + let mut new_regions = vec![ + new_region(1, "", "key5"), + new_region(2, "key5", "key8"), + new_region(3, "key8", "z"), + ]; + for r in &mut new_regions { + r.mut_region_epoch().version = 1; + } + let region2 = new_regions[1].clone(); + engine.on_region_event(RegionEvent::Split { + source: region.clone(), + new_regions, + }); + assert_eq!(engine.core.read().range_manager().regions().len(), 3); + engine.evict_region(®ion2, EvictReason::AutoEvict); assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); @@ -2409,17 +2461,24 @@ pub mod tests { Arc::new(MockPdClient {}), ); - let ranges: Vec<_> = engine + let regions: Vec<_> = engine .core .read() .range_manager() - .ranges() - .keys() - .cloned() + .regions() + .values() + .filter_map(|m| { + if m.get_state() == RegionState::Active { + Some(m.region().clone()) + } else { + None + } + }) .collect(); + assert_eq!(regions.len(), 2); let mut filter = FilterMetrics::default(); - for r in &ranges { - filter.merge(&worker.core.gc_range(r, 50, 1000)); + for r in ®ions { + filter.merge(&worker.core.gc_region(r, 50, 1000)); } assert_eq!(2, filter.filtered); assert_eq!(4, element_count(&default)); @@ -2427,8 +2486,8 @@ pub mod tests { drop(snap1); let mut filter = FilterMetrics::default(); - for r in &ranges { - filter.merge(&worker.core.gc_range(r, 50, 1000)); + for r in ®ions { + filter.merge(&worker.core.gc_region(r, 50, 1000)); } assert_eq!(0, filter.filtered); assert_eq!(4, element_count(&default)); @@ -2436,8 +2495,8 @@ pub mod tests { drop(snap2); let mut filter = FilterMetrics::default(); - for r in &ranges { - filter.merge(&worker.core.gc_range(r, 50, 1000)); + for r in ®ions { + filter.merge(&worker.core.gc_region(r, 50, 1000)); } assert_eq!(2, filter.filtered); assert_eq!(2, element_count(&default)); @@ -2467,15 +2526,19 @@ pub mod tests { } let k = format!("zk{:08}", 15).into_bytes(); - let r1 = CacheRange::new(DATA_MIN_KEY.to_vec(), k.clone()); - let r2 = CacheRange::new(k, DATA_MAX_KEY.to_vec()); + let region1 = new_region(1, DATA_MIN_KEY, k.clone()); + let region2 = new_region(2, k, DATA_MAX_KEY); { let mut core = engine.core.write(); - core.mut_range_manager().pending_ranges.push(r1.clone()); - core.mut_range_manager().pending_ranges.push(r2.clone()); + core.mut_range_manager() + .load_region(region1.clone()) + .unwrap(); + core.mut_range_manager() + .load_region(region2.clone()) + .unwrap(); } - engine.prepare_for_apply(1, &r1); - engine.prepare_for_apply(1, &r2); + engine.prepare_for_apply(1, CacheRange::from_region(®ion1), ®ion1); + engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); // concurrent write to rocksdb, but the key will not be loaded in the memory // engine @@ -2501,8 +2564,24 @@ pub mod tests { // wait for background load std::thread::sleep(Duration::from_secs(1)); - let _ = engine.snapshot(r1, u64::MAX, u64::MAX).unwrap(); - let _ = engine.snapshot(r2, u64::MAX, u64::MAX).unwrap(); + let _ = engine + .snapshot( + region1.id, + 0, + CacheRange::from_region(®ion1), + u64::MAX, + u64::MAX, + ) + .unwrap(); + let _ = engine + .snapshot( + region2.id, + 0, + CacheRange::from_region(®ion2), + u64::MAX, + u64::MAX, + ) + .unwrap(); let guard = &epoch::pin(); for i in 10..20 { @@ -2531,12 +2610,12 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let memory_controller = engine.memory_controller(); - let r1 = CacheRange::new(b"a".to_vec(), b"b".to_vec()); - let r2 = CacheRange::new(b"b".to_vec(), b"c".to_vec()); - engine.new_range(r1); - engine.new_range(r2); + let r1 = new_region(1, b"a", b"b"); + let r2 = new_region(2, b"b", b"c"); + engine.new_region(r1); + engine.new_region(r2); - let (mut runner, _) = BackgroundRunner::new( + let (runner, _) = BackgroundRunner::new( engine.core.clone(), memory_controller, None, @@ -2544,15 +2623,47 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - let ranges = runner.core.ranges_for_gc().unwrap(); - assert_eq!(2, ranges.len()); + let regions = runner.core.regions_for_gc(); + assert_eq!(2, regions.len()); // until the previous gc finished, node ranges will be returned - assert!(runner.core.ranges_for_gc().is_none()); - runner.core.on_gc_finished(ranges); + assert!(runner.core.regions_for_gc().is_empty()); + runner.core.on_gc_finished(); + + let regions = runner.core.regions_for_gc(); + assert_eq!(2, regions.len()); + } + + #[derive(Default)] + struct MockRegionInfoProvider { + regions: Mutex>, + } + + impl MockRegionInfoProvider { + fn add_region(&self, region: Region) { + self.regions.lock().unwrap().push(region); + } + } - let ranges = runner.core.ranges_for_gc().unwrap(); - assert_eq!(2, ranges.len()); + impl RegionInfoProvider for MockRegionInfoProvider { + fn get_regions_in_range( + &self, + start: &[u8], + end: &[u8], + ) -> raftstore::coprocessor::Result> { + let regions: Vec<_> = self + .regions + .lock() + .unwrap() + .iter() + .filter(|r| { + (r.end_key.is_empty() || r.end_key.as_slice() > start) + && (end.is_empty() || end > r.start_key.as_slice()) + }) + .cloned() + .collect(); + Ok(regions) + } } // Test creating and loading cache hint using a region label rule: @@ -2563,9 +2674,14 @@ pub mod tests { // 4. Verify that only the labeled key range has been loaded. #[test] fn test_load_from_pd_hint_service() { - let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( - Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), - )); + let region_info_provider = Arc::new(MockRegionInfoProvider::default()); + + let mut engine = RangeCacheMemoryEngine::with_region_info_provider( + RangeCacheEngineContext::new_for_tests(Arc::new(VersionTrack::new( + RangeCacheEngineConfig::config_for_test(), + ))), + Some(region_info_provider.clone()), + ); let path = Builder::new() .prefix("test_load_from_pd_hint_service") .tempdir() @@ -2576,7 +2692,6 @@ pub mod tests { for i in 10..20 { let key = construct_key(i, 1); - let key = data_key(&key); let value = construct_value(i, i); rocks_engine .put_cf(CF_DEFAULT, &key, value.as_bytes()) @@ -2585,6 +2700,8 @@ pub mod tests { .put_cf(CF_WRITE, &key, value.as_bytes()) .unwrap(); } + let region = new_region(1, format!("k{:08}", 10), format!("k{:08}", 15)); + region_info_provider.add_region(region.clone()); let (mut pd_server, pd_client) = new_test_server_and_client(ReadableDuration::millis(100)); let cluster_id = pd_client.get_cluster_id().unwrap(); @@ -2593,19 +2710,37 @@ pub mod tests { let meta_client = region_label_meta_client(pd_client.clone()); let label_rule = new_region_label_rule( "cache/0", - &hex::encode(format!("k{:08}", 10).into_bytes()), - &hex::encode(format!("k{:08}", 15).into_bytes()), + &hex::encode(format!("k{:08}", 0).into_bytes()), + &hex::encode(format!("k{:08}", 20).into_bytes()), ); add_region_label_rule(meta_client, cluster_id, &label_rule); // Wait for the watch to fire. - std::thread::sleep(Duration::from_millis(200)); - let r1 = CacheRange::try_from(&label_rule.data[0]).unwrap(); - engine.prepare_for_apply(1, &r1); + test_util::eventually( + Duration::from_millis(10), + Duration::from_millis(200), + || !engine.core.read().range_manager().regions().is_empty(), + ); + engine.prepare_for_apply(1, CacheRange::from_region(®ion), ®ion); // Wait for the range to be loaded. - std::thread::sleep(Duration::from_secs(1)); - let _ = engine.snapshot(r1, u64::MAX, u64::MAX).unwrap(); + test_util::eventually( + Duration::from_millis(50), + Duration::from_millis(1000), + || { + let core = engine.core.read(); + core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active + }, + ); + let _ = engine + .snapshot( + region.id, + 0, + CacheRange::from_region(®ion), + u64::MAX, + u64::MAX, + ) + .unwrap(); let (write, default) = { let core = engine.core().write(); @@ -2619,7 +2754,6 @@ pub mod tests { let guard = &epoch::pin(); for i in 10..15 { let key = construct_key(i, 1); - let key = data_key(&key); let value = construct_value(i, i); let key = encode_seek_key(&key, u64::MAX); assert_eq!( @@ -2659,7 +2793,7 @@ pub mod tests { engine.set_disk_engine(rocks_engine.clone()); let mem_controller = engine.memory_controller(); - let range1 = CacheRange::new(construct_user_key(1), construct_user_key(3)); + let region1 = new_region(1, construct_region_key(1), construct_region_key(3)); // Memory for one put is 17(key) + 3(val) + 8(Seqno) + 16(Memory controller in // key and val) + 96(Node overhead) = 140 let key = construct_key(1, 10); @@ -2673,7 +2807,7 @@ pub mod tests { rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); // After loading range1, the memory usage should be 140*6=840 - let range2 = CacheRange::new(construct_user_key(3), construct_user_key(5)); + let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); let key = construct_key(3, 10); rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); @@ -2686,7 +2820,7 @@ pub mod tests { // 840*2 > hard limit 1500, so the load will fail and the loaded keys should be // removed - let range3 = CacheRange::new(construct_user_key(5), construct_user_key(6)); + let region3 = new_region(3, construct_region_key(5), construct_region_key(6)); let key = construct_key(5, 10); rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); @@ -2696,34 +2830,36 @@ pub mod tests { rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); - for r in [&range1, &range2, &range3] { - engine.load_range(r.clone()).unwrap(); - engine.prepare_for_apply(1, r); + for r in [®ion1, ®ion2, ®ion3] { + engine.load_region(r.clone()).unwrap(); + engine.prepare_for_apply(1, CacheRange::from_region(r), r); } // ensure all ranges are finshed - { - let mut count = 0; - while count < 20 { - { - let core = engine.core.read(); - let range_manager = core.range_manager(); - if range_manager.pending_ranges.is_empty() - && range_manager.pending_ranges_loading_data.is_empty() - { - break; - } - } - std::thread::sleep(Duration::from_millis(100)); - count += 1; - } - } + test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { + !engine + .core + .read() + .range_manager() + .regions() + .values() + .any(|m| matches!(m.get_state(), Pending | ReadyToLoad | Loading)) + }); - let verify = |range: CacheRange, exist, expect_count| { + let verify = |region: &Region, exist, expect_count| { if exist { let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); - let snap = engine.snapshot(range.clone(), read_ts, u64::MAX).unwrap(); + let snap = engine + .snapshot( + region.id, + 0, + CacheRange::from_region(region), + read_ts, + u64::MAX, + ) + .unwrap(); let mut count = 0; + let range = CacheRange::from_region(region); for cf in DATA_CFS { let mut iter = IterOptions::default(); iter.set_lower_bound(&range.start, 0); @@ -2737,13 +2873,15 @@ pub mod tests { } assert_eq!(count, expect_count); } else { - engine.snapshot(range, 10, 10).unwrap_err(); + engine + .snapshot(region.id, 0, CacheRange::from_region(region), 10, 10) + .unwrap_err(); } }; - verify(range1, true, 6); - verify(range2, false, 0); - verify(range3, false, 3); - assert_eq!(mem_controller.mem_usage(), 1540); + verify(®ion1, true, 6); + verify(®ion2, false, 0); + verify(®ion3, false, 3); + assert_eq!(mem_controller.mem_usage(), 1551); } #[test] @@ -2763,7 +2901,7 @@ pub mod tests { engine.set_disk_engine(rocks_engine.clone()); let mem_controller = engine.memory_controller(); - let range1 = CacheRange::new(construct_user_key(1), construct_user_key(3)); + let region1 = new_region(1, construct_region_key(1), construct_region_key(3)); // Memory for one put is 17(key) + 3(val) + 8(Seqno) + 16(Memory controller in // key and val) + 96(Node overhead) = 140 let key = construct_key(1, 10); @@ -2776,10 +2914,10 @@ pub mod tests { rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); // After loading range1, the memory usage should be 140*6=840 - engine.load_range(range1.clone()).unwrap(); - engine.prepare_for_apply(1, &range1); + engine.load_region(region1.clone()).unwrap(); + engine.prepare_for_apply(1, CacheRange::from_region(®ion1), ®ion1); - let range2 = CacheRange::new(construct_user_key(3), construct_user_key(5)); + let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); let key = construct_key(3, 10); rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); @@ -2801,32 +2939,28 @@ pub mod tests { config_manager.dispatch(config_change).unwrap(); assert_eq!(config.value().hard_limit_threshold(), 2000); - engine.load_range(range2.clone()).unwrap(); - engine.prepare_for_apply(1, &range2); + engine.load_region(region2.clone()).unwrap(); + engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); // ensure all ranges are finshed - { - let mut count = 0; - while count < 20 { - { - let core = engine.core.read(); - let range_manager = core.range_manager(); - if range_manager.pending_ranges.is_empty() - && range_manager.pending_ranges_loading_data.is_empty() - { - break; - } - } - std::thread::sleep(Duration::from_millis(100)); - count += 1; - } - } + test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { + !engine + .core + .read() + .range_manager() + .regions() + .values() + .any(|m| matches!(m.get_state(), Pending | ReadyToLoad | Loading)) + }); - let verify = |range: CacheRange, exist, expect_count| { + let verify = |r: &Region, exist, expect_count| { if exist { let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); - let snap = engine.snapshot(range.clone(), read_ts, u64::MAX).unwrap(); + let snap = engine + .snapshot(r.id, 0, CacheRange::from_region(r), read_ts, u64::MAX) + .unwrap(); let mut count = 0; + let range = CacheRange::from_region(r); for cf in DATA_CFS { let mut iter = IterOptions::default(); iter.set_lower_bound(&range.start, 0); @@ -2840,12 +2974,14 @@ pub mod tests { } assert_eq!(count, expect_count); } else { - engine.snapshot(range, 10, 10).unwrap_err(); + engine + .snapshot(r.id, 0, CacheRange::from_region(r), 10, 10) + .unwrap_err(); } }; - verify(range1, true, 6); - verify(range2, true, 6); - assert_eq!(mem_controller.mem_usage(), 1680); + verify(®ion1, true, 6); + verify(®ion2, true, 6); + assert_eq!(mem_controller.mem_usage(), 1692); } #[test] @@ -2876,7 +3012,7 @@ pub mod tests { }; let safe_point = TimeStamp::from(safe_point); // Make sure it is a reasonable timestamp. - assert!(safe_point > start_time, "{safe_point}, {start_time}"); + assert!(safe_point >= start_time, "{safe_point}, {start_time}"); let now = TimeStamp::compose(TimeStamp::physical_now(), 0); assert!(safe_point < now, "{safe_point}, {now}"); // Must get ts from PD. diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 6912f9ab232..a3061535708 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -1,7 +1,6 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - collections::BTreeMap, fmt::{self, Debug}, ops::Bound, result, @@ -19,9 +18,10 @@ use crossbeam_skiplist::{ use engine_rocks::RocksEngine; use engine_traits::{ CacheRange, EvictReason, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, - Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; -use parking_lot::{lock_api::RwLockUpgradableReadGuard, RwLock, RwLockWriteGuard}; +use kvproto::metapb::Region; +use parking_lot::RwLock; use raftstore::coprocessor::RegionInfoProvider; use slog_global::error; use tikv_util::{config::VersionTrack, info}; @@ -32,10 +32,9 @@ use crate::{ encode_key_for_boundary_with_mvcc, encode_key_for_boundary_without_mvcc, InternalBytes, }, memory_controller::MemoryController, - range_manager::{LoadFailedReason, RangeCacheStatus, RangeManager}, + range_manager::{LoadFailedReason, RangeCacheStatus, RegionManager, RegionState}, read::{RangeCacheIterator, RangeCacheSnapshot}, statistics::Statistics, - write_batch::{group_write_batch_entries, RangeCacheWriteBatchEntry}, RangeCacheEngineConfig, RangeCacheEngineContext, }; @@ -186,8 +185,7 @@ impl Debug for SkiplistEngine { pub struct RangeCacheMemoryEngineCore { pub(crate) engine: SkiplistEngine, - pub(crate) range_manager: RangeManager, - pub(crate) cached_write_batch: BTreeMap>, + pub(crate) range_manager: RegionManager, } impl Default for RangeCacheMemoryEngineCore { @@ -200,8 +198,7 @@ impl RangeCacheMemoryEngineCore { pub fn new() -> RangeCacheMemoryEngineCore { RangeCacheMemoryEngineCore { engine: SkiplistEngine::new(), - range_manager: RangeManager::default(), - cached_write_batch: BTreeMap::default(), + range_manager: RegionManager::default(), } } @@ -209,64 +206,13 @@ impl RangeCacheMemoryEngineCore { self.engine.clone() } - pub fn range_manager(&self) -> &RangeManager { + pub fn range_manager(&self) -> &RegionManager { &self.range_manager } - pub fn mut_range_manager(&mut self) -> &mut RangeManager { + pub fn mut_range_manager(&mut self) -> &mut RegionManager { &mut self.range_manager } - - // `cached_range` must not exist in the `cached_write_batch` - pub fn init_cached_write_batch(&mut self, cache_range: &CacheRange) { - assert!( - self.cached_write_batch - .insert(cache_range.clone(), vec![]) - .is_none() - ); - } - - pub fn has_cached_write_batch(&self, cache_range: &CacheRange) -> bool { - self.cached_write_batch - .get(cache_range) - .map_or(false, |entries| !entries.is_empty()) - } - - pub(crate) fn take_cached_write_batch_entries( - &mut self, - cache_range: &CacheRange, - ) -> Vec<(u64, RangeCacheWriteBatchEntry)> { - std::mem::take(self.cached_write_batch.get_mut(cache_range).unwrap()) - } - - pub fn remove_cached_write_batch(&mut self, cache_range: &CacheRange) { - self.cached_write_batch - .remove(cache_range) - .unwrap_or_else(|| { - panic!( - "range cannot be found in cached_write_batch: {:?}", - cache_range - ); - }); - } - - // ensure that the transfer from `pending_ranges_loading_data` to - // `range` is atomic with cached_write_batch empty - pub(crate) fn pending_range_completes_loading( - core: &mut RwLockWriteGuard<'_, Self>, - range: &CacheRange, - safe_point: u64, - ) { - assert!(!core.has_cached_write_batch(range)); - let range_manager = core.mut_range_manager(); - let (r, _, canceled) = range_manager - .pending_ranges_loading_data - .pop_front() - .unwrap(); - assert_eq!(&r, range); - assert!(!canceled); - range_manager.new_range_with_safe_point(r, safe_point); - } } /// The RangeCacheMemoryEngine serves as a range cache, storing hot ranges in @@ -351,37 +297,31 @@ impl RangeCacheMemoryEngine { self.config.value().expected_region_size() } - pub fn new_range(&self, range: CacheRange) { - let mut core = self.core.write(); - core.range_manager.new_range(range); + pub fn new_region(&self, region: Region) { + self.core.write().range_manager.new_region(region); } - /// Load the range in the in-memory engine. - // This method only push the range in the `pending_range` where sometime - // later in `prepare_for_apply`, the range will be scheduled to load snapshot - // data into engine. - pub fn load_range(&self, range: CacheRange) -> result::Result<(), LoadFailedReason> { - let mut core = self.core.write(); - core.mut_range_manager().load_range(range) + pub fn load_region(&self, region: Region) -> result::Result<(), LoadFailedReason> { + self.core.write().mut_range_manager().load_region(region) } - /// Evict a range from the in-memory engine. After this call, the range will - /// not be readable, but the data of the range may not be deleted + /// Evict a region from the in-memory engine. After this call, the region + /// will not be readable, but the data of the region may not be deleted /// immediately due to some ongoing snapshots. - pub fn evict_range(&self, range: &CacheRange, evict_reason: EvictReason) { - let mut core = self.core.write(); - let mut ranges_to_delete = core.range_manager.evict_range(range, evict_reason); - core.mut_range_manager() - .mark_delete_ranges_scheduled(&mut ranges_to_delete); - if !ranges_to_delete.is_empty() { - drop(core); + pub fn evict_region(&self, region: &Region, evict_reason: EvictReason) { + let deleteable_regions = self + .core + .write() + .range_manager + .evict_region(region, evict_reason); + if !deleteable_regions.is_empty() { // The range can be deleted directly. if let Err(e) = self .bg_worker_manager() - .schedule_task(BackgroundTask::DeleteRange(ranges_to_delete)) + .schedule_task(BackgroundTask::DeleteRegions(deleteable_regions)) { error!( - "schedule delete range failed"; + "schedule delete region failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -394,135 +334,58 @@ impl RangeCacheMemoryEngine { pub(crate) fn prepare_for_apply( &self, write_batch_id: u64, - range: &CacheRange, + range: CacheRange, + region: &Region, ) -> RangeCacheStatus { let mut core = self.core.write(); let range_manager = core.mut_range_manager(); - if range_manager.pending_ranges_in_loading_contains(range) { - range_manager.record_in_ranges_being_written(write_batch_id, range); - return RangeCacheStatus::Loading; - } - if range_manager.contains_range(range) { - range_manager.record_in_ranges_being_written(write_batch_id, range); - return RangeCacheStatus::Cached; + let Some(mut region_state) = range_manager.check_region_state(region) else { + return RangeCacheStatus::NotInCache; + }; + + let schedule_load = region_state == RegionState::Pending; + if schedule_load { + range_manager.update_region_state(region.id, RegionState::ReadyToLoad); + info!( + "range to load"; + "region" => ?region, + "cached" => range_manager.regions().len(), + ); + region_state = RegionState::ReadyToLoad; } - let mut overlapped = false; - // check whether the range is in pending_range and we can schedule load task if - // it is - if let Some((idx, (left_range, right_range))) = range_manager - .pending_ranges - .iter() - .enumerate() - .find_map(|(idx, pending_range)| { - if pending_range.contains_range(range) { - // The `range` may be a proper subset of `r` and we should split it in this case - // and push the rest back to `pending_range` so that each range only schedules - // load task of its own. - Some((idx, pending_range.split_off(range))) - } else if range.overlaps(pending_range) { - // Pending range `range` does not contains the applying range `r` but overlap - // with it, which means the pending range is out dated, we remove it directly. - info!( - "out of date pending ranges"; - "applying_range" => ?range, - "pending_range" => ?pending_range, - ); - overlapped = true; - Some((idx, (None, None))) - } else { - None - } - }) + let mut result = RangeCacheStatus::NotInCache; + if region_state == RegionState::ReadyToLoad + || region_state == RegionState::Loading + || region_state == RegionState::Active { - if overlapped { - core.mut_range_manager().pending_ranges.swap_remove(idx); - return RangeCacheStatus::NotInCache; - } - - let range_manager = core.mut_range_manager(); - if let Some(left_range) = left_range { - range_manager.pending_ranges.push(left_range); - } - - if let Some(right_range) = right_range { - range_manager.pending_ranges.push(right_range); + range_manager.record_in_region_being_written(write_batch_id, range); + if region_state == RegionState::Active { + result = RangeCacheStatus::Cached; + } else { + result = RangeCacheStatus::Loading; } + } + drop(core); - let range_manager = core.mut_range_manager(); - range_manager.pending_ranges.swap_remove(idx); + // get snapshot and schedule loading task at last to avoid locking IME for too + // long. + if schedule_load { let rocks_snap = Arc::new(self.rocks_engine.as_ref().unwrap().snapshot(None)); - // Here, we use the range in `pending_ranges` rather than the parameter range as - // the region may be splitted. - range_manager - .pending_ranges_loading_data - .push_back((range.clone(), rocks_snap, false)); - - range_manager.record_in_ranges_being_written(write_batch_id, range); - - info!( - "Range to load"; - "Tag" => &range.tag, - "Cached" => range_manager.ranges().len(), - "Pending" => range_manager.pending_ranges_loading_data.len(), - ); - - // init cached write batch to cache the writes before loading complete - core.init_cached_write_batch(range); - if let Err(e) = self - .bg_worker_manager() - .schedule_task(BackgroundTask::LoadRange) + .bg_work_manager + .schedule_task(BackgroundTask::LoadRegion(region.clone(), rocks_snap)) { error!( - "schedule range load failed"; + "schedule region load failed"; "err" => ?e, - "tag" => &range.tag, + "region" => ?region, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } - // We have scheduled the range to loading data, so the writes of the range - // should be buffered - return RangeCacheStatus::Loading; } - RangeCacheStatus::NotInCache - } - - // The writes in `handle_pending_range_in_loading_buffer` indicating the ranges - // of the writes are pending_ranges that are still loading data at the time of - // `prepare_for_apply`. But some of them may have been finished the load and - // become a normal range so that the writes should be written to the engine - // directly rather than cached. This method decides which writes should be - // cached and which writes should be written directly. - pub(crate) fn handle_pending_range_in_loading_buffer( - &self, - seq: &mut u64, - pending_range_in_loading_buffer: Vec, - ) -> (Vec, SkiplistEngine) { - if !pending_range_in_loading_buffer.is_empty() { - let core = self.core.upgradable_read(); - let (group_entries_to_cache, entries_to_write) = - group_write_batch_entries(pending_range_in_loading_buffer, core.range_manager()); - let engine = core.engine().clone(); - if !group_entries_to_cache.is_empty() { - let mut core = RwLockUpgradableReadGuard::upgrade(core); - for (range, write_batches) in group_entries_to_cache { - core.cached_write_batch.entry(range).or_default().extend( - write_batches.into_iter().map(|e| { - // We should confirm the sequence number for cached entries, and - // also increased for each of them. - *seq += 1; - (*seq - 1, e) - }), - ); - } - } - (entries_to_write, engine) - } else { - let core = self.core.read(); - (vec![], core.engine().clone()) - } + result } pub fn bg_worker_manager(&self) -> &BgWorkManager { @@ -560,11 +423,20 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { fn snapshot( &self, + region_id: u64, + region_epoch: u64, range: CacheRange, read_ts: u64, seq_num: u64, ) -> result::Result { - RangeCacheSnapshot::new(self.clone(), range, read_ts, seq_num) + RangeCacheSnapshot::new( + self.clone(), + region_id, + region_epoch, + range, + read_ts, + seq_num, + ) } type DiskEngine = RocksEngine; @@ -588,17 +460,43 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { .start_bg_hint_service(range_hint_service) } - fn get_range_for_key(&self, key: &[u8]) -> Option { - let core = self.core.read(); - core.range_manager().get_range_for_key(key) + fn get_region_for_key(&self, key: &[u8]) -> Option { + self.core.read().range_manager().get_region_for_key(key) } fn enabled(&self) -> bool { self.config.value().enabled } - fn evict_range(&self, range: &CacheRange, evict_range: EvictReason) { - self.evict_range(range, evict_range) + fn on_region_event(&self, event: RegionEvent) { + match event { + RegionEvent::Eviction { region, reason } => { + self.evict_region(®ion, reason); + } + RegionEvent::Split { + source, + new_regions, + } => { + self.core + .write() + .range_manager + .split_region(&source, new_regions); + } + RegionEvent::EvictByRange { range, reason } => { + let mut regions = vec![]; + self.core() + .read() + .range_manager() + .iter_overlapped_regions(&range, |meta| { + assert!(meta.get_range().overlaps(&range)); + regions.push(meta.region().clone()); + true + }); + for r in regions { + self.evict_region(&r, reason); + } + } + } } } @@ -623,43 +521,44 @@ pub mod tests { use crate::{ keys::{construct_key, construct_user_key, encode_key}, memory_controller::MemoryController, + range_manager::{RangeMeta, RegionManager, RegionState::*}, + test_util::new_region, InternalBytes, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, ValueType, }; + fn count_region(mgr: &RegionManager, mut f: impl FnMut(&RangeMeta) -> bool) -> usize { + mgr.regions().values().filter(|m| f(m)).count() + } #[test] - fn test_overlap_with_pending() { + fn test_region_overlap_with_outdated_epoch() { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range1 = CacheRange::new(b"k1".to_vec(), b"k3".to_vec()); - engine.load_range(range1).unwrap(); - - let range2 = CacheRange::new(b"k1".to_vec(), b"k5".to_vec()); - engine.prepare_for_apply(1, &range2); - assert!( - engine.core.read().range_manager().pending_ranges.is_empty() - && engine - .core - .read() - .range_manager() - .pending_ranges_loading_data - .is_empty() + let region1 = new_region(1, b"k1", b"k3"); + engine.load_region(region1).unwrap(); + + let mut region2 = new_region(1, b"k1", b"k5"); + region2.mut_region_epoch().version = 2; + engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + assert_eq!( + count_region(engine.core.read().range_manager(), |m| { + matches!(m.get_state(), Pending | ReadyToLoad | Loading) + }), + 0 ); - let range1 = CacheRange::new(b"k1".to_vec(), b"k3".to_vec()); - engine.load_range(range1).unwrap(); - - let range2 = CacheRange::new(b"k2".to_vec(), b"k5".to_vec()); - engine.prepare_for_apply(1, &range2); - assert!( - engine.core.read().range_manager().pending_ranges.is_empty() - && engine - .core - .read() - .range_manager() - .pending_ranges_loading_data - .is_empty() + let region1 = new_region(1, b"k1", b"k3"); + engine.load_region(region1).unwrap(); + + let mut region2 = new_region(1, b"k2", b"k5"); + region2.mut_region_epoch().version = 2; + engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + assert_eq!( + count_region(engine.core.read().range_manager(), |m| { + matches!(m.get_state(), Pending | ReadyToLoad | Loading) + }), + 0 ); } diff --git a/components/range_cache_memory_engine/src/keys.rs b/components/range_cache_memory_engine/src/keys.rs index e7705cdf3e0..5015d08c90d 100644 --- a/components/range_cache_memory_engine/src/keys.rs +++ b/components/range_cache_memory_engine/src/keys.rs @@ -3,6 +3,7 @@ use core::slice::SlicePattern; use std::{ cmp::{self, Ordering}, + fmt, sync::Arc, }; @@ -115,14 +116,7 @@ impl Ord for InternalBytes { .unwrap(), ); - #[allow(clippy::comparison_chain)] - if n1 < n2 { - Ordering::Greater - } else if n1 > n2 { - Ordering::Less - } else { - Ordering::Equal - } + n2.cmp(&n1) } } @@ -154,6 +148,7 @@ impl TryFrom for ValueType { } } +#[derive(PartialEq)] pub struct InternalKey<'a> { // key with mvcc version in memory comparable format pub user_key: &'a [u8], @@ -161,6 +156,18 @@ pub struct InternalKey<'a> { pub sequence: u64, } +impl<'a> fmt::Debug for InternalKey<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "(key: {:?}, type: {:?}, seq: {})", + log_wrappers::Value(self.user_key), + self.v_type, + self.sequence + ) + } +} + // The size of sequence number suffix pub const ENC_KEY_SEQ_LENGTH: usize = std::mem::size_of::(); @@ -268,13 +275,19 @@ pub fn encoding_for_filter(mvcc_prefix: &[u8], start_ts: TimeStamp) -> InternalB #[cfg(test)] pub fn construct_user_key(i: u64) -> Vec { + let k = format!("zk{:08}", i); + k.as_bytes().to_owned() +} + +#[cfg(test)] +pub fn construct_region_key(i: u64) -> Vec { let k = format!("k{:08}", i); k.as_bytes().to_owned() } #[cfg(test)] pub fn construct_key(i: u64, ts: u64) -> Vec { - let k = format!("k{:08}", i); + let k = format!("zk{:08}", i); Key::from_encoded(k.as_bytes().to_vec()) .append_ts(TimeStamp::new(ts)) .into_encoded() diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index 7bcabb8e033..87a319d3e34 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -1,5 +1,6 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. +#![feature(assert_matches)] #![feature(let_chains)] #![allow(internal_features)] #![feature(core_intrinsics)] @@ -38,7 +39,7 @@ pub use keys::{ InternalKey, ValueType, }; pub use metrics::flush_range_cache_engine_statistics; -pub use range_manager::RangeCacheStatus; +pub use range_manager::{RangeCacheStatus, RegionState}; pub use statistics::Statistics as RangeCacheMemoryEngineStatistics; use txn_types::TimeStamp; pub use write_batch::RangeCacheWriteBatch; @@ -65,10 +66,8 @@ impl Default for RangeCacheEngineConfig { Self { enabled: false, gc_interval: ReadableDuration(Duration::from_secs(180)), - load_evict_interval: ReadableDuration(Duration::from_secs(300)), /* Each load/evict - * operation should - * run within five - * minutes. */ + // Each load/evict operation should run within five minutes. + load_evict_interval: ReadableDuration(Duration::from_secs(300)), soft_limit_threshold: None, hard_limit_threshold: None, expected_region_size: None, diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index db51af4a202..ee1fe4dd557 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -96,8 +96,9 @@ impl MemoryController { } #[inline] - pub(crate) fn set_memory_checking(&self, v: bool) { - self.memory_checking.store(v, Ordering::Relaxed); + // return the previous status. + pub(crate) fn set_memory_checking(&self, v: bool) -> bool { + self.memory_checking.swap(v, Ordering::Relaxed) } #[inline] diff --git a/components/range_cache_memory_engine/src/metrics.rs b/components/range_cache_memory_engine/src/metrics.rs index 187d2359f4b..b3379138b38 100644 --- a/components/range_cache_memory_engine/src/metrics.rs +++ b/components/range_cache_memory_engine/src/metrics.rs @@ -39,6 +39,7 @@ make_auto_flush_static_metric! { delete_range, become_follower, memory_limit_reached, + disabled, } pub struct GcFilteredCountVec: LocalIntCounter { @@ -200,5 +201,8 @@ pub(crate) fn observe_eviction_duration(secs: f64, evict_reason: EvictReason) { .memory_limit_reached .observe(secs), EvictReason::Merge => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC.merge.observe(secs), + EvictReason::Disabled => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .disabled + .observe(secs), } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 89eaa35ef56..930c1db4a62 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -1,18 +1,64 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, + assert_matches::assert_matches, + collections::{ + BTreeMap, + Bound::{self, Excluded, Unbounded}, + }, result, - sync::Arc, + sync::atomic::{AtomicBool, Ordering}, }; use collections::HashMap; -use engine_rocks::RocksSnapshot; use engine_traits::{CacheRange, EvictReason, FailedReason}; +use kvproto::metapb::Region; use tikv_util::{info, time::Instant}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; +#[derive(PartialEq, Eq, Debug, Clone, Copy, Default, Hash)] +pub enum RegionState { + // waiting to be load. + // NOTE: in this state, the region's epoch may be older than + // target region in raftstore. + #[default] + Pending, + // Region is ready to do batch load but not started. In this state, + // apply thread starts directly write new KVs into the skiplist. + ReadyToLoad, + // Region is handling batch loading from rocksdb snapshot. + Loading, + // Region is cached, ready to handle foreground read. + Active, + // region should be evicted, but batch loading is possible still running. + LoadingCanceled, + // region should be evicted, but there are possible active snapshot or gc task. + PendingEvict, + // evicting event is running, the region will be removed after the evict task finished. + Evicting, +} + +impl RegionState { + pub fn as_str(&self) -> &'static str { + use RegionState::*; + match *self { + Pending => "pending", + ReadyToLoad => "ready_to_load", + Loading => "loading", + Active => "cached", + LoadingCanceled => "loading_canceled", + PendingEvict => "pending_evict", + Evicting => "evicting", + } + } + + pub fn is_evict(&self) -> bool { + use RegionState::*; + matches!(*self, LoadingCanceled | PendingEvict | Evicting) + } +} + // read_ts -> ref_count #[derive(Default, Debug)] pub(crate) struct SnapshotList(pub(crate) BTreeMap); @@ -20,8 +66,7 @@ pub(crate) struct SnapshotList(pub(crate) BTreeMap); impl SnapshotList { pub(crate) fn new_snapshot(&mut self, read_ts: u64) { // snapshot with this ts may be granted before - let count = self.0.get(&read_ts).unwrap_or(&0) + 1; - self.0.insert(read_ts, count); + *self.0.entry(read_ts).or_default() += 1; } pub(crate) fn remove_snapshot(&mut self, read_ts: u64) { @@ -44,24 +89,66 @@ impl SnapshotList { } } -#[derive(Debug, Default)] +#[derive(Debug)] pub struct RangeMeta { - // start_key and end_key cannot uniquely identify a range as range can split and merge, so we - // need a range id. - id: u64, - range_snapshot_list: SnapshotList, + region: Region, + // the data range of this region. + range: CacheRange, + // active region snapshots. + region_snapshot_list: SnapshotList, + // the gc safe point. safe_point: u64, + state: RegionState, + // whether a gc task is running with this region. + in_gc: bool, + // region eviction triggers info, used for logging. + evict_info: Option, +} + +#[derive(Debug, Clone, Copy)] +struct EvictInfo { + start: Instant, + reason: EvictReason, } impl RangeMeta { - fn new(id: u64) -> Self { + fn new(region: Region) -> Self { + let range = CacheRange::from_region(®ion); Self { - id, - range_snapshot_list: SnapshotList::default(), + region, + range, + region_snapshot_list: SnapshotList::default(), safe_point: 0, + state: RegionState::Pending, + in_gc: false, + evict_info: None, } } + #[inline] + pub fn region(&self) -> &Region { + &self.region + } + + // update region info due to epoch version changes. This can only + // happen for pending region because otherwise we will always update + // the region epoch with ApplyObserver(for loading/active regions) or + // no need to update the epoch for evicting regions. + fn amend_pending_region(&mut self, region: &Region) -> bool { + assert!( + self.region.id == region.id + && self.region.get_region_epoch().version < region.get_region_epoch().version + ); + let new_range = CacheRange::from_region(region); + if !self.range.contains_range(&new_range) { + return false; + } + + self.region = region.clone(); + self.range = new_range; + true + } + pub(crate) fn safe_point(&self) -> u64 { self.safe_point } @@ -71,124 +158,210 @@ impl RangeMeta { self.safe_point = safe_point; } - fn derive_from(id: u64, r: &RangeMeta) -> Self { - Self { - id, - range_snapshot_list: SnapshotList::default(), - safe_point: r.safe_point, - } + pub fn get_range(&self) -> &CacheRange { + &self.range } - pub(crate) fn range_snapshot_list(&self) -> &SnapshotList { - &self.range_snapshot_list + pub fn get_state(&self) -> RegionState { + self.state } -} -#[derive(Default)] -struct IdAllocator(u64); + // each state can only be updated to some specific new state. + fn validate_update_region_state(&self, new_state: RegionState) -> bool { + use RegionState::*; + let valid_new_states: &[RegionState] = match self.state { + Pending => &[ReadyToLoad], + ReadyToLoad => &[Loading, LoadingCanceled], + Loading => &[Active, LoadingCanceled, Evicting], + Active => &[PendingEvict], + LoadingCanceled => &[PendingEvict, Evicting], + PendingEvict => &[Evicting], + Evicting => &[], + }; + valid_new_states.contains(&new_state) + } + + pub(crate) fn set_state(&mut self, new_state: RegionState) { + assert!(self.validate_update_region_state(new_state)); + info!( + "update region meta state"; + "region_id" => self.region.id, + "epoch" => self.region.get_region_epoch().version, + "curr_state" => ?self.state, + "new_state" => ?new_state); + self.state = new_state; + } + + pub(crate) fn mark_evict(&mut self, state: RegionState, reason: EvictReason) { + use RegionState::*; + assert_matches!(self.state, Loading | Active | LoadingCanceled); + assert_matches!(state, PendingEvict | Evicting); + self.set_state(state); + self.evict_info = Some(EvictInfo { + start: Instant::now_coarse(), + reason, + }); + } + + pub(crate) fn set_in_gc(&mut self, in_gc: bool) { + assert!(self.in_gc != in_gc); + self.in_gc = in_gc; + } + + pub(crate) fn is_in_gc(&self) -> bool { + self.in_gc + } + + // Build a new RangeMeta from a existing meta, the new meta should inherit + // the safe_point, state, in_gc and evict_info. + // This method is currently only used for handling region split. + pub(crate) fn derive_from(region: Region, source_meta: &Self) -> Self { + let range = CacheRange::from_region(®ion); + assert!(source_meta.range.contains_range(&range)); + Self { + region, + range, + region_snapshot_list: SnapshotList::default(), + safe_point: source_meta.safe_point, + state: source_meta.state, + in_gc: source_meta.in_gc, + evict_info: source_meta.evict_info, + } + } -impl IdAllocator { - fn allocate_id(&mut self) -> u64 { - self.0 += 1; - self.0 + pub(crate) fn region_snapshot_list(&self) -> &SnapshotList { + &self.region_snapshot_list } } -// RangeManger manges the ranges for RangeCacheMemoryEngine. Every new ranges -// (whether created by new_range or by splitted due to eviction) has an unique -// id so that range + id can exactly identify which range it is. -// When an eviction occured, say we now have k1-k10 in self.ranges and the -// eviction range is k3-k5. k1-k10 will be splitted to three ranges: k1-k3, -// k3-k5, and k5-k10. -// k1-k3 and k5-k10 will be new ranges inserted in self.ranges with meta dervied -// from meta of k1-k10 (only safe_ts will be derived). k1-k10 will be removed -// from self.ranges and inserted to self.historical_ranges. Then, k3-k5 will be -// in the self.evicted_ranges. Now, we cannot remove the data of k3-k5 as there -// may be some snapshot of k1-k10. After these snapshot are dropped, k3-k5 can -// be acutally removed. +// TODO: it's currently impossible to implement a `Borrow`ed instance +// for `KeyAndVersion` from a borrowed key without clone. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] +struct KeyAndVersion(Vec, u64); + +// RegionManger manges the regions for RangeCacheMemoryEngine. Every new region +// (whether created by new_region/load_region or by split)'s range is unique and +// is not overlap with any other regions. +// +// Each region is first added with `pending` state. Because `pending` can be +// added by the background workers, it is possible the pending region is added +// with an outdated epoch. We handle this outdated epoch in the raft apply +// thread, before handling a region, the apply worker will check the region in +// RegionManager, if its epoch is outdated(only possible in `pending` state), if +// the old region's range contains new region's range, then we update it to the +// new version, else we just drop the outdated region. +// +// In RegionCacheEngine, we only keep region's epoch version updated with +// raftstore, but not the conf version for simplicity because conf version +// change doesn't affect the correctness of data. In order to always keep the +// region epoch version updated, we handle region epoch we use a ApplyObserver +// to watch following event: +// - PrepareMerge/CommitMerge. We evict target region currently for simplicity. +// - Leader Resign. evict the region. +// - SST Ingestion. evict the region. +// - Split/BatchSplit. For split event, we just replace the source region with +// the split new regions. The new regions should inherit the state of the +// source region including(state, safe_point, in_gc). If there are ongoing +// snapshot in the source region, the source region meta should be put in +// `historical_regions`. #[derive(Default)] -pub struct RangeManager { - // Each new range will increment it by one. - id_allocator: IdAllocator, - // Range before an eviction. It is recorded due to some undropped snapshot, which block the - // evicted range deleting the relevant data. - historical_ranges: BTreeMap, - // `ranges_being_deleted` contains ranges that are evicted but not finished the delete (or even - // not start to delete due to ongoing snapshot) - // `bool` means whether the range has been scheduled to the delete range worker - pub(crate) ranges_being_deleted: BTreeMap, +pub struct RegionManager { // ranges that are cached now - ranges: BTreeMap, - - // `pending_ranges` contains ranges that will be loaded into the memory engine. To guarantee - // the completeness of the data, we also need to write the data that is applied after the - // snapshot is acquired. And to ensure the data is written by order, we should cache the data - // that is applied after the snapshot acquired and only consume them when snapshot load - // finishes. - // So, at sometime in the apply thread, the pending ranges, coupled with rocksdb - // snapshot, will be poped and pushed into `pending_ranges_loading_data` (data here means the - // data in snapshot and in further applied write). Then the data in the snapshot of the - // given ranges will be loaded in the memory engine in the background worker. When the - // snapshot load is finished, we begin to consume the write batch that is cached after the - // snapshot is acquired. - // - // Note: as we will release lock during the consuming of the cached write batch, there could be - // further write batch being cached. We must ensure the cached write batch is empty at the time - // the range becoming accessable range. - // - // Note: the region with range equaling to the range in the `pending_range` may have been - // split. This is fine, we just let the first child region that calls the prepare_for_apply - // to schedule it. We should cache writes for all child regions, and the load task - // completes as long as the snapshot has been loaded and the cached write batches for this - // super range have all been consumed. - pub(crate) pending_ranges: Vec, - // The bool indicates the loading is canceled due to memory capcity issue - pub(crate) pending_ranges_loading_data: VecDeque<(CacheRange, Arc, bool)>, - - ranges_in_gc: BTreeSet, - // Record the ranges that are being written. + // data_end_key --> region_id + regions_by_range: BTreeMap, u64>, + // region_id --> region_meta + regions: HashMap, + // we use this flag to ensure there is only 1 running gc task. + is_gc_task_running: AtomicBool, + // Outdated regions that are split but still hold some on going snapshots. + // These on going snapshot should block regions fell in this range from gc or eviction. + // It's possible that multi region with the same end key are in `historical_regions`, + // so we add epoch version into the key to ensure the uniqueness. + // (data_end_key, epoch_version) --> region_id + historical_regions: BTreeMap, + // Record the region ranges that are being written. // // It is used to avoid the conccurency issue between delete range and write to memory: after - // the range is evicted or failed to load, the range is recorded in `ranges_being_deleted` - // which means no further write of it is allowed, and a DeleteRange task of the range will be - // scheduled to cleanup the dirty data. However, it is possible that the apply thread is - // writting data for this range. Therefore, we have to delay the DeleteRange task until the - // range leaves the `ranges_being_written`. + // the range is evicted or failed to load, the range is marked as `PendingEvict` + // which means no further write of it is allowed, and a DeleteRegion task of the range will be + // scheduled to cleanup the KVs of this region. However, it is possible that the apply thread + // is writing data for this range. Therefore, we have to delay the DeleteRange task until + // the range leaves the `ranges_being_written`. // // The key in this map is the id of the write batch, and the value is a collection // the ranges of this batch. So, when the write batch is consumed by the in-memory engine, // all ranges of it are cleared from `ranges_being_written`. - ranges_being_written: HashMap>, + // write_batch_id --> Vec + regions_being_written: HashMap>, } -impl RangeManager { - pub(crate) fn ranges(&self) -> &BTreeMap { - &self.ranges +impl RegionManager { + pub(crate) fn regions(&self) -> &HashMap { + &self.regions + } + + // load a new region directly in the active state. + // This fucntion is used for unit/integration tests only. + pub fn new_region(&mut self, region: Region) { + let mut range_meta = RangeMeta::new(region); + range_meta.state = RegionState::Active; + self.new_region_meta(range_meta); } - pub(crate) fn historical_ranges(&self) -> &BTreeMap { - &self.historical_ranges + fn new_region_meta(&mut self, meta: RangeMeta) { + assert!(!self.overlaps_with(&meta.range)); + let id = meta.region.id; + let data_end_key = meta.range.end.clone(); + self.regions.insert(id, meta); + self.regions_by_range.insert(data_end_key, id); } - pub fn new_range(&mut self, range: CacheRange) { - assert!(!self.overlap_with_range(&range)); - let range_meta = RangeMeta::new(self.id_allocator.allocate_id()); - self.ranges.insert(range, range_meta); + pub fn region_meta(&self, id: u64) -> Option<&RangeMeta> { + self.regions.get(&id) } - pub fn new_range_with_safe_point(&mut self, range: CacheRange, safe_point: u64) { - assert!(!self.overlap_with_range(&range)); - let mut range_meta = RangeMeta::new(self.id_allocator.allocate_id()); - range_meta.set_safe_point(safe_point); - self.ranges.insert(range, range_meta); + pub fn mut_region_meta(&mut self, id: u64) -> Option<&mut RangeMeta> { + self.regions.get_mut(&id) + } + + pub fn iter_overlapped_regions( + &self, + range: &CacheRange, + mut f: impl FnMut(&RangeMeta) -> bool, + ) { + for (_key, id) in self + .regions_by_range + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + { + let region_meta = &self.regions[id]; + if region_meta.range.start >= range.end { + break; + } + if !f(region_meta) { + break; + } + } } - pub fn mut_range_meta(&mut self, range: &CacheRange) -> Option<&mut RangeMeta> { - self.ranges.get_mut(range) + pub fn iter_overlapped_regions_mut( + &mut self, + range: &CacheRange, + mut f: impl FnMut(&mut RangeMeta), + ) { + for (_key, id) in self + .regions_by_range + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + { + let region_meta = self.regions.get_mut(id).unwrap(); + if region_meta.range.start >= range.end { + break; + } + f(region_meta); + } } - pub fn set_safe_point(&mut self, range: &CacheRange, safe_ts: u64) -> bool { - if let Some(meta) = self.ranges.get_mut(range) { + pub fn set_safe_point(&mut self, region_id: u64, safe_ts: u64) -> bool { + if let Some(meta) = self.regions.get_mut(®ion_id) { if meta.safe_point > safe_ts { return false; } @@ -199,127 +372,230 @@ impl RangeManager { } } - pub fn contains(&self, key: &[u8]) -> bool { - self.ranges.keys().any(|r| r.contains_key(key)) - } - - pub fn get_range_for_key(&self, key: &[u8]) -> Option { - self.ranges.keys().find_map(|r| { - if r.contains_key(key) { - Some(r.clone()) - } else { - None + pub fn get_region_for_key(&self, key: &[u8]) -> Option { + if let Some((key, id)) = self + .regions_by_range + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(key), Unbounded)) + .next() + { + let meta = &self.regions[id]; + if &meta.range.start <= key { + return Some(meta.region.clone()); } - }) - } - - pub fn contains_range(&self, range: &CacheRange) -> bool { - self.ranges.keys().any(|r| r.contains_range(range)) + } + None } - pub fn pending_ranges_in_loading_contains(&self, range: &CacheRange) -> bool { - self.pending_ranges_loading_data - .iter() - .any(|(r, ..)| r.contains_range(range)) + pub fn contains_region(&self, region_id: u64) -> bool { + self.regions.contains_key(®ion_id) } - fn overlap_with_range(&self, range: &CacheRange) -> bool { - self.ranges.keys().any(|r| r.overlaps(range)) + pub fn check_region_state(&mut self, region: &Region) -> Option { + use RegionState::*; + let Some(cached_meta) = self.regions.get_mut(®ion.id) else { + return None; + }; + if cached_meta.state == Pending + && cached_meta.region.get_region_epoch().version != region.get_region_epoch().version + && !cached_meta.amend_pending_region(region) + { + info!("remove outdated pending region"; "pending_region" => ?cached_meta.region, "new_region" => ?region); + self.remove_region(region.id); + return None; + } + Some(cached_meta.state) } - fn overlap_with_evicting_range(&self, range: &CacheRange) -> bool { - self.ranges_being_deleted - .iter() - .any(|(r, _)| r.overlaps(range)) + pub fn update_region_state(&mut self, id: u64, state: RegionState) { + self.regions.get_mut(&id).unwrap().state = state; } - fn overlap_with_range_in_gc(&self, range: &CacheRange) -> bool { - self.ranges_in_gc.iter().any(|r| r.overlaps(range)) + fn overlaps_with(&self, range: &CacheRange) -> bool { + let entry = self + .regions_by_range + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + .next(); + if let Some((_key, id)) = entry { + let meta = &self.regions[id]; + if meta.range.start < range.end { + return true; + } + } + false } - fn overlap_with_pending_range(&self, range: &CacheRange) -> bool { - self.pending_ranges.iter().any(|r| r.overlaps(range)) - || self - .pending_ranges_loading_data - .iter() - .any(|(r, ..)| r.overlaps(range)) + /// `check_overlap_with_region` check whether there are regions overlap with + /// target region. If there are regions with `pending` state and whose + /// epoch version is smaller than target region, the pending regions will + /// be removed first. + fn check_overlap_with_region(&mut self, region: &Region) -> Option { + let region_range = CacheRange::from_region(region); + let mut removed_regions = vec![]; + let mut overlapped_region_state = None; + self.iter_overlapped_regions(®ion_range, |region_meta| { + // pending region with out-dated epoch, should be removed. + if region_meta.state == RegionState::Pending + && region_meta.region.get_region_epoch().version < region.get_region_epoch().version + { + removed_regions.push(region_meta.region.id); + return true; + } + tikv_util::warn!("load region overlaps with existing region"; + "region" => ?region, + "exist_meta" => ?region_meta); + overlapped_region_state = Some(region_meta.state); + false + }); + if !removed_regions.is_empty() { + info!("load region meet pending region with stale epoch, removed"; + "region" => ?region, "stale_regions" => ?removed_regions); + } + for id in removed_regions { + self.remove_region(id); + } + overlapped_region_state } // Acquire a snapshot of the `range` with `read_ts`. If the range is not // accessable, None will be returned. Otherwise, the range id will be returned. - pub(crate) fn range_snapshot( + pub(crate) fn region_snapshot( &mut self, - range: &CacheRange, + region_id: u64, + region_epoch: u64, read_ts: u64, - ) -> result::Result { - let Some(range_key) = self - .ranges - .keys() - .find(|&r| r.contains_range(range)) - .cloned() - else { + ) -> result::Result<(), FailedReason> { + let Some(meta) = self.regions.get_mut(®ion_id) else { return Err(FailedReason::NotCached); }; - let meta = self.ranges.get_mut(&range_key).unwrap(); + + if meta.state != RegionState::Active { + return Err(FailedReason::NotCached); + } + + if meta.region.get_region_epoch().version != region_epoch { + return Err(FailedReason::EpochNotMatch); + } if read_ts <= meta.safe_point { return Err(FailedReason::TooOldRead); } - meta.range_snapshot_list.new_snapshot(read_ts); - Ok(meta.id) + meta.region_snapshot_list.new_snapshot(read_ts); + Ok(()) } // If the snapshot is the last one in the snapshot list of one cache range in - // historical_ranges, it means one or some evicted_ranges may be ready to be + // historical_regions, it means one or some evicted_ranges may be ready to be // removed physically. // So, we return a vector of ranges to denote the ranges that are ready to be // removed. - pub(crate) fn remove_range_snapshot( + pub(crate) fn remove_region_snapshot( &mut self, snapshot_meta: &RangeCacheSnapshotMeta, - ) -> Vec { - if let Some(range_key) = self - .historical_ranges - .iter() - .find(|&(range, meta)| { - range.contains_range(&snapshot_meta.range) && meta.id == snapshot_meta.range_id - }) - .map(|(r, _)| r.clone()) + ) -> Vec { + // fast path: in most case, region is not changed. + if let Some(region_meta) = self.regions.get_mut(&snapshot_meta.region_id) + && region_meta.region.get_region_epoch().version == snapshot_meta.epoch_version { - let meta = self.historical_ranges.get_mut(&range_key).unwrap(); - meta.range_snapshot_list + // epoch not changed + region_meta + .region_snapshot_list .remove_snapshot(snapshot_meta.snapshot_ts); - if meta.range_snapshot_list.is_empty() { - self.historical_ranges.remove(&range_key); + if Self::region_ready_to_evict(region_meta, &self.historical_regions) { + region_meta.set_state(RegionState::Evicting); + return vec![region_meta.region.clone()]; } + return vec![]; + } - return self - .ranges_being_deleted - .keys() - .filter(|evicted_range| { - !self - .historical_ranges - .keys() - .any(|r| r.overlaps(evicted_range)) - }) - .cloned() - .collect::>(); - } - - // It must belong to the `self.ranges` if not found in `self.historical_ranges` - let range_key = self - .ranges - .iter() - .find(|&(range, meta)| { - range.contains_range(&snapshot_meta.range) && meta.id == snapshot_meta.range_id - }) - .map(|(r, _)| r.clone()) - .unwrap(); - let meta = self.ranges.get_mut(&range_key).unwrap(); - meta.range_snapshot_list + // slow path: region not found or epoch version changes, must fell in the + // history regions. + let hist_key = KeyAndVersion(snapshot_meta.range.end.clone(), snapshot_meta.epoch_version); + let meta = self.historical_regions.get_mut(&hist_key).unwrap(); + meta.region_snapshot_list .remove_snapshot(snapshot_meta.snapshot_ts); - vec![] + + let mut deletable_regions = vec![]; + if meta.region_snapshot_list.is_empty() { + self.historical_regions.remove(&hist_key).unwrap(); + self.iter_overlapped_regions(&snapshot_meta.range, |meta| { + if matches!( + meta.get_state(), + RegionState::PendingEvict | RegionState::Evicting + ) { + assert_eq!(meta.get_state(), RegionState::PendingEvict); + if Self::region_ready_to_evict(meta, &self.historical_regions) { + deletable_regions.push(meta.region.clone()); + } + } + true + }); + for r in &deletable_regions { + let meta = self.regions.get_mut(&r.id).unwrap(); + meta.set_state(RegionState::Evicting); + } + } + deletable_regions + } + + // whether target region is ready to be physically evicted. + // NOTE: region in_gc or region is actively written will also block + // evicting, but we check these two factor in the DeleteRange worker, + // so we don't check these two factors here for simplicity. + #[inline] + fn region_ready_to_evict( + meta: &RangeMeta, + historical_regions: &BTreeMap, + ) -> bool { + if meta.state != RegionState::PendingEvict { + return false; + } + meta.region_snapshot_list.is_empty() + && !Self::overlaps_with_historical_regions(&meta.range, historical_regions) + } + + fn overlaps_with_historical_regions( + range: &CacheRange, + historical_regions: &BTreeMap, + ) -> bool { + for (_, meta) in historical_regions.range(( + Excluded(KeyAndVersion(range.start.clone(), u64::MAX)), + Unbounded, + )) { + if meta.range.start < range.end { + return true; + } + } + false + } + + pub(crate) fn get_history_regions_min_ts(&self, range: &CacheRange) -> Option { + self.historical_regions + .range(( + Excluded(KeyAndVersion(range.start.clone(), u64::MAX)), + Unbounded, + )) + .filter_map(|(_, meta)| { + if meta.range.start < range.end { + meta.region_snapshot_list.min_snapshot_ts() + } else { + None + } + }) + .min() + } + + pub(crate) fn on_gc_region_finished(&mut self, region: &Region) { + let region_meta = self.regions.get_mut(®ion.id).unwrap(); + if region_meta.region.get_region_epoch().version == region.get_region_epoch().version { + region_meta.set_in_gc(false); + } else { + let range = region_meta.range.clone(); + self.iter_overlapped_regions_mut(&range, |meta| { + assert!(range.contains_range(&meta.range)); + meta.set_in_gc(false); + }); + } } /// Return ranges that can be deleted now (no ongoing snapshot). @@ -336,178 +612,243 @@ impl RangeManager { // // For 2, this is caused by some special operations such as merge and delete // range. So, conservatively, we evict all ranges overlap with it. - pub(crate) fn evict_range( + pub(crate) fn evict_region( &mut self, - evict_range: &CacheRange, + evict_region: &Region, evict_reason: EvictReason, - ) -> Vec { + ) -> Vec { info!( - "try to evict range"; - "evict_range" => ?evict_range, + "try to evict region"; + "evict_region" => ?evict_region, + "reason" => ?evict_reason, ); - // cancel loading ranges overlapped with `evict_range` - self.pending_ranges_loading_data - .iter_mut() - .for_each(|(r, _, canceled)| { - if evict_range.overlaps(r) { - info!( - "evict range that overlaps with loading range"; - "evicted_range" => ?evict_range, - "overlapped_range" => ?r, - ); - *canceled = true; - } - }); - - let mut overlapped_ranges = vec![]; - for r in self.ranges.keys() { - if r.contains_range(evict_range) { - if self.evict_within_range(evict_range, &r.clone(), evict_reason) { - return vec![evict_range.clone()]; - } else { - return vec![]; + if let Some(meta) = self.regions.get(&evict_region.id) { + // if epoch not changed, no need to do range scan. + if meta.region.get_region_epoch().version == evict_region.get_region_epoch().version { + if let Some(region) = + self.do_evict_region(evict_region.id, evict_region, evict_reason) + { + return vec![region]; } - } else if r.overlaps(evict_range) { - overlapped_ranges.push(r.clone()); } } - if overlapped_ranges.is_empty() { - info!( - "evict a range that is not cached"; - "range" => ?evict_range, - ); - return vec![]; + let mut deleteable_regions = vec![]; + let mut evict_ids = vec![]; + let evict_range = CacheRange::from_region(evict_region); + self.iter_overlapped_regions(&evict_range, |meta| { + if evict_range.start >= meta.range.end { + return false; + } + evict_ids.push(meta.region.id); + true + }); + if evict_ids.is_empty() { + info!("evict a region that is not cached"; + "reason" => ?evict_reason, + "region" => ?evict_region); } - - overlapped_ranges - .into_iter() - .filter(|r| self.evict_within_range(r, r, evict_reason)) - .collect() + for rid in evict_ids { + if let Some(region) = self.do_evict_region(rid, evict_region, evict_reason) { + deleteable_regions.push(region); + } + } + deleteable_regions } - // Return true means there is no ongoing snapshot, the evicted_range can be - // deleted now. - fn evict_within_range( + // return the region if it can be directly deleted. + fn do_evict_region( &mut self, - evict_range: &CacheRange, - cached_range: &CacheRange, + id: u64, + evict_region: &Region, evict_reason: EvictReason, - ) -> bool { - assert!(cached_range.contains_range(evict_range)); - info!( - "evict range in cache range engine"; - "evict_range" => ?evict_range, - "cached_range" => ?cached_range, + ) -> Option { + let meta = self.regions.get_mut(&id).unwrap(); + let prev_state = meta.state; + assert!( + meta.range.overlaps(&CacheRange::from_region(evict_region)), + "meta: {:?}, evict_region: {:?}", + meta, + evict_region ); - let meta = self.ranges.remove(cached_range).unwrap(); - let (left_range, right_range) = cached_range.split_off(evict_range); - assert!((left_range.is_some() || right_range.is_some()) || evict_range == cached_range); - - if let Some(left_range) = left_range { - let left_meta = RangeMeta::derive_from(self.id_allocator.allocate_id(), &meta); - self.ranges.insert(left_range, left_meta); + if prev_state == RegionState::Pending { + let meta = self.remove_region(id); + info!( + "evict overlap pending region in cache range engine"; + "reason" => ?evict_reason, + "target_region" => ?evict_region, + "overlap_region" => ?meta.region, + "state" => ?prev_state, + ); + return None; + } else if prev_state.is_evict() { + info!("region already evicted"; "region" => ?meta.region, "state" => ?prev_state); + return None; } - if let Some(right_range) = right_range { - let right_meta = RangeMeta::derive_from(self.id_allocator.allocate_id(), &meta); - self.ranges.insert(right_range, right_meta); - } + if prev_state == RegionState::Active { + meta.mark_evict(RegionState::PendingEvict, evict_reason); + } else { + meta.set_state(RegionState::LoadingCanceled) + }; - self.ranges_being_deleted - .insert(evict_range.clone(), (false, Instant::now(), evict_reason)); + info!( + "evict overlap region in cache range engine"; + "reason" => ?evict_reason, + "target_region" => ?evict_region, + "overlap_region" => ?meta.region, + "state" => ?prev_state, + "new_state" => ?meta.state, + ); - if !meta.range_snapshot_list.is_empty() { - self.historical_ranges.insert(cached_range.clone(), meta); - return false; + if meta.state == RegionState::PendingEvict + && Self::region_ready_to_evict(meta, &self.historical_regions) + { + meta.set_state(RegionState::Evicting); + return Some(meta.region.clone()); } - - // we also need to check with previous historical_ranges - !self - .historical_ranges - .keys() - .any(|r| r.overlaps(evict_range)) + None } - pub fn has_ranges_in_gc(&self) -> bool { - !self.ranges_in_gc.is_empty() + fn remove_region(&mut self, id: u64) -> RangeMeta { + let meta = self.regions.remove(&id).unwrap(); + self.regions_by_range.remove(&meta.range.end); + meta } - pub fn on_delete_ranges(&mut self, ranges: &[CacheRange]) { - for r in ranges { - let (_, t, evict_reason) = self.ranges_being_deleted.remove(r).unwrap(); - observe_eviction_duration(t.saturating_elapsed_secs(), evict_reason); + pub fn on_delete_regions(&mut self, regions: &[Region]) { + for r in regions { + let meta = self.remove_region(r.id); + assert_eq!( + meta.region.get_region_epoch().version, + r.get_region_epoch().version + ); + + let evict_info = meta.evict_info.unwrap(); + observe_eviction_duration( + evict_info.start.saturating_elapsed_secs(), + evict_info.reason, + ); info!( "range eviction done"; - "range" => ?r, + "region" => ?r, ); } } - pub fn set_ranges_in_gc(&mut self, ranges_in_gc: BTreeSet) { - self.ranges_in_gc = ranges_in_gc; + // return whether the operation is successful. + pub fn try_set_regions_in_gc(&self, in_gc: bool) -> bool { + self.is_gc_task_running + .compare_exchange(!in_gc, in_gc, Ordering::AcqRel, Ordering::Relaxed) + .is_ok() } - pub(crate) fn is_overlapped_with_ranges_being_written(&self, range: &CacheRange) -> bool { - self.ranges_being_written.iter().any(|(_, ranges)| { + pub(crate) fn is_overlapped_with_regions_being_written(&self, range: &CacheRange) -> bool { + self.regions_being_written.iter().any(|(_, ranges)| { ranges .iter() .any(|range_being_written| range_being_written.overlaps(range)) }) } - pub(crate) fn record_in_ranges_being_written( + pub(crate) fn record_in_region_being_written( &mut self, write_batch_id: u64, - range: &CacheRange, + range: CacheRange, ) { - self.ranges_being_written + self.regions_being_written .entry(write_batch_id) .or_default() - .push(range.clone()) + .push(range); } - pub(crate) fn clear_ranges_in_being_written( + pub(crate) fn clear_regions_in_being_written( &mut self, write_batch_id: u64, has_entry_applied: bool, ) { - let ranges = self.ranges_being_written.remove(&write_batch_id); + let regions = self.regions_being_written.remove(&write_batch_id); if has_entry_applied { - assert!(!ranges.unwrap().is_empty()); + assert!(!regions.unwrap().is_empty()); } } - pub fn on_gc_finished(&mut self, range: BTreeSet) { - assert_eq!(range, std::mem::take(&mut self.ranges_in_gc)); + pub fn load_region(&mut self, region: Region) -> Result<(), LoadFailedReason> { + use RegionState::*; + if let Some(state) = self.check_overlap_with_region(®ion) { + let reason = match state { + Pending | ReadyToLoad | Loading => LoadFailedReason::PendingRange, + Active => LoadFailedReason::Overlapped, + LoadingCanceled | PendingEvict | Evicting => LoadFailedReason::Evicting, + }; + return Err(reason); + } + let meta = RangeMeta::new(region); + self.new_region_meta(meta); + Ok(()) } - pub fn load_range(&mut self, cache_range: CacheRange) -> Result<(), LoadFailedReason> { - if self.overlap_with_range(&cache_range) { - return Err(LoadFailedReason::Overlapped); - }; - if self.overlap_with_pending_range(&cache_range) { - return Err(LoadFailedReason::PendingRange); + // return `true` is the region is evicted. + pub(crate) fn split_region( + &mut self, + source_region: &Region, + mut new_regions: Vec, + ) { + if let Some(region_meta) = self.region_meta(source_region.id) { + // if region is evicting, skip handling split for simplicity. + if region_meta.state.is_evict() { + info!("region is evicted, skip split"; "meta" => ?®ion_meta, "new_regions" => ?new_regions); + return; + } + } else { + info!("split source region not cached"; "region_id" => source_region.id); + return; } - if self.overlap_with_range_in_gc(&cache_range) { - return Err(LoadFailedReason::InGc); + + let region_meta = self.remove_region(source_region.id); + assert!(!region_meta.state.is_evict()); + if region_meta.region.get_region_epoch().version != source_region.get_region_epoch().version + { + // for pending regions, we keep regions that still fall in this range if epoch + // version changed. + assert_eq!(region_meta.state, RegionState::Pending); + assert!( + region_meta.region.get_region_epoch().version + < source_region.get_region_epoch().version + ); + new_regions.retain(|r| { + r.start_key <= source_region.start_key + && (source_region.end_key.is_empty() + || (source_region.end_key >= r.end_key && !r.end_key.as_slice().is_empty())) + }); + info!("[IME] handle split region met pending region epoch stale"; + "cached" => ?region_meta, + "split_source" => ?source_region, + "cache_new_regions" => ?new_regions); } - if self.overlap_with_evicting_range(&cache_range) { - return Err(LoadFailedReason::Evicting); + + info!("handle region split"; + "region_id" => source_region.id, + "meta" => ?region_meta, + "new_regions" => ?new_regions); + + for r in new_regions { + let meta = RangeMeta::derive_from(r, ®ion_meta); + self.new_region_meta(meta); } - self.pending_ranges.push(cache_range); - Ok(()) - } - // Only ranges that have not been scheduled will be retained in `ranges` - pub fn mark_delete_ranges_scheduled(&mut self, ranges: &mut Vec) { - ranges.retain(|r| { - let (ref mut scheduled, ..) = self.ranges_being_deleted.get_mut(r).unwrap(); - let has_scheduled = *scheduled; - *scheduled = true; - !has_scheduled - }); + // if there are still active snapshot, we need to put the orginal region + // into `historical_regions` to track these snapshots. + if !region_meta.region_snapshot_list.is_empty() { + self.historical_regions.insert( + KeyAndVersion( + region_meta.range.end.clone(), + region_meta.region.get_region_epoch().version, + ), + region_meta, + ); + } } } @@ -515,10 +856,10 @@ impl RangeManager { pub enum LoadFailedReason { Overlapped, PendingRange, - InGc, Evicting, } +#[derive(PartialEq, Debug)] pub enum RangeCacheStatus { NotInCache, Cached, @@ -527,221 +868,241 @@ pub enum RangeCacheStatus { #[cfg(test)] mod tests { - use std::collections::BTreeSet; - use engine_traits::{CacheRange, EvictReason, FailedReason}; - use super::RangeManager; - use crate::range_manager::LoadFailedReason; + use super::*; + use crate::{range_manager::LoadFailedReason, test_util::new_region}; #[test] fn test_range_manager() { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, "k00", b"k10"); - range_mgr.new_range(r1.clone()); - range_mgr.set_safe_point(&r1, 5); + range_mgr.new_region(r1.clone()); + range_mgr.set_safe_point(r1.id, 5); assert_eq!( - range_mgr.range_snapshot(&r1, 5).unwrap_err(), + range_mgr.region_snapshot(r1.id, 0, 5).unwrap_err(), FailedReason::TooOldRead ); - range_mgr.range_snapshot(&r1, 8).unwrap(); - range_mgr.range_snapshot(&r1, 10).unwrap(); - let tmp_r = CacheRange::new(b"k08".to_vec(), b"k15".to_vec()); + range_mgr.region_snapshot(r1.id, 0, 8).unwrap(); + let snapshot1 = RangeCacheSnapshotMeta::new(1, 0, CacheRange::from_region(&r1), 8, 1); + range_mgr.region_snapshot(r1.id, 0, 10).unwrap(); + let snapshot2 = RangeCacheSnapshotMeta::new(1, 0, CacheRange::from_region(&r1), 10, 2); assert_eq!( - range_mgr.range_snapshot(&tmp_r, 8).unwrap_err(), + range_mgr.region_snapshot(2, 0, 8).unwrap_err(), FailedReason::NotCached ); - let tmp_r = CacheRange::new(b"k10".to_vec(), b"k11".to_vec()); + + let mut r_evict = new_region(2, b"k03", b"k06"); + let mut r_left = new_region(1, b"k00", b"k03"); + let mut r_right = new_region(3, b"k06", b"k10"); + for r in [&mut r_evict, &mut r_left, &mut r_right] { + r.mut_region_epoch().version = 2; + } + range_mgr.split_region(&r1, vec![r_left.clone(), r_evict.clone(), r_right.clone()]); + range_mgr.evict_region(&r_evict, EvictReason::AutoEvict); + let range1 = CacheRange::from_region(&r1); + let meta1 = range_mgr + .historical_regions + .get(&KeyAndVersion(range1.end.clone(), 0)) + .unwrap(); assert_eq!( - range_mgr.range_snapshot(&tmp_r, 8).unwrap_err(), - FailedReason::NotCached + range_mgr.regions.get(&r_evict.id).unwrap().state, + RegionState::PendingEvict, ); - - let r_evict = CacheRange::new(b"k03".to_vec(), b"k06".to_vec()); - let r_left = CacheRange::new(b"k00".to_vec(), b"k03".to_vec()); - let r_right = CacheRange::new(b"k06".to_vec(), b"k10".to_vec()); - range_mgr.evict_range(&r_evict, EvictReason::AutoEvict); - let meta1 = range_mgr.historical_ranges.get(&r1).unwrap(); - assert!(range_mgr.ranges_being_deleted.get(&r_evict).is_some()); - assert!(range_mgr.ranges.get(&r1).is_none()); - let meta2 = range_mgr.ranges.get(&r_left).unwrap(); - let meta3 = range_mgr.ranges.get(&r_right).unwrap(); + assert_eq!( + range_mgr.regions_by_range.get(&range1.end).unwrap(), + &r_right.id + ); + let meta2 = range_mgr.regions.get(&r_left.id).unwrap(); + let meta3 = range_mgr.regions.get(&r_right.id).unwrap(); assert!(meta1.safe_point == meta2.safe_point && meta1.safe_point == meta3.safe_point); // evict a range with accurate match - let _ = range_mgr.range_snapshot(&r_left, 10); - range_mgr.evict_range(&r_left, EvictReason::AutoEvict); - assert!(range_mgr.historical_ranges.get(&r_left).is_some()); - assert!(range_mgr.ranges_being_deleted.get(&r_left).is_some()); - assert!(range_mgr.ranges.get(&r_left).is_none()); + range_mgr.region_snapshot(r_left.id, 2, 10).unwrap(); + let snapshot3 = + RangeCacheSnapshotMeta::new(r_left.id, 2, CacheRange::from_region(&r1), 10, 3); + range_mgr.evict_region(&r_left, EvictReason::AutoEvict); + assert_eq!( + range_mgr.regions.get(&r_left.id).unwrap().state, + RegionState::PendingEvict, + ); + assert!(range_mgr.remove_region_snapshot(&snapshot1).is_empty()); - assert!( - range_mgr - .evict_range(&r_right, EvictReason::AutoEvict) - .is_empty() + let regions = range_mgr.remove_region_snapshot(&snapshot2); + assert_eq!(regions, vec![r_evict.clone()]); + assert_eq!( + range_mgr.region_meta(r_evict.id).unwrap().get_state(), + RegionState::Evicting + ); + + let regions = range_mgr.remove_region_snapshot(&snapshot3); + assert_eq!(regions, vec![r_left.clone()]); + assert_eq!( + range_mgr.region_meta(r_left.id).unwrap().get_state(), + RegionState::Evicting ); - assert!(range_mgr.historical_ranges.get(&r_right).is_none()); } #[test] fn test_range_load() { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k10".to_vec(), b"k20".to_vec()); - let r3 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let r4 = CacheRange::new(b"k25".to_vec(), b"k35".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.new_range(r3.clone()); - range_mgr.evict_range(&r1, EvictReason::AutoEvict); - - let mut gced = BTreeSet::default(); - gced.insert(r2.clone()); - range_mgr.set_ranges_in_gc(gced); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + let mut r2 = new_region(2, b"k10", b"k20"); + r2.mut_region_epoch().version = 2; + let r3 = new_region(3, b"k20", b"k30"); + let r4 = new_region(4, b"k25", b"k35"); + + range_mgr.new_region(r1.clone()); + range_mgr.load_region(r2.clone()).unwrap(); + range_mgr.new_region(r3.clone()); + range_mgr.evict_region(&r1, EvictReason::AutoEvict); assert_eq!( - range_mgr.load_range(r1).unwrap_err(), + range_mgr.load_region(r1).unwrap_err(), LoadFailedReason::Evicting ); + // load r2 with an outdated epoch. + r2.mut_region_epoch().version = 1; assert_eq!( - range_mgr.load_range(r2).unwrap_err(), - LoadFailedReason::InGc + range_mgr.load_region(r2).unwrap_err(), + LoadFailedReason::PendingRange, ); assert_eq!( - range_mgr.load_range(r4).unwrap_err(), + range_mgr.load_region(r4).unwrap_err(), LoadFailedReason::Overlapped ); } #[test] fn test_range_load_overlapped() { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let r3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.evict_range(&r1, EvictReason::AutoEvict); - - let mut gced = BTreeSet::default(); - gced.insert(r2); - range_mgr.set_ranges_in_gc(gced); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + // let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); + range_mgr.new_region(r1.clone()); + range_mgr.evict_region(&r1, EvictReason::AutoEvict); - range_mgr.load_range(r3).unwrap(); + range_mgr.load_region(r3).unwrap(); - let r = CacheRange::new(b"".to_vec(), b"k05".to_vec()); + let r = new_region(4, b"k00", b"k05"); assert_eq!( - range_mgr.load_range(r).unwrap_err(), + range_mgr.load_region(r).unwrap_err(), LoadFailedReason::Evicting ); - let r = CacheRange::new(b"k05".to_vec(), b"k15".to_vec()); + let r = new_region(4, b"k05", b"k15"); assert_eq!( - range_mgr.load_range(r).unwrap_err(), + range_mgr.load_region(r).unwrap_err(), LoadFailedReason::Evicting ); - let r = CacheRange::new(b"k15".to_vec(), b"k25".to_vec()); - assert_eq!(range_mgr.load_range(r).unwrap_err(), LoadFailedReason::InGc); - let r = CacheRange::new(b"k25".to_vec(), b"k35".to_vec()); - assert_eq!(range_mgr.load_range(r).unwrap_err(), LoadFailedReason::InGc); - - let r = CacheRange::new(b"k35".to_vec(), b"k45".to_vec()); + let r = new_region(4, b"k35", b"k45"); assert_eq!( - range_mgr.load_range(r).unwrap_err(), + range_mgr.load_region(r).unwrap_err(), LoadFailedReason::PendingRange ); - let r = CacheRange::new(b"k45".to_vec(), b"k55".to_vec()); + let r = new_region(4, b"k45", b"k55"); assert_eq!( - range_mgr.load_range(r).unwrap_err(), + range_mgr.load_region(r).unwrap_err(), LoadFailedReason::PendingRange ); } #[test] - fn test_evict_ranges() { + fn test_evict_regions() { { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let r3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.new_range(r2.clone()); - range_mgr.new_range(r3.clone()); - range_mgr.contains_range(&r1); - range_mgr.contains_range(&r2); - range_mgr.contains_range(&r3); - - let r4 = CacheRange::new(b"k00".to_vec(), b"k05".to_vec()); - let r5 = CacheRange::new(b"k05".to_vec(), b"k10".to_vec()); - assert_eq!(range_mgr.evict_range(&r4, EvictReason::AutoEvict), vec![r4]); - assert_eq!( - range_mgr.ranges().keys().collect::>(), - vec![&r5, &r2, &r3] - ); - - let r6 = CacheRange::new(b"k24".to_vec(), b"k27".to_vec()); - let r7 = CacheRange::new(b"k20".to_vec(), b"k24".to_vec()); - let r8 = CacheRange::new(b"k27".to_vec(), b"k30".to_vec()); - assert_eq!(range_mgr.evict_range(&r6, EvictReason::AutoEvict), vec![r6]); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); + range_mgr.new_region(r1.clone()); + range_mgr.new_region(r2.clone()); + range_mgr.new_region(r3.clone()); + range_mgr.contains_region(r1.id); + range_mgr.contains_region(r2.id); + range_mgr.contains_region(r3.id); + + let mut r4 = new_region(4, b"k00", b"k05"); + r4.mut_region_epoch().version = 2; assert_eq!( - range_mgr.ranges().keys().collect::>(), - vec![&r5, &r7, &r8, &r3] + range_mgr.evict_region(&r4, EvictReason::AutoEvict), + vec![r1] ); } { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let r3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.new_range(r2.clone()); - range_mgr.new_range(r3.clone()); - range_mgr.contains_range(&r1); - range_mgr.contains_range(&r2); - range_mgr.contains_range(&r3); - - let r4 = CacheRange::new(b"k".to_vec(), b"k51".to_vec()); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); + range_mgr.new_region(r1.clone()); + range_mgr.new_region(r2.clone()); + range_mgr.new_region(r3.clone()); + assert!(range_mgr.contains_region(r1.id)); + assert!(range_mgr.contains_region(r2.id)); + assert!(range_mgr.contains_region(r3.id)); + + let r4 = new_region(4, b"k", b"k51"); assert_eq!( - range_mgr.evict_range(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r1, r2, r3] ); - assert!(range_mgr.ranges().is_empty()); + assert!( + range_mgr + .regions() + .values() + .all(|m| m.get_state() == RegionState::Evicting) + ); } { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let r3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.new_range(r2.clone()); - range_mgr.new_range(r3.clone()); - - let r4 = CacheRange::new(b"k25".to_vec(), b"k55".to_vec()); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); + range_mgr.new_region(r1.clone()); + range_mgr.new_region(r2.clone()); + range_mgr.new_region(r3.clone()); + + let r4 = new_region(4, b"k25", b"k55"); assert_eq!( - range_mgr.evict_range(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r2, r3] ); - assert_eq!(range_mgr.ranges().len(), 1); + assert_eq!( + range_mgr + .regions() + .values() + .filter(|m| m.get_state() == RegionState::Active) + .count(), + 1 + ); } { - let mut range_mgr = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k30".to_vec(), b"k40".to_vec()); - let r3 = CacheRange::new(b"k50".to_vec(), b"k60".to_vec()); - range_mgr.new_range(r1.clone()); - range_mgr.new_range(r2.clone()); - range_mgr.new_range(r3.clone()); - - let r4 = CacheRange::new(b"k25".to_vec(), b"k75".to_vec()); + let mut range_mgr = RegionManager::default(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k30", b"k40"); + let r3 = new_region(3, b"k50", b"k60"); + range_mgr.new_region(r1.clone()); + range_mgr.new_region(r2.clone()); + range_mgr.new_region(r3.clone()); + + let r4 = new_region(4, b"k25", b"k75"); assert_eq!( - range_mgr.evict_range(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r2, r3] ); - assert_eq!(range_mgr.ranges().len(), 1); + assert_eq!( + range_mgr + .regions() + .values() + .filter(|m| m.get_state() == RegionState::Active) + .count(), + 1 + ); } } } diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 555319a4a20..88370596d7b 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -11,7 +11,6 @@ use std::{ }; use crossbeam::sync::ShardedLock; -use engine_traits::CacheRange; use kvproto::metapb::Region; use parking_lot::Mutex; use raftstore::coprocessor::RegionInfoProvider; @@ -57,13 +56,9 @@ impl RangeStatsManager { } /// Prevents two instances of this from running concurrently. - pub fn set_checking_top_regions(&self, v: bool) { - self.checking_top_regions.store(v, Ordering::Relaxed); - } - - /// Returns true if another thread is checking top regions. - pub fn checking_top_regions(&self) -> bool { - self.checking_top_regions.load(Ordering::Relaxed) + /// Return the previous checking status. + pub fn set_checking_top_regions(&self, v: bool) -> bool { + self.checking_top_regions.swap(v, Ordering::Relaxed) } fn set_max_num_regions(&self, v: usize) { @@ -89,20 +84,19 @@ impl RangeStatsManager { /// 4. Store the results in `ranges_out` using [Vec::extend]. pub fn collect_candidates_for_eviction( &self, - ranges_out: &mut Vec<(CacheRange, u64)>, + regions_out: &mut Vec<(Region, u64)>, is_cached_pred: F, ) where - F: Fn(&CacheRange) -> bool, + F: Fn(&Region) -> bool, { // Gets all of the regions, sorted by activity. let all_regions = self.info_provider.get_top_regions(None).unwrap(); let regions_loaded = self.region_loaded_at.read().unwrap(); - ranges_out.extend( + regions_out.extend( all_regions .iter() .filter_map(|(region, approx_size)| { - let r = CacheRange::from_region(region); - is_cached_pred(&r) + is_cached_pred(region) .then(|| { match regions_loaded.get(®ion.get_id()) { // Do not evict ranges that were loaded less than @@ -115,7 +109,7 @@ impl RangeStatsManager { Some(_) | None => // None indicates range loaded from a hint, not by this manager. { - Some((r, *approx_size)) + Some((region.clone(), *approx_size)) } } }) @@ -134,19 +128,9 @@ impl RangeStatsManager { /// /// TODO (afeinberg): This is inefficient, either make this method bulk, or /// find another way to avoid calling `find_region_by_key` in a loop. - pub fn handle_range_evicted(&self, evicted_range: &CacheRange) { - // TODO (afeinberg): This is inefficient. - let _ = self - .info_provider - .find_region_by_key(&evicted_range.start) - .map(|region| { - let id = region.get_id(); - let _ = self.prev_top_regions.lock().remove(&id); - let _ = { - let mut regions_loaded = self.region_loaded_at.write().unwrap(); - regions_loaded.remove(&id) - }; - }); + pub fn handle_region_evicted(&self, region: &Region) { + self.prev_top_regions.lock().remove(®ion.id); + self.region_loaded_at.write().unwrap().remove(®ion.id); } /// Attempt to adjust the maximum number of cached regions based on memory @@ -212,8 +196,8 @@ impl RangeStatsManager { /// current ones are stored in `ranges_removed_out`. pub fn collect_changed_ranges( &self, - ranges_added_out: &mut Vec, - ranges_removed_out: &mut Vec, + regions_added_out: &mut Vec, + regions_removed_out: &mut Vec, ) { info!("collect_changed_ranges"; "num_regions" => self.max_num_regions()); let curr_top_regions = self @@ -236,13 +220,13 @@ impl RangeStatsManager { ret }; if prev_top_regions.is_empty() { - ranges_added_out.extend(curr_top_regions.values().map(CacheRange::from_region)); + regions_added_out.extend(curr_top_regions.values().cloned()); return; } let added_ranges = curr_top_regions .iter() .filter(|(id, _)| !prev_top_regions.contains_key(id)) - .map(|(_, region)| CacheRange::from_region(region)); + .map(|(_, region)| region.clone()); let regions_loaded = self.region_loaded_at.read().unwrap(); let removed_ranges = prev_top_regions.iter().filter_map(|(&id, region)| { if !curr_top_regions.contains_key(&id) { @@ -255,25 +239,24 @@ impl RangeStatsManager { let _ = mut_prev_top_regions.insert(id, region.clone()); None } - _ => Some(CacheRange::from_region(region)), + _ => Some(region.clone()), } } else { None } }); - ranges_added_out.extend(added_ranges); - ranges_removed_out.extend(removed_ranges); + regions_added_out.extend(added_ranges); + regions_removed_out.extend(removed_ranges); } } #[cfg(test)] pub mod tests { - use kvproto::metapb::Peer; use raftstore::coprocessor::{self, region_info_accessor::TopRegions, RegionInfoProvider}; use tikv_util::box_err; use super::*; - use crate::RangeCacheEngineConfig; + use crate::{test_util::new_region, RangeCacheEngineConfig}; struct RegionInfoSimulator { regions: Mutex, @@ -312,21 +295,11 @@ pub mod tests { } } - fn new_region(id: u64, start_key: &[u8], end_key: &[u8], version: u64) -> Region { - let mut region = Region::default(); - region.set_id(id); - region.set_start_key(start_key.to_vec()); - region.set_end_key(end_key.to_vec()); - region.mut_region_epoch().set_version(version); - region.mut_peers().push(Peer::default()); - region - } - #[test] fn test_collect_changed_regions() { - let region_1 = new_region(1, b"k1", b"k2", 0); + let region_1 = new_region(1, b"k1", b"k2"); - let region_2 = new_region(2, b"k3", b"k4", 0); + let region_2 = new_region(2, b"k3", b"k4"); let sim = Arc::new(RegionInfoSimulator { regions: Mutex::new(vec![(region_1.clone(), 42)]), }); @@ -337,22 +310,22 @@ pub mod tests { RangeCacheEngineConfig::config_for_test().expected_region_size(), sim.clone(), ); - let mut added = Vec::::new(); - let mut removed = Vec::::new(); + let mut added = Vec::new(); + let mut removed = Vec::new(); rsm.collect_changed_ranges(&mut added, &mut removed); - assert_eq!(&added, &[CacheRange::from_region(®ion_1)]); + assert_eq!(&added, &[region_1.clone()]); assert!(removed.is_empty()); let top_regions = vec![(region_1.clone(), 42), (region_2.clone(), 7)]; sim.set_top_regions(&top_regions); added.clear(); removed.clear(); rsm.collect_changed_ranges(&mut added, &mut removed); - assert_eq!(&added, &[CacheRange::from_region(®ion_2)]); + assert_eq!(&added, &[region_2.clone()]); assert!(removed.is_empty()); - let region_3 = new_region(3, b"k5", b"k6", 0); - let region_4 = new_region(4, b"k7", b"k8", 0); - let region_5 = new_region(5, b"k9", b"k10", 0); - let region_6 = new_region(6, b"k11", b"k12", 0); + let region_3 = new_region(3, b"k5", b"k6"); + let region_4 = new_region(4, b"k7", b"k8"); + let region_5 = new_region(5, b"k9", b"k10"); + let region_6 = new_region(6, b"k11", b"k12"); let top_regions = vec![ (region_6.clone(), 42), (region_2.clone(), 7), @@ -364,22 +337,14 @@ pub mod tests { added.clear(); removed.clear(); rsm.collect_changed_ranges(&mut added, &mut removed); - assert_eq!( - &added, - &[ - CacheRange::from_region(®ion_3), - CacheRange::from_region(®ion_4), - CacheRange::from_region(®ion_5), - CacheRange::from_region(®ion_6) - ] - ); + assert_eq!(&added, &[region_3, region_4, region_5, region_6]); // `region_1` is no longer in the top regions list, but since it was loaded less // than 10 ms ago, it should not be included in the removed ranges. assert!(removed.is_empty()); std::thread::sleep(Duration::from_millis(100)); // After 100 ms passed, check again, and verify `region_1` is evictable. rsm.collect_changed_ranges(&mut added, &mut removed); - assert_eq!(&removed, &[CacheRange::from_region(®ion_1)]); + assert_eq!(&removed, &[region_1.clone()]); } #[test] @@ -388,12 +353,12 @@ pub mod tests { rs.iter().map(|&r| (r.clone(), 42)).collect::>() } - let region_1 = new_region(1, b"k1", b"k2", 0); - let region_2 = new_region(2, b"k3", b"k4", 0); - let region_3 = new_region(3, b"k5", b"k6", 0); - let region_4 = new_region(4, b"k7", b"k8", 0); - let region_5 = new_region(5, b"k9", b"k10", 0); - let region_6 = new_region(6, b"k11", b"k12", 0); + let region_1 = new_region(1, b"k1", b"k2"); + let region_2 = new_region(2, b"k3", b"k4"); + let region_3 = new_region(3, b"k5", b"k6"); + let region_4 = new_region(4, b"k7", b"k8"); + let region_5 = new_region(5, b"k9", b"k10"); + let region_6 = new_region(6, b"k11", b"k12"); let all_regions = make_region_vec(&[ ®ion_1, ®ion_2, ®ion_3, ®ion_4, ®ion_5, ®ion_6, @@ -410,17 +375,13 @@ pub mod tests { sim.clone(), ); let r_i_p: Arc = sim.clone(); - let check_is_cached = move |range: &CacheRange| -> bool { - r_i_p - .find_region_by_key(&range.start[1..]) - .unwrap() - .get_id() - <= 5 + let check_is_cached = move |r: &Region| -> bool { + r_i_p.find_region_by_key(&r.start_key).unwrap().get_id() <= 5 }; - let mut _added = Vec::::new(); - let mut _removed = Vec::::new(); + let mut _added = Vec::new(); + let mut _removed = Vec::new(); rsm.collect_changed_ranges(&mut _added, &mut _removed); - let mut candidates_for_eviction = Vec::<(CacheRange, u64)>::new(); + let mut candidates_for_eviction = Vec::new(); rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, &check_is_cached); assert!(candidates_for_eviction.is_empty()); std::thread::sleep(Duration::from_millis(100)); @@ -430,7 +391,7 @@ pub mod tests { .rev() .filter_map(|(r, s)| { if r.get_id() <= 5 { - Some((CacheRange::from_region(r), *s)) + Some((r.clone(), *s)) } else { None } diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index fd5bbf73a5f..516ff312998 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -43,8 +43,9 @@ enum Direction { #[derive(Clone, Debug)] pub struct RangeCacheSnapshotMeta { - pub(crate) range_id: u64, pub(crate) range: CacheRange, + pub(crate) epoch_version: u64, + pub(crate) region_id: u64, pub(crate) snapshot_ts: u64, // Sequence number is shared between RangeCacheEngine and disk KvEnigne to // provide atomic write @@ -52,17 +53,24 @@ pub struct RangeCacheSnapshotMeta { } impl RangeCacheSnapshotMeta { - fn new(range_id: u64, range: CacheRange, snapshot_ts: u64, sequence_number: u64) -> Self { + pub(crate) fn new( + region_id: u64, + epoch_version: u64, + range: CacheRange, + snapshot_ts: u64, + sequence_number: u64, + ) -> Self { Self { - range_id, range, + epoch_version, + region_id, snapshot_ts, sequence_number, } } } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct RangeCacheSnapshot { snapshot_meta: RangeCacheSnapshotMeta, skiplist_engine: SkiplistEngine, @@ -72,14 +80,23 @@ pub struct RangeCacheSnapshot { impl RangeCacheSnapshot { pub fn new( engine: RangeCacheMemoryEngine, + region_id: u64, + region_epoch: u64, range: CacheRange, read_ts: u64, seq_num: u64, ) -> result::Result { let mut core = engine.core.write(); - let range_id = core.range_manager.range_snapshot(&range, read_ts)?; + core.range_manager + .region_snapshot(region_id, region_epoch, read_ts)?; Ok(RangeCacheSnapshot { - snapshot_meta: RangeCacheSnapshotMeta::new(range_id, range, read_ts, seq_num), + snapshot_meta: RangeCacheSnapshotMeta::new( + region_id, + region_epoch, + range, + read_ts, + seq_num, + ), skiplist_engine: core.engine.clone(), engine: engine.clone(), }) @@ -89,17 +106,15 @@ impl RangeCacheSnapshot { impl Drop for RangeCacheSnapshot { fn drop(&mut self) { let mut core = self.engine.core.write(); - let mut ranges_removable = core + let regions_removable = core .range_manager - .remove_range_snapshot(&self.snapshot_meta); - core.mut_range_manager() - .mark_delete_ranges_scheduled(&mut ranges_removable); - if !ranges_removable.is_empty() { + .remove_region_snapshot(&self.snapshot_meta); + if !regions_removable.is_empty() { drop(core); if let Err(e) = self .engine .bg_worker_manager() - .schedule_task(BackgroundTask::DeleteRange(ranges_removable)) + .schedule_task(BackgroundTask::DeleteRegions(regions_removable)) { error!( "schedule delete range failed"; @@ -672,9 +687,11 @@ mod tests { }; use engine_traits::{ CacheRange, EvictReason, FailedReason, IterMetricsCollector, IterOptions, Iterable, - Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, WriteBatch, - WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, + Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, RegionEvent, + WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, }; + use keys::DATA_PREFIX_KEY; + use kvproto::metapb::Region; use tempfile::Builder; use tikv_util::config::VersionTrack; @@ -682,11 +699,13 @@ mod tests { use crate::{ engine::{cf_to_id, SkiplistEngine}, keys::{ - construct_key, construct_user_key, construct_value, decode_key, encode_key, - encode_seek_key, InternalBytes, ValueType, + construct_key, construct_region_key, construct_user_key, construct_value, decode_key, + encode_key, encode_seek_key, InternalBytes, ValueType, }, perf_context::PERF_CONTEXT, + range_manager::RegionState, statistics::Tickers, + test_util::new_region, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, RangeCacheWriteBatch, }; @@ -696,19 +715,15 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"k00", b"k10"); + engine.new_region(region.clone()); let verify_snapshot_count = |snapshot_ts, count| { let core = engine.core.read(); if count > 0 { assert_eq!( - *core - .range_manager - .ranges() - .get(&range) - .unwrap() - .range_snapshot_list() + *core.range_manager.regions()[®ion.id] + .region_snapshot_list() .0 .get(&snapshot_ts) .unwrap(), @@ -716,11 +731,8 @@ mod tests { ); } else { assert!( - core.range_manager - .ranges() - .get(&range) - .unwrap() - .range_snapshot_list() + core.range_manager.regions()[®ion.id] + .region_snapshot_list() .0 .get(&snapshot_ts) .is_none() @@ -728,30 +740,31 @@ mod tests { } }; - let s1 = engine.snapshot(range.clone(), 5, u64::MAX).unwrap(); + let range = CacheRange::from_region(®ion); + let s1 = engine.snapshot(1, 0, range.clone(), 5, u64::MAX).unwrap(); { let mut core = engine.core.write(); - let t_range = CacheRange::new(b"k00".to_vec(), b"k02".to_vec()); - assert!(!core.range_manager.set_safe_point(&t_range, 5)); - assert!(core.range_manager.set_safe_point(&range, 5)); + assert!(core.range_manager.set_safe_point(region.id, 5)); } assert_eq!( - engine.snapshot(range.clone(), 5, u64::MAX).unwrap_err(), + engine + .snapshot(region.id, 0, CacheRange::from_region(®ion), 5, u64::MAX) + .unwrap_err(), FailedReason::TooOldRead ); - let s2 = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let s2 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(5, 1); verify_snapshot_count(10, 1); - let s3 = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let s3 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(10, 2); drop(s1); verify_snapshot_count(5, 0); drop(s2); verify_snapshot_count(10, 1); - let s4 = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let s4 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(10, 2); drop(s4); verify_snapshot_count(10, 1); @@ -759,11 +772,8 @@ mod tests { { let core = engine.core.write(); assert!( - core.range_manager - .ranges() - .get(&range) - .unwrap() - .range_snapshot_list() + core.range_manager.regions()[®ion.id] + .region_snapshot_list() .is_empty() ); } @@ -808,6 +818,7 @@ mod tests { fn construct_mvcc_key(key: &str, mvcc: u64) -> Vec { let mut k = vec![]; + k.extend_from_slice(DATA_PREFIX_KEY); k.extend_from_slice(key.as_bytes()); k.put_u64(!mvcc); k @@ -886,19 +897,20 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "b", "val", 10, 5); put_key_val(&sl, "c", "vall", 10, 5); } - let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -924,12 +936,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); fill_data_in_skiplist(sl.clone(), (1..10).step_by(1), 1..50, 1); // k1 is deleted at seq_num 150 while k49 is deleted at seq num 101 @@ -938,7 +951,7 @@ mod tests { let opts = ReadOptions::default(); { - let snapshot = engine.snapshot(range.clone(), 10, 60).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 60).unwrap(); for i in 1..10 { for mvcc in 1..50 { let k = construct_key(i, mvcc); @@ -960,7 +973,7 @@ mod tests { // all deletions { - let snapshot = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); for i in 1..10 { for mvcc in 1..50 { let k = construct_key(i, mvcc); @@ -976,7 +989,7 @@ mod tests { // some deletions { - let snapshot = engine.snapshot(range.clone(), 10, 105).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 105).unwrap(); for mvcc in 1..50 { for i in 1..7 { let k = construct_key(i, mvcc); @@ -1004,20 +1017,21 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); - let step: i32 = 2; + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); + let step: i32 = 2; { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); fill_data_in_skiplist(sl.clone(), (1..100).step_by(step as usize), 1..10, 1); delete_data_in_skiplist(sl, (1..100).step_by(step as usize), 1..10, 200); } let mut iter_opt = IterOptions::default(); - let snapshot = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); // boundaries are not set assert!(snapshot.iterator_opt("lock", iter_opt.clone()).is_err()); @@ -1034,7 +1048,7 @@ mod tests { // Not restricted by bounds, no deletion (seq_num 150) { - let snapshot = engine.snapshot(range.clone(), 100, 150).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 100, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); verify_key_values( @@ -1070,7 +1084,7 @@ mod tests { // Not restricted by bounds, some deletions (seq_num 230) { - let snapshot = engine.snapshot(range.clone(), 10, 230).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 230).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); verify_key_values( @@ -1114,7 +1128,7 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); { - let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_first().unwrap()); @@ -1155,7 +1169,7 @@ mod tests { // with bounds, some deletions (seq_num 215) { - let snapshot = engine.snapshot(range.clone(), 10, 215).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 215).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt).unwrap(); // sequence can see the deletion @@ -1191,13 +1205,14 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); let step: i32 = 2; { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); fill_data_in_skiplist(sl.clone(), (1..100).step_by(step as usize), 1..10, 1); delete_data_in_skiplist(sl, (1..100).step_by(step as usize), 1..10, 200); @@ -1211,7 +1226,7 @@ mod tests { // Not restricted by bounds, no deletion (seq_num 150) { - let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); verify_key_values( @@ -1250,7 +1265,7 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); { - let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt).unwrap(); assert!(iter.seek_to_last().unwrap()); @@ -1295,12 +1310,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "aaa", "va1", 10, 1); @@ -1323,7 +1339,7 @@ mod tests { // seq num 1 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 1).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 1).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va1"); @@ -1351,7 +1367,7 @@ mod tests { // seq num 2 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 2).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 2).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va1"); @@ -1364,7 +1380,7 @@ mod tests { // seq num 5 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 5).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 5).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"vb2"); @@ -1375,7 +1391,7 @@ mod tests { // seq num 6 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 6).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 6).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va4"); @@ -1418,12 +1434,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "aaa", "va1", 10, 2); @@ -1446,7 +1463,7 @@ mod tests { // seq num 1 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 1).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 1).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc1"); @@ -1464,7 +1481,7 @@ mod tests { // seq num 2 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 2).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 2).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc1"); @@ -1477,7 +1494,7 @@ mod tests { // seq num 5 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 5).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 5).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vb2"); @@ -1488,7 +1505,7 @@ mod tests { // seq num 6 { - let snapshot = engine.snapshot(range.clone(), u64::MAX, 6).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 6).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc4"); @@ -1512,7 +1529,8 @@ mod tests { #[test] fn test_iter_user_skip() { let mut iter_opt = IterOptions::default(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -1521,10 +1539,10 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), )); - engine.new_range(range.clone()); + engine.new_region(region.clone()); let sl = { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); core.engine.data[cf_to_id("write")].clone() }; @@ -1536,7 +1554,7 @@ mod tests { put_key_val(&sl, "b", v.as_str(), 10, s + i); } - let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("b", 10); @@ -1559,10 +1577,10 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), )); - engine.new_range(range.clone()); + engine.new_region(region.clone()); let sl = { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); core.engine.data[cf_to_id("write")].clone() }; @@ -1573,7 +1591,7 @@ mod tests { delete_key(&sl, "b", 10, s + i); } - let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("a", 10); @@ -1590,10 +1608,10 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), )); - engine.new_range(range.clone()); + engine.new_region(region.clone()); let sl = { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); core.engine.data[cf_to_id("write")].clone() }; put_key_val(&sl, "a", "val", 10, 1); @@ -1602,7 +1620,7 @@ mod tests { } let v = construct_value(50, 50); put_key_val(&sl, "b", v.as_str(), 10, 50); - let snapshot = engine.snapshot(range.clone(), 10, 50).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, 50).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("b", 10); @@ -1623,10 +1641,10 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), )); - engine.new_range(range.clone()); + engine.new_region(region.clone()); let sl = { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); core.engine.data[cf_to_id("write")].clone() }; let mut s = 1; @@ -1637,7 +1655,7 @@ mod tests { let v = construct_value(50, 50); put_key_val(&sl, "b", v.as_str(), 10, s + 50); - let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(!iter.seek_to_first().unwrap()); assert!(!iter.valid().unwrap()); @@ -1655,12 +1673,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"k000".to_vec(), b"k100".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"k000", b"k100"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); let guard = &epoch::pin(); @@ -1681,7 +1700,9 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); iter_opt.set_prefix_same_as_start(true); - let snapshot = engine.snapshot(range.clone(), u64::MAX, u64::MAX).unwrap(); + let snapshot = engine + .snapshot(1, 0, range.clone(), u64::MAX, u64::MAX) + .unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); // prefix seek, forward @@ -1749,45 +1770,43 @@ mod tests { }); } - fn verify_evict_range_deleted(engine: &RangeCacheMemoryEngine, range: &CacheRange) { - let mut wait = 0; - while wait < 10 { - wait += 1; - if !engine - .core - .read() - .range_manager() - .ranges_being_deleted - .is_empty() - { - std::thread::sleep(Duration::from_millis(200)); - } else { - break; - } - } + fn verify_evict_region_deleted(engine: &RangeCacheMemoryEngine, region: &Region) { + test_util::eventually( + Duration::from_millis(100), + Duration::from_millis(2000), + || { + !engine + .core + .read() + .range_manager() + .regions() + .values() + .any(|m| m.get_state().is_evict()) + }, + ); let write_handle = engine.core.read().engine.cf_handle("write"); - let start_key = encode_seek_key(&range.start, u64::MAX); + let start_key = encode_seek_key(®ion.start_key, u64::MAX); let mut iter = write_handle.iterator(); let guard = &epoch::pin(); iter.seek(&start_key, guard); - let end = encode_seek_key(&range.end, u64::MAX); + let end = encode_seek_key(®ion.end_key, u64::MAX); assert!(iter.key() > &end || !iter.valid()); } #[test] - fn test_evict_range_without_snapshot() { + fn test_evict_region_without_snapshot() { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(construct_user_key(0), construct_user_key(30)); - let evict_range = CacheRange::new(construct_user_key(10), construct_user_key(20)); - engine.new_range(range.clone()); + let region = new_region(1, construct_region_key(0), construct_region_key(30)); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); let guard = &epoch::pin(); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); for i in 0..30 { let user_key = construct_key(i, 10); @@ -1798,19 +1817,38 @@ mod tests { } } - engine.evict_range(&evict_range, EvictReason::AutoEvict); + let mut new_regions = vec![ + new_region(1, construct_region_key(0), construct_region_key(10)), + new_region(2, construct_region_key(10), construct_region_key(20)), + new_region(3, construct_region_key(20), construct_region_key(30)), + ]; + new_regions.iter_mut().for_each(|r| { + r.mut_region_epoch().version = 1; + }); + + engine.on_region_event(RegionEvent::Split { + source: region.clone(), + new_regions: new_regions.clone(), + }); + + let evict_region = new_regions[1].clone(); + engine.evict_region(&evict_region, EvictReason::AutoEvict); assert_eq!( - engine.snapshot(range.clone(), 10, 200).unwrap_err(), - FailedReason::NotCached + engine.snapshot(1, 0, range.clone(), 10, 200).unwrap_err(), + FailedReason::EpochNotMatch ); assert_eq!( - engine.snapshot(evict_range.clone(), 10, 200).unwrap_err(), + engine + .snapshot(2, 1, CacheRange::from_region(&evict_region), 10, 200) + .unwrap_err(), FailedReason::NotCached ); - let r_left = CacheRange::new(construct_user_key(0), construct_user_key(10)); - let r_right = CacheRange::new(construct_user_key(20), construct_user_key(30)); - let snap_left = engine.snapshot(r_left, 10, 200).unwrap(); + let r_left = new_regions[0].clone(); + let r_right = new_regions[2].clone(); + let snap_left = engine + .snapshot(r_left.id, 1, CacheRange::from_region(&r_left), 10, 200) + .unwrap(); let mut iter_opt = IterOptions::default(); let lower_bound = construct_user_key(0); @@ -1821,7 +1859,9 @@ mod tests { iter.seek_to_first().unwrap(); verify_key_values(&mut iter, (0..10).step_by(1), 10..11, true, true); - let snap_right = engine.snapshot(r_right, 10, 200).unwrap(); + let snap_right = engine + .snapshot(r_right.id, 1, CacheRange::from_region(&r_right), 10, 200) + .unwrap(); let lower_bound = construct_user_key(20); let upper_bound = construct_user_key(30); iter_opt.set_upper_bound(&upper_bound, 0); @@ -1831,7 +1871,7 @@ mod tests { verify_key_values(&mut iter, (20..30).step_by(1), 10..11, true, true); // verify the key, values are delete - verify_evict_range_deleted(&engine, &evict_range); + verify_evict_region_deleted(&engine, &evict_region); } #[test] @@ -1839,14 +1879,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(construct_user_key(0), construct_user_key(30)); - let evict_range = CacheRange::new(construct_user_key(10), construct_user_key(20)); - engine.new_range(range.clone()); + let region = new_region(1, construct_region_key(0), construct_region_key(30)); + engine.new_region(region.clone()); let guard = &epoch::pin(); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); for i in 0..30 { let user_key = construct_key(i, 10); @@ -1861,51 +1900,86 @@ mod tests { } } - let s1 = engine.snapshot(range.clone(), 10, 10); - let s2 = engine.snapshot(range, 20, 20); - engine.evict_range(&evict_range, EvictReason::AutoEvict); - let range_left = CacheRange::new(construct_user_key(0), construct_user_key(10)); - let s3 = engine.snapshot(range_left, 20, 20).unwrap(); - let range_right = CacheRange::new(construct_user_key(20), construct_user_key(30)); - let s4 = engine.snapshot(range_right, 20, 20).unwrap(); + let range = CacheRange::from_region(®ion); + let s1 = engine.snapshot(1, 0, range.clone(), 10, 10); + let s2 = engine.snapshot(1, 0, range, 20, 20); + + let mut new_regions = vec![ + new_region(1, construct_region_key(0), construct_region_key(10)), + new_region(2, construct_region_key(10), construct_region_key(20)), + new_region(3, construct_region_key(20), construct_region_key(30)), + ]; + new_regions.iter_mut().for_each(|r| { + r.mut_region_epoch().version = 1; + }); + + engine.on_region_event(RegionEvent::Split { + source: region.clone(), + new_regions: new_regions.clone(), + }); + + let evict_region = new_regions[1].clone(); + engine.evict_region(&evict_region, EvictReason::AutoEvict); + + let r_left = new_regions[0].clone(); + let s3 = engine + .snapshot( + r_left.id, + r_left.get_region_epoch().version, + CacheRange::from_region(&r_left), + 20, + 20, + ) + .unwrap(); + let r_right = new_regions[2].clone(); + let s4 = engine + .snapshot( + r_right.id, + r_right.get_region_epoch().version, + CacheRange::from_region(&r_left), + 20, + 20, + ) + .unwrap(); drop(s3); - let range_left_eviction = CacheRange::new(construct_user_key(0), construct_user_key(5)); - engine.evict_range(&range_left_eviction, EvictReason::AutoEvict); + engine.evict_region(&r_left, EvictReason::AutoEvict); // todo(SpadeA): memory limiter { // evict_range is not eligible for delete - assert!( + assert_eq!( engine .core .read() .range_manager() - .ranges_being_deleted - .get(&evict_range) - .is_some() + .region_meta(evict_region.id) + .unwrap() + .get_state(), + RegionState::PendingEvict ); } drop(s1); { // evict_range is still not eligible for delete - assert!( + assert_eq!( engine .core .read() .range_manager() - .ranges_being_deleted - .get(&evict_range) - .is_some() + .region_meta(evict_region.id) + .unwrap() + .get_state(), + RegionState::PendingEvict ); } drop(s2); // Now, all snapshots before evicting `evict_range` are released - verify_evict_range_deleted(&engine, &evict_range); + verify_evict_region_deleted(&engine, &evict_region); drop(s4); - verify_evict_range_deleted(&engine, &range_left_eviction); + verify_evict_region_deleted(&engine, &r_left); } #[test] @@ -1913,12 +1987,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); delete_key(&sl, "a", 10, 5); @@ -1933,7 +2008,7 @@ mod tests { let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); - let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); while iter.valid().unwrap() { @@ -1957,12 +2032,13 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); { let mut core = engine.core.write(); - core.range_manager.set_safe_point(&range, 5); + core.range_manager.set_safe_point(region.id, 5); let sl = core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "a", "val", 10, 5); @@ -1995,7 +2071,7 @@ mod tests { } let statistics = engine.statistics(); - let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); assert_eq!(PERF_CONTEXT.with(|c| c.borrow().get_read_bytes), 0); let key = construct_mvcc_key("a", 10); snapshot.get_value_cf("write", &key).unwrap(); @@ -2037,7 +2113,7 @@ mod tests { iter.next().unwrap(); rocks_iter.next().unwrap(); drop(iter); - assert_eq!(PERF_CONTEXT.with(|c| c.borrow().iter_read_bytes), 54); + assert_eq!(PERF_CONTEXT.with(|c| c.borrow().iter_read_bytes), 58); assert_eq!(2, statistics.get_ticker_count(Tickers::NumberDbSeek)); assert_eq!(2, statistics.get_ticker_count(Tickers::NumberDbSeekFound)); assert_eq!(2, statistics.get_ticker_count(Tickers::NumberDbNext)); @@ -2054,12 +2130,12 @@ mod tests { rocks_iter.prev().unwrap(); drop(rocks_iter); drop(iter); - assert_eq!(statistics.get_ticker_count(Tickers::IterBytesRead), 108); + assert_eq!(statistics.get_ticker_count(Tickers::IterBytesRead), 116); assert_eq!( rocks_statistics.get_and_reset_ticker_count(DBStatisticsTickerType::IterBytesRead), statistics.get_and_reset_ticker_count(Tickers::IterBytesRead) ); - assert_eq!(PERF_CONTEXT.with(|c| c.borrow().iter_read_bytes), 108); + assert_eq!(PERF_CONTEXT.with(|c| c.borrow().iter_read_bytes), 116); assert_eq!(3, statistics.get_ticker_count(Tickers::NumberDbSeek)); assert_eq!(3, statistics.get_ticker_count(Tickers::NumberDbSeekFound)); assert_eq!(3, statistics.get_ticker_count(Tickers::NumberDbPrev)); @@ -2081,16 +2157,19 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(range.clone()); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.new_region(region.clone()); let mut wb = engine.write_batch(); - wb.prepare_for_range(range.clone()); + wb.prepare_for_region(®ion); put_entries(&mut wb); wb.set_sequence_number(wb_sequence).unwrap(); wb.write().unwrap(); - let snap = engine.snapshot(range.clone(), 100, snap_sequence).unwrap(); + let snap = engine + .snapshot(1, 0, range.clone(), 100, snap_sequence) + .unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -2103,34 +2182,34 @@ mod tests { #[test] fn test_iterator() { let (.., mut iter) = set_up_for_iteator(100, 200, |wb| { - wb.put(b"a", b"1").unwrap(); - wb.put(b"b", b"2").unwrap(); - wb.put(b"c", b"3").unwrap(); - wb.put(b"d", b"4").unwrap(); + wb.put(b"za", b"1").unwrap(); + wb.put(b"zb", b"2").unwrap(); + wb.put(b"zc", b"3").unwrap(); + wb.put(b"zd", b"4").unwrap(); }); - iter.seek(b"c").unwrap(); + iter.seek(b"zc").unwrap(); assert!(iter.valid().unwrap()); iter.prev().unwrap(); assert!(iter.valid().unwrap()); - assert_eq!(iter.key(), b"b"); + assert_eq!(iter.key(), b"zb"); assert_eq!(iter.value(), b"2"); iter.next().unwrap(); assert!(iter.valid().unwrap()); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"3"); - iter.seek_for_prev(b"c").unwrap(); + iter.seek_for_prev(b"zc").unwrap(); assert!(iter.valid().unwrap()); iter.next().unwrap(); assert!(iter.valid().unwrap()); - assert_eq!(iter.key(), b"d"); + assert_eq!(iter.key(), b"zd"); assert_eq!(iter.value(), b"4"); iter.prev().unwrap(); assert!(iter.valid().unwrap()); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"3"); } @@ -2139,56 +2218,57 @@ mod tests { #[test] fn test_next_with_newer_seq() { let (engine, _, mut iter) = set_up_for_iteator(100, 110, |wb| { - wb.put(b"0", b"0").unwrap(); - wb.put(b"a", b"b").unwrap(); - wb.put(b"c", b"d").unwrap(); - wb.put(b"d", b"e").unwrap(); + wb.put(b"z0", b"0").unwrap(); + wb.put(b"za", b"b").unwrap(); + wb.put(b"zc", b"d").unwrap(); + wb.put(b"zd", b"e").unwrap(); }); let mut wb = engine.write_batch(); - wb.prepare_for_range(CacheRange::new(b"".to_vec(), b"z".to_vec())); - wb.put(b"b", b"f").unwrap(); + let region = new_region(1, b"", b"z"); + wb.prepare_for_region(®ion); + wb.put(b"zb", b"f").unwrap(); wb.set_sequence_number(200).unwrap(); - iter.seek(b"a").unwrap(); - assert_eq!(iter.key(), b"a"); + iter.seek(b"za").unwrap(); + assert_eq!(iter.key(), b"za"); assert_eq!(iter.value(), b"b"); iter.next().unwrap(); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"d"); - iter.seek_for_prev(b"b").unwrap(); - assert_eq!(iter.key(), b"a"); + iter.seek_for_prev(b"zb").unwrap(); + assert_eq!(iter.key(), b"za"); assert_eq!(iter.value(), b"b"); iter.next().unwrap(); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"d"); - iter.seek(b"d").unwrap(); - assert_eq!(iter.key(), b"d"); + iter.seek(b"zd").unwrap(); + assert_eq!(iter.key(), b"zd"); assert_eq!(iter.value(), b"e"); iter.prev().unwrap(); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"d"); iter.prev().unwrap(); - assert_eq!(iter.key(), b"a"); + assert_eq!(iter.key(), b"za"); assert_eq!(iter.value(), b"b"); iter.prev().unwrap(); - iter.seek_for_prev(b"d").unwrap(); - assert_eq!(iter.key(), b"d"); + iter.seek_for_prev(b"zd").unwrap(); + assert_eq!(iter.key(), b"zd"); assert_eq!(iter.value(), b"e"); iter.prev().unwrap(); - assert_eq!(iter.key(), b"c"); + assert_eq!(iter.key(), b"zc"); assert_eq!(iter.value(), b"d"); iter.prev().unwrap(); - assert_eq!(iter.key(), b"a"); + assert_eq!(iter.key(), b"za"); assert_eq!(iter.value(), b"b"); } @@ -2210,7 +2290,7 @@ mod tests { // For sequence number 102 let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - let snap = engine.snapshot(range.clone(), 100, 102).unwrap(); + let snap = engine.snapshot(1, 0, range.clone(), 100, 102).unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -2252,7 +2332,7 @@ mod tests { assert!(!iter.valid().unwrap()); // For sequence number 104 - let snap = engine.snapshot(range.clone(), 100, 104).unwrap(); + let snap = engine.snapshot(1, 0, range.clone(), 100, 104).unwrap(); let mut iter = snap.iterator_opt("default", iter_opt.clone()).unwrap(); iter.seek(b"c").unwrap(); assert_eq!(iter.key(), b"c"); @@ -2290,7 +2370,7 @@ mod tests { assert!(!iter.valid().unwrap()); // For sequence number 108 - let snap = engine.snapshot(range.clone(), 100, 108).unwrap(); + let snap = engine.snapshot(1, 0, range.clone(), 100, 108).unwrap(); let mut iter = snap.iterator_opt("default", iter_opt.clone()).unwrap(); iter.seek(b"c").unwrap(); assert_eq!(iter.key(), b"c"); diff --git a/components/range_cache_memory_engine/src/test_util.rs b/components/range_cache_memory_engine/src/test_util.rs index 1a68ea3fb84..4f68378a03a 100644 --- a/components/range_cache_memory_engine/src/test_util.rs +++ b/components/range_cache_memory_engine/src/test_util.rs @@ -5,6 +5,8 @@ use std::sync::Arc; use crossbeam::epoch; use engine_rocks::RocksEngine; use engine_traits::{SyncMutable, CF_WRITE}; +use keys::data_key; +use kvproto::metapb::{Peer, Region}; use txn_types::{Key, TimeStamp, Write, WriteType}; use crate::{ @@ -80,7 +82,8 @@ fn put_data_impl( write_cf: &SkiplistHandle, mem_controller: Arc, ) { - let raw_write_k = Key::from_raw(key) + let data_key = data_key(key); + let raw_write_k = Key::from_raw(&data_key) .append_ts(TimeStamp::new(commit_ts)) .into_encoded(); let mut write_k = encode_key(&raw_write_k, seq_num, ValueType::Value); @@ -112,7 +115,7 @@ fn put_data_impl( } if !short_value { - let raw_default_k = Key::from_raw(key) + let raw_default_k = Key::from_raw(&data_key) .append_ts(TimeStamp::new(start_ts)) .into_encoded(); let mut default_k = encode_key(&raw_default_k, seq_num + 1, ValueType::Value); @@ -136,7 +139,8 @@ pub fn put_data_in_rocks( rocks_engine: &RocksEngine, write_type: WriteType, ) { - let raw_write_k = Key::from_raw(key) + let data_key = data_key(key); + let raw_write_k = Key::from_raw(&data_key) .append_ts(TimeStamp::new(commit_ts)) .into_encoded(); let write_v = Write::new( @@ -164,3 +168,13 @@ pub fn put_data_in_rocks( rocks_engine.put(&raw_default_k, value).unwrap(); } } + +pub fn new_region>, T2: Into>>(id: u64, start: T1, end: T2) -> Region { + let mut region = Region::new(); + region.id = id; + region.start_key = start.into(); + region.end_key = end.into(); + // push a dummy peer to avoid CacheRange::from_region panic. + region.mut_peers().push(Peer::default()); + region +} diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index a9e4abcff24..5995a069730 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -1,5 +1,6 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + use std::{ - collections::BTreeSet, sync::{atomic::Ordering, Arc}, time::Duration, }; @@ -10,6 +11,7 @@ use engine_traits::{ CacheRange, EvictReason, MiscExt, Mutable, RangeCacheEngine, Result, WriteBatch, WriteBatchExt, WriteOptions, CF_DEFAULT, }; +use kvproto::metapb::Region; use tikv_util::{box_err, config::ReadableSize, error, info, time::Instant, warn}; use crate::{ @@ -18,7 +20,7 @@ use crate::{ keys::{encode_key, InternalBytes, ValueType, ENC_KEY_SEQ_LENGTH}, memory_controller::{MemoryController, MemoryUsage}, metrics::{RANGE_PREPARE_FOR_WRITE_DURATION_HISTOGRAM, WRITE_DURATION_HISTOGRAM}, - range_manager::{RangeCacheStatus, RangeManager}, + range_manager::RangeCacheStatus, RangeCacheMemoryEngine, }; @@ -40,7 +42,7 @@ const AMOUNT_TO_CLEAN_TOMBSTONE: u64 = ReadableSize::mb(16).0; // slice. const DELETE_ENTRY_VAL: &[u8] = b""; -// `prepare_for_range` should be called before raft command apply for each peer +// `prepare_for_region` should be called before raft command apply for each peer // delegate. It sets `range_cache_status` which is used to determine whether the // writes of this peer should be buffered. pub struct RangeCacheWriteBatch { @@ -55,16 +57,14 @@ pub struct RangeCacheWriteBatch { // after the snapshot has been loaded. range_cache_status: RangeCacheStatus, buffer: Vec, - pending_range_in_loading_buffer: Vec, engine: RangeCacheMemoryEngine, save_points: Vec, sequence_number: Option, memory_controller: Arc, memory_usage_reach_hard_limit: bool, - - current_range: Option, - // the ranges that reaches the hard limit and need to be evicted - ranges_to_evict: BTreeSet, + region_save_point: usize, + current_region_evicted: bool, + current_region: Option, // record the total durations of the prepare work for write in the write batch prepare_for_write_duration: Duration, @@ -86,15 +86,15 @@ impl From<&RangeCacheMemoryEngine> for RangeCacheWriteBatch { id: engine.alloc_write_batch_id(), range_cache_status: RangeCacheStatus::NotInCache, buffer: Vec::new(), - pending_range_in_loading_buffer: Vec::new(), engine: engine.clone(), save_points: Vec::new(), sequence_number: None, memory_controller: engine.memory_controller(), memory_usage_reach_hard_limit: false, - current_range: None, - ranges_to_evict: BTreeSet::default(), + region_save_point: 0, + current_region_evicted: false, prepare_for_write_duration: Duration::default(), + current_region: None, } } } @@ -106,15 +106,15 @@ impl RangeCacheWriteBatch { range_cache_status: RangeCacheStatus::NotInCache, buffer: Vec::with_capacity(cap), // cache_buffer should need small capacity - pending_range_in_loading_buffer: Vec::new(), engine: engine.clone(), save_points: Vec::new(), sequence_number: None, memory_controller: engine.memory_controller(), memory_usage_reach_hard_limit: false, - current_range: None, - ranges_to_evict: BTreeSet::default(), + region_save_point: 0, + current_region_evicted: false, prepare_for_write_duration: Duration::default(), + current_region: None, } } @@ -174,20 +174,15 @@ impl RangeCacheWriteBatch { // that all keys have unique sequence numbers. fn write_impl(&mut self, mut seq: u64) -> Result<()> { fail::fail_point!("on_write_impl"); - let mut ranges_to_delete = self.handle_ranges_to_evict(); - let (entries_to_write, engine) = self.engine.handle_pending_range_in_loading_buffer( - &mut seq, - std::mem::take(&mut self.pending_range_in_loading_buffer), - ); let guard = &epoch::pin(); let start = Instant::now(); let mut lock_modification: u64 = 0; let mut have_entry_applied = false; + let engine = self.engine.core.read().engine(); // Some entries whose ranges may be marked as evicted above, but it does not // matter, they will be deleted later. - let res = entries_to_write + let res = std::mem::take(&mut self.buffer) .into_iter() - .chain(std::mem::take(&mut self.buffer)) .try_for_each(|e| { have_entry_applied = true; if is_lock_cf(e.cf) { @@ -205,120 +200,94 @@ impl RangeCacheWriteBatch { { let mut core = self.engine.core.write(); core.mut_range_manager() - .clear_ranges_in_being_written(self.id, have_entry_applied); - core.mut_range_manager() - .mark_delete_ranges_scheduled(&mut ranges_to_delete); + .clear_regions_in_being_written(self.id, have_entry_applied); } self.engine .lock_modification_bytes .fetch_add(lock_modification, Ordering::Relaxed); - if !ranges_to_delete.is_empty() { - if let Err(e) = self - .engine - .bg_worker_manager() - .schedule_task(BackgroundTask::DeleteRange(ranges_to_delete)) - { - error!( - "schedule delete range failed"; - "err" => ?e, - ); - assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); - } - } - - let dur = std::mem::take(&mut self.prepare_for_write_duration); - RANGE_PREPARE_FOR_WRITE_DURATION_HISTOGRAM.observe(dur.as_secs_f64()); + RANGE_PREPARE_FOR_WRITE_DURATION_HISTOGRAM + .observe(self.prepare_for_write_duration.as_secs_f64()); res } - // return ranges that can be deleted from engine now - fn handle_ranges_to_evict(&mut self) -> Vec { - if self.ranges_to_evict.is_empty() { - return vec![]; - } - let mut core = self.engine.core.write(); - let mut ranges = vec![]; - let range_manager = core.mut_range_manager(); - for r in std::mem::take(&mut self.ranges_to_evict) { - let mut ranges_to_delete = - range_manager.evict_range(&r, EvictReason::MemoryLimitReached); - if !ranges_to_delete.is_empty() { - ranges.append(&mut ranges_to_delete); - continue; - } - } - ranges - } - #[inline] pub fn set_range_cache_status(&mut self, range_cache_status: RangeCacheStatus) { self.range_cache_status = range_cache_status; } + fn evict_current_region(&mut self, reason: EvictReason) { + if self.current_region_evicted { + return; + } + self.engine + .evict_region(self.current_region.as_ref().unwrap(), reason); + // cleanup cached entries belong to this region as there is no need + // to write them. + assert!(self.save_points.is_empty()); + if self.buffer.len() > self.region_save_point { + let mut total_size = 0; + for e in &self.buffer[self.region_save_point..] { + total_size += e.memory_size_required(); + } + self.memory_controller.release(total_size); + self.buffer.truncate(self.region_save_point); + } + self.current_region_evicted = true; + } + fn process_cf_operation(&mut self, entry_size: F1, entry: F2) where F1: FnOnce() -> usize, F2: FnOnce() -> RangeCacheWriteBatchEntry, { - if !matches!( - self.range_cache_status, - RangeCacheStatus::Cached | RangeCacheStatus::Loading - ) || self.memory_usage_reach_hard_limit - { + if self.range_cache_status == RangeCacheStatus::NotInCache || self.current_region_evicted { return; } if !self.engine.enabled() { - let range = self.current_range.clone().unwrap(); + let region = self.current_region.as_ref().unwrap(); info!( "range cache is disabled, evict the range"; - "range_start" => log_wrappers::Value(&range.start), - "range_end" => log_wrappers::Value(&range.end), + "range_start" => log_wrappers::Value(®ion.start_key), + "range_end" => log_wrappers::Value(®ion.end_key), ); - self.ranges_to_evict.insert(range); + self.evict_current_region(EvictReason::Disabled); return; } let memory_expect = entry_size(); if !self.memory_acquire(memory_expect) { - let range = self.current_range.clone().unwrap(); + let region = self.current_region.as_ref().unwrap(); info!( "memory acquire failed due to reaching hard limit"; - "range_start" => log_wrappers::Value(&range.start), - "range_end" => log_wrappers::Value(&range.end), + "range_start" => log_wrappers::Value(®ion.start_key), + "range_end" => log_wrappers::Value(®ion.end_key), ); - self.ranges_to_evict.insert(range); + self.evict_current_region(EvictReason::MemoryLimitReached); return; } - match self.range_cache_status { - RangeCacheStatus::Cached => { - self.buffer.push(entry()); - } - RangeCacheStatus::Loading => { - self.pending_range_in_loading_buffer.push(entry()); - } - RangeCacheStatus::NotInCache => {} - } + self.buffer.push(entry()); } fn schedule_memory_check(&self) { if self.memory_controller.memory_checking() { return; } - self.memory_controller.set_memory_checking(true); - if let Err(e) = self - .engine - .bg_worker_manager() - .schedule_task(BackgroundTask::MemoryCheckAndEvict) - { - error!( - "schedule memory check failed"; - "err" => ?e, - ); - assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); + if !self.memory_controller.set_memory_checking(true) { + if let Err(e) = self + .engine + .bg_worker_manager() + .schedule_task(BackgroundTask::MemoryCheckAndEvict) + { + error!( + "schedule memory check failed"; + "err" => ?e, + ); + assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); + } } } @@ -330,7 +299,7 @@ impl RangeCacheWriteBatch { self.memory_usage_reach_hard_limit = true; warn!( "the memory usage of in-memory engine reaches to hard limit"; - "range" => ?self.current_range.as_ref().unwrap(), + "region" => ?self.current_region.as_ref().unwrap(), "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), ); self.schedule_memory_check(); @@ -364,6 +333,14 @@ impl WriteBatchEntryInternal { ), } } + + fn value(&self) -> &[u8] { + match self { + WriteBatchEntryInternal::PutValue(value) => value, + WriteBatchEntryInternal::Deletion => &[], + } + } + fn data_size(&self) -> usize { match self { WriteBatchEntryInternal::PutValue(value) => value.len(), @@ -421,6 +398,10 @@ impl RangeCacheWriteBatchEntry { self.key.len() + ENC_KEY_SEQ_LENGTH + self.inner.data_size() } + fn memory_size_required(&self) -> usize { + Self::memory_size_required_for_key_value(&self.key, self.inner.value()) + } + #[inline] pub fn write_to_memory( &self, @@ -440,70 +421,6 @@ impl RangeCacheWriteBatchEntry { } } -// group_write_batch_entries classifies the entries to two categories according -// to the infomation in range manager: -// 1. entreis that can be written to memory engine directly -// 2. entreis that need to be cached -// For 2, we group the entries according to the range. The method uses the -// property that entries in the same range are neighbors. Though that the method -// still handles corretly even they are randomly positioned. -// -// Note: Some entries may not found a range in both -// `pending_ranges_loading_data` and `ranges`, it means the range has been -// evicted. -pub fn group_write_batch_entries( - mut entries: Vec, - range_manager: &RangeManager, -) -> ( - Vec<(CacheRange, Vec)>, - Vec, -) { - let mut group_entries_to_cache: Vec<(CacheRange, Vec)> = vec![]; - let mut entries_to_write: Vec = vec![]; - let mut drain = entries.drain(..).peekable(); - while let Some(mut e) = drain.next() { - if let Some((range_loading, ..)) = range_manager - .pending_ranges_loading_data - .iter() - .find(|r| r.0.contains_key(&e.key)) - { - // The range of this write batch entry is still in loading status - let mut current_group = vec![]; - loop { - current_group.push(e); - if let Some(next_e) = drain.peek() - && range_loading.contains_key(&next_e.key) - { - e = drain.next().unwrap(); - } else { - break; - } - } - group_entries_to_cache.push((range_loading.clone(), current_group)); - } else if let Some(range) = range_manager - .ranges() - .keys() - .find(|r| r.contains_key(&e.key)) - { - // The range has finished loading and became a normal cache range - loop { - entries_to_write.push(e); - if let Some(next_e) = drain.peek() - && range.contains_key(&next_e.key) - { - e = drain.next().unwrap(); - } else { - break; - } - } - } else { - // The range of the entry is not found, it means the ranges has been - // evicted - } - } - (group_entries_to_cache, entries_to_write) -} - impl WriteBatchExt for RangeCacheMemoryEngine { type WriteBatch = RangeCacheWriteBatch; // todo: adjust it @@ -548,7 +465,11 @@ impl WriteBatch for RangeCacheWriteBatch { fn clear(&mut self) { self.buffer.clear(); self.save_points.clear(); - _ = self.sequence_number.take(); + self.sequence_number = None; + self.prepare_for_write_duration = Duration::ZERO; + self.current_region = None; + self.current_region_evicted = false; + self.region_save_point = 0; } fn set_save_point(&mut self) { @@ -576,11 +497,15 @@ impl WriteBatch for RangeCacheWriteBatch { Ok(()) } - fn prepare_for_range(&mut self, range: CacheRange) { + fn prepare_for_region(&mut self, region: &Region) { let time = Instant::now(); - self.set_range_cache_status(self.engine.prepare_for_apply(self.id, &range)); + self.current_region = Some(region.clone()); + // TODO: remote range. + let range = CacheRange::from_region(region); + self.set_range_cache_status(self.engine.prepare_for_apply(self.id, range, region)); self.memory_usage_reach_hard_limit = false; - self.current_range = Some(range); + self.region_save_point = self.buffer.len(); + self.current_region_evicted = false; self.prepare_for_write_duration += time.saturating_elapsed(); } } @@ -612,15 +537,13 @@ impl Mutable for RangeCacheWriteBatch { // rather than delete the keys in the range, we evict ranges that overlap with // them directly - fn delete_range(&mut self, begin_key: &[u8], end_key: &[u8]) -> Result<()> { - let range = CacheRange::new(begin_key.to_vec(), end_key.to_vec()); - self.engine.evict_range(&range, EvictReason::DeleteRange); + fn delete_range(&mut self, _begin_key: &[u8], _end_key: &[u8]) -> Result<()> { + self.evict_current_region(EvictReason::DeleteRange); Ok(()) } - fn delete_range_cf(&mut self, _: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()> { - let range = CacheRange::new(begin_key.to_vec(), end_key.to_vec()); - self.engine.evict_range(&range, EvictReason::DeleteRange); + fn delete_range_cf(&mut self, _: &str, _begin_key: &[u8], _end_key: &[u8]) -> Result<()> { + self.evict_current_region(EvictReason::DeleteRange); Ok(()) } } @@ -632,8 +555,7 @@ mod tests { use crossbeam_skiplist::SkipList; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, FailedReason, KvEngine, Peekable, RangeCacheEngine, WriteBatch, CF_WRITE, - DATA_CFS, + CacheRange, FailedReason, Peekable, RangeCacheEngine, WriteBatch, DATA_CFS, }; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use tempfile::Builder; @@ -641,8 +563,8 @@ mod tests { use super::*; use crate::{ - background::flush_epoch, config::RangeCacheConfigManager, RangeCacheEngineConfig, - RangeCacheEngineContext, + background::flush_epoch, config::RangeCacheConfigManager, range_manager::RegionState, + test_util::new_region, RangeCacheEngineConfig, RangeCacheEngineContext, }; // We should not use skiplist.get directly as we only cares keys without @@ -665,15 +587,15 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let r = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(r.clone()); + let r = new_region(1, b"", b"z"); + engine.new_region(r.clone()); { let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(&r, 10); + core.mut_range_manager().set_safe_point(r.id, 10); } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_range(r.clone()); + wb.prepare_for_region(&r); wb.put(b"aaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); assert_eq!(wb.write().unwrap(), 1); @@ -688,15 +610,15 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let r = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(r.clone()); + let r = new_region(1, b"", b"z"); + engine.new_region(r.clone()); { let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(&r, 10); + core.mut_range_manager().set_safe_point(r.id, 10); } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_range(r.clone()); + wb.prepare_for_region(&r); wb.put(b"aaa", b"bbb").unwrap(); wb.set_save_point(); wb.put(b"aaa", b"ccc").unwrap(); @@ -716,30 +638,32 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); - let r = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.new_range(r.clone()); + let r = new_region(1, b"", b"z"); + engine.new_region(r.clone()); { let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(&r, 10); + core.mut_range_manager().set_safe_point(r.id, 10); } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_range(r.clone()); - wb.put(b"aaa", b"bbb").unwrap(); + wb.prepare_for_region(&r); + wb.put(b"zaaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); _ = wb.write(); wb.clear(); - wb.prepare_for_range(r.clone()); - wb.put(b"bbb", b"ccc").unwrap(); - wb.delete(b"aaa").unwrap(); + wb.prepare_for_region(&r); + wb.put(b"zbbb", b"ccc").unwrap(); + wb.delete(b"zaaa").unwrap(); wb.set_sequence_number(2).unwrap(); _ = wb.write(); - let snapshot = engine.snapshot(r, u64::MAX, 3).unwrap(); + let snapshot = engine + .snapshot(r.id, 0, CacheRange::from_region(&r), u64::MAX, 3) + .unwrap(); assert_eq!( - snapshot.get_value(&b"bbb"[..]).unwrap().unwrap(), + snapshot.get_value(&b"zbbb"[..]).unwrap().unwrap(), &b"ccc"[..] ); - assert!(snapshot.get_value(&b"aaa"[..]).unwrap().is_none()) + assert!(snapshot.get_value(&b"zaaa"[..]).unwrap().is_none()) } #[test] @@ -751,122 +675,110 @@ mod tests { let path_str = path.path().to_str().unwrap(); let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); - let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( - VersionTrack::new(RangeCacheEngineConfig::config_for_test()), - ))); - let r1 = CacheRange::new(b"k01".to_vec(), b"k05".to_vec()); - let r2 = CacheRange::new(b"k05".to_vec(), b"k10".to_vec()); - let r3 = CacheRange::new(b"k10".to_vec(), b"k15".to_vec()); - { - engine.new_range(r1.clone()); - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(&r1, 10); + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( + Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), + )); + engine.set_disk_engine(rocks_engine.clone()); - let snap = Arc::new(rocks_engine.snapshot(None)); - core.mut_range_manager() - .pending_ranges_loading_data - .push_back((r2.clone(), snap, false)); + let r1 = new_region(1, b"k01".to_vec(), b"k05".to_vec()); + { + // load region with epoch and range change, will remove the pending region. + engine.load_region(r1.clone()).unwrap(); + let mut r1_new = new_region(1, b"k01".to_vec(), b"k06".to_vec()); + r1_new.mut_region_epoch().version = 2; + let mut wb = RangeCacheWriteBatch::from(&engine); + wb.prepare_for_region(&r1_new); + assert!(engine.core().read().range_manager().regions().is_empty()); + wb.put(b"zk01", b"val1").unwrap(); + wb.put(b"zk03", b"val1").unwrap(); + wb.put(b"zk05", b"val1").unwrap(); + wb.set_sequence_number(2).unwrap(); + wb.write().unwrap(); } + // pending region is removed, no data should write to skiplist. + let skip_engine = engine.core.read().engine(); + assert_eq!(skip_engine.node_count(), 0); + + // epoch changes but new range is contained by the pending region, will update + // the region. + engine.load_region(r1.clone()).unwrap(); + let mut r1_new = new_region(1, b"k01".to_vec(), b"k05".to_vec()); + r1_new.mut_region_epoch().version = 2; let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_range(r1.clone()); - wb.put(b"k01", b"val1").unwrap(); - wb.prepare_for_range(r2.clone()); - wb.put(b"k05", b"val5").unwrap(); - wb.prepare_for_range(r3); - wb.put(b"k10", b"val10").unwrap(); - wb.set_sequence_number(2).unwrap(); - let _ = wb.write(); - let snapshot = engine.snapshot(r1.clone(), u64::MAX, 5).unwrap(); - assert_eq!( - snapshot.get_value(&b"k01"[..]).unwrap().unwrap(), - &b"val1"[..] - ); + wb.prepare_for_region(&r1_new); { let core = engine.core.read(); - assert_eq!(core.cached_write_batch.get(&r2).unwrap().len(), 1); + let region_meta = core.range_manager().region_meta(1).unwrap(); + assert_eq!(region_meta.region(), &r1_new); + assert_eq!(region_meta.get_state(), RegionState::ReadyToLoad); + } + wb.put(b"zk02", b"val1").unwrap(); + wb.put(b"zk04", b"val1").unwrap(); + wb.set_sequence_number(5).unwrap(); + wb.write().unwrap(); + + test_util::eventually( + Duration::from_millis(50), + Duration::from_millis(1000), + || { + let core = engine.core.read(); + core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active + }, + ); + let snapshot = engine + .snapshot(r1.id, 2, CacheRange::from_region(&r1_new), u64::MAX, 6) + .unwrap(); + for i in 1..5 { + let res = snapshot.get_value(format!("zk0{}", i).as_bytes()).unwrap(); + if i % 2 == 0 { + assert_eq!(res.unwrap(), b"val1".as_slice()); + } else { + assert!(res.is_none()); + } } + let skip_engine = engine.core.read().engine(); + assert_eq!(skip_engine.node_count(), 2); + let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_range(r1.clone()); - wb.delete(b"k01").unwrap(); - wb.set_sequence_number(5).unwrap(); - let _ = wb.write(); - let snapshot = engine.snapshot(r1, u64::MAX, 6).unwrap(); - assert!(snapshot.get_value(&b"k01"[..]).unwrap().is_none(),); - } + wb.prepare_for_region(&r1_new); + wb.put(b"zk01", b"val2").unwrap(); + wb.set_sequence_number(6).unwrap(); + wb.write().unwrap(); - #[test] - fn test_group_entries() { - let path = Builder::new().prefix("test_group").tempdir().unwrap(); - let path_str = path.path().to_str().unwrap(); - let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); - let snap = rocks_engine.snapshot(None); - - let mut range_manager = RangeManager::default(); - let r1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let r2 = CacheRange::new(b"k10".to_vec(), b"k20".to_vec()); - let r3 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - range_manager.new_range(r1.clone()); - let snap = Arc::new(snap); - range_manager - .pending_ranges_loading_data - .push_back((r2.clone(), snap.clone(), false)); - range_manager - .pending_ranges_loading_data - .push_back((r3.clone(), snap, false)); - - let entries = vec![ - RangeCacheWriteBatchEntry::put_value(CF_DEFAULT, b"k22", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_DEFAULT, b"k21", b"val"), - RangeCacheWriteBatchEntry::deletion(CF_DEFAULT, b"k25"), - RangeCacheWriteBatchEntry::put_value(CF_DEFAULT, b"k28", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k03", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k05", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k09", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k10", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k19", b"val"), - // Mock the range is evicted - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k32", b"val"), - RangeCacheWriteBatchEntry::put_value(CF_WRITE, b"k45", b"val"), - ]; + assert_eq!(skip_engine.node_count(), 3); - let (group_entries_to_cache, entries_to_write) = - group_write_batch_entries(entries, &range_manager); - assert_eq!(group_entries_to_cache.len(), 2); - assert_eq!(entries_to_write.len(), 3); - entries_to_write - .iter() - .for_each(|e| assert!(r1.contains_key(&e.key))); - group_entries_to_cache.iter().for_each(|(range, entries)| { - if *range == r2 { - assert_eq!(entries.len(), 2); - } else if *range == r3 { - assert_eq!(entries.len(), 4); - } else { - unreachable!(); - } - entries - .iter() - .for_each(|e| assert!(range.contains_key(&e.key))) - }); + // evict region, data should not be updated. + { + let mut core = engine.core.write(); + core.mut_range_manager() + .mut_region_meta(1) + .unwrap() + .set_state(RegionState::PendingEvict); + } + let mut wb = RangeCacheWriteBatch::from(&engine); + wb.prepare_for_region(&r1_new); + wb.put(b"zk02", b"val2").unwrap(); + wb.set_sequence_number(7).unwrap(); + wb.write().unwrap(); + // node count should not change. + assert_eq!(skip_engine.node_count(), 3); } fn wait_evict_done(engine: &RangeCacheMemoryEngine) { - let mut wait = 0; - while wait < 10 { - wait += 1; - if !engine - .core - .read() - .range_manager() - .ranges_being_deleted - .is_empty() - { - std::thread::sleep(Duration::from_millis(200)); - } else { - break; - } - } + test_util::eventually( + Duration::from_millis(100), + Duration::from_millis(2000), + || { + !engine + .core + .read() + .range_manager() + .regions() + .values() + .any(|meta| meta.get_state().is_evict()) + }, + ); } #[test] @@ -878,91 +790,137 @@ mod tests { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( VersionTrack::new(config), ))); - let range1 = CacheRange::new(b"kk00".to_vec(), b"kk10".to_vec()); - let range2 = CacheRange::new(b"kk10".to_vec(), b"kk20".to_vec()); - let range3 = CacheRange::new(b"kk20".to_vec(), b"kk30".to_vec()); - let range4 = CacheRange::new(b"kk30".to_vec(), b"kk40".to_vec()); - let range5 = CacheRange::new(b"kk40".to_vec(), b"kk50".to_vec()); - for r in [&range1, &range2, &range3, &range4, &range5] { - engine.new_range(r.clone()); + let regions = [ + new_region(1, b"k00", b"k10"), + new_region(2, b"k10", b"k20"), + new_region(3, b"k20", b"k30"), + new_region(4, b"k30", b"k40"), + new_region(5, b"k40", b"k50"), + ]; + for r in ®ions { + engine.new_region(r.clone()); { let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r, 10); + core.mut_range_manager().set_safe_point(r.id, 10); } - let _ = engine.snapshot(r.clone(), 1000, 1000).unwrap(); + let _ = engine + .snapshot(r.id, 0, CacheRange::from_region(r), 1000, 1000) + .unwrap(); } + let memory_controller = engine.memory_controller(); - let val1: Vec = (0..150).map(|_| 0).collect(); + let val1: Vec = vec![0; 150]; let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_range(range1.clone()); + wb.prepare_for_region(®ions[0]); // memory required: // 4(key) + 8(sequencen number) + 150(value) + 16(2 Arc) = 28 // Now, 562 - wb.delete(b"kk21").unwrap(); - let val2: Vec = (0..500).map(|_| 2).collect(); + wb.delete(b"zk21").unwrap(); + assert_eq!(562, memory_controller.mem_usage()); + assert_eq!(wb.count(), 4); + + let val2: Vec = vec![2; 500]; // The memory will fail to acquire - wb.put(b"kk22", &val2).unwrap(); + wb.put(b"zk22", &val2).unwrap(); + + wb.prepare_for_region(®ions[3]); + // region 2 is evicted due to memory insufficient, + // after preprare, all region 2's entries are removed. + assert_eq!(356, memory_controller.mem_usage()); + assert_eq!(wb.count(), 2); // The memory capacity is enough for the following two inserts - let val3: Vec = (0..150).map(|_| 3).collect(); - wb.prepare_for_range(range4.clone()); - // Now, 740 - wb.put(b"kk32", &val3).unwrap(); + // Now, 534 + let val3: Vec = vec![3; 150]; + wb.put(b"zk32", &val3).unwrap(); + assert_eq!(534, memory_controller.mem_usage()); - // The memory will fail to acquire - let val4: Vec = (0..300).map(|_| 3).collect(); - wb.prepare_for_range(range5.clone()); - wb.put(b"kk41", &val4).unwrap(); + // Now, 862 + let val4: Vec = vec![3; 300]; + wb.prepare_for_region(®ions[4]); + wb.put(b"zk41", &val4).unwrap(); - let memory_controller = engine.memory_controller(); // We should have allocated 740 as calculated above - assert_eq!(740, memory_controller.mem_usage()); + assert_eq!(862, memory_controller.mem_usage()); wb.write_impl(1000).unwrap(); // We dont count the node overhead (96 bytes for each node) in write batch, so // after they are written into the engine, the mem usage can even exceed // the hard limit. But this should be fine as this amount should be at // most MB level. - assert_eq!(1220, memory_controller.mem_usage()); - - let snap1 = engine.snapshot(range1.clone(), 1000, 1010).unwrap(); - assert_eq!(snap1.get_value(b"kk01").unwrap().unwrap(), &val1); - let snap2 = engine.snapshot(range2.clone(), 1000, 1010).unwrap(); - assert_eq!(snap2.get_value(b"kk11").unwrap().unwrap(), &val1); - - assert_eq!( - engine.snapshot(range3.clone(), 1000, 1000).unwrap_err(), - FailedReason::NotCached - ); - - let snap4 = engine.snapshot(range4.clone(), 1000, 1010).unwrap(); - assert_eq!(snap4.get_value(b"kk32").unwrap().unwrap(), &val3); + assert_eq!(1246, memory_controller.mem_usage()); + + let snap1 = engine + .snapshot( + regions[0].id, + 0, + CacheRange::from_region(®ions[0]), + 1000, + 1010, + ) + .unwrap(); + assert_eq!(snap1.get_value(b"zk01").unwrap().unwrap(), &val1); + let snap2 = engine + .snapshot( + regions[1].id, + 0, + CacheRange::from_region(®ions[1]), + 1000, + 1010, + ) + .unwrap(); + assert_eq!(snap2.get_value(b"zk11").unwrap().unwrap(), &val1); assert_eq!( - engine.snapshot(range5.clone(), 1000, 1010).unwrap_err(), + engine + .snapshot( + regions[2].id, + 0, + CacheRange::from_region(®ions[2]), + 1000, + 1000 + ) + .unwrap_err(), FailedReason::NotCached ); - // For range3, one write is buffered but others is rejected, so the range3 is - // evicted and the keys of it are deleted. After flush the epoch, we should - // get 1220-178-28(kv)-96*2(node overhead) = 822 memory usage. - flush_epoch(); - wait_evict_done(&engine); - assert_eq!(822, memory_controller.mem_usage()); + let snap4 = engine + .snapshot( + regions[3].id, + 0, + CacheRange::from_region(®ions[3]), + 1000, + 1010, + ) + .unwrap(); + assert_eq!(snap4.get_value(b"zk32").unwrap().unwrap(), &val3); + + let _snap5 = engine + .snapshot( + regions[4].id, + 0, + CacheRange::from_region(®ions[4]), + 1000, + 1010, + ) + .unwrap(); drop(snap1); - engine.evict_range(&range1, EvictReason::AutoEvict); - flush_epoch(); + engine.evict_region(®ions[0], EvictReason::AutoEvict); wait_evict_done(&engine); - assert_eq!(548, memory_controller.mem_usage()); + flush_epoch(); + assert_eq!(972, memory_controller.mem_usage()); } #[test] @@ -974,22 +932,26 @@ mod tests { let config = Arc::new(VersionTrack::new(config)); let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config.clone())); - let r1 = CacheRange::new(b"kk00".to_vec(), b"kk10".to_vec()); - let r2 = CacheRange::new(b"kk10".to_vec(), b"kk20".to_vec()); + let r1 = new_region(1, b"kk00".to_vec(), b"kk10".to_vec()); + let r2 = new_region(2, b"kk10".to_vec(), b"kk20".to_vec()); for r in [&r1, &r2] { - engine.new_range(r.clone()); + engine.new_region(r.clone()); { let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r, 10); + core.mut_range_manager().set_safe_point(r.id, 10); } - let _ = engine.snapshot(r.clone(), 1000, 1000).unwrap(); + let _ = engine + .snapshot(r.id, 0, CacheRange::from_region(r), 1000, 1000) + .unwrap(); } let val1: Vec = (0..150).map(|_| 0).collect(); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_range(r2.clone()); - wb.put(b"kk11", &val1).unwrap(); - let snap1 = engine.snapshot(r1.clone(), 1000, 1000).unwrap(); + wb.prepare_for_region(&r2); + wb.put(b"zkk11", &val1).unwrap(); + let snap1 = engine + .snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000) + .unwrap(); // disable the range cache let mut config_manager = RangeCacheConfigManager(config.clone()); @@ -1000,20 +962,22 @@ mod tests { wb.write_impl(1000).unwrap(); // existing snapshot can still work after the range cache is disabled, but new // snapshot will fail to create - assert!(snap1.get_value(b"kk00").unwrap().is_none()); + assert!(snap1.get_value(b"zkk00").unwrap().is_none()); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_range(r1.clone()); + wb.prepare_for_region(&r1); // put should trigger the evict and it won't write into range cache - wb.put(b"kk01", &val1).unwrap(); + wb.put(b"zkk01", &val1).unwrap(); wb.write_impl(1000).unwrap(); // new snapshot will fail to create as it's evicted already - let snap1 = engine.snapshot(r1.clone(), 1000, 1000); + let snap1 = engine.snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000); assert_eq!(snap1.unwrap_err(), FailedReason::NotCached); - let snap2 = engine.snapshot(r2.clone(), 1000, 1000).unwrap(); + let snap2 = engine + .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) + .unwrap(); // if no new write, the range cache can still be used. - assert_eq!(snap2.get_value(b"kk11").unwrap().unwrap(), &val1); + assert_eq!(snap2.get_value(b"zkk11").unwrap().unwrap(), &val1); // enable the range cache again let mut config_manager = RangeCacheConfigManager(config.clone()); @@ -1021,9 +985,11 @@ mod tests { config_change.insert(String::from("enabled"), ConfigValue::Bool(true)); config_manager.dispatch(config_change).unwrap(); - let snap1 = engine.snapshot(r1.clone(), 1000, 1000); + let snap1 = engine.snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000); assert_eq!(snap1.unwrap_err(), FailedReason::NotCached); - let snap2 = engine.snapshot(r2.clone(), 1000, 1000).unwrap(); - assert_eq!(snap2.get_value(b"kk11").unwrap().unwrap(), &val1); + let snap2 = engine + .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) + .unwrap(); + assert_eq!(snap2.get_value(b"zkk11").unwrap().unwrap(), &val1); } } diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 987a2a74de1..57023b067e8 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -11,9 +11,11 @@ use engine_traits::{ CacheRange, EvictReason, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; +use keys::data_key; +use kvproto::metapb::Region; use range_cache_memory_engine::{ decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, - test_util::{put_data, put_data_in_rocks}, + test_util::{new_region, put_data, put_data_in_rocks}, BackgroundTask, InternalBytes, InternalKey, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, SkiplistHandle, ValueType, }; @@ -63,7 +65,7 @@ fn test_gc_worker() { let (write, default) = { let mut core = engine.core().write(); core.mut_range_manager() - .new_range(CacheRange::new(b"".to_vec(), b"z".to_vec())); + .new_region(new_region(1, b"", b"z")); let engine = core.engine(); (engine.cf_handle(CF_WRITE), engine.cf_handle(CF_DEFAULT)) }; @@ -134,7 +136,7 @@ fn test_gc_worker() { let guard = &epoch::pin(); for &ts in &[commit_ts1, commit_ts2, commit_ts3] { - let key = Key::from_raw(b"k"); + let key = Key::from_raw(b"zk"); let key = encoding_for_filter(key.as_encoded(), TimeStamp::new(ts)); assert!(key_exist(&write, &key, guard)); @@ -142,7 +144,7 @@ fn test_gc_worker() { let _ = rx.recv_timeout(Duration::from_secs(5)).unwrap(); - let key = Key::from_raw(b"k"); + let key = Key::from_raw(b"zk"); // now, the outdated mvcc versions should be gone for &ts in &[commit_ts1, commit_ts2, commit_ts3] { let key = encoding_for_filter(key.as_encoded(), TimeStamp::new(ts)); @@ -158,7 +160,7 @@ fn test_clean_up_tombstone() { let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config.clone())); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); + let region = new_region(1, b"".to_vec(), b"z".to_vec()); let (tx, rx) = sync_channel(0); fail::cfg_callback("clean_lock_tombstone_done", move || { @@ -166,9 +168,9 @@ fn test_clean_up_tombstone() { }) .unwrap(); - engine.new_range(range.clone()); + engine.new_region(region.clone()); let mut wb = engine.write_batch(); - wb.prepare_for_range(range.clone()); + wb.prepare_for_region(®ion); wb.put_cf("lock", b"k", b"val").unwrap(); wb.put_cf("lock", b"k1", b"val").unwrap(); wb.put_cf("lock", b"k2", b"val").unwrap(); @@ -180,7 +182,7 @@ fn test_clean_up_tombstone() { wb.write().unwrap(); let mut wb = engine.write_batch(); - wb.prepare_for_range(range.clone()); + wb.prepare_for_region(®ion); wb.put_cf("lock", b"k", b"val").unwrap(); // seq 120 wb.put_cf("lock", b"k1", b"val").unwrap(); // seq 121 wb.put_cf("lock", b"k2", b"val").unwrap(); // seq 122 @@ -244,35 +246,35 @@ fn test_evict_with_loading_range() { ))); engine.set_disk_engine(rocks_engine); - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let range3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); + let r1 = new_region(1, b"k00".to_vec(), b"k10".to_vec()); + let r2 = new_region(2, b"k20".to_vec(), b"k30".to_vec()); + let r3 = new_region(3, b"k40".to_vec(), b"k50".to_vec()); let (snapshot_load_tx, snapshot_load_rx) = sync_channel(0); // range1 and range2 will be evicted - let r = CacheRange::new(b"k05".to_vec(), b"k25".to_vec()); + let r = new_region(4, b"k05".to_vec(), b"k25".to_vec()); let engine_clone = engine.clone(); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); - engine_clone.evict_range(&r, EvictReason::AutoEvict); + engine_clone.evict_region(&r, EvictReason::AutoEvict); }) .unwrap(); let (loading_complete_tx, loading_complete_rx) = sync_channel(0); - fail::cfg_callback("pending_range_completes_loading", move || { + fail::cfg_callback("on_completes_batch_loading", move || { let _ = loading_complete_tx.send(true); }) .unwrap(); - engine.load_range(range1.clone()).unwrap(); - engine.load_range(range2.clone()).unwrap(); - engine.load_range(range3.clone()).unwrap(); + engine.load_region(r1.clone()).unwrap(); + engine.load_region(r2.clone()).unwrap(); + engine.load_region(r3.clone()).unwrap(); let mut wb = engine.write_batch(); // prepare range to trigger loading - wb.prepare_for_range(range1.clone()); - wb.prepare_for_range(range2.clone()); - wb.prepare_for_range(range3.clone()); + wb.prepare_for_region(&r1); + wb.prepare_for_region(&r2); + wb.prepare_for_region(&r3); wb.set_sequence_number(10).unwrap(); wb.write().unwrap(); @@ -288,9 +290,15 @@ fn test_evict_with_loading_range() { .unwrap(); let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); - engine.snapshot(range1, read_ts, 100).unwrap_err(); - engine.snapshot(range2, read_ts, 100).unwrap_err(); - engine.snapshot(range3, read_ts, 100).unwrap(); + engine + .snapshot(r1.id, 0, CacheRange::from_region(&r1), read_ts, 100) + .unwrap_err(); + engine + .snapshot(r2.id, 0, CacheRange::from_region(&r2), read_ts, 100) + .unwrap_err(); + engine + .snapshot(r3.id, 0, CacheRange::from_region(&r3), read_ts, 100) + .unwrap(); } #[test] @@ -317,36 +325,36 @@ fn test_cached_write_batch_cleared_when_load_failed() { // range1 will be canceled in on_snapshot_load_finished whereas range2 will be // canceled at begin - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - engine.load_range(range1.clone()).unwrap(); - engine.load_range(range2.clone()).unwrap(); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + engine.load_region(r1.clone()).unwrap(); + engine.load_region(r2.clone()).unwrap(); let mut wb = engine.write_batch(); // range1 starts to load - wb.prepare_for_range(range1.clone()); + wb.prepare_for_region(&r1); rx.recv_timeout(Duration::from_secs(5)).unwrap(); - wb.put(b"k05", b"val").unwrap(); - wb.put(b"k06", b"val").unwrap(); - wb.prepare_for_range(range2.clone()); - wb.put(b"k25", b"val").unwrap(); + wb.put(b"zk05", b"val").unwrap(); + wb.put(b"zk06", b"val").unwrap(); + wb.prepare_for_region(&r2); + wb.put(b"zk25", b"val").unwrap(); wb.set_sequence_number(100).unwrap(); wb.write().unwrap(); fail::remove("on_snapshot_load_finished2"); - let mut tried = 0; - while tried < 20 { - if !engine.core().read().has_cached_write_batch(&range1) - && !engine.core().read().has_cached_write_batch(&range2) - { - return; - } - std::thread::sleep(Duration::from_millis(100)); - tried += 1; - } - panic!("write batches are not cleared"); + test_util::eventually( + Duration::from_millis(100), + Duration::from_millis(2000), + || { + let core = engine.core().read(); + // all failed regions should be removed. + [1, 2] + .into_iter() + .all(|i| core.range_manager().region_meta(i).is_none()) + }, + ); } #[test] @@ -355,9 +363,9 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { let path_str = path.path().to_str().unwrap(); let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); let mut wb = rocks_engine.write_batch(); - wb.put_cf(CF_LOCK, b"k40", b"val").unwrap(); - wb.put_cf(CF_LOCK, b"k41", b"val").unwrap(); - wb.put_cf(CF_LOCK, b"k42", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk40", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk41", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk42", b"val").unwrap(); wb.write().unwrap(); let config = RangeCacheEngineConfig::config_for_test(); @@ -366,9 +374,9 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { ))); engine.set_disk_engine(rocks_engine); - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let range3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); + let r1 = new_region(1, b"k00".to_vec(), b"k10".to_vec()); + let r2 = new_region(2, b"k20".to_vec(), b"k30".to_vec()); + let r3 = new_region(3, b"k40".to_vec(), b"k50".to_vec()); let (snapshot_load_cancel_tx, snapshot_load_cancel_rx) = sync_channel(0); fail::cfg_callback("in_memory_engine_snapshot_load_canceled", move || { let _ = snapshot_load_cancel_tx.send(true); @@ -393,31 +401,31 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { }) .unwrap(); - engine.new_range(range1.clone()); - engine.new_range(range2.clone()); - engine.load_range(range3.clone()).unwrap(); + engine.new_region(r1.clone()); + engine.new_region(r2.clone()); + engine.load_region(r3.clone()).unwrap(); let engine_clone = engine.clone(); let (range_prepared_tx, range_prepared_rx) = sync_channel(0); - let range1_clone = range1.clone(); - let range2_clone = range2.clone(); - let range3_clone = range3.clone(); + let region1_clone = r1.clone(); + let region2_clone = r2.clone(); + let region3_clone = r3.clone(); let handle = std::thread::spawn(move || { let mut wb = engine_clone.write_batch(); - wb.prepare_for_range(range1_clone); - wb.put_cf(CF_LOCK, b"k02", b"val").unwrap(); - wb.put_cf(CF_LOCK, b"k03", b"val").unwrap(); - wb.put_cf(CF_LOCK, b"k04", b"val").unwrap(); + wb.prepare_for_region(®ion1_clone); + wb.put_cf(CF_LOCK, b"zk02", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk03", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk04", b"val").unwrap(); wb.set_sequence_number(100).unwrap(); let mut wb2 = engine_clone.write_batch(); - wb2.prepare_for_range(range2_clone); - wb.put_cf(CF_LOCK, b"k22", b"val").unwrap(); - wb.put_cf(CF_LOCK, b"k23", b"val").unwrap(); + wb2.prepare_for_region(®ion2_clone); + wb.put_cf(CF_LOCK, b"zk22", b"val").unwrap(); + wb.put_cf(CF_LOCK, b"zk23", b"val").unwrap(); wb2.set_sequence_number(200).unwrap(); let mut wb3 = engine_clone.write_batch(); - wb3.prepare_for_range(range3_clone); + wb3.prepare_for_region(®ion3_clone); wb3.set_sequence_number(300).unwrap(); range_prepared_tx.send(true).unwrap(); @@ -433,12 +441,12 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { // Now, three ranges are in write status, delete range will not be performed // until they leave the write status - engine.evict_range(&range1, EvictReason::AutoEvict); - engine.evict_range(&range2, EvictReason::AutoEvict); + engine.evict_region(&r1, EvictReason::AutoEvict); + engine.evict_region(&r2, EvictReason::AutoEvict); - let verify_data = |range, expected_num: u64| { - let handle = engine.core().write().engine().cf_handle(CF_LOCK); - let (start, end) = encode_key_for_boundary_without_mvcc(range); + let verify_data = |r: &Region, expected_num: u64| { + let handle = engine.core().read().engine().cf_handle(CF_LOCK); + let (start, end) = encode_key_for_boundary_without_mvcc(&CacheRange::from_region(r)); let mut iter = handle.iterator(); let guard = &epoch::pin(); let mut count = 0; @@ -455,39 +463,39 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { .unwrap(); // Now, a DeleteRange task has been done: actually, the task will be delayed, so // the data has not be deleted - verify_data(&range1, 3); + verify_data(&r1, 3); // remove failpoint so that the range can leave write status fail::remove("before_clear_ranges_in_being_written"); delete_range_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); // Now, data should be deleted - verify_data(&range1, 0); + verify_data(&r1, 0); // Next to test range2 fail::cfg("before_clear_ranges_in_being_written", "pause").unwrap(); write_batch_consume_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - verify_data(&range2, 2); + verify_data(&r2, 2); // remove failpoint so that the range can leave write status fail::remove("before_clear_ranges_in_being_written"); delete_range_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - verify_data(&range2, 0); + verify_data(&r2, 0); // ensure the range enters on_snapshot_load_finished before eviction snapshot_load_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - engine.evict_range(&range3, EvictReason::AutoEvict); + engine.evict_region(&r3, EvictReason::AutoEvict); fail::cfg("before_clear_ranges_in_being_written", "pause").unwrap(); write_batch_consume_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - verify_data(&range3, 3); + verify_data(&r3, 3); snapshot_load_cancel_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); @@ -495,7 +503,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { delete_range_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - verify_data(&range3, 0); + verify_data(&r3, 0); let _ = handle.join(); } @@ -512,17 +520,17 @@ fn test_double_delete_range_schedule() { ))); engine.set_disk_engine(rocks_engine); - let range1 = CacheRange::new(b"k00".to_vec(), b"k10".to_vec()); - let range2 = CacheRange::new(b"k20".to_vec(), b"k30".to_vec()); - let range3 = CacheRange::new(b"k40".to_vec(), b"k50".to_vec()); + let r1 = new_region(1, b"k00".to_vec(), b"k10".to_vec()); + let r2 = new_region(2, b"k20".to_vec(), b"k30".to_vec()); + let r3 = new_region(3, b"k40".to_vec(), b"k50".to_vec()); let (snapshot_load_tx, snapshot_load_rx) = sync_channel(0); let engine_clone = engine.clone(); - let r = CacheRange::new(b"k00".to_vec(), b"k60".to_vec()); + let r = new_region(4, b"k00".to_vec(), b"k60".to_vec()); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); // evict all ranges. So the loading ranges will also be evicted and a delete // range task will be scheduled. - engine_clone.evict_range(&r, EvictReason::AutoEvict); + engine_clone.evict_region(&r, EvictReason::AutoEvict); }) .unwrap(); @@ -532,16 +540,20 @@ fn test_double_delete_range_schedule() { }) .unwrap(); - engine.new_range(range1.clone()); - engine.new_range(range2.clone()); - engine.load_range(range3.clone()).unwrap(); + engine.new_region(r1.clone()); + engine.new_region(r2.clone()); + engine.load_region(r3.clone()).unwrap(); - let snap1 = engine.snapshot(range1.clone(), 100, 100).unwrap(); - let snap2 = engine.snapshot(range2.clone(), 100, 100).unwrap(); + let snap1 = engine + .snapshot(r1.id, 0, CacheRange::from_region(&r1), 100, 100) + .unwrap(); + let snap2 = engine + .snapshot(r2.id, 0, CacheRange::from_region(&r2), 100, 100) + .unwrap(); let mut wb = engine.write_batch(); // prepare range to trigger loading - wb.prepare_for_range(range3.clone()); + wb.prepare_for_region(&r3); wb.set_sequence_number(10).unwrap(); wb.write().unwrap(); @@ -597,15 +609,16 @@ fn test_load_with_gc() { fail::cfg("in_memory_engine_safe_point_in_loading", "return(6)").unwrap(); let (load_tx, load_rx) = sync_channel(0); - fail::cfg_callback("pending_range_completes_loading", move || { + fail::cfg_callback("on_completes_batch_loading", move || { let _ = load_tx.send(true); }) .unwrap(); - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - engine.load_range(range.clone()).unwrap(); + let region = new_region(1, b"", b"z"); + let range = CacheRange::from_region(®ion); + engine.load_region(region.clone()).unwrap(); let mut wb = engine.write_batch(); - wb.prepare_for_range(range.clone()); + wb.prepare_for_region(®ion); wb.set_sequence_number(100).unwrap(); wb.write().unwrap(); @@ -618,7 +631,7 @@ fn test_load_with_gc() { let guard = &epoch::pin(); iter.seek_to_first(guard); for (key, commit_ts) in expects { - let expect_key = Key::from_raw(key).into_encoded(); + let expect_key = Key::from_raw(&data_key(key)).into_encoded(); let InternalKey { user_key, .. } = decode_key(iter.key().as_bytes()); let (mem_key, ts) = Key::split_on_ts_for(user_key).unwrap(); assert_eq!(expect_key, mem_key); @@ -627,6 +640,8 @@ fn test_load_with_gc() { } // ensure the safe point of the engine - engine.snapshot(range.clone(), 6, 100).unwrap_err(); - engine.snapshot(range, 7, 100).unwrap(); + engine + .snapshot(region.id, 0, range.clone(), 6, 100) + .unwrap_err(); + engine.snapshot(region.id, 0, range, 7, 100).unwrap(); } diff --git a/components/test_pd_client/src/pd.rs b/components/test_pd_client/src/pd.rs index d275ac538e5..ec7b43f6887 100644 --- a/components/test_pd_client/src/pd.rs +++ b/components/test_pd_client/src/pd.rs @@ -581,6 +581,20 @@ impl PdCluster { .and_then(|k| self.regions.get(k).cloned())) } + fn scan_regions(&self, start: &[u8], end: &[u8], limit: i32) -> Vec { + let mut regions = vec![]; + for (_, region) in self.regions.range((Excluded(start.to_vec()), Unbounded)) { + if !end.is_empty() && region.start_key.as_slice() >= end { + break; + } + regions.push(region.clone()); + if regions.len() as i32 >= limit { + break; + } + } + regions + } + fn get_region_approximate_size(&self, region_id: u64) -> Option { self.region_approximate_size.get(®ion_id).cloned() } @@ -1656,6 +1670,28 @@ impl PdClient for TestPdClient { } } + fn scan_regions( + &self, + start_key: &[u8], + end_key: &[u8], + limit: i32, + ) -> Result> { + self.check_bootstrap()?; + + let result: Vec<_> = self + .cluster + .rl() + .scan_regions(start_key, end_key, limit) + .into_iter() + .map(|r| { + let mut res = pdpb::Region::new(); + res.set_region(r); + res + }) + .collect(); + Ok(result) + } + fn get_cluster_config(&self) -> Result { self.check_bootstrap()?; Ok(self.cluster.rl().meta.clone()) diff --git a/components/test_raftstore/src/cluster.rs b/components/test_raftstore/src/cluster.rs index 04b2cf2cee1..d417a4b88df 100644 --- a/components/test_raftstore/src/cluster.rs +++ b/components/test_raftstore/src/cluster.rs @@ -369,9 +369,15 @@ where self.bootstrap_region().unwrap(); self.start().unwrap(); if self.range_cache_engine_enabled_with_whole_range { + let pd_regions = self.pd_client.scan_regions(&[], &[], i32::MAX).unwrap(); + let regions: Vec<_> = pd_regions + .into_iter() + .map(|mut r| r.take_region()) + .collect(); + self.engines .iter() - .for_each(|(_, engines)| engines.kv.cache_all()); + .for_each(|(_, engines)| engines.kv.cache_regions(®ions)); } } @@ -1023,6 +1029,8 @@ where DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec(), )), + region_id: 0, + epoch_version: 0, }; self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) } @@ -1038,6 +1046,8 @@ where DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec(), )), + region_id: 0, + epoch_version: 0, }; self.get_cf_with_snap_ctx(cf, key, true, ctx) } @@ -1053,6 +1063,8 @@ where DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec(), )), + region_id: 0, + epoch_version: 0, }; self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) } diff --git a/components/test_raftstore/src/range_cache_engine.rs b/components/test_raftstore/src/range_cache_engine.rs index 57af823211c..0cdf50fd09d 100644 --- a/components/test_raftstore/src/range_cache_engine.rs +++ b/components/test_raftstore/src/range_cache_engine.rs @@ -1,24 +1,22 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. use engine_rocks::RocksEngine; -use engine_traits::CacheRange; -use keys::{DATA_MAX_KEY, DATA_MIN_KEY}; +use kvproto::metapb::Region; use crate::HybridEngineImpl; pub trait RangCacheEngineExt { - fn cache_all(&self); + fn cache_regions(&self, _regions: &[Region]); } impl RangCacheEngineExt for HybridEngineImpl { - fn cache_all(&self) { - self.range_cache_engine().new_range(CacheRange::new( - DATA_MIN_KEY.to_vec(), - DATA_MAX_KEY.to_vec(), - )); + fn cache_regions(&self, regions: &[Region]) { + for r in regions { + self.range_cache_engine().new_region(r.clone()); + } } } impl RangCacheEngineExt for RocksEngine { - fn cache_all(&self) {} + fn cache_regions(&self, _regions: &[Region]) {} } diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index 4497159f4cd..4b750a2da17 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -19,6 +19,7 @@ use engine_traits::{Engines, KvEngine, SnapshotContext}; use futures::executor::block_on; use grpcio::{ChannelBuilder, EnvBuilder, Environment, Error as GrpcError, Service}; use health_controller::HealthController; +use hybrid_engine::observer::Observer as HybridEngineObserver; use kvproto::{ deadlock::create_deadlock, debugpb::{create_debug, DebugClient}, @@ -324,6 +325,12 @@ impl ServerCluster { } } + // Hybrid engine observer. + if cfg.tikv.range_cache_engine.enabled { + let observer = HybridEngineObserver::new(Arc::new(engines.kv.clone())); + observer.register_to(&mut coprocessor_host); + } + // Create storage. let pd_worker = LazyWorker::new("test-pd-worker"); let pd_sender = pd_worker.scheduler(); diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index 584fd37746f..073f2854e20 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -2195,7 +2195,7 @@ def RaftProcess() -> RowPanel: layout.row( [ graph_panel( - title="Enable apply unpersisted log regoin count", + title="Enable apply unpersisted log region count", description="The number of regions that enable apply unpersisted raft log", yaxes=yaxes(left_format=UNITS.SHORT), targets=[ diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index 984604b6ac4..81050501887 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -21353,7 +21353,7 @@ "thresholds": [], "timeFrom": null, "timeShift": null, - "title": "Enable apply unpersisted log regoin count", + "title": "Enable apply unpersisted log region count", "tooltip": { "msResolution": true, "shared": true, diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index e34ded46ab7..d22d98615a6 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -623607982360b0eb9e6df493d0fb821428fa97c08280fe558e004256114c7752 ./metrics/grafana/tikv_details.json +56699194c49baa1d686f33f734a553fbfe50c76b1bf8bfe0b61ce64a242dba65 ./metrics/grafana/tikv_details.json diff --git a/src/server/raftkv/mod.rs b/src/server/raftkv/mod.rs index f30114445ae..4d3d2712431 100644 --- a/src/server/raftkv/mod.rs +++ b/src/server/raftkv/mod.rs @@ -650,6 +650,8 @@ where // When range cache engine is enabled, we need snapshot context to determine // whether we should use range cache engine snapshot for this request. ctx.start_ts.map(|ts| SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: ts.into_inner(), range: None, }) diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 7a98d3f8c43..3772bf140f9 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -100,6 +100,7 @@ raft_log_engine = { workspace = true } raftstore = { workspace = true } raftstore-v2 = { workspace = true } rand = "0.8.3" +range_cache_memory_engine = { workspace = true } resource_control = { workspace = true } server = { workspace = true } service = { workspace = true } diff --git a/tests/failpoints/cases/test_early_apply.rs b/tests/failpoints/cases/test_early_apply.rs index 65f3655e8f9..540ce408d58 100644 --- a/tests/failpoints/cases/test_early_apply.rs +++ b/tests/failpoints/cases/test_early_apply.rs @@ -148,7 +148,7 @@ fn test_early_apply_yield_followed_with_many_entries() { fail::remove(before_handle_normal_3_fp); - // Wait for apply state writting to kv db + // Wait for apply state writing to kv db sleep_ms(200); cluster.shutdown(); diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index c52127c16fd..883bccb0843 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -11,11 +11,12 @@ use engine_traits::{ CF_DEFAULT, CF_WRITE, }; use file_system::calc_crc32_bytes; -use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; +use keys::data_key; use kvproto::{ import_sstpb::SstMeta, raft_cmdpb::{CmdType, RaftCmdRequest, RaftRequestHeader, Request}, }; +use range_cache_memory_engine::test_util::new_region; use tempfile::tempdir; use test_raftstore::{ make_cb, new_node_cluster_with_hybrid_engine_with_no_range_cache, new_peer, new_put_cmd, @@ -33,14 +34,17 @@ fn test_basic_put_get() { let range_cache_engine = cluster.get_range_cache_engine(1); // FIXME: load is not implemented, so we have to insert range manually { + let region = cluster.get_region(b"k"); + let rid = region.id; let mut core = range_cache_engine.core().write(); - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().new_range(cache_range.clone()); - core.mut_range_manager().set_safe_point(&cache_range, 1000); + core.mut_range_manager().new_region(region); + core.mut_range_manager().set_safe_point(rid, 1000); } cluster.put(b"k05", b"val").unwrap(); let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: 1001, range: None, }; @@ -59,117 +63,11 @@ fn test_basic_put_get() { #[test] fn test_load() { - let test_load = |concurrent_with_split: bool| { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); - cluster.cfg.raft_store.apply_batch_system.pool_size = 2; - cluster.run(); - - for i in (0..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); - } - let r = cluster.get_region(b""); - let split_key1 = format!("key-{:04}", 10).into_bytes(); - cluster.must_split(&r, &split_key1); - let r = cluster.get_region(&split_key1); - let split_key2 = format!("key-{:04}", 20).into_bytes(); - cluster.must_split(&r, &split_key2); - - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_snapshot_load_finished", move || { - tx.send(true).unwrap(); - }) - .unwrap(); - - // load range - { - let range_cache_engine = cluster.get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - if concurrent_with_split { - // Load the whole range as if it is not splitted. Loading process should handle - // it correctly. - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().load_range(cache_range).unwrap(); - } else { - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), data_key(&split_key1)); - let cache_range2 = CacheRange::new(data_key(&split_key1), data_key(&split_key2)); - let cache_range3 = CacheRange::new(data_key(&split_key2), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().load_range(cache_range).unwrap(); - core.mut_range_manager().load_range(cache_range2).unwrap(); - core.mut_range_manager().load_range(cache_range3).unwrap(); - } - } - - // put key to trigger load task - for i in &[0, 10, 20] { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); - } - - // ensure the snapshot is loaded - rx.recv_timeout(Duration::from_secs(5)).unwrap(); - rx.recv_timeout(Duration::from_secs(5)).unwrap(); - rx.recv_timeout(Duration::from_secs(5)).unwrap(); - - for i in (1..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); - } - - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { - tx.send(true).unwrap(); - }) - .unwrap(); - - let snap_ctx = SnapshotContext { - read_ts: 20, - range: None, - }; - - for i in 0..30 { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - let val = cluster - .get_cf_with_snap_ctx(CF_WRITE, &encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-write"); - // verify it's read from range cache engine - assert!(rx.try_recv().unwrap()); - - let val = cluster - .get_with_snap_ctx(&encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-default"); - // verify it's read from range cache engine - assert!(rx.try_recv().unwrap()); - } - }; - test_load(false); - test_load(true); -} - -#[test] -fn test_write_batch_cache_during_load() { let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.cfg.raft_store.apply_batch_system.pool_size = 2; cluster.run(); - for i in 0..10 { + for i in (0..30).step_by(2) { let key = format!("key-{:04}", i); let encoded_key = Key::from_raw(key.as_bytes()) .append_ts(20.into()) @@ -177,20 +75,33 @@ fn test_write_batch_cache_during_load() { cluster.must_put(&encoded_key, b"val-default"); cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); } + let r = cluster.get_region(b""); + let split_key1 = format!("key-{:04}", 10).into_bytes(); + cluster.must_split(&r, &split_key1); + let r = cluster.get_region(&split_key1); + let split_key2 = format!("key-{:04}", 20).into_bytes(); + cluster.must_split(&r, &split_key2); + + let (tx, rx) = sync_channel(1); + fail::cfg_callback("on_snapshot_load_finished", move || { + tx.send(true).unwrap(); + }) + .unwrap(); - fail::cfg("on_snapshot_load_finished", "pause").unwrap(); // load range { + let r = cluster.get_region(b""); + let r1 = cluster.get_region(&split_key1); + let r2 = cluster.get_region(&split_key2); let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().load_range(cache_range).unwrap(); + core.mut_range_manager().load_region(r).unwrap(); + core.mut_range_manager().load_region(r1).unwrap(); + core.mut_range_manager().load_region(r2).unwrap(); } - // First, cache some entries after the acquire of the snapshot - // Then, cache some additional entries after the snapshot loaded and the - // previous cache consumed - for i in 10..20 { + // put key to trigger load task + for i in &[0, 10, 20] { let key = format!("key-{:04}", i); let encoded_key = Key::from_raw(key.as_bytes()) .append_ts(20.into()) @@ -199,41 +110,12 @@ fn test_write_batch_cache_during_load() { cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); } - let (tx1, rx1) = sync_channel(1); - fail::cfg_callback("pending_range_completes_loading", move || { - tx1.send(true).unwrap(); - }) - .unwrap(); - - // use it to mock concurrency between consuming cached write batch and cache - // further writes - fail::cfg("on_cached_write_batch_consumed", "pause").unwrap(); - fail::remove("on_snapshot_load_finished"); - - let (tx2, rx2) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { - tx2.send(true).unwrap(); - }) - .unwrap(); - let snap_ctx = SnapshotContext { - read_ts: 20, - range: None, - }; + // ensure the snapshot is loaded + rx.recv_timeout(Duration::from_secs(5)).unwrap(); + rx.recv_timeout(Duration::from_secs(5)).unwrap(); + rx.recv_timeout(Duration::from_secs(5)).unwrap(); - for i in 20..30 { - if i == 29 { - let key = format!("key-{:04}", 1); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - let val = cluster - .get_cf_with_snap_ctx(CF_WRITE, &encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-write"); - // We should not read the value in the memory engine at this phase. - rx2.try_recv().unwrap_err(); - fail::remove("on_cached_write_batch_consumed"); - } + for i in (1..30).step_by(2) { let key = format!("key-{:04}", i); let encoded_key = Key::from_raw(key.as_bytes()) .append_ts(20.into()) @@ -242,8 +124,18 @@ fn test_write_batch_cache_during_load() { cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); } - // ensure the pending range is transfered to normal range - rx1.recv_timeout(Duration::from_secs(5)).unwrap(); + let (tx, rx) = sync_channel(1); + fail::cfg_callback("on_range_cache_get_value", move || { + tx.send(true).unwrap(); + }) + .unwrap(); + + let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, + read_ts: 20, + range: None, + }; for i in 0..30 { let key = format!("key-{:04}", i); @@ -255,14 +147,14 @@ fn test_write_batch_cache_during_load() { .unwrap(); assert_eq!(&val, b"val-write"); // verify it's read from range cache engine - assert!(rx2.try_recv().unwrap()); + assert!(rx.try_recv().unwrap()); let val = cluster .get_with_snap_ctx(&encoded_key, false, snap_ctx.clone()) .unwrap(); assert_eq!(&val, b"val-default"); // verify it's read from range cache engine - assert!(rx2.try_recv().unwrap()); + assert!(rx.try_recv().unwrap()); } } @@ -299,8 +191,8 @@ fn test_load_with_split() { let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().load_range(cache_range).unwrap(); + let cache_range = new_region(1, "", ""); + core.mut_range_manager().load_region(cache_range).unwrap(); } rx.recv_timeout(Duration::from_secs(5)).unwrap(); @@ -334,6 +226,8 @@ fn test_load_with_split() { .unwrap(); let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: 20, range: None, }; @@ -362,8 +256,8 @@ fn test_load_with_split() { // It tests race between split and load. // Takes k1-k10 as an example: // We want to load k1-k10 where k1-k10 is already split into k1-k5, and k5-k10. -// And before we `load_range` k1-k10, k1-k5 has cached some writes, say k1, in -// write_batch which means k1 cannot be loaded from snapshot. Now, `load_range` +// And before we `load_region` k1-k10, k1-k5 has cached some writes, say k1, in +// write_batch which means k1 cannot be loaded from snapshot. Now, `load_region` // k1-k10 is called, and k5-k10 calls prepare_for_apply and the snapshot is // acquired and load task of k1-k10 is scheduled. We will loss data of k1 before // this PR. @@ -379,6 +273,8 @@ fn test_load_with_split2() { let r = cluster.get_region(b""); cluster.must_split(&r, b"k05"); + let r_split = cluster.get_region(b"k05"); + fail::cfg("on_handle_put", "pause").unwrap(); let write_req = make_write_req(&mut cluster, b"k02"); let (cb, _) = make_cb::(&write_req); @@ -392,11 +288,10 @@ fn test_load_with_split2() { { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); + // try to load a region with old epoch and bigger range, + // it should be updated to the real region range. core.mut_range_manager() - .load_range(CacheRange::new( - DATA_MIN_KEY.to_vec(), - DATA_MAX_KEY.to_vec(), - )) + .load_region(new_region(r_split.id, "", "")) .unwrap(); } @@ -415,6 +310,14 @@ fn test_load_with_split2() { .unwrap(); let _ = rx.recv_timeout(Duration::from_secs(5)).unwrap(); + { + let range_cache_engine = cluster.get_range_cache_engine(1); + let core = range_cache_engine.core().read(); + let meta = core.range_manager().region_meta(r_split.id).unwrap(); + let split_range = CacheRange::from_region(&r_split); + assert_eq!(&split_range, meta.get_range()); + } + fail::remove("on_handle_put"); std::thread::sleep(Duration::from_secs(1)); @@ -424,6 +327,8 @@ fn test_load_with_split2() { }) .unwrap(); let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: 20, range: None, }; @@ -433,18 +338,11 @@ fn test_load_with_split2() { .unwrap(); assert!(rx.try_recv().unwrap()); - // k1-k5 should not cached now + // k1-k5 should not cached. let _ = cluster .get_with_snap_ctx(b"k02", false, snap_ctx.clone()) .unwrap(); rx.try_recv().unwrap_err(); - - // write a key to trigger load task - cluster.must_put(b"k03", b"val"); - let _ = cluster - .get_with_snap_ctx(b"k02", false, snap_ctx.clone()) - .unwrap(); - assert!(rx.try_recv().unwrap()); } fn make_write_req( @@ -477,8 +375,8 @@ fn test_load_with_eviction() { let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); - core.mut_range_manager().load_range(cache_range).unwrap(); + let cache_range = new_region(1, "", ""); + core.mut_range_manager().load_region(cache_range).unwrap(); } let r = cluster.get_region(b""); @@ -505,20 +403,16 @@ fn test_load_with_eviction() { let range_cache_engine = cluster.get_range_cache_engine(1); let mut tried_count = 0; while range_cache_engine - .snapshot( - CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()), - u64::MAX, - u64::MAX, - ) + .snapshot(1, 0, CacheRange::from_region(&r), u64::MAX, u64::MAX) .is_err() && tried_count < 5 { std::thread::sleep(Duration::from_millis(100)); tried_count += 1; } - // Now, the range (DATA_MIN_KEY, DATA_MAX_KEY) should be cached - let range = CacheRange::new(data_key(b"k10"), DATA_MAX_KEY.to_vec()); - range_cache_engine.evict_range(&range, EvictReason::AutoEvict); + // Now, the range ["", "") should be cached + let region = new_region(1, b"k10", ""); + range_cache_engine.evict_region(®ion, EvictReason::AutoEvict); } fail::remove("on_write_impl"); @@ -532,6 +426,8 @@ fn test_load_with_eviction() { .unwrap(); let snap_ctx = SnapshotContext { + region_id: 0, + epoch_version: 0, read_ts: u64::MAX, range: None, }; @@ -556,22 +452,34 @@ fn test_evictions_after_transfer_leader() { let r = cluster.get_region(b""); cluster.must_transfer_leader(r.id, new_peer(1, 1)); - let cache_range = CacheRange::new(DATA_MIN_KEY.to_vec(), DATA_MAX_KEY.to_vec()); + let cache_region = new_region(1, "", ""); let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_range(cache_range.clone()); + core.mut_range_manager().new_region(cache_region.clone()); drop(core); range_cache_engine }; range_cache_engine - .snapshot(cache_range.clone(), 100, 100) + .snapshot( + cache_region.id, + 0, + CacheRange::from_region(&cache_region), + 100, + 100, + ) .unwrap(); cluster.must_transfer_leader(r.id, new_peer(2, 2)); range_cache_engine - .snapshot(cache_range, 100, 100) + .snapshot( + cache_region.id, + 0, + CacheRange::from_region(&cache_region), + 100, + 100, + ) .unwrap_err(); } @@ -590,24 +498,34 @@ fn test_eviction_after_merge() { let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_range(range1.clone()); - core.mut_range_manager().new_range(range2.clone()); + core.mut_range_manager().new_region(r.clone()); + core.mut_range_manager().new_region(r2.clone()); drop(core); range_cache_engine }; range_cache_engine - .snapshot(range1.clone(), 100, 100) + .snapshot(r.id, r.get_region_epoch().version, range1.clone(), 100, 100) .unwrap(); range_cache_engine - .snapshot(range2.clone(), 100, 100) + .snapshot( + r2.id, + r2.get_region_epoch().version, + range2.clone(), + 100, + 100, + ) .unwrap(); let pd_client = Arc::clone(&cluster.pd_client); pd_client.must_merge(r.get_id(), r2.get_id()); - range_cache_engine.snapshot(range1, 100, 100).unwrap_err(); - range_cache_engine.snapshot(range2, 100, 100).unwrap_err(); + range_cache_engine + .snapshot(r.id, r.get_region_epoch().version, range1, 100, 100) + .unwrap_err(); + range_cache_engine + .snapshot(r2.id, r2.get_region_epoch().version, range2, 100, 100) + .unwrap_err(); } #[test] @@ -630,13 +548,19 @@ fn test_eviction_after_ingest_sst() { let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_range(range.clone()); + core.mut_range_manager().new_region(region.clone()); drop(core); range_cache_engine }; range_cache_engine - .snapshot(range.clone(), 100, 100) + .snapshot( + region.id, + region.get_region_epoch().version, + range.clone(), + 100, + 100, + ) .unwrap(); // Ingest the sst file. @@ -676,5 +600,13 @@ fn test_eviction_after_ingest_sst() { .unwrap(); assert!(!resp.get_header().has_error(), "{:?}", resp); - range_cache_engine.snapshot(range, 100, 100).unwrap_err(); + range_cache_engine + .snapshot( + region.id, + region.get_region_epoch().version, + range, + 100, + 100, + ) + .unwrap_err(); } diff --git a/tests/failpoints/cases/test_stale_read.rs b/tests/failpoints/cases/test_stale_read.rs index ceb018fc610..26da3746d7b 100644 --- a/tests/failpoints/cases/test_stale_read.rs +++ b/tests/failpoints/cases/test_stale_read.rs @@ -286,7 +286,7 @@ fn test_stale_read_during_merging() { // Note: L: leader, F: follower, X: peer is not exist. // TODO: what if cluster runs slow and lease is expired. // Epoch changed by prepare merge. - // We can not use `get_region_with` to get the latest info of reigon 1000, + // We can not use `get_region_with` to get the latest info of region 1000, // because leader1 is not paused, it executes commit merge very fast // and reports pd, its range covers region1000. // From 9734214510548db97c6ff61c3af52fb9dee13de0 Mon Sep 17 00:00:00 2001 From: Ling Jin <7138436+3AceShowHand@users.noreply.github.com> Date: Mon, 19 Aug 2024 19:12:11 +0800 Subject: [PATCH 029/144] cdc: print log to indicate memory free, and adjust finish_scan_lock method (#17357) close tikv/tikv#17368 * add one log to indicate the memory quota is freed when drop the `Drain` * free the truncated scanned event memory quota. * refactor `finish_scan_lock` method, to remove the else branch. * row size calculation should also consider old value * remove some outdate todo Signed-off-by: 3AceShowHand Signed-off-by: Ling Jin <7138436+3AceShowHand@users.noreply.github.com> Co-authored-by: Neil Shen --- components/cdc/src/channel.rs | 52 +++++++++++++++--- components/cdc/src/delegate.rs | 10 ++-- components/cdc/src/endpoint.rs | 90 ++++++++++++++++--------------- components/cdc/src/initializer.rs | 2 +- components/cdc/src/observer.rs | 2 - components/cdc/src/service.rs | 16 +++--- 6 files changed, 107 insertions(+), 65 deletions(-) diff --git a/components/cdc/src/channel.rs b/components/cdc/src/channel.rs index c49bec00547..ad9ebdd0d44 100644 --- a/components/cdc/src/channel.rs +++ b/components/cdc/src/channel.rs @@ -22,13 +22,13 @@ use kvproto::cdcpb::{ChangeDataEvent, Event, ResolvedTs}; use protobuf::Message; use tikv_util::{ future::block_on_timeout, - impl_display_as_debug, + impl_display_as_debug, info, memory::{MemoryQuota, MemoryQuotaExceeded}, time::Instant, warn, }; -use crate::metrics::*; +use crate::{metrics::*, service::ConnId}; /// The maximum bytes of events can be batched into one `CdcEvent::Event`, 32KB. pub const CDC_EVENT_MAX_BYTES: usize = 32 * 1024; @@ -194,7 +194,7 @@ impl EventBatcher { } } -pub fn channel(buffer: usize, memory_quota: Arc) -> (Sink, Drain) { +pub fn channel(conn_id: ConnId, buffer: usize, memory_quota: Arc) -> (Sink, Drain) { let (unbounded_sender, unbounded_receiver) = unbounded(); let (bounded_sender, bounded_receiver) = bounded(buffer); ( @@ -207,6 +207,7 @@ pub fn channel(buffer: usize, memory_quota: Arc) -> (Sink, Drain) { unbounded_receiver, bounded_receiver, memory_quota, + conn_id, }, ) } @@ -355,6 +356,7 @@ pub struct Drain { unbounded_receiver: UnboundedReceiver, bounded_receiver: Receiver, memory_quota: Arc, + conn_id: ConnId, } impl<'a> Drain { @@ -362,6 +364,7 @@ impl<'a> Drain { let observed = (&mut self.unbounded_receiver).map(|x| (x.created, x.event, x.size)); let scaned = (&mut self.bounded_receiver).filter_map(|x| { if x.truncated.load(Ordering::Acquire) { + self.memory_quota.free(x.size as _); return futures::future::ready(None); } futures::future::ready(Some((x.created, x.event, x.size))) @@ -420,14 +423,17 @@ impl Drop for Drain { self.bounded_receiver.close(); self.unbounded_receiver.close(); let start = Instant::now(); - let mut drain = Box::pin(async { + let mut total_bytes = 0; + let mut drain = Box::pin(async move { + let conn_id = self.conn_id; let memory_quota = self.memory_quota.clone(); - let mut total_bytes = 0; let mut drain = self.drain(); while let Some((_, bytes)) = drain.next().await { total_bytes += bytes; } memory_quota.free(total_bytes); + info!("drop Drain finished, free memory"; "conn_id" => ?conn_id, + "freed_bytes" => total_bytes, "inuse_bytes" => memory_quota.in_use()); }); block_on(&mut drain); let takes = start.saturating_elapsed(); @@ -463,7 +469,7 @@ mod tests { type Send = Box Result<(), SendError>>; fn new_test_channel(buffer: usize, capacity: usize, force_send: bool) -> (Send, Drain) { let memory_quota = Arc::new(MemoryQuota::new(capacity)); - let (mut tx, rx) = channel(buffer, memory_quota); + let (mut tx, rx) = channel(ConnId::default(), buffer, memory_quota); let mut flag = true; let send = move |event| { flag = !flag; @@ -476,6 +482,38 @@ mod tests { (Box::new(send), rx) } + #[test] + fn test_scanned_event() { + let mut e = Event::default(); + e.region_id = 233; + { + let memory_quota = Arc::new(MemoryQuota::new(1024)); + let (mut tx, mut rx) = channel(ConnId::default(), 10, memory_quota); + + let truncated = Arc::new(AtomicBool::new(false)); + let event = CdcEvent::Event(e.clone()); + let size = event.size() as usize; + let _ = block_on(tx.send_all(vec![event], truncated)); + + let memory_quota = rx.memory_quota.clone(); + let mut drain = rx.drain(); + assert_matches!(block_on(drain.next()), Some((CdcEvent::Event(_), _))); + assert_eq!(memory_quota.in_use(), size); + } + { + let memory_quota = Arc::new(MemoryQuota::new(1024)); + let (mut tx, mut rx) = channel(ConnId::default(), 10, memory_quota); + + let truncated = Arc::new(AtomicBool::new(true)); + let _ = block_on(tx.send_all(vec![CdcEvent::Event(e)], truncated)); + + let memory_quota = rx.memory_quota.clone(); + let mut drain = rx.drain(); + recv_timeout(&mut drain, Duration::from_millis(100)).unwrap_err(); + assert_eq!(memory_quota.in_use(), 0); + } + } + #[test] fn test_barrier() { let force_send = false; @@ -611,7 +649,7 @@ mod tests { let max_pending_bytes = 1024; let buffer = max_pending_bytes / event.size(); let memory_quota = Arc::new(MemoryQuota::new(max_pending_bytes as _)); - let (tx, _rx) = channel(buffer as _, memory_quota); + let (tx, _rx) = channel(ConnId::default(), buffer as _, memory_quota); for _ in 0..buffer { tx.unbounded_send(CdcEvent::Event(e.clone()), false) .unwrap(); diff --git a/components/cdc/src/delegate.rs b/components/cdc/src/delegate.rs index a4e04c6540a..5b979ade2ec 100644 --- a/components/cdc/src/delegate.rs +++ b/components/cdc/src/delegate.rs @@ -769,7 +769,7 @@ impl Delegate { } decode_default(default.1, &mut row, &mut _has_value); row.old_value = old_value.finalized().unwrap_or_default(); - row_size = row.key.len() + row.value.len(); + row_size = row.key.len() + row.value.len() + row.old_value.len(); } Some(KvEntry::TxnEntry(TxnEntry::Commit { default, @@ -797,7 +797,7 @@ impl Delegate { } set_event_row_type(&mut row, EventLogType::Committed); row.old_value = old_value.finalized().unwrap_or_default(); - row_size = row.key.len() + row.value.len(); + row_size = row.key.len() + row.value.len() + row.old_value.len(); } None => { // This type means scan has finished. @@ -1433,7 +1433,7 @@ mod tests { let region_epoch = region.get_region_epoch().clone(); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (sink, mut drain) = crate::channel::channel(1, quota.clone()); + let (sink, mut drain) = channel(ConnId::default(), 1, quota.clone()); let rx = drain.drain(); let request_id = RequestId(123); let mut downstream = Downstream::new( @@ -1725,7 +1725,7 @@ mod tests { } assert_eq!(rows_builder.txns_by_key.len(), 5); - let (sink, mut drain) = channel(1, Arc::new(MemoryQuota::new(1024))); + let (sink, mut drain) = channel(ConnId::default(), 1, Arc::new(MemoryQuota::new(1024))); let mut downstream = Downstream::new( "peer".to_owned(), RegionEpoch::default(), @@ -1792,7 +1792,7 @@ mod tests { } assert_eq!(rows_builder.txns_by_key.len(), 5); - let (sink, mut drain) = channel(1, Arc::new(MemoryQuota::new(1024))); + let (sink, mut drain) = channel(ConnId::default(), 1, Arc::new(MemoryQuota::new(1024))); let mut downstream = Downstream::new( "peer".to_owned(), RegionEpoch::default(), diff --git a/components/cdc/src/endpoint.rs b/components/cdc/src/endpoint.rs index 9bfe2fd88e6..972be77067e 100644 --- a/components/cdc/src/endpoint.rs +++ b/components/cdc/src/endpoint.rs @@ -1023,11 +1023,22 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint, ) { let region_id = region.get_id(); - let mut deregisters = Vec::new(); - if let Some(delegate) = self.capture_regions.get_mut(®ion_id) { - if delegate.handle.id == observe_id { + match self.capture_regions.get_mut(®ion_id) { + None => { + debug!("cdc region not found on region ready (finish scan locks)"; + "region_id" => region.get_id()); + } + Some(delegate) => { + if delegate.handle.id != observe_id { + debug!("cdc stale region ready"; + "region_id" => region.get_id(), + "observe_id" => ?observe_id, + "current_id" => ?delegate.handle.id); + return; + } match delegate.finish_scan_locks(region, locks) { Ok(fails) => { + let mut deregisters = Vec::new(); for (downstream, e) in fails { deregisters.push(Deregister::Downstream { conn_id: downstream.conn_id, @@ -1037,27 +1048,18 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint deregisters.push(Deregister::Delegate { + Err(e) => self.on_deregister(Deregister::Delegate { region_id, observe_id, err: e, }), } - } else { - debug!("cdc stale region ready"; - "region_id" => region.get_id(), - "observe_id" => ?observe_id, - "current_id" => ?delegate.handle.id); } - } else { - debug!("cdc region not found on region ready (finish scan locks)"; - "region_id" => region.get_id()); - } - - // Deregister downstreams if there is any downstream fails to subscribe. - for deregister in deregisters { - self.on_deregister(deregister); } } @@ -1136,7 +1138,7 @@ impl, E: KvEngine, S: StoreRegionMeta> Endpoint (), // Must schedule `RegisterMinTsEvent` event otherwise resolved ts can not // advance normally. - Err(err) => panic!("failed to regiester min ts event, error: {:?}", err), + Err(err) => panic!("failed to register min ts event, error: {:?}", err), } } else { // During shutdown, tso runtime drops future immediately, @@ -1518,10 +1520,10 @@ mod tests { let mut suite = mock_endpoint(&cfg, None, ApiVersion::V1); suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); suite.run(set_conn_version_task( @@ -1798,14 +1800,14 @@ mod tests { #[test] fn test_raftstore_is_busy() { let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, _rx) = channel::channel(1, quota); + let (tx, _rx) = channel::channel(ConnId::default(), 1, quota); let mut suite = mock_endpoint(&CdcConfig::default(), None, ApiVersion::V1); // Fill the channel. suite.add_region(1 /* region id */, 1 /* cap */); suite.fill_raft_rx(1); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); suite.run(set_conn_version_task( @@ -1853,10 +1855,10 @@ mod tests { let mut suite = mock_endpoint(&cfg, None, ApiVersion::V1); suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); @@ -2016,10 +2018,10 @@ mod tests { suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); @@ -2119,11 +2121,11 @@ mod tests { suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); let mut region = Region::default(); region.set_id(1); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); @@ -2215,11 +2217,11 @@ mod tests { // Register region 3 to another conn which is not support batch resolved ts. let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx2) = channel::channel(1, quota); + let (tx, mut rx2) = channel::channel(ConnId::default(), 1, quota); let mut rx2 = rx2.drain(); let mut region = Region::default(); region.set_id(3); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); suite.run(set_conn_version_task( @@ -2292,10 +2294,10 @@ mod tests { let mut suite = mock_endpoint(&CdcConfig::default(), None, ApiVersion::V1); suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); suite.run(set_conn_version_task( @@ -2445,9 +2447,9 @@ mod tests { let mut conn_rxs = vec![]; let quota = Arc::new(MemoryQuota::new(usize::MAX)); for region_ids in [vec![1, 2], vec![3]] { - let (tx, rx) = channel::channel(1, quota.clone()); + let (tx, rx) = channel::channel(ConnId::default(), 1, quota.clone()); conn_rxs.push(rx); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); let version = FeatureGate::batch_resolved_ts(); @@ -2562,8 +2564,8 @@ mod tests { let quota = Arc::new(MemoryQuota::new(usize::MAX)); // Open conn a - let (tx1, _rx1) = channel::channel(1, quota.clone()); - let conn_a = Conn::new(tx1, String::new()); + let (tx1, _rx1) = channel::channel(ConnId::default(), 1, quota.clone()); + let conn_a = Conn::new(ConnId::default(), tx1, String::new()); let conn_id_a = conn_a.get_id(); suite.run(Task::OpenConn { conn: conn_a }); suite.run(set_conn_version_task( @@ -2572,9 +2574,9 @@ mod tests { )); // Open conn b - let (tx2, mut rx2) = channel::channel(1, quota); + let (tx2, mut rx2) = channel::channel(ConnId::default(), 1, quota); let mut rx2 = rx2.drain(); - let conn_b = Conn::new(tx2, String::new()); + let conn_b = Conn::new(ConnId::default(), tx2, String::new()); let conn_id_b = conn_b.get_id(); suite.run(Task::OpenConn { conn: conn_b }); suite.run(set_conn_version_task( @@ -2720,10 +2722,10 @@ mod tests { }; let mut suite = mock_endpoint(&cfg, None, ApiVersion::V1); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); // Enable batch resolved ts in the test. @@ -2817,10 +2819,10 @@ mod tests { let mut suite = mock_endpoint(&cfg, None, ApiVersion::V1); suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, mut rx) = channel::channel(1, quota); + let (tx, mut rx) = channel::channel(ConnId::default(), 1, quota); let mut rx = rx.drain(); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); @@ -3071,9 +3073,9 @@ mod tests { let mut suite = mock_endpoint(&cfg, None, ApiVersion::V1); suite.add_region(1, 100); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (tx, _rx) = channel::channel(1, quota); + let (tx, _rx) = channel::channel(ConnId::default(), 1, quota); - let conn = Conn::new(tx, String::new()); + let conn = Conn::new(ConnId::default(), tx, String::new()); let conn_id = conn.get_id(); suite.run(Task::OpenConn { conn }); diff --git a/components/cdc/src/initializer.rs b/components/cdc/src/initializer.rs index 0330e3fca56..488a8e432f7 100644 --- a/components/cdc/src/initializer.rs +++ b/components/cdc/src/initializer.rs @@ -707,7 +707,7 @@ mod tests { ) { let (receiver_worker, rx) = new_receiver_worker(); let quota = Arc::new(MemoryQuota::new(usize::MAX)); - let (sink, drain) = crate::channel::channel(buffer, quota); + let (sink, drain) = crate::channel::channel(ConnId::default(), buffer, quota); let pool = Builder::new_multi_thread() .thread_name("test-initializer-worker") diff --git a/components/cdc/src/observer.rs b/components/cdc/src/observer.rs index 2e1a7f7734d..6bc36e56c98 100644 --- a/components/cdc/src/observer.rs +++ b/components/cdc/src/observer.rs @@ -119,8 +119,6 @@ impl CmdObserver for CdcObserver { let mut region = Region::default(); region.mut_peers().push(Peer::default()); // Create a snapshot here for preventing the old value was GC-ed. - // TODO: only need it after enabling old value, may add a flag to indicate - // whether to get it. let snapshot = RegionSnapshot::from_snapshot(Arc::new(engine.snapshot(None)), Arc::new(region)); let get_old_value = move |key, diff --git a/components/cdc/src/service.rs b/components/cdc/src/service.rs index d6c223d2ec7..0ecd2eb606c 100644 --- a/components/cdc/src/service.rs +++ b/components/cdc/src/service.rs @@ -103,9 +103,9 @@ struct DownstreamValue { } impl Conn { - pub fn new(sink: Sink, peer: String) -> Conn { + pub fn new(conn_id: ConnId, sink: Sink, peer: String) -> Conn { Conn { - id: ConnId::new(), + id: conn_id, sink, downstreams: HashMap::default(), peer, @@ -338,8 +338,12 @@ impl Service { .unwrap_or_else(|e| { warn!( "cdc invalid observed start key or end key version"; - "downstream" => ?peer, "region_id" => request.region_id, + "downstream" => ?peer, + "region_id" => request.region_id, + "request_id" => request.region_id, "error" => ?e, + "start_key" => log_wrappers::Value::key(&request.start_key), + "end_key" => log_wrappers::Value::key(&request.end_key), ); ObservedRange::default() }); @@ -401,10 +405,10 @@ impl Service { event_feed_v2: bool, ) { sink.enhance_batch(true); + let conn_id = ConnId::new(); let (event_sink, mut event_drain) = - channel(CDC_CHANNLE_CAPACITY, self.memory_quota.clone()); - let conn = Conn::new(event_sink, ctx.peer()); - let conn_id = conn.get_id(); + channel(conn_id, CDC_CHANNLE_CAPACITY, self.memory_quota.clone()); + let conn = Conn::new(conn_id, event_sink, ctx.peer()); let mut explicit_features = vec![]; if event_feed_v2 { From 4f3f9517b4e8a9ea34629c2d19439c031d14326d Mon Sep 17 00:00:00 2001 From: Wenxuan Date: Tue, 20 Aug 2024 15:04:42 +0800 Subject: [PATCH 030/144] copr: Support Vector Data Type and Functions (#17303) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref tikv/tikv#17290 Signed-off-by: EricZequan <110292382+EricZequan@users.noreply.github.com> Signed-off-by: “EricZequan” Co-authored-by: EricZequan <110292382+EricZequan@users.noreply.github.com> Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 6 +- components/tidb_query_aggr/src/impl_first.rs | 1 + .../tidb_query_aggr/src/impl_max_min.rs | 1 + components/tidb_query_aggr/src/lib.rs | 1 + .../tidb_query_codegen/src/rpn_function.rs | 18 +- components/tidb_query_datatype/Cargo.toml | 9 + .../benches/bench_vector_distance.rs | 191 ++++++++ .../src/codec/chunk/column.rs | 55 ++- .../data_type/chunked_vec_vector_float32.rs | 135 ++++++ .../src/codec/data_type/mod.rs | 87 +++- .../src/codec/data_type/scalar.rs | 37 +- .../src/codec/data_type/vector.rs | 48 +- .../tidb_query_datatype/src/codec/datum.rs | 30 +- .../src/codec/datum_codec.rs | 63 ++- .../src/codec/mysql/mod.rs | 2 + .../src/codec/mysql/vector.rs | 449 ++++++++++++++++++ .../src/codec/row/v2/compat_v1.rs | 4 + .../tidb_query_datatype/src/codec/table.rs | 1 + .../tidb_query_datatype/src/def/eval_type.rs | 3 + .../tidb_query_datatype/src/def/field_type.rs | 2 + .../src/fast_hash_aggr_executor.rs | 10 +- .../src/util/top_n_heap.rs | 1 + components/tidb_query_expr/src/impl_cast.rs | 18 + .../tidb_query_expr/src/impl_compare.rs | 13 + .../tidb_query_expr/src/impl_miscellaneous.rs | 12 + components/tidb_query_expr/src/impl_op.rs | 6 + components/tidb_query_expr/src/impl_vec.rs | 226 +++++++++ components/tidb_query_expr/src/lib.rs | 26 +- components/tidb_query_expr/src/types/expr.rs | 1 + .../tidb_query_expr/src/types/expr_builder.rs | 18 +- .../tidb_query_expr/src/types/expr_eval.rs | 2 + .../tidb_query_expr/src/types/function.rs | 3 + 32 files changed, 1457 insertions(+), 22 deletions(-) create mode 100644 components/tidb_query_datatype/benches/bench_vector_distance.rs create mode 100644 components/tidb_query_datatype/src/codec/data_type/chunked_vec_vector_float32.rs create mode 100644 components/tidb_query_datatype/src/codec/mysql/vector.rs create mode 100644 components/tidb_query_expr/src/impl_vec.rs diff --git a/Cargo.lock b/Cargo.lock index e0255c05042..7e9eac0090d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -715,9 +715,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -6346,11 +6346,13 @@ dependencies = [ "bitflags 1.3.2", "boolinator", "bstr", + "bytemuck", "chrono", "chrono-tz", "codec", "collections", "crc32fast", + "criterion", "encoding_rs 0.8.29", "error_code", "hex 0.4.2", diff --git a/components/tidb_query_aggr/src/impl_first.rs b/components/tidb_query_aggr/src/impl_first.rs index 3eb9a8e04aa..fbd23822f1f 100644 --- a/components/tidb_query_aggr/src/impl_first.rs +++ b/components/tidb_query_aggr/src/impl_first.rs @@ -62,6 +62,7 @@ impl super::AggrDefinitionParser for AggrFnDefinitionParserFirst { Bytes => BytesRef<'static>, Enum => EnumRef<'static>, Set => SetRef<'static>, + VectorFloat32 => VectorFloat32Ref<'static>, ], match eval_type { EvalType::TT => Ok(Box::new(AggrFnFirst::::new())), diff --git a/components/tidb_query_aggr/src/impl_max_min.rs b/components/tidb_query_aggr/src/impl_max_min.rs index c18710b3645..0ee7ceb570a 100644 --- a/components/tidb_query_aggr/src/impl_max_min.rs +++ b/components/tidb_query_aggr/src/impl_max_min.rs @@ -92,6 +92,7 @@ impl super::AggrDefinitionParser for AggrFnDefinitionParserExtremum Decimal => &'static Decimal, DateTime => &'static DateTime, Json => JsonRef<'static>, + VectorFloat32 => VectorFloat32Ref<'static>, ], match eval_type { EvalType::T => Ok(Box::new(AggFnExtremum::::new())), diff --git a/components/tidb_query_aggr/src/lib.rs b/components/tidb_query_aggr/src/lib.rs index c6ddfb96d2f..8b53c8a078d 100644 --- a/components/tidb_query_aggr/src/lib.rs +++ b/components/tidb_query_aggr/src/lib.rs @@ -76,6 +76,7 @@ pub trait AggrFunctionState: + AggrFunctionStateUpdatePartial> + AggrFunctionStateUpdatePartial> + AggrFunctionStateUpdatePartial> + + AggrFunctionStateUpdatePartial> { // TODO: A better implementation is to specialize different push result targets. // However current aggregation executor cannot utilize it. diff --git a/components/tidb_query_codegen/src/rpn_function.rs b/components/tidb_query_codegen/src/rpn_function.rs index ea3017d5d02..8b414b64a63 100644 --- a/components/tidb_query_codegen/src/rpn_function.rs +++ b/components/tidb_query_codegen/src/rpn_function.rs @@ -497,7 +497,7 @@ impl RpnFnRefEvaluableType { match self { RpnFnRefEvaluableType::Ref(x) => quote! { &#lifetime #x }, RpnFnRefEvaluableType::Type(x) => { - if is_json(x) || is_bytes(x) || is_enum(x) || is_set(x) { + if is_json(x) || is_bytes(x) || is_enum(x) || is_set(x) || is_vector_float32(x) { quote! { #x <#lifetime> } @@ -846,6 +846,14 @@ fn is_json(ty: &TypePath) -> bool { } } +/// Checks if parameter type is VectorFloat32 +fn is_vector_float32(ty: &TypePath) -> bool { + match ty.path.get_ident() { + Some(x) => *x == "VectorFloat32Ref" || *x == "VectorFloat32", + None => false, + } +} + /// Checks if parameter type is Bytes fn is_bytes(ty: &TypePath) -> bool { match ty.path.get_ident() { @@ -880,6 +888,8 @@ fn get_vargs_buf(ty: &TypePath) -> TokenStream { quote! { VARG_PARAM_BUF_JSON_REF } } else if *x == "BytesRef" { quote! { VARG_PARAM_BUF_BYTES_REF } + } else if *x == "VectorFloat32Ref" { + quote! { VARG_PARAM_BUF_VECTOR_FLOAT32_REF } } else { quote! { VARG_PARAM_BUF } } @@ -896,6 +906,8 @@ fn get_vectoried_type(ty: &TypePath) -> TokenStream { Some(x) => { if *x == "JsonRef" { quote! { JsonRef } + } else if *x == "VectorFloat32Ref" { + quote! { VectorFloat32Ref } } else if *x == "BytesRef" { quote! { BytesRef } } else if *x == "EnumRef" { @@ -1048,6 +1060,10 @@ impl VargsRpnFn { quote! { let arg: Option = unsafe { std::mem::transmute::, Option>>(arg) }; } + } else if is_vector_float32(arg_type) { + quote! { + let arg: Option = unsafe { std::mem::transmute::, Option>>(arg) }; + } } else if is_bytes(arg_type) { quote! { let arg: Option = unsafe { std::mem::transmute::, Option>>(arg) }; diff --git a/components/tidb_query_datatype/Cargo.toml b/components/tidb_query_datatype/Cargo.toml index e789e8c856d..ccfb82750c0 100644 --- a/components/tidb_query_datatype/Cargo.toml +++ b/components/tidb_query_datatype/Cargo.toml @@ -13,6 +13,7 @@ bitfield = "0.13.2" bitflags = "1.0.1" boolinator = "2.4.0" bstr = "0.2.8" +bytemuck = "1.14.3" chrono = { workspace = true } chrono-tz = "0.5.1" codec = { workspace = true } @@ -42,3 +43,11 @@ tidb_query_common = { workspace = true } tikv_alloc = { workspace = true } tikv_util = { workspace = true } tipb = { workspace = true } + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "bench_vector_distance" +path = "benches/bench_vector_distance.rs" +harness = false diff --git a/components/tidb_query_datatype/benches/bench_vector_distance.rs b/components/tidb_query_datatype/benches/bench_vector_distance.rs new file mode 100644 index 00000000000..62cf2b2ad98 --- /dev/null +++ b/components/tidb_query_datatype/benches/bench_vector_distance.rs @@ -0,0 +1,191 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use tidb_query_datatype::codec::mysql::VectorFloat32Ref; + +fn bench_l1_distance_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + let vb: Vec = vec![1.1, 2.2, 3.3]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l1_distance_3d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l1_distance(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_l1_distance_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + let vb: Vec = vec![1.0; 784]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l1_distance_784d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l1_distance(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_l2_squared_distance_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + let vb: Vec = vec![1.1, 2.2, 3.3]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l2_squared_distance_3d", |b| { + b.iter(|| { + black_box( + black_box(vec_va) + .l2_squared_distance(black_box(vec_vb)) + .unwrap(), + ); + }); + }); +} + +fn bench_l2_squared_distance_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + let vb: Vec = vec![1.0; 784]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l2_squared_distance_784d", |b| { + b.iter(|| { + black_box( + black_box(vec_va) + .l2_squared_distance(black_box(vec_vb)) + .unwrap(), + ); + }); + }); +} + +fn bench_l2_distance_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + let vb: Vec = vec![1.1, 2.2, 3.3]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l2_distance_3d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l2_distance(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_l2_distance_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + let vb: Vec = vec![1.0; 784]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("l2_distance_784d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l2_distance(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_inner_product_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + let vb: Vec = vec![1.1, 2.2, 3.3]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("inner_product_3d", |b| { + b.iter(|| { + black_box(black_box(vec_va).inner_product(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_inner_product_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + let vb: Vec = vec![1.0; 784]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("inner_product_784d", |b| { + b.iter(|| { + black_box(black_box(vec_va).inner_product(black_box(vec_vb)).unwrap()); + }); + }); +} + +fn bench_cosine_distance_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + let vb: Vec = vec![1.1, 2.2, 3.3]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("cosine_distance_3d", |b| { + b.iter(|| { + black_box( + black_box(vec_va) + .cosine_distance(black_box(vec_vb)) + .unwrap(), + ); + }); + }); +} + +fn bench_cosine_distance_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + let vb: Vec = vec![1.0; 784]; + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + let vec_vb = VectorFloat32Ref::from_f32(vb.as_slice()).unwrap(); + + c.bench_function("cosine_distance_784d", |b| { + b.iter(|| { + black_box( + black_box(vec_va) + .cosine_distance(black_box(vec_vb)) + .unwrap(), + ); + }); + }); +} + +fn bench_l2_norm_3d(c: &mut Criterion) { + let va: Vec = vec![1.1, 2.2, 3.3]; + + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + + c.bench_function("l2_norm_3d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l2_norm()); + }); + }); +} + +fn bench_l2_norm_784d(c: &mut Criterion) { + let va: Vec = vec![1.0; 784]; + + let vec_va = VectorFloat32Ref::from_f32(va.as_slice()).unwrap(); + + c.bench_function("l2_norm_784d", |b| { + b.iter(|| { + black_box(black_box(vec_va).l2_norm()); + }); + }); +} + +criterion_group!( + benches, + bench_l1_distance_3d, + bench_l1_distance_784d, + bench_l2_squared_distance_3d, + bench_l2_squared_distance_784d, + bench_l2_distance_3d, + bench_l2_distance_784d, + bench_inner_product_3d, + bench_inner_product_784d, + bench_cosine_distance_3d, + bench_cosine_distance_784d, + bench_l2_norm_3d, + bench_l2_norm_784d, +); +criterion_main!(benches); diff --git a/components/tidb_query_datatype/src/codec/chunk/column.rs b/components/tidb_query_datatype/src/codec/chunk/column.rs index d308248e4eb..1068f0d7ba5 100644 --- a/components/tidb_query_datatype/src/codec/chunk/column.rs +++ b/components/tidb_query_datatype/src/codec/chunk/column.rs @@ -10,7 +10,7 @@ use tipb::FieldType; use super::{Error, Result}; use crate::{ codec::{ - data_type::{ChunkRef, VectorValue}, + data_type::{ChunkRef, VectorFloat32Ref, VectorValue}, datum, datum_codec::DatumPayloadDecoder, mysql::{ @@ -24,6 +24,10 @@ use crate::{ enums::{Enum, EnumDatumPayloadChunkEncoder, EnumDecoder, EnumEncoder, EnumRef}, json::{Json, JsonDatumPayloadChunkEncoder, JsonDecoder, JsonEncoder, JsonRef}, time::{Time, TimeDatumPayloadChunkEncoder, TimeDecoder, TimeEncoder}, + vector::{ + VectorFloat32, VectorFloat32DatumPayloadChunkEncoder, VectorFloat32Decoder, + VectorFloat32Encoder, + }, }, Datum, }, @@ -130,6 +134,11 @@ impl Column { col.append_json_datum(&raw_datums[row_index])? } } + EvalType::VectorFloat32 => { + for &row_index in logical_rows { + col.append_vector_float32_datum(&raw_datums[row_index])? + } + } EvalType::Enum => { for &row_index in logical_rows { col.append_enum_datum(&raw_datums[row_index], field_type)? @@ -274,6 +283,16 @@ impl Column { } } } + VectorValue::VectorFloat32(vec) => { + for &row_index in logical_rows { + match vec.get_option_ref(row_index) { + None => { + col.append_null(); + } + Some(val) => col.append_vector_float32(val)?, + } + } + } VectorValue::Enum(vec) => { for &row_index in logical_rows { match vec.get_option_ref(row_index) { @@ -315,6 +334,7 @@ impl Column { FieldTypeTp::Duration => Datum::Dur(self.get_duration(idx, field_type.decimal())?), FieldTypeTp::NewDecimal => Datum::Dec(self.get_decimal(idx)?), FieldTypeTp::Json => Datum::Json(self.get_json(idx)?), + FieldTypeTp::TiDbVectorFloat32 => Datum::VectorFloat32(self.get_vector_float32(idx)?), FieldTypeTp::Enum => Datum::Enum(self.get_enum(idx)?), FieldTypeTp::Bit => Datum::Bytes(self.get_bytes(idx).to_vec()), FieldTypeTp::Set => { @@ -901,6 +921,39 @@ impl Column { data.read_json() } + pub fn append_vector_float32(&mut self, v: VectorFloat32Ref<'_>) -> Result<()> { + self.data.write_vector_float32(v)?; + self.finished_append_var(); + Ok(()) + } + + pub fn append_vector_float32_datum(&mut self, src_datum: &[u8]) -> Result<()> { + let raw_datum = &src_datum[1..]; + let flag = src_datum[0]; + match flag { + datum::NIL_FLAG => self.append_null(), + datum::VECTOR_FLOAT32_FLAG => { + self.data + .write_vector_float32_to_chunk_by_datum_payload(raw_datum)?; + self.finished_append_var(); + } + _ => { + return Err(Error::InvalidDataType(format!( + "Unsupported datum flag {} for VectorFloat32 vector", + flag + ))); + } + } + Ok(()) + } + + pub fn get_vector_float32(&self, idx: usize) -> Result { + let start = self.var_offsets[idx]; + let end = self.var_offsets[idx + 1]; + let mut data = &self.data[start..end]; + data.read_vector_float32() + } + // Append an Enum datum to the column #[inline] pub fn append_enum(&mut self, e: EnumRef<'_>) -> Result<()> { diff --git a/components/tidb_query_datatype/src/codec/data_type/chunked_vec_vector_float32.rs b/components/tidb_query_datatype/src/codec/data_type/chunked_vec_vector_float32.rs new file mode 100644 index 00000000000..d065a8ec0ff --- /dev/null +++ b/components/tidb_query_datatype/src/codec/data_type/chunked_vec_vector_float32.rs @@ -0,0 +1,135 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use super::{ + bit_vec::BitVec, ChunkRef, ChunkedVec, UnsafeRefInto, VectorFloat32, VectorFloat32Ref, +}; +use crate::{ + codec::mysql::{VectorFloat32Decoder, VectorFloat32Encoder}, + impl_chunked_vec_common, +}; + +/// A vector storing `Option` with a compact layout. +/// +/// Inside `ChunkedVecVectorFloat32`, `bitmap` indicates if an element at given +/// index is null, and `data` stores actual data. VectorFloat32 data are stored +/// adjacent to each other in `data`. If element at a given index is null, then +/// it takes no space in `data`. Otherwise, a variable size VectorFloat32 data +/// is stored in `data`, and `var_offset` indicates the starting position of +/// each element. +#[derive(Debug, PartialEq, Clone)] +pub struct ChunkedVecVectorFloat32 { + data: Vec, + bitmap: BitVec, + length: usize, + var_offset: Vec, +} + +impl ChunkedVecVectorFloat32 { + #[inline] + pub fn get(&self, idx: usize) -> Option> { + assert!(idx < self.len()); + if self.bitmap.get(idx) { + let mut sliced_data = &self.data[self.var_offset[idx]..self.var_offset[idx + 1]]; + let v: VectorFloat32Ref<'_> = sliced_data.read_vector_float32_ref().unwrap(); + unsafe { + let v_with_static_lifetime = v.unsafe_into(); + Some(v_with_static_lifetime) + } + } else { + None + } + } +} + +impl ChunkedVec for ChunkedVecVectorFloat32 { + impl_chunked_vec_common! { VectorFloat32 } + + fn with_capacity(capacity: usize) -> Self { + Self { + data: Vec::with_capacity(capacity), + bitmap: BitVec::with_capacity(capacity), + var_offset: vec![0], + length: 0, + } + } + + #[inline] + fn push_data(&mut self, value: VectorFloat32) { + self.bitmap.push(true); + self.data.write_vector_float32(value.as_ref()).unwrap(); + self.var_offset.push(self.data.len()); + self.length += 1; + } + + #[inline] + fn push_null(&mut self) { + self.bitmap.push(false); + self.var_offset.push(self.data.len()); + self.length += 1; + } + + fn len(&self) -> usize { + self.length + } + + fn truncate(&mut self, len: usize) { + if len < self.len() { + self.data.truncate(self.var_offset[len]); + self.bitmap.truncate(len); + self.var_offset.truncate(len + 1); + self.length = len; + } + } + + fn capacity(&self) -> usize { + self.data.capacity().max(self.length) + } + + fn append(&mut self, other: &mut Self) { + self.data.append(&mut other.data); + self.bitmap.append(&mut other.bitmap); + let var_offset_last = *self.var_offset.last().unwrap(); + for i in 1..other.var_offset.len() { + self.var_offset.push(other.var_offset[i] + var_offset_last); + } + self.length += other.length; + other.var_offset = vec![0]; + other.length = 0; + } + + fn to_vec(&self) -> Vec> { + let mut x = Vec::with_capacity(self.len()); + for i in 0..self.len() { + x.push(self.get(i).map(|x| x.to_owned())); + } + x + } +} + +impl<'a> ChunkRef<'a, VectorFloat32Ref<'a>> for &'a ChunkedVecVectorFloat32 { + #[inline] + fn get_option_ref(self, idx: usize) -> Option> { + self.get(idx) + } + + fn get_bit_vec(self) -> &'a BitVec { + &self.bitmap + } + + #[inline] + fn phantom_data(self) -> Option> { + None + } +} + +impl From>> for ChunkedVecVectorFloat32 { + fn from(v: Vec>) -> ChunkedVecVectorFloat32 { + ChunkedVecVectorFloat32::from_vec(v) + } +} + +impl<'a> UnsafeRefInto<&'static ChunkedVecVectorFloat32> for &'a ChunkedVecVectorFloat32 { + unsafe fn unsafe_into(self) -> &'static ChunkedVecVectorFloat32 { + std::mem::transmute(self) + } +} diff --git a/components/tidb_query_datatype/src/codec/data_type/mod.rs b/components/tidb_query_datatype/src/codec/data_type/mod.rs index b464b1119c8..5a11a5f295e 100644 --- a/components/tidb_query_datatype/src/codec/data_type/mod.rs +++ b/components/tidb_query_datatype/src/codec/data_type/mod.rs @@ -7,6 +7,7 @@ mod chunked_vec_enum; mod chunked_vec_json; mod chunked_vec_set; mod chunked_vec_sized; +mod chunked_vec_vector_float32; mod logical_rows; mod scalar; mod vector; @@ -17,10 +18,10 @@ pub use logical_rows::{LogicalRows, BATCH_MAX_SIZE, IDENTICAL_LOGICAL_ROWS}; macro_rules! match_template_evaltype { ($t:tt, $($tail:tt)*) => {{ #[allow(unused_imports)] - use $crate::codec::data_type::{Int, Real, Decimal, Bytes, DateTime, Duration, Json, Set, Enum}; + use $crate::codec::data_type::{Int, Real, Decimal, Bytes, DateTime, Duration, Json, Set, Enum, VectorFloat32}; match_template::match_template! { - $t = [Int, Real, Decimal, Bytes, DateTime, Duration, Json, Set, Enum], + $t = [Int, Real, Decimal, Bytes, DateTime, Duration, Json, Set, Enum, VectorFloat32], $($tail)* }} } @@ -38,6 +39,7 @@ pub use chunked_vec_enum::ChunkedVecEnum; pub use chunked_vec_json::ChunkedVecJson; pub use chunked_vec_set::ChunkedVecSet; pub use chunked_vec_sized::ChunkedVecSized; +pub use chunked_vec_vector_float32::ChunkedVecVectorFloat32; // Dynamic eval types. pub use self::{ @@ -47,6 +49,7 @@ pub use self::{ use super::Result; pub use crate::codec::mysql::{ json::JsonRef, Decimal, Duration, Enum, EnumRef, Json, JsonType, Set, SetRef, Time as DateTime, + VectorFloat32, VectorFloat32Ref, }; use crate::{codec::convert::ConvertTo, expr::EvalContext, EvalType}; @@ -104,12 +107,24 @@ where } } +impl AsMySqlBool for VectorFloat32 { + fn as_mysql_bool(&self, _context: &mut EvalContext) -> Result { + Ok(!self.as_ref().is_empty()) + } +} + impl<'a> AsMySqlBool for JsonRef<'a> { fn as_mysql_bool(&self, _context: &mut EvalContext) -> Result { Ok(!self.is_zero()) } } +impl<'a> AsMySqlBool for VectorFloat32Ref<'a> { + fn as_mysql_bool(&self, _context: &mut EvalContext) -> Result { + Ok(!self.is_empty()) + } +} + impl<'a> AsMySqlBool for EnumRef<'a> { fn as_mysql_bool(&self, _context: &mut EvalContext) -> Result { Ok(!self.is_empty()) @@ -140,6 +155,15 @@ impl<'a> AsMySqlBool for Option> { } } +impl<'a> AsMySqlBool for Option> { + fn as_mysql_bool(&self, context: &mut EvalContext) -> Result { + match self { + None => Ok(false), + Some(ref v) => v.as_mysql_bool(context), + } + } +} + impl<'a> AsMySqlBool for Option> { fn as_mysql_bool(&self, context: &mut EvalContext) -> Result { match self { @@ -355,6 +379,7 @@ impl_evaluable_ret! { Duration, ChunkedVecSized } impl_evaluable_ret! { Json, ChunkedVecJson } impl_evaluable_ret! { Enum, ChunkedVecEnum } impl_evaluable_ret! { Set, ChunkedVecSet } +impl_evaluable_ret! { VectorFloat32, ChunkedVecVectorFloat32 } pub trait EvaluableRef<'a>: Clone + std::fmt::Debug + Send + Sync { const EVAL_TYPE: EvalType; @@ -501,6 +526,12 @@ impl<'a> UnsafeRefInto> for SetRef<'a> { } } +impl<'a> UnsafeRefInto> for VectorFloat32Ref<'a> { + unsafe fn unsafe_into(self) -> VectorFloat32Ref<'static> { + std::mem::transmute(self) + } +} + impl<'a> EvaluableRef<'a> for JsonRef<'a> { const EVAL_TYPE: EvalType = EvalType::Json; type EvaluableType = Json; @@ -553,6 +584,58 @@ impl<'a> EvaluableRef<'a> for JsonRef<'a> { } } +impl<'a> EvaluableRef<'a> for VectorFloat32Ref<'a> { + const EVAL_TYPE: EvalType = EvalType::VectorFloat32; + type EvaluableType = VectorFloat32; + type ChunkedType = &'a ChunkedVecVectorFloat32; + + #[inline] + fn borrow_scalar_value(v: &'a ScalarValue) -> Option { + match v { + ScalarValue::VectorFloat32(x) => x.as_ref().map(|x| x.as_ref()), + other => panic!( + "Cannot cast {} scalar value into {}", + other.eval_type(), + stringify!(VectorFloat32), + ), + } + } + + #[inline] + fn borrow_scalar_value_ref(v: ScalarValueRef<'a>) -> Option { + match v { + ScalarValueRef::VectorFloat32(x) => x, + other => panic!( + "Cannot cast {} scalar value into {}", + other.eval_type(), + stringify!(VectorFloat32), + ), + } + } + + #[inline] + fn borrow_vector_value(v: &VectorValue) -> &ChunkedVecVectorFloat32 { + match v { + VectorValue::VectorFloat32(x) => x, + other => panic!( + "Cannot cast {} scalar value into {}", + other.eval_type(), + stringify!(VectorFloat32), + ), + } + } + + #[inline] + fn into_owned_value(self) -> Self::EvaluableType { + self.to_owned() + } + + #[inline] + fn from_owned_value(value: &'a VectorFloat32) -> Self { + value.as_ref() + } +} + impl<'a> EvaluableRef<'a> for EnumRef<'a> { const EVAL_TYPE: EvalType = EvalType::Enum; type EvaluableType = Enum; diff --git a/components/tidb_query_datatype/src/codec/data_type/scalar.rs b/components/tidb_query_datatype/src/codec/data_type/scalar.rs index c74423107e4..85197547964 100644 --- a/components/tidb_query_datatype/src/codec/data_type/scalar.rs +++ b/components/tidb_query_datatype/src/codec/data_type/scalar.rs @@ -37,6 +37,7 @@ pub enum ScalarValue { Json(Option), Enum(Option), Set(Option), + VectorFloat32(Option), } impl ScalarValue { @@ -61,6 +62,9 @@ impl ScalarValue { ScalarValue::Json(x) => ScalarValueRef::Json(x.as_ref().map(|x| x.as_ref())), ScalarValue::Enum(x) => ScalarValueRef::Enum(x.as_ref().map(|x| x.as_ref())), ScalarValue::Set(x) => ScalarValueRef::Set(x.as_ref().map(|x| x.as_ref())), + ScalarValue::VectorFloat32(x) => { + ScalarValueRef::VectorFloat32(x.as_ref().map(|x| x.as_ref())) + } } } @@ -133,6 +137,7 @@ impl_from! { Bytes } impl_from! { DateTime } impl_from! { Duration } impl_from! { Json } +impl_from! { VectorFloat32 } impl From> for ScalarValue { #[inline] @@ -155,6 +160,13 @@ impl<'a> From>> for ScalarValue { } } +impl<'a> From>> for ScalarValue { + #[inline] + fn from(s: Option>) -> ScalarValue { + ScalarValue::VectorFloat32(s.map(|x| x.to_owned())) + } +} + impl From for ScalarValue { #[inline] fn from(s: f64) -> ScalarValue { @@ -193,6 +205,7 @@ pub enum ScalarValueRef<'a> { Json(Option>), Enum(Option>), Set(Option>), + VectorFloat32(Option>), } impl<'a> ScalarValueRef<'a> { @@ -209,6 +222,7 @@ impl<'a> ScalarValueRef<'a> { ScalarValueRef::Json(x) => ScalarValue::Json(x.map(|x| x.to_owned())), ScalarValueRef::Enum(x) => ScalarValue::Enum(x.map(|x| x.to_owned())), ScalarValueRef::Set(x) => ScalarValue::Set(x.map(|x| x.to_owned())), + ScalarValueRef::VectorFloat32(x) => ScalarValue::VectorFloat32(x.map(|x| x.to_owned())), } } @@ -310,6 +324,17 @@ impl<'a> ScalarValueRef<'a> { } Ok(()) } + ScalarValueRef::VectorFloat32(val) => { + match val { + None => { + output.write_evaluable_datum_null()?; + } + Some(val) => { + output.write_evaluable_datum_vector_float32(*val)?; + } + } + Ok(()) + } // TODO: we should implement enum/set encode ScalarValueRef::Enum(_) => unimplemented!(), ScalarValueRef::Set(_) => unimplemented!(), @@ -352,7 +377,7 @@ impl<'a> ScalarValueRef<'a> { field_type: &FieldType, ) -> crate::codec::Result { Ok(match_template! { - TT = [Real, Decimal, DateTime, Duration, Json, Enum], + TT = [Real, Decimal, DateTime, Duration, Json, Enum, VectorFloat32], match (self, other) { (ScalarValueRef::TT(v1), ScalarValueRef::TT(v2)) => v1.cmp(v2), (ScalarValueRef::Int(v1), ScalarValueRef::Int(v2)) => compare_int(&v1.cloned(), &v2.cloned(), field_type), @@ -442,6 +467,11 @@ impl ScalarValue { pub fn as_json(&self) -> Option> { EvaluableRef::borrow_scalar_value(self) } + + #[inline] + pub fn as_vector_float32(&self) -> Option> { + EvaluableRef::borrow_scalar_value(self) + } } impl<'a> ScalarValueRef<'a> { @@ -449,6 +479,11 @@ impl<'a> ScalarValueRef<'a> { pub fn as_json(&'a self) -> Option> { EvaluableRef::borrow_scalar_value_ref(*self) } + + #[inline] + pub fn as_vector_float32(&'a self) -> Option> { + EvaluableRef::borrow_scalar_value_ref(*self) + } } impl ScalarValue { diff --git a/components/tidb_query_datatype/src/codec/data_type/vector.rs b/components/tidb_query_datatype/src/codec/data_type/vector.rs index 49a4e3a1cff..9086ac3f7b9 100644 --- a/components/tidb_query_datatype/src/codec/data_type/vector.rs +++ b/components/tidb_query_datatype/src/codec/data_type/vector.rs @@ -15,13 +15,13 @@ pub enum VectorValue { Int(ChunkedVecSized), Real(ChunkedVecSized), Decimal(ChunkedVecSized), - // TODO: We need to improve its performance, i.e. store strings in adjacent memory places Bytes(ChunkedVecBytes), DateTime(ChunkedVecSized), Duration(ChunkedVecSized), Json(ChunkedVecJson), Enum(ChunkedVecEnum), Set(ChunkedVecSet), + VectorFloat32(ChunkedVecVectorFloat32), } impl VectorValue { @@ -63,6 +63,7 @@ impl VectorValue { } } } + expand_convertion!( scalar, Int: ChunkedVecSized, @@ -72,6 +73,7 @@ impl VectorValue { Duration: ChunkedVecSized, Set: ChunkedVecSet, Json: ChunkedVecJson, + VectorFloat32: ChunkedVecVectorFloat32, Enum: ChunkedVecEnum, Bytes: ChunkedVecBytes ) @@ -261,6 +263,21 @@ impl VectorValue { } size } + VectorValue::VectorFloat32(vec) => { + let mut size = 0; + for idx in logical_rows { + let el = vec.get_option_ref(*idx); + match el { + Some(v) => { + size += 1 /* FLAG */ + v.encoded_len(); + } + None => { + size += 1; + } + } + } + size + } VectorValue::Enum(_) => logical_rows.len() * 9, // TODO: implement here after we implement set encoding VectorValue::Set(_) => unimplemented!(), @@ -305,6 +322,21 @@ impl VectorValue { } size } + VectorValue::VectorFloat32(vec) => { + let mut size = logical_rows.len() + 10; + for idx in logical_rows { + let el = vec.get_option_ref(*idx); + match el { + Some(v) => { + size += 8 /* Offset */ + v.encoded_len(); + } + None => { + size += 8 /* Offset */; + } + } + } + size + } VectorValue::Enum(vec) => { let mut size = logical_rows.len() * 9 + 10; for idx in logical_rows { @@ -415,6 +447,17 @@ impl VectorValue { } Ok(()) } + VectorValue::VectorFloat32(ref vec) => { + match &vec.get_option_ref(row_index) { + None => { + output.write_evaluable_datum_null()?; + } + Some(ref val) => { + output.write_evaluable_datum_vector_float32(*val)?; + } + } + Ok(()) + } VectorValue::Enum(ref vec) => { match &vec.get_option_ref(row_index) { None => { @@ -496,6 +539,7 @@ impl_as_slice! { Bytes, to_bytes_vec } impl_as_slice! { DateTime, to_date_time_vec } impl_as_slice! { Duration, to_duration_vec } impl_as_slice! { Json, to_json_vec } +impl_as_slice! { VectorFloat32, to_vector_float32_vec } impl_as_slice! { Enum, to_enum_vec } impl_as_slice! { Set, to_set_vec } @@ -548,6 +592,7 @@ impl_ext! { Bytes, push_bytes } impl_ext! { DateTime, push_date_time } impl_ext! { Duration, push_duration } impl_ext! { Json, push_json } +impl_ext! { VectorFloat32, push_vector_float32 } impl_ext! { Enum, push_enum } impl_ext! { Set, push_set } @@ -569,6 +614,7 @@ impl_from! { Bytes, ChunkedVecBytes } impl_from! { DateTime, ChunkedVecSized } impl_from! { Duration, ChunkedVecSized } impl_from! { Json, ChunkedVecJson } +impl_from! { VectorFloat32, ChunkedVecVectorFloat32 } impl_from! { Enum, ChunkedVecEnum } impl_from! { Set, ChunkedVecSet } diff --git a/components/tidb_query_datatype/src/codec/datum.rs b/components/tidb_query_datatype/src/codec/datum.rs index f91d204b3b0..9da537a2c09 100644 --- a/components/tidb_query_datatype/src/codec/datum.rs +++ b/components/tidb_query_datatype/src/codec/datum.rs @@ -12,12 +12,14 @@ use codec::{ number::{self, NumberCodec}, prelude::*, }; +use mysql::VectorFloat32; use tikv_util::{codec::BytesSlice, escape}; use super::{ mysql::{ self, parse_json_path_expr, Decimal, DecimalDecoder, DecimalEncoder, Duration, Enum, Json, - JsonDecoder, JsonEncoder, PathExpression, Set, Time, DEFAULT_FSP, MAX_FSP, + JsonDecoder, JsonEncoder, PathExpression, Set, Time, VectorFloat32Decoder, + VectorFloat32Encoder, DEFAULT_FSP, MAX_FSP, }, Result, }; @@ -41,6 +43,7 @@ pub const DURATION_FLAG: u8 = 7; pub const VAR_INT_FLAG: u8 = 8; pub const VAR_UINT_FLAG: u8 = 9; pub const JSON_FLAG: u8 = 10; +pub const VECTOR_FLOAT32_FLAG: u8 = 20; pub const MAX_FLAG: u8 = 250; pub const DATUM_DATA_NULL: &[u8; 1] = &[NIL_FLAG]; @@ -57,6 +60,7 @@ pub enum Datum { Dec(Decimal), Time(Time), Json(Json), + VectorFloat32(VectorFloat32), Enum(Enum), Set(Set), Min, @@ -141,6 +145,7 @@ impl Display for Datum { Datum::Dec(ref d) => write!(f, "Dec({})", d), Datum::Time(t) => write!(f, "Time({})", t), Datum::Json(ref j) => write!(f, "Json({})", j), + Datum::VectorFloat32(ref v) => write!(f, "VectorFloat32({})", v), Datum::Enum(ref e) => write!(f, "Enum({})", e), Datum::Set(ref s) => write!(f, "Set({})", s), Datum::Min => write!(f, "MIN"), @@ -207,6 +212,7 @@ impl Datum { Datum::Dec(ref d) => self.cmp_dec(ctx, d), Datum::Time(t) => self.cmp_time(ctx, t), Datum::Json(ref j) => self.cmp_json(ctx, j), + Datum::VectorFloat32(_) => Err(box_err!("not implemented")), Datum::Enum(ref e) => self.cmp_enum(ctx, e), Datum::Set(ref s) => self.cmp_set(ctx, s), } @@ -252,6 +258,7 @@ impl Datum { Datum::Dur(ref d) => cmp_f64(d.to_secs_f64(), f), Datum::Time(t) => cmp_f64(t.convert(ctx)?, f), Datum::Json(_) => Ok(Ordering::Less), + Datum::VectorFloat32(_) => Err(box_err!("not implemented")), Datum::Enum(_) => Ok(Ordering::Less), Datum::Set(_) => Ok(Ordering::Less), } @@ -475,6 +482,7 @@ impl Datum { | Datum::Bytes(_) | Datum::Dec(_) | Datum::Json(_) + | Datum::VectorFloat32(_) | Datum::Enum(_) | Datum::Set(_) | Datum::Max @@ -896,7 +904,7 @@ impl From for Datum { /// `DatumDecoder` decodes the datum. pub trait DatumDecoder: - DecimalDecoder + JsonDecoder + CompactByteDecoder + MemComparableByteDecoder + DecimalDecoder + JsonDecoder + VectorFloat32Decoder + CompactByteDecoder + MemComparableByteDecoder { /// `read_datum` decodes on a datum from a byte slice generated by TiDB. fn read_datum(&mut self) -> Result { @@ -919,6 +927,7 @@ pub trait DatumDecoder: VAR_INT_FLAG => self.read_var_i64().map(Datum::I64)?, VAR_UINT_FLAG => self.read_var_u64().map(Datum::U64)?, JSON_FLAG => self.read_json().map(Datum::Json)?, + VECTOR_FLOAT32_FLAG => self.read_vector_float32().map(Datum::VectorFloat32)?, f => return Err(invalid_type!("unsupported data type `{}`", f)), }; Ok(datum) @@ -939,7 +948,7 @@ pub fn decode(data: &mut BytesSlice<'_>) -> Result> { /// `DatumEncoder` encodes the datum. pub trait DatumEncoder: - DecimalEncoder + JsonEncoder + CompactByteEncoder + MemComparableByteEncoder + DecimalEncoder + JsonEncoder + VectorFloat32Encoder + CompactByteEncoder + MemComparableByteEncoder { /// Encode values to buf slice. fn write_datum( @@ -1011,6 +1020,10 @@ pub trait DatumEncoder: self.write_u8(JSON_FLAG)?; self.write_json(j.as_ref())?; } + Datum::VectorFloat32(ref v) => { + self.write_u8(VECTOR_FLOAT32_FLAG)?; + self.write_vector_float32(v.as_ref())?; + } // TODO: implement datum write here. Datum::Enum(_) => unimplemented!(), Datum::Set(_) => unimplemented!(), @@ -1057,6 +1070,7 @@ pub fn approximate_size(values: &[Datum], comparable: bool) -> usize { Datum::Dec(ref d) => d.approximate_encoded_size(), Datum::Json(ref d) => d.as_ref().binary_len(), Datum::Null | Datum::Min | Datum::Max => 0, + Datum::VectorFloat32(ref v) => v.as_ref().encoded_len(), // TODO: implement here after we implement datum write Datum::Enum(_) => unimplemented!(), Datum::Set(_) => unimplemented!(), @@ -1126,6 +1140,12 @@ pub fn split_datum(buf: &[u8], desc: bool) -> Result<(&[u8], &[u8])> { v.read_json()?; l - v.len() } + VECTOR_FLOAT32_FLAG => { + let mut v = &buf[1..]; + let l = v.len(); + v.read_vector_float32_ref()?; + l - v.len() + } f => return Err(invalid_type!("unsupported data type `{}`", f)), }; if buf.len() < pos + 1 { @@ -1246,6 +1266,10 @@ mod tests { .unwrap(), ), ], + vec![ + Datum::VectorFloat32(VectorFloat32::from_f32(vec![1.0, 2.0, 3.0]).unwrap()), + Datum::VectorFloat32(VectorFloat32::from_f32(vec![]).unwrap()), + ], ]; for vs in table { let mut buf = encode_key(&mut ctx, &vs).unwrap(); diff --git a/components/tidb_query_datatype/src/codec/datum_codec.rs b/components/tidb_query_datatype/src/codec/datum_codec.rs index 9d3f5058d0b..930a9986a86 100644 --- a/components/tidb_query_datatype/src/codec/datum_codec.rs +++ b/components/tidb_query_datatype/src/codec/datum_codec.rs @@ -13,7 +13,7 @@ use crate::{ datum, mysql::{ DecimalDecoder, DecimalEncoder, DurationDecoder, EnumDecoder, EnumEncoder, JsonDecoder, - JsonEncoder, TimeDecoder, + JsonEncoder, TimeDecoder, VectorFloat32Decoder, VectorFloat32Encoder, }, Error, Result, }, @@ -33,6 +33,7 @@ pub trait DatumPayloadDecoder: + DecimalDecoder + JsonDecoder + EnumDecoder + + VectorFloat32Decoder { #[inline] fn read_datum_payload_i64(&mut self) -> Result { @@ -130,6 +131,13 @@ pub trait DatumPayloadDecoder: }) } + #[inline] + fn read_datum_payload_vector_float32(&mut self) -> Result { + self.read_vector_float32().map_err(|_| { + Error::InvalidDataType("Failed to decode datum payload as vectorFloat32".to_owned()) + }) + } + #[inline] fn read_datum_payload_enum_compact_bytes(&mut self, field_type: &FieldType) -> Result { self.read_enum_compact_bytes(field_type).map_err(|_| { @@ -158,7 +166,12 @@ impl DatumPayloadDecoder for T {} /// /// The types this encoder accepts are not fully 1:1 mapping to evaluable types. pub trait DatumPayloadEncoder: - NumberEncoder + CompactByteEncoder + JsonEncoder + DecimalEncoder + EnumEncoder + NumberEncoder + + CompactByteEncoder + + JsonEncoder + + DecimalEncoder + + EnumEncoder + + VectorFloat32Encoder { #[inline] fn write_datum_payload_i64(&mut self, v: i64) -> Result<()> { @@ -211,6 +224,13 @@ pub trait DatumPayloadEncoder: }) } + #[inline] + fn write_datum_payload_vector_float32(&mut self, v: VectorFloat32Ref<'_>) -> Result<()> { + self.write_vector_float32(v).map_err(|_| { + Error::InvalidDataType("Failed to encode datum payload from vectorFloat32".to_owned()) + }) + } + #[inline] fn write_datum_payload_enum_uint(&mut self, v: EnumRef<'_>) -> Result<()> { self.write_enum_uint(v).map_err(|_| { @@ -290,6 +310,12 @@ pub trait DatumFlagAndPayloadEncoder: BufferWriter + DatumPayloadEncoder { Ok(()) } + fn write_datum_vector_float32(&mut self, val: VectorFloat32Ref<'_>) -> Result<()> { + self.write_u8(datum::VECTOR_FLOAT32_FLAG)?; + self.write_datum_payload_vector_float32(val)?; + Ok(()) + } + fn write_datum_enum_uint(&mut self, val: EnumRef<'_>) -> Result<()> { self.write_u8(datum::UINT_FLAG)?; self.write_datum_payload_enum_uint(val)?; @@ -348,6 +374,11 @@ pub trait EvaluableDatumEncoder: DatumFlagAndPayloadEncoder { self.write_datum_json(val) } + #[inline] + fn write_evaluable_datum_vector_float32(&mut self, val: VectorFloat32Ref<'_>) -> Result<()> { + self.write_datum_vector_float32(val) + } + #[inline] fn write_evaluable_datum_enum_uint(&mut self, val: EnumRef<'_>) -> Result<()> { self.write_datum_enum_uint(val) @@ -529,6 +560,24 @@ pub fn decode_json_datum(mut raw_datum: &[u8]) -> Result> { } } +pub fn decode_vector_float32_datum(mut raw_datum: &[u8]) -> Result> { + if raw_datum.is_empty() { + return Err(Error::InvalidDataType( + "Failed to decode datum flag".to_owned(), + )); + } + let flag = raw_datum[0]; + raw_datum = &raw_datum[1..]; + match flag { + datum::NIL_FLAG => Ok(None), + datum::VECTOR_FLOAT32_FLAG => Ok(Some(raw_datum.read_datum_payload_vector_float32()?)), + _ => Err(Error::InvalidDataType(format!( + "Unsupported datum flag {} for VectorFloat32 vector", + flag + ))), + } +} + pub fn decode_enum_datum(mut raw_datum: &[u8], field_type: &FieldType) -> Result> { if raw_datum.is_empty() { return Err(Error::InvalidDataType( @@ -599,6 +648,16 @@ impl<'a> RawDatumDecoder for &'a [u8] { } } +impl<'a> RawDatumDecoder for &'a [u8] { + fn decode( + self, + _field_type: &FieldType, + _ctx: &mut EvalContext, + ) -> Result> { + decode_vector_float32_datum(self) + } +} + impl<'a> RawDatumDecoder for &'a [u8] { fn decode(self, field_type: &FieldType, _ctx: &mut EvalContext) -> Result> { decode_enum_datum(self, field_type) diff --git a/components/tidb_query_datatype/src/codec/mysql/mod.rs b/components/tidb_query_datatype/src/codec/mysql/mod.rs index 5f15fd2c107..95523b24297 100644 --- a/components/tidb_query_datatype/src/codec/mysql/mod.rs +++ b/components/tidb_query_datatype/src/codec/mysql/mod.rs @@ -33,6 +33,7 @@ pub mod enums; pub mod json; pub mod set; pub mod time; +pub mod vector; pub use self::{ decimal::{dec_encoded_len, Decimal, DecimalDecoder, DecimalEncoder, Res, RoundMode}, @@ -44,4 +45,5 @@ pub use self::{ }, set::{Set, SetRef}, time::{Time, TimeDecoder, TimeEncoder, TimeType, Tz}, + vector::{VectorFloat32, VectorFloat32Decoder, VectorFloat32Encoder, VectorFloat32Ref}, }; diff --git a/components/tidb_query_datatype/src/codec/mysql/vector.rs b/components/tidb_query_datatype/src/codec/mysql/vector.rs new file mode 100644 index 00000000000..039638be792 --- /dev/null +++ b/components/tidb_query_datatype/src/codec/mysql/vector.rs @@ -0,0 +1,449 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::cmp::Ordering; + +use codec::prelude::*; + +use crate::codec::Result; + +const F32_SIZE: usize = std::mem::size_of::(); + +// TODO: Implement generic version +#[derive(Clone, Eq, Hash, PartialEq)] +pub struct VectorFloat32 { + // Use Vec instead of Vec to avoid reading from unaligned bytes. For example, + // bytes read from protobuf is usually not aligned by f32. + pub value: Vec, +} + +impl Ord for VectorFloat32 { + fn cmp(&self, other: &Self) -> Ordering { + self.as_ref().cmp(&other.as_ref()) + } +} + +impl PartialOrd for VectorFloat32 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl VectorFloat32 { + pub fn new(value: Vec) -> Result { + _ = VectorFloat32Ref::new(&value[..])?; + Ok(VectorFloat32 { value }) + } + + pub fn from_f32(value: Vec) -> Result { + let value_u8: &[u8] = bytemuck::cast_slice(&value); + VectorFloat32::new(value_u8.to_owned()) + } + + pub fn as_ref(&self) -> VectorFloat32Ref<'_> { + VectorFloat32Ref { value: &self.value } + } +} + +impl std::fmt::Display for VectorFloat32 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_ref()) + } +} + +impl std::fmt::Debug for VectorFloat32 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_ref()) + } +} + +pub trait VectorFloat32DatumPayloadChunkEncoder: BufferWriter { + fn write_vector_float32_to_chunk_by_datum_payload(&mut self, src_payload: &[u8]) -> Result<()> { + // VectorFloat32's chunk format is same as binary format. + self.write_bytes(src_payload)?; + Ok(()) + } +} + +impl VectorFloat32DatumPayloadChunkEncoder for T {} + +impl VectorFloat32Encoder for T {} + +pub trait VectorFloat32Decoder: NumberDecoder { + // `read_vector_float32_ref` decodes value encoded by `write_vector_float32` + // before. + fn read_vector_float32_ref(&mut self) -> Result> { + if !cfg!(target_endian = "little") { + return Err(box_err!("VectorFloat32 only support Little Endian")); + } + + if self.bytes().is_empty() { + return VectorFloat32Ref::new(&[]); + } + let n = self.read_u32_le()? as usize; + let data_size = n * F32_SIZE; + let data = self.read_bytes(data_size)?; + VectorFloat32Ref::new(data) + } + + // `read_vector_float32` decodes value encoded by `write_vector_float32` before. + fn read_vector_float32(&mut self) -> Result { + let r = self.read_vector_float32_ref()?; + Ok(r.to_owned()) + } +} + +impl VectorFloat32Decoder for T {} + +/// Represents a reference of VectorFloat32 value aiming to reduce memory copy. +#[derive(Clone, Copy, Eq, PartialEq, Hash)] +pub struct VectorFloat32Ref<'a> { + // Use &[u8] instead of &[u32] to allow reading from unaligned bytes. For example, + // bytes read from protobuf is usually not aligned by f32. + value: &'a [u8], +} + +impl<'a> Ord for VectorFloat32Ref<'a> { + fn cmp(&self, other: &Self) -> Ordering { + let la = self.len(); + let lb = other.len(); + let common_len = std::cmp::min(la, lb); + for i in 0..common_len { + if self.index(i) > other.index(i) { + return Ordering::Greater; + } else if self.index(i) < other.index(i) { + return Ordering::Less; + } + } + la.cmp(&lb) + } +} + +impl<'a> PartialOrd for VectorFloat32Ref<'a> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a> VectorFloat32Ref<'a> { + pub fn new(value: &[u8]) -> Result> { + if value.len() % F32_SIZE != 0 { + return Err(box_err!("Vector length error. Please check the input.")); + } + let check_vec = VectorFloat32Ref { value }; + for i in 0..check_vec.len() { + if check_vec.index(i).is_nan() { + return Err(box_err!("NaN not allowed in vector")); + } + if check_vec.index(i).is_infinite() { + return Err(box_err!("infinite value not allowed in vector")); + } + } + Ok(check_vec) + } + + pub fn from_f32(value: &[f32]) -> Result> { + let vec_u8: &[u8] = bytemuck::cast_slice(value); + VectorFloat32Ref::new(vec_u8) + } + + pub fn encoded_len(&self) -> usize { + self.value.len() + std::mem::size_of::() + } + + pub fn to_owned(&self) -> VectorFloat32 { + VectorFloat32 { + value: self.value.to_owned(), + } + } + + pub fn len(&self) -> usize { + self.value.len() / F32_SIZE + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + fn check_dims(&self, b: VectorFloat32Ref<'a>) -> Result<()> { + if self.len() != b.len() { + return Err(box_err!( + "vectors have different dimensions: {} and {}", + self.len(), + b.len() + )); + } + Ok(()) + } + + fn index(&self, idx: usize) -> f32 { + if idx > self.len() { + panic!( + "Index out of bounds: index = {}, length = {}", + idx, + self.len() + ); + } + let byte_index: usize = idx * F32_SIZE; + unsafe { + let float_ptr = self.value.as_ptr().add(byte_index) as *const f32; + float_ptr.read_unaligned() + } + } + + // An unsafe function to get the 'f32' value without boundary check. + // it will check the bounding in debug model and remove the check in + // release. + unsafe fn index_unchecked(&self, idx: usize) -> f32 { + #[cfg(debug_assertions)] + { + if idx > self.len() { + panic!( + "Index out of bounds: index = {}, length = {}", + idx, + self.len() + ); + } + } + let byte_index: usize = idx * 4; + let float_ptr = self.value.as_ptr().add(byte_index) as *const f32; + float_ptr.read_unaligned() + } + + pub fn l2_squared_distance(&self, b: VectorFloat32Ref<'a>) -> Result { + self.check_dims(b)?; + let mut distance: f32 = 0.0; + + for i in 0..self.len() { + let diff = unsafe { self.index_unchecked(i) - b.index_unchecked(i) }; + distance += diff * diff; + } + + Ok(distance as f64) + } + + pub fn l2_distance(&self, b: VectorFloat32Ref<'a>) -> Result { + Ok(self.l2_squared_distance(b)?.sqrt()) + } + + pub fn inner_product(&self, b: VectorFloat32Ref<'a>) -> Result { + self.check_dims(b)?; + let mut distance: f32 = 0.0; + for i in 0..self.len() { + distance += unsafe { self.index_unchecked(i) * b.index_unchecked(i) }; + } + + Ok(distance as f64) + } + + pub fn cosine_distance(&self, b: VectorFloat32Ref<'a>) -> Result { + self.check_dims(b)?; + let mut distance: f32 = 0.0; + let mut norma: f32 = 0.0; + let mut normb: f32 = 0.0; + for i in 0..self.len() { + unsafe { + distance += self.index_unchecked(i) * b.index_unchecked(i); + norma += self.index_unchecked(i) * self.index_unchecked(i); + normb += b.index_unchecked(i) * b.index_unchecked(i); + } + } + + let similarity = (distance as f64) / ((norma as f64) * (normb as f64)).sqrt(); + if similarity.is_nan() { + // Divide by zero + return Ok(std::f64::NAN); + } + let similarity = similarity.clamp(-1.0, 1.0); + Ok(1.0 - similarity) + } + + pub fn l1_distance(&self, b: VectorFloat32Ref<'a>) -> Result { + self.check_dims(b)?; + let mut distance: f32 = 0.0; + for i in 0..self.len() { + let diff = unsafe { self.index_unchecked(i) - b.index_unchecked(i) }; + distance += diff.abs(); + } + + Ok(distance as f64) + } + + pub fn l2_norm(&self) -> f64 { + // Note: We align the impl with pgvector: Only l2_norm use double + // precision during calculation. + let mut norm: f64 = 0.0; + for i in 0..self.len() { + let v = unsafe { self.index_unchecked(i) as f64 }; + norm += v * v; + } + + norm.sqrt() + } +} + +pub trait VectorFloat32Encoder: NumberEncoder { + fn write_vector_float32(&mut self, data: VectorFloat32Ref<'_>) -> Result<()> { + if !cfg!(target_endian = "little") { + return Err(box_err!("VectorFloat32 only support Little Endian")); + } + + self.write_u32_le(data.len() as u32)?; + self.write_bytes(data.value)?; + + Ok(()) + } +} + +impl std::fmt::Display for VectorFloat32Ref<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[")?; + let mut is_first = true; + for i in 0..self.len() { + if is_first { + write!(f, "{}", self.index(i))?; + is_first = false; + } else { + write!(f, ",{}", self.index(i))?; + } + } + write!(f, "]")?; + Ok(()) + } +} + +impl std::fmt::Debug for VectorFloat32Ref<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } +} + +impl ToString for VectorFloat32Ref<'_> { + fn to_string(&self) -> String { + format!("{}", self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_nan_inf() { + let v = VectorFloat32::from_f32(vec![1.0, std::f32::NAN]); + v.unwrap_err(); + + let v = VectorFloat32::from_f32(vec![1.0, std::f32::INFINITY]); + v.unwrap_err(); + + let v = VectorFloat32::from_f32(vec![1.0, std::f32::NEG_INFINITY]); + v.unwrap_err(); + + let v = VectorFloat32Ref::from_f32(&[1.0, std::f32::NAN]); + v.unwrap_err(); + + let v = VectorFloat32Ref::from_f32(&[1.0, std::f32::INFINITY]); + v.unwrap_err(); + + let v = VectorFloat32Ref::from_f32(&[1.0, std::f32::NEG_INFINITY]); + v.unwrap_err(); + } + + #[test] + fn test_to_string() { + let v = VectorFloat32::from_f32(vec![1.0, 2.0]).unwrap(); + assert_eq!("[1,2]", v.to_string()); + + let v = VectorFloat32::from_f32(vec![1.1, 2.2]).unwrap(); + assert_eq!("[1.1,2.2]", v.to_string()); + + let v = VectorFloat32::from_f32(vec![]).unwrap(); + assert_eq!("[]", v.to_string()); + } + + #[test] + fn test_input_length() { + let buf: Vec = vec![ + 0xcd, 0xcc, 0x8c, 0x3f, // Element 1 = 0x3f8ccccd + 0xcd, 0xcc, 0x0c, 0x40, // Element 2 = 0x400ccccd + 0xcd, 0xcc, 0x0c, + ]; + let v = VectorFloat32Ref::new(&buf[..]); + v.unwrap_err(); + + let buf: Vec = vec![ + 0xcd, 0xcc, 0x8c, 0x3f, // Element 1 = 0x3f8ccccd + 0xcd, 0xcc, 0x0c, 0x40, // Element 2 = 0x400ccccd + 0xcd, 0xcc, 0x0c, 0x40, + ]; + let v = VectorFloat32Ref::new(&buf[..]); + v.unwrap(); + } + + #[test] + fn test_compare() { + let v1 = VectorFloat32::from_f32(vec![1.0, 2.0]).unwrap(); + let v2 = VectorFloat32::from_f32(vec![1.1, 2.2]).unwrap(); + assert!(v1 < v2); + + let v3 = VectorFloat32::from_f32(vec![1.0, 2.0]).unwrap(); + assert!(v1 == v3); + + let v4 = VectorFloat32::from_f32(vec![0.3, 0.4]).unwrap(); + assert!(v1 > v4); + + let v4 = VectorFloat32::from_f32(vec![1.0]).unwrap(); + assert!(v1 > v4); + + let v5 = VectorFloat32::from_f32(vec![1.0, 2.0, 0.5]).unwrap(); + assert!(v1 < v5); + } + + #[test] + fn test_encode() { + let v = VectorFloat32::from_f32(vec![1.1, 2.2]).unwrap(); + let mut encoded = Vec::new(); + + encoded.write_vector_float32(v.as_ref()).unwrap(); + assert_eq!( + encoded, + vec![ + 0x02, 0x00, 0x00, 0x00, // Length = 0x02 + 0xcd, 0xcc, 0x8c, 0x3f, // Element 1 = 0x3f8ccccd + 0xcd, 0xcc, 0x0c, 0x40, // Element 2 = 0x400ccccd + ] + ); + assert_eq!(v.as_ref().encoded_len(), 12); + } + + #[test] + fn test_decode() { + let buf: Vec = vec![ + 0x02, 0x00, 0x00, 0x00, // Length = 0x02 + 0xcd, 0xcc, 0x8c, 0x3f, // Element 1 = 0x3f8ccccd + 0xcd, 0xcc, 0x0c, 0x40, // Element 2 = 0x400ccccd + 0xff, // Remaining dummy data + ]; + + let mut buf_slice = &buf[..]; + + let v = buf_slice.read_vector_float32_ref().unwrap(); + + assert_eq!(v.len(), 2); + assert_eq!(v.to_string(), "[1.1,2.2]"); + + assert_eq!(buf_slice.len(), 1); + assert_eq!(buf_slice, &[0xff]); + + buf_slice.read_vector_float32_ref().unwrap_err(); + assert_eq!(buf_slice.len(), 1); + assert_eq!(buf_slice, &[0xff]); + + buf_slice = &[]; + let v = buf_slice.read_vector_float32_ref().unwrap(); + assert_eq!(v.len(), 0); + assert_eq!(v.to_string(), "[]"); + let mut encode_buf = Vec::new(); + encode_buf.write_vector_float32(v).unwrap(); + assert_eq!(encode_buf, vec![0x00, 0x00, 0x00, 0x00]); + } +} diff --git a/components/tidb_query_datatype/src/codec/row/v2/compat_v1.rs b/components/tidb_query_datatype/src/codec/row/v2/compat_v1.rs index 8d0e34dfdf7..3afc9b2ebbe 100644 --- a/components/tidb_query_datatype/src/codec/row/v2/compat_v1.rs +++ b/components/tidb_query_datatype/src/codec/row/v2/compat_v1.rs @@ -108,6 +108,10 @@ pub trait V1CompatibleEncoder: DatumFlagAndPayloadEncoder { // Copy datum payload as it is self.write_bytes(src)?; } + FieldTypeTp::TiDbVectorFloat32 => { + self.write_u8(datum::VECTOR_FLOAT32_FLAG)?; + self.write_bytes(src)?; + } FieldTypeTp::Null => { self.write_u8(datum::NIL_FLAG)?; } diff --git a/components/tidb_query_datatype/src/codec/table.rs b/components/tidb_query_datatype/src/codec/table.rs index 919cb18594d..5712a50f66f 100644 --- a/components/tidb_query_datatype/src/codec/table.rs +++ b/components/tidb_query_datatype/src/codec/table.rs @@ -291,6 +291,7 @@ fn unflatten( FieldTypeTp::String, FieldTypeTp::NewDecimal, FieldTypeTp::Json, + FieldTypeTp::TiDbVectorFloat32, ] .contains(&t), "unknown type {} {}", diff --git a/components/tidb_query_datatype/src/def/eval_type.rs b/components/tidb_query_datatype/src/def/eval_type.rs index e959ea2feda..ff60755512a 100644 --- a/components/tidb_query_datatype/src/def/eval_type.rs +++ b/components/tidb_query_datatype/src/def/eval_type.rs @@ -18,6 +18,7 @@ pub enum EvalType { Json, Enum, Set, + VectorFloat32, } impl EvalType { @@ -36,6 +37,7 @@ impl EvalType { EvalType::Json => crate::FieldTypeTp::Json, EvalType::Enum => crate::FieldTypeTp::Enum, EvalType::Set => crate::FieldTypeTp::Set, + EvalType::VectorFloat32 => crate::FieldTypeTp::TiDbVectorFloat32, } } } @@ -67,6 +69,7 @@ impl std::convert::TryFrom for EvalType { | crate::FieldTypeTp::DateTime => EvalType::DateTime, crate::FieldTypeTp::Duration => EvalType::Duration, crate::FieldTypeTp::Json => EvalType::Json, + crate::FieldTypeTp::TiDbVectorFloat32 => EvalType::VectorFloat32, crate::FieldTypeTp::VarChar | crate::FieldTypeTp::TinyBlob | crate::FieldTypeTp::MediumBlob diff --git a/components/tidb_query_datatype/src/def/field_type.rs b/components/tidb_query_datatype/src/def/field_type.rs index 8a56ac5ac68..ad76a8e339c 100644 --- a/components/tidb_query_datatype/src/def/field_type.rs +++ b/components/tidb_query_datatype/src/def/field_type.rs @@ -47,12 +47,14 @@ pub enum FieldTypeTp { VarString = 0xfd, String = 0xfe, Geometry = 0xff, + TiDbVectorFloat32 = 0xe1, } impl FieldTypeTp { pub fn from_i32(i: i32) -> Option { if (i >= FieldTypeTp::Unspecified as i32 && i <= FieldTypeTp::Bit as i32) || (i >= FieldTypeTp::Json as i32 && i <= FieldTypeTp::Geometry as i32) + || (i == FieldTypeTp::TiDbVectorFloat32 as i32) { Some(unsafe { ::std::mem::transmute::(i) }) } else { diff --git a/components/tidb_query_executors/src/fast_hash_aggr_executor.rs b/components/tidb_query_executors/src/fast_hash_aggr_executor.rs index a878347fc68..4f5156510a0 100644 --- a/components/tidb_query_executors/src/fast_hash_aggr_executor.rs +++ b/components/tidb_query_executors/src/fast_hash_aggr_executor.rs @@ -27,7 +27,7 @@ use crate::{ macro_rules! match_template_hashable { ($t:tt, $($tail:tt)*) => {{ match_template::match_template! { - $t = [Int, Real, Bytes, Duration, Decimal, DateTime, Enum], + $t = [Int, Real, Bytes, Duration, Decimal, DateTime, Enum, VectorFloat32], $($tail)* } }} @@ -96,7 +96,8 @@ impl BatchFastHashAggregationExecutor>> | EvalType::Bytes | EvalType::Duration | EvalType::Decimal - | EvalType::DateTime => {} + | EvalType::DateTime + | EvalType::VectorFloat32 => {} _ => return Err(other_err!("Eval type {} is not supported", eval_type)), } @@ -209,6 +210,7 @@ enum Groups { Decimal(HashMap, usize>), DateTime(HashMap, usize>), Enum(HashMap, usize>), + VectorFloat32(HashMap, usize>), } impl Groups { @@ -267,7 +269,7 @@ impl AggregationExecutorImpl for FastHashAggregationImp match group_by_result { RpnStackNode::Scalar { value, .. } => { match_template::match_template! { - TT = [Int, Bytes, Real, Duration, Decimal, DateTime, Enum], + TT = [Int, Bytes, Real, Duration, Decimal, DateTime, Enum, VectorFloat32], match value { ScalarValue::TT(v) => { if let Groups::TT(group) = &mut self.groups { @@ -292,7 +294,7 @@ impl AggregationExecutorImpl for FastHashAggregationImp let group_by_logical_rows = value.logical_rows_struct(); match_template::match_template! { - TT = [Int, Real, Duration, Decimal, DateTime, Enum], + TT = [Int, Real, Duration, Decimal, DateTime, Enum, VectorFloat32], match group_by_physical_vec { VectorValue::TT(v) => { if let Groups::TT(group) = &mut self.groups { diff --git a/components/tidb_query_executors/src/util/top_n_heap.rs b/components/tidb_query_executors/src/util/top_n_heap.rs index 57bd4b63017..dd37ab1d92f 100644 --- a/components/tidb_query_executors/src/util/top_n_heap.rs +++ b/components/tidb_query_executors/src/util/top_n_heap.rs @@ -92,6 +92,7 @@ impl TopNHeap { Json => JsonRef, Enum => EnumRef, Set => SetRef, + VectorFloat32 => VectorFloat32Ref, ], match dest_vector_value { VectorValue::TT(dest_column) => { diff --git a/components/tidb_query_expr/src/impl_cast.rs b/components/tidb_query_expr/src/impl_cast.rs index da5da737453..b55f441a2a1 100644 --- a/components/tidb_query_expr/src/impl_cast.rs +++ b/components/tidb_query_expr/src/impl_cast.rs @@ -145,6 +145,7 @@ fn get_cast_fn_rpn_meta( (EvalType::Duration, EvalType::Bytes) => cast_any_as_string_fn_meta::(), (EvalType::Json, EvalType::Bytes) => cast_json_as_bytes_fn_meta(), (EvalType::Enum, EvalType::Bytes) => cast_enum_as_bytes_fn_meta(), + (EvalType::VectorFloat32, EvalType::Bytes) => cast_vector_float32_as_bytes_fn_meta(), // any as decimal (EvalType::Int, EvalType::Decimal) => { @@ -219,6 +220,11 @@ fn get_cast_fn_rpn_meta( (EvalType::Json, EvalType::Json) => cast_json_as_json_fn_meta(), (EvalType::Enum, EvalType::Json) => cast_enum_as_json_fn_meta(), + // any as VectorFloat32 + (EvalType::VectorFloat32, EvalType::VectorFloat32) => { + cast_vector_float32_as_vector_float32_fn_meta() + } + _ => return Err(other_err!("Unsupported cast from {} to {}", from, to)), }; Ok(func_meta) @@ -1421,6 +1427,12 @@ fn cast_json_as_json(val: Option) -> Result> { } } +#[rpn_fn] +#[inline] +fn cast_vector_float32_as_vector_float32(val: VectorFloat32Ref) -> Result> { + Ok(Some(val.to_owned())) +} + #[rpn_fn(nullable, capture = [ctx])] #[inline] fn cast_any_as_any + Evaluable + EvaluableRet, To: Evaluable + EvaluableRet>( @@ -1493,6 +1505,12 @@ fn cast_json_as_bytes(ctx: &mut EvalContext, val: Option) -> Result Result> { + Ok(Some(val.to_string().into_bytes())) +} + #[rpn_fn(nullable, capture = [ctx])] #[inline] fn cast_enum_as_int(ctx: &mut EvalContext, val: Option) -> Result> { diff --git a/components/tidb_query_expr/src/impl_compare.rs b/components/tidb_query_expr/src/impl_compare.rs index e0a6acab2f8..54925ad2072 100644 --- a/components/tidb_query_expr/src/impl_compare.rs +++ b/components/tidb_query_expr/src/impl_compare.rs @@ -31,6 +31,19 @@ pub fn compare_json(lhs: Option, rhs: Option) -> Res }) } +#[rpn_fn(nullable)] +#[inline] +pub fn compare_vector_float32( + lhs: Option, + rhs: Option, +) -> Result> { + Ok(match (lhs, rhs) { + (None, None) => F::compare_null(), + (None, _) | (_, None) => F::compare_partial_null(), + (Some(lhs), Some(rhs)) => Some(F::compare_order(lhs.cmp(&rhs)) as i64), + }) +} + #[rpn_fn(nullable)] #[inline] pub fn compare_bytes( diff --git a/components/tidb_query_expr/src/impl_miscellaneous.rs b/components/tidb_query_expr/src/impl_miscellaneous.rs index 5ab17c1226b..0bac7a12cab 100644 --- a/components/tidb_query_expr/src/impl_miscellaneous.rs +++ b/components/tidb_query_expr/src/impl_miscellaneous.rs @@ -38,6 +38,18 @@ pub fn any_value_json(args: &[Option]) -> Result> { } } +#[rpn_fn(nullable, varg)] +#[inline] +pub fn any_value_vector_float32( + args: &[Option], +) -> Result> { + if let Some(arg) = args.first() { + Ok(arg.map(|x| x.to_owned())) + } else { + Ok(None) + } +} + #[rpn_fn(nullable, varg)] #[inline] pub fn any_value_bytes(args: &[Option]) -> Result> { diff --git a/components/tidb_query_expr/src/impl_op.rs b/components/tidb_query_expr/src/impl_op.rs index 665448279fb..659f6b5efba 100644 --- a/components/tidb_query_expr/src/impl_op.rs +++ b/components/tidb_query_expr/src/impl_op.rs @@ -135,6 +135,12 @@ pub fn is_null_json(arg: Option) -> Result> { is_null_ref(arg) } +#[rpn_fn(nullable)] +#[inline] +pub fn is_null_vector_float32(arg: Option) -> Result> { + is_null_ref(arg) +} + #[rpn_fn(nullable)] #[inline] pub fn bit_and(lhs: Option<&Int>, rhs: Option<&Int>) -> Result> { diff --git a/components/tidb_query_expr/src/impl_vec.rs b/components/tidb_query_expr/src/impl_vec.rs new file mode 100644 index 00000000000..1ebe423e2ae --- /dev/null +++ b/components/tidb_query_expr/src/impl_vec.rs @@ -0,0 +1,226 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use tidb_query_codegen::rpn_fn; +use tidb_query_common::Result; +use tidb_query_datatype::codec::data_type::*; + +#[rpn_fn(writer)] +#[inline] +fn vec_as_text(a: VectorFloat32Ref, writer: BytesWriter) -> Result { + Ok(writer.write(Some(Bytes::from(a.to_string())))) +} + +#[rpn_fn] +#[inline] +fn vec_dims(arg: VectorFloat32Ref) -> Result> { + Ok(Some(arg.len() as Int)) +} + +#[rpn_fn] +#[inline] +fn vec_l1_distance(a: VectorFloat32Ref, b: VectorFloat32Ref) -> Result> { + // TiKV does not support NaN. This turns NaN into null + Ok(Real::new(a.l1_distance(b)?).ok()) +} + +#[rpn_fn] +#[inline] +fn vec_l2_distance(a: VectorFloat32Ref, b: VectorFloat32Ref) -> Result> { + // TiKV does not support NaN. This turns NaN into null + Ok(Real::new(a.l2_distance(b)?).ok()) +} + +#[rpn_fn] +#[inline] +fn vec_negative_inner_product(a: VectorFloat32Ref, b: VectorFloat32Ref) -> Result> { + // TiKV does not support NaN. This turns NaN into null + Ok(Real::new(a.inner_product(b)? * -1.0).ok()) +} + +#[rpn_fn] +#[inline] +fn vec_cosine_distance(a: VectorFloat32Ref, b: VectorFloat32Ref) -> Result> { + // TiKV does not support NaN. This turns NaN into null + Ok(Real::new(a.cosine_distance(b)?).ok()) +} + +#[rpn_fn] +#[inline] +fn vec_l2_norm(a: VectorFloat32Ref) -> Result> { + // TiKV does not support NaN. This turns NaN into null + Ok(Real::new(a.l2_norm()).ok()) +} + +#[cfg(test)] +mod tests { + use tipb::ScalarFuncSig; + + use super::*; + use crate::types::test_util::RpnFnScalarEvaluator; + + // Test cases are ported from pgvector: https://github.com/pgvector/pgvector/blob/master/test/expected/functions.out + // Copyright (c) 1996-2023, PostgreSQL Global Development Group + + #[test] + fn test_dims() { + let cases = vec![ + (vec![], Some(0)), + (vec![1.0, 2.0], Some(2)), + (vec![1.0, 2.0, 3.0], Some(3)), + ]; + for (arg, expected_output) in cases { + let arg = VectorFloat32::from_f32(arg).unwrap(); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg) + .evaluate(ScalarFuncSig::VecDimsSig) + .unwrap(); + assert_eq!(output, expected_output); + } + } + + #[test] + fn test_l2_norm() { + let cases = vec![ + (vec![], Some(0.0)), + (vec![3.0, 4.0], Some(5.0)), + (vec![0.0, 1.0], Some(1.0)), + ]; + + for (arg, expected_output) in cases { + let arg = VectorFloat32::from_f32(arg).unwrap(); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg) + .evaluate(ScalarFuncSig::VecL2NormSig) + .unwrap(); + assert_eq!(output, expected_output.map(|x| Real::new(x).unwrap())); + } + } + + #[test] + fn test_l2_distance() { + let ok_cases = vec![ + (Some(vec![0.0, 0.0]), Some(vec![3.0, 4.0]), Some(5.0)), + (Some(vec![0.0, 0.0]), Some(vec![0.0, 1.0]), Some(1.0)), + (Some(vec![3e38]), Some(vec![-3e38]), Some(f64::INFINITY)), + (Some(vec![1.0, 2.0]), None, None), + ]; + for (arg1, arg2, expected_output) in ok_cases { + let arg1 = arg1.map(|v| VectorFloat32::from_f32(v).unwrap()); + let arg2 = arg2.map(|v| VectorFloat32::from_f32(v).unwrap()); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecL2DistanceSig) + .unwrap(); + assert_eq!(output, expected_output.map(|x| Real::new(x).unwrap())); + } + + let err_cases = vec![(vec![1.0, 2.0], vec![3.0])]; + for (arg1, arg2) in err_cases { + let arg1 = VectorFloat32::from_f32(arg1).unwrap(); + let arg2 = VectorFloat32::from_f32(arg2).unwrap(); + let output: Result> = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecL2DistanceSig); + assert!(output.is_err(), "expected error, got {:?}", output); + } + } + + #[test] + fn test_negative_inner_product() { + let ok_cases = vec![ + (Some(vec![1.0, 2.0]), Some(vec![3.0, 4.0]), Some(-11.0)), + (Some(vec![3e38]), Some(vec![3e38]), Some(f64::NEG_INFINITY)), + (Some(vec![1.0, 2.0]), None, None), + ]; + for (arg1, arg2, expected_output) in ok_cases { + let arg1 = arg1.map(|v| VectorFloat32::from_f32(v).unwrap()); + let arg2 = arg2.map(|v| VectorFloat32::from_f32(v).unwrap()); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecNegativeInnerProductSig) + .unwrap(); + assert_eq!(output, expected_output.map(|x| Real::new(x).unwrap())); + } + + let err_cases = vec![(vec![1.0, 2.0], vec![3.0])]; + for (arg1, arg2) in err_cases { + let arg1 = VectorFloat32::from_f32(arg1).unwrap(); + let arg2 = VectorFloat32::from_f32(arg2).unwrap(); + let output: Result> = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecNegativeInnerProductSig); + assert!(output.is_err(), "expected error, got {:?}", output); + } + } + + #[test] + fn test_cosine_distance() { + let ok_cases = vec![ + (Some(vec![1.0, 2.0]), Some(vec![2.0, 4.0]), Some(0.0)), + (Some(vec![1.0, 2.0]), Some(vec![0.0, 0.0]), None), // NaN turns to NULL + (Some(vec![1.0, 1.0]), Some(vec![1.0, 1.0]), Some(0.0)), + (Some(vec![1.0, 0.0]), Some(vec![0.0, 2.0]), Some(1.0)), + (Some(vec![1.0, 1.0]), Some(vec![-1.0, -1.0]), Some(2.0)), + (Some(vec![1.0, 1.0]), Some(vec![1.1, 1.1]), Some(0.0)), + (Some(vec![1.0, 1.0]), Some(vec![-1.1, -1.1]), Some(2.0)), + (Some(vec![3e38]), Some(vec![3e38]), None), // NaN turns to NULL + (Some(vec![1.0, 2.0]), None, None), + ]; + for (arg1, arg2, expected_output) in ok_cases { + let arg1 = arg1.map(|v| VectorFloat32::from_f32(v).unwrap()); + let arg2 = arg2.map(|v| VectorFloat32::from_f32(v).unwrap()); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecCosineDistanceSig) + .unwrap(); + assert_eq!(output, expected_output.map(|x| Real::new(x).unwrap())); + } + + let err_cases = vec![(vec![1.0, 2.0], vec![3.0])]; + for (arg1, arg2) in err_cases { + let arg1 = VectorFloat32::from_f32(arg1).unwrap(); + let arg2 = VectorFloat32::from_f32(arg2).unwrap(); + let output: Result> = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecCosineDistanceSig); + assert!(output.is_err(), "expected error, got {:?}", output); + } + } + + #[test] + fn test_l1_distance() { + let ok_cases = vec![ + (Some(vec![0.0, 0.0]), Some(vec![3.0, 4.0]), Some(7.0)), + (Some(vec![0.0, 0.0]), Some(vec![0.0, 1.0]), Some(1.0)), + (Some(vec![3e38]), Some(vec![-3e38]), Some(f64::INFINITY)), + (Some(vec![1.0, 2.0]), None, None), + ]; + for (arg1, arg2, expected_output) in ok_cases { + let arg1 = arg1.map(|v| VectorFloat32::from_f32(v).unwrap()); + let arg2 = arg2.map(|v| VectorFloat32::from_f32(v).unwrap()); + let output: Option = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecL1DistanceSig) + .unwrap(); + assert_eq!(output, expected_output.map(|x| Real::new(x).unwrap())); + } + + let err_cases = vec![(vec![1.0, 2.0], vec![3.0])]; + for (arg1, arg2) in err_cases { + let arg1 = VectorFloat32::from_f32(arg1).unwrap(); + let arg2 = VectorFloat32::from_f32(arg2).unwrap(); + let output: Result> = RpnFnScalarEvaluator::new() + .push_param(arg1) + .push_param(arg2) + .evaluate(ScalarFuncSig::VecL1DistanceSig); + assert!(output.is_err(), "expected error, got {:?}", output); + } + } +} diff --git a/components/tidb_query_expr/src/lib.rs b/components/tidb_query_expr/src/lib.rs index b2906276bda..b4dbb0f02ed 100644 --- a/components/tidb_query_expr/src/lib.rs +++ b/components/tidb_query_expr/src/lib.rs @@ -41,6 +41,7 @@ pub mod impl_other; pub mod impl_regexp; pub mod impl_string; pub mod impl_time; +pub mod impl_vec; use tidb_query_common::Result; use tidb_query_datatype::{ @@ -57,7 +58,7 @@ pub use self::types::*; use self::{ impl_arithmetic::*, impl_cast::*, impl_compare::*, impl_compare_in::*, impl_control::*, impl_encryption::*, impl_json::*, impl_like::*, impl_math::*, impl_miscellaneous::*, - impl_op::*, impl_other::*, impl_regexp::*, impl_string::*, impl_time::*, + impl_op::*, impl_other::*, impl_regexp::*, impl_string::*, impl_time::*, impl_vec::*, }; fn map_to_binary_fn_sig(expr: &Expr) -> Result { @@ -436,7 +437,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::ModIntUnsignedSigned => arithmetic_fn_meta::(), ScalarFuncSig::ModIntSignedUnsigned => arithmetic_fn_meta::(), ScalarFuncSig::ModIntSignedSigned => arithmetic_fn_meta::(), - + // impl_cast ScalarFuncSig::CastIntAsInt | ScalarFuncSig::CastIntAsReal | @@ -486,7 +487,9 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::CastJsonAsDecimal | ScalarFuncSig::CastJsonAsTime | ScalarFuncSig::CastJsonAsDuration | - ScalarFuncSig::CastJsonAsJson => map_cast_func(expr)?, + ScalarFuncSig::CastJsonAsJson | + ScalarFuncSig::CastVectorFloat32AsString | + ScalarFuncSig::CastVectorFloat32AsVectorFloat32 => map_cast_func(expr)?, ScalarFuncSig::ToBinary => map_to_binary_fn_sig(expr)?, ScalarFuncSig::FromBinary => map_from_binary_fn_sig(expr)?, @@ -498,6 +501,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::LtTime => compare_fn_meta::>(), ScalarFuncSig::LtDuration => compare_fn_meta::>(), ScalarFuncSig::LtJson => compare_json_fn_meta::(), + ScalarFuncSig::LtVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::LeInt => map_int_sig(value, children, compare_mapper::)?, ScalarFuncSig::LeReal => compare_fn_meta::>(), ScalarFuncSig::LeDecimal => compare_fn_meta::>(), @@ -505,6 +509,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::LeTime => compare_fn_meta::>(), ScalarFuncSig::LeDuration => compare_fn_meta::>(), ScalarFuncSig::LeJson => compare_json_fn_meta::(), + ScalarFuncSig::LeVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::GreatestInt => greatest_int_fn_meta(), ScalarFuncSig::GreatestDecimal => greatest_decimal_fn_meta(), ScalarFuncSig::GreatestString => greatest_string_fn_meta(), @@ -532,6 +537,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::GtTime => compare_fn_meta::>(), ScalarFuncSig::GtDuration => compare_fn_meta::>(), ScalarFuncSig::GtJson => compare_json_fn_meta::(), + ScalarFuncSig::GtVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::GeInt => map_int_sig(value, children, compare_mapper::)?, ScalarFuncSig::GeReal => compare_fn_meta::>(), ScalarFuncSig::GeDecimal => compare_fn_meta::>(), @@ -539,6 +545,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::GeTime => compare_fn_meta::>(), ScalarFuncSig::GeDuration => compare_fn_meta::>(), ScalarFuncSig::GeJson => compare_json_fn_meta::(), + ScalarFuncSig::GeVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::NeInt => map_int_sig(value, children, compare_mapper::)?, ScalarFuncSig::NeReal => compare_fn_meta::>(), ScalarFuncSig::NeDecimal => compare_fn_meta::>(), @@ -546,6 +553,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::NeTime => compare_fn_meta::>(), ScalarFuncSig::NeDuration => compare_fn_meta::>(), ScalarFuncSig::NeJson => compare_json_fn_meta::(), + ScalarFuncSig::NeVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::EqInt => map_int_sig(value, children, compare_mapper::)?, ScalarFuncSig::EqReal => compare_fn_meta::>(), ScalarFuncSig::EqDecimal => compare_fn_meta::>(), @@ -553,6 +561,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::EqTime => compare_fn_meta::>(), ScalarFuncSig::EqDuration => compare_fn_meta::>(), ScalarFuncSig::EqJson => compare_json_fn_meta::(), + ScalarFuncSig::EqVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::NullEqInt => map_int_sig(value, children, compare_mapper::)?, ScalarFuncSig::NullEqReal => compare_fn_meta::>(), ScalarFuncSig::NullEqDecimal => compare_fn_meta::>(), @@ -560,6 +569,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::NullEqTime => compare_fn_meta::>(), ScalarFuncSig::NullEqDuration => compare_fn_meta::>(), ScalarFuncSig::NullEqJson => compare_json_fn_meta::(), + ScalarFuncSig::NullEqVectorFloat32 => compare_vector_float32_fn_meta::(), ScalarFuncSig::CoalesceInt => coalesce_fn_meta::(), ScalarFuncSig::CoalesceReal => coalesce_fn_meta::(), ScalarFuncSig::CoalesceString => coalesce_bytes_fn_meta(), @@ -629,6 +639,14 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::JsonMemberOfSig => member_of_fn_meta(), ScalarFuncSig::JsonArrayAppendSig => json_array_append_fn_meta(), ScalarFuncSig::JsonMergePatchSig => json_merge_patch_fn_meta(), + // impl_vec + ScalarFuncSig::VecAsTextSig => vec_as_text_fn_meta(), + ScalarFuncSig::VecDimsSig => vec_dims_fn_meta(), + ScalarFuncSig::VecL1DistanceSig => vec_l1_distance_fn_meta(), + ScalarFuncSig::VecL2DistanceSig => vec_l2_distance_fn_meta(), + ScalarFuncSig::VecNegativeInnerProductSig => vec_negative_inner_product_fn_meta(), + ScalarFuncSig::VecCosineDistanceSig => vec_cosine_distance_fn_meta(), + ScalarFuncSig::VecL2NormSig => vec_l2_norm_fn_meta(), // impl_like ScalarFuncSig::LikeSig => map_like_sig(ft, children)?, // impl_regexp @@ -692,6 +710,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::DurationAnyValue => any_value_fn_meta::(), ScalarFuncSig::IntAnyValue => any_value_fn_meta::(), ScalarFuncSig::JsonAnyValue => any_value_json_fn_meta(), + ScalarFuncSig::VectorFloat32AnyValue => any_value_vector_float32_fn_meta(), ScalarFuncSig::RealAnyValue => any_value_fn_meta::(), ScalarFuncSig::StringAnyValue => any_value_bytes_fn_meta(), ScalarFuncSig::TimeAnyValue => any_value_fn_meta::(), @@ -712,6 +731,7 @@ fn map_expr_node_to_rpn_func(expr: &Expr) -> Result { ScalarFuncSig::TimeIsNull => is_null_fn_meta::(), ScalarFuncSig::DurationIsNull => is_null_fn_meta::(), ScalarFuncSig::JsonIsNull => is_null_json_fn_meta(), + ScalarFuncSig::VectorFloat32IsNull => is_null_vector_float32_fn_meta(), ScalarFuncSig::IntIsTrue => int_is_true_fn_meta::(), ScalarFuncSig::IntIsTrueWithNull => int_is_true_fn_meta::(), ScalarFuncSig::RealIsTrue => real_is_true_fn_meta::(), diff --git a/components/tidb_query_expr/src/types/expr.rs b/components/tidb_query_expr/src/types/expr.rs index 26689e762ff..aa72b93624d 100644 --- a/components/tidb_query_expr/src/types/expr.rs +++ b/components/tidb_query_expr/src/types/expr.rs @@ -57,6 +57,7 @@ impl RpnExpressionNode { EvalType::Real => ExprType::Float64, EvalType::Enum => ExprType::MysqlEnum, EvalType::Set => ExprType::MysqlSet, + EvalType::VectorFloat32 => ExprType::TiDbVectorFloat32, }, RpnExpressionNode::ColumnRef { .. } => ExprType::ColumnRef, } diff --git a/components/tidb_query_expr/src/types/expr_builder.rs b/components/tidb_query_expr/src/types/expr_builder.rs index 6ccfd35631e..2c5590e3f1e 100644 --- a/components/tidb_query_expr/src/types/expr_builder.rs +++ b/components/tidb_query_expr/src/types/expr_builder.rs @@ -7,7 +7,7 @@ use tidb_query_common::Result; use tidb_query_datatype::{ codec::{ data_type::*, - mysql::{EnumDecoder, JsonDecoder, MAX_FSP}, + mysql::{EnumDecoder, JsonDecoder, VectorFloat32Decoder, MAX_FSP}, }, expr::EvalContext, match_template_evaltype, EvalType, FieldTypeAccessor, @@ -47,6 +47,7 @@ impl RpnExpressionBuilder { ExprType::MysqlDuration => {} ExprType::MysqlDecimal => {} ExprType::MysqlJson => {} + ExprType::TiDbVectorFloat32 => {} ExprType::ColumnRef => {} _ => return Err(other_err!("Blacklist expression type {:?}", c.get_tp())), } @@ -69,7 +70,8 @@ impl RpnExpressionBuilder { | ExprType::MysqlDuration | ExprType::MysqlDecimal | ExprType::MysqlJson - | ExprType::MysqlEnum => Ok(true), + | ExprType::MysqlEnum + | ExprType::TiDbVectorFloat32 => Ok(true), ExprType::ScalarFunc => Ok(false), ExprType::ColumnRef => Ok(false), _ => Err(other_err!("Unsupported expression type {:?}", c.get_tp())), @@ -373,6 +375,9 @@ fn handle_node_constant( ExprType::MysqlBit if eval_type == EvalType::Int => { extract_scalar_value_uint64_from_bits(tree_node.take_val())? } + ExprType::TiDbVectorFloat32 if eval_type == EvalType::VectorFloat32 => { + extract_scalar_value_vector_float32(tree_node.take_val())? + } expr_type => { return Err(other_err!( "Unexpected ExprType {:?} and EvalType {:?}", @@ -495,6 +500,15 @@ fn extract_scalar_value_enum(val: Vec, field_type: &FieldType) -> Result) -> Result { + let value = val + .as_slice() + .read_vector_float32() + .map_err(|_| other_err!("Unable to decode vector float32 from the request"))?; + Ok(ScalarValue::VectorFloat32(Some(value))) +} + #[cfg(test)] mod tests { use tidb_query_codegen::rpn_fn; diff --git a/components/tidb_query_expr/src/types/expr_eval.rs b/components/tidb_query_expr/src/types/expr_eval.rs index bcad70ac8b5..94d620f4f9a 100644 --- a/components/tidb_query_expr/src/types/expr_eval.rs +++ b/components/tidb_query_expr/src/types/expr_eval.rs @@ -66,6 +66,7 @@ impl<'a> RpnStackNodeVectorValue<'a> { Json => JsonRef, Enum => EnumRef, Set => SetRef, + VectorFloat32 => VectorFloat32Ref, ], match &mut result_vec { VectorValue::TT(dest_column) => { @@ -76,6 +77,7 @@ impl<'a> RpnStackNodeVectorValue<'a> { }, } } + Ok(result_vec) } } diff --git a/components/tidb_query_expr/src/types/function.rs b/components/tidb_query_expr/src/types/function.rs index dee74d2a434..4912c6439d5 100644 --- a/components/tidb_query_expr/src/types/function.rs +++ b/components/tidb_query_expr/src/types/function.rs @@ -345,6 +345,9 @@ thread_local! { pub static VARG_PARAM_BUF_JSON_REF: std::cell::RefCell>>> = std::cell::RefCell::new(Vec::with_capacity(20)); + pub static VARG_PARAM_BUF_VECTOR_FLOAT32_REF: std::cell::RefCell>>> = + std::cell::RefCell::new(Vec::with_capacity(20)); + pub static RAW_VARG_PARAM_BUF: std::cell::RefCell>> = std::cell::RefCell::new(Vec::with_capacity(20)); } From a2a81a9af7956485762b7faf7e60e0f3a154c78e Mon Sep 17 00:00:00 2001 From: Jianjun Liao <36503113+Leavrth@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:25:42 +0800 Subject: [PATCH 031/144] backup-stream: clean the `pause-guard-gc-safepoint` when unregister the log task (#17317) close tikv/tikv#17316 clean `pause-guard-gc-safepoint` when unregister the log task Signed-off-by: Jianjun Liao Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/backup-stream/src/endpoint.rs | 35 ++++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index ed58d63352b..a40fb06c71c 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -685,18 +685,7 @@ where ); let task_name = task.info.get_name().to_owned(); - // clean the safepoint created at pause(if there is) - self.pool.spawn(root!("load_initial_task"; - self.pd_client - .update_service_safe_point( - self.pause_guard_id_for_task(task.info.get_name()), - TimeStamp::zero(), - Duration::new(0, 0), - ) - .map(|r| { - r.map_err(|err| Error::from(err).report("removing safe point for pausing")) - }) - )); + self.clean_pause_guard_id_for_task(&task_name); self.pool.block_on(async move { let task_name_clone = task.info.get_name().to_owned(); let run = async move { @@ -738,6 +727,21 @@ where metrics::update_task_status(TaskStatus::Running, &task_name); } + // clean the safepoint created at pause(if there is) + fn clean_pause_guard_id_for_task(&self, task_name: &str) { + self.pool.spawn(root!("unregister_task"; + self.pd_client + .update_service_safe_point( + self.pause_guard_id_for_task(task_name), + TimeStamp::zero(), + Duration::new(0, 0), + ) + .map(|r| { + r.map_err(|err| Error::from(err).report("removing safe point for pausing")) + }) + )); + } + fn pause_guard_id_for_task(&self, task: &str) -> String { format!("{}-{}-pause-guard", task, self.store_id) } @@ -772,9 +776,10 @@ where } } - pub fn on_unregister(&self, task: &str) -> Option { - let info = self.unload_task(task); - self.remove_metrics_after_unregister(task); + pub fn on_unregister(&self, task_name: &str) -> Option { + let info = self.unload_task(task_name); + self.clean_pause_guard_id_for_task(task_name); + self.remove_metrics_after_unregister(task_name); info } From 7fe2039f1d62a4a42616c795c8d45611df1e568e Mon Sep 17 00:00:00 2001 From: Purelind Date: Tue, 20 Aug 2024 21:15:12 +0800 Subject: [PATCH 032/144] chore: bump version to v8.4.0-alpha (#17393) ref tikv/tikv#16890 Signed-off-by: purelind Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e9eac0090d..f5fc5f3fa93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6448,7 +6448,7 @@ dependencies = [ [[package]] name = "tikv" -version = "8.3.0-alpha" +version = "8.4.0-alpha" dependencies = [ "anyhow", "api_version", diff --git a/Cargo.toml b/Cargo.toml index 5ba83b30a82..3cef40497bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tikv" -version = "8.3.0-alpha" +version = "8.4.0-alpha" authors = ["The TiKV Authors"] description = "A distributed transactional key-value database powered by Rust and Raft" license = "Apache-2.0" From 9b897d23efa5256689efd9f3fb22ef8d2c32c03e Mon Sep 17 00:00:00 2001 From: glorv Date: Wed, 21 Aug 2024 02:34:42 +0800 Subject: [PATCH 033/144] In-memory Engine: fix panic when pending region split before start batch loading (#17398) ref tikv/tikv#16141, close tikv/tikv#17403 Fix the bug that pending region split before batch loading start can cause panic. When handle LoadRegion event, the background worker only update the region with the same id to Loading state, but the region is possible already split so other region within the same range will still in `ReadyToLoad` state. So it will cause panic in `on_snapshot_load_finished`. The PR removes the useless intermediate state `ReadyToLoad`. After this change, the raft apply worker will directly update state from Pending to Loading before scheduler LoadRegion task. So the background worker will not try to update target region's state. Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 16 +-- .../range_cache_memory_engine/src/engine.rs | 13 +-- .../src/range_manager.rs | 9 +- .../src/write_batch.rs | 2 +- .../tests/failpoints/test_memory_engine.rs | 110 +++++++++++++++++- 5 files changed, 121 insertions(+), 29 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index f5996e72226..90c8e943264 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -919,24 +919,20 @@ impl Runnable for BackgroundRunner { let pd_client = self.pd_client.clone(); let gc_interval = self.gc_interval; let f = async move { + fail::fail_point!("before_start_loading_region"); fail::fail_point!("on_start_loading_region"); let mut is_canceled = false; let region_range = CacheRange::from_region(®ion); let skiplist_engine = { - let mut engine = core.engine.write(); - let region_meta = engine - .mut_range_manager() - .mut_region_meta(region.id) - .unwrap(); + let engine = core.engine.read(); + let region_meta = engine.range_manager().region_meta(region.id).unwrap(); // if loading is canceled, we skip the batch load. // NOTE: here we don't check the region epoch version change, // We will handle possible region split and partial cancelation // in `on_snapshot_load_canceled` and `on_snapshot_load_finished`. - if region_meta.get_state() != RegionState::ReadyToLoad { + if region_meta.get_state() != RegionState::Loading { assert_eq!(region_meta.get_state(), RegionState::LoadingCanceled); is_canceled = true; - } else { - region_meta.set_state(RegionState::Loading); } engine.engine.clone() @@ -2843,7 +2839,7 @@ pub mod tests { .range_manager() .regions() .values() - .any(|m| matches!(m.get_state(), Pending | ReadyToLoad | Loading)) + .any(|m| matches!(m.get_state(), Pending | Loading)) }); let verify = |region: &Region, exist, expect_count| { @@ -2950,7 +2946,7 @@ pub mod tests { .range_manager() .regions() .values() - .any(|m| matches!(m.get_state(), Pending | ReadyToLoad | Loading)) + .any(|m| matches!(m.get_state(), Pending | Loading)) }); let verify = |r: &Region, exist, expect_count| { diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index a3061535708..939ac00c3cd 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -345,20 +345,17 @@ impl RangeCacheMemoryEngine { let schedule_load = region_state == RegionState::Pending; if schedule_load { - range_manager.update_region_state(region.id, RegionState::ReadyToLoad); + range_manager.update_region_state(region.id, RegionState::Loading); info!( "range to load"; "region" => ?region, "cached" => range_manager.regions().len(), ); - region_state = RegionState::ReadyToLoad; + region_state = RegionState::Loading; } let mut result = RangeCacheStatus::NotInCache; - if region_state == RegionState::ReadyToLoad - || region_state == RegionState::Loading - || region_state == RegionState::Active - { + if region_state == RegionState::Loading || region_state == RegionState::Active { range_manager.record_in_region_being_written(write_batch_id, range); if region_state == RegionState::Active { result = RangeCacheStatus::Cached; @@ -543,7 +540,7 @@ pub mod tests { engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); assert_eq!( count_region(engine.core.read().range_manager(), |m| { - matches!(m.get_state(), Pending | ReadyToLoad | Loading) + matches!(m.get_state(), Pending | Loading) }), 0 ); @@ -556,7 +553,7 @@ pub mod tests { engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); assert_eq!( count_region(engine.core.read().range_manager(), |m| { - matches!(m.get_state(), Pending | ReadyToLoad | Loading) + matches!(m.get_state(), Pending | Loading) }), 0 ); diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 930c1db4a62..ed38edb7e4a 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -24,9 +24,6 @@ pub enum RegionState { // target region in raftstore. #[default] Pending, - // Region is ready to do batch load but not started. In this state, - // apply thread starts directly write new KVs into the skiplist. - ReadyToLoad, // Region is handling batch loading from rocksdb snapshot. Loading, // Region is cached, ready to handle foreground read. @@ -44,7 +41,6 @@ impl RegionState { use RegionState::*; match *self { Pending => "pending", - ReadyToLoad => "ready_to_load", Loading => "loading", Active => "cached", LoadingCanceled => "loading_canceled", @@ -170,8 +166,7 @@ impl RangeMeta { fn validate_update_region_state(&self, new_state: RegionState) -> bool { use RegionState::*; let valid_new_states: &[RegionState] = match self.state { - Pending => &[ReadyToLoad], - ReadyToLoad => &[Loading, LoadingCanceled], + Pending => &[Loading], Loading => &[Active, LoadingCanceled, Evicting], Active => &[PendingEvict], LoadingCanceled => &[PendingEvict, Evicting], @@ -778,7 +773,7 @@ impl RegionManager { use RegionState::*; if let Some(state) = self.check_overlap_with_region(®ion) { let reason = match state { - Pending | ReadyToLoad | Loading => LoadFailedReason::PendingRange, + Pending | Loading => LoadFailedReason::PendingRange, Active => LoadFailedReason::Overlapped, LoadingCanceled | PendingEvict | Evicting => LoadFailedReason::Evicting, }; diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 5995a069730..b654b5313d6 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -710,7 +710,7 @@ mod tests { let core = engine.core.read(); let region_meta = core.range_manager().region_meta(1).unwrap(); assert_eq!(region_meta.region(), &r1_new); - assert_eq!(region_meta.get_state(), RegionState::ReadyToLoad); + assert_eq!(region_meta.get_state(), RegionState::Loading); } wb.put(b"zk02", b"val1").unwrap(); wb.put(b"zk04", b"val1").unwrap(); diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 57023b067e8..9f02caaf2b9 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -8,8 +8,8 @@ use std::{ use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, EvictReason, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, - CF_LOCK, CF_WRITE, DATA_CFS, + CacheRange, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, WriteBatchExt, + CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use keys::data_key; use kvproto::metapb::Region; @@ -17,7 +17,7 @@ use range_cache_memory_engine::{ decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, test_util::{new_region, put_data, put_data_in_rocks}, BackgroundTask, InternalBytes, InternalKey, RangeCacheEngineConfig, RangeCacheEngineContext, - RangeCacheMemoryEngine, SkiplistHandle, ValueType, + RangeCacheMemoryEngine, RegionState, SkiplistHandle, ValueType, }; use tempfile::Builder; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; @@ -645,3 +645,107 @@ fn test_load_with_gc() { .unwrap_err(); engine.snapshot(region.id, 0, range, 7, 100).unwrap(); } + +// test in-memory-engine can handle region split event after load region task +// is scheduled but before the task start running. As source region is split +// into multiple regions, IME should handle all the regions with in the range +// and update their state to active when batch loading task is finished. +#[test] +fn test_region_split_before_batch_loading_start() { + let path = Builder::new().prefix("test").tempdir().unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + + let mut config = RangeCacheEngineConfig::config_for_test(); + config.gc_interval = ReadableDuration(Duration::from_secs(1)); + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(config), + ))); + engine.set_disk_engine(rocks_engine.clone()); + + let (tx, rx) = sync_channel(0); + fail::cfg_callback("before_start_loading_region", move || { + let _ = tx.send(()); + }) + .unwrap(); + fail::cfg("on_start_loading_region", "pause").unwrap(); + + let region = new_region(1, b"k00", b"k30"); + + // write some data into rocksdb to trigger batch loading. + for i in 0..30 { + let key = format!("k{:02}", i); + put_data_in_rocks( + key.as_bytes(), + b"val", + 2, + 1, + false, + &rocks_engine, + WriteType::Put, + ); + } + + engine.load_region(region.clone()).unwrap(); + + // use write batch to trigger scheduling pending region loading task. + let mut wb = engine.write_batch(); + wb.prepare_for_region(®ion); + wb.set_sequence_number(10).unwrap(); + wb.put(b"k00", b"val2").unwrap(); + wb.put(b"k10", b"val2").unwrap(); + wb.put(b"k20", b"val2").unwrap(); + wb.write().unwrap(); + assert_eq!( + engine + .core() + .read() + .range_manager() + .region_meta(1) + .unwrap() + .get_state(), + RegionState::Loading + ); + + // wait for task start. + rx.recv().unwrap(); + + // split source region into multiple new regions. + let mut new_regions = vec![ + new_region(1, b"k00", b"k10"), + new_region(2, b"k10", b"k20"), + new_region(3, b"k20", b"k30"), + ]; + for r in &mut new_regions { + r.mut_region_epoch().version = 2; + } + let event = RegionEvent::Split { + source: region.clone(), + new_regions: new_regions.clone(), + }; + engine.on_region_event(event); + { + let core = engine.core().read(); + for i in 1..=3 { + assert_eq!( + core.range_manager().region_meta(i).unwrap().get_state(), + RegionState::Loading + ); + } + } + + // unblock batch loading. + fail::remove("on_start_loading_region"); + + // all new regions should be active after batch loading task finished. + test_util::eventually( + Duration::from_millis(50), + Duration::from_millis(2000), + || { + let core = engine.core().read(); + (1..=3).all(|i| { + core.range_manager().region_meta(i).unwrap().get_state() == RegionState::Active + }) + }, + ); +} From 7b52a3a5efd426035beaf2f14ee29efd7d402025 Mon Sep 17 00:00:00 2001 From: YangKeao Date: Wed, 21 Aug 2024 16:30:14 +0800 Subject: [PATCH 034/144] copr: add a `force_no_pad` argument to `sort_compare`, and fix `like` behavior (#17337) close tikv/tikv#17332 Signed-off-by: Yang Keao Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../tidb_query_aggr/src/impl_max_min.rs | 7 +++- .../src/codec/collation/collator/binary.rs | 2 +- .../codec/collation/collator/gbk_collation.rs | 10 +++-- .../codec/collation/collator/latin1_bin.rs | 12 ++++-- .../src/codec/collation/collator/mod.rs | 4 +- .../collation/collator/utf8mb4_binary.rs | 12 ++++-- .../collation/collator/utf8mb4_general_ci.rs | 10 +++-- .../collation/collator/utf8mb4_uca/mod.rs | 13 ++++-- .../src/codec/collation/mod.rs | 8 ++-- .../src/codec/data_type/scalar.rs | 2 +- .../tidb_query_expr/src/impl_compare.rs | 2 +- components/tidb_query_expr/src/impl_like.rs | 40 ++++++++++++++----- components/tidb_query_expr/src/impl_string.rs | 6 +-- 13 files changed, 89 insertions(+), 39 deletions(-) diff --git a/components/tidb_query_aggr/src/impl_max_min.rs b/components/tidb_query_aggr/src/impl_max_min.rs index 0ee7ceb570a..aada14e7bfa 100644 --- a/components/tidb_query_aggr/src/impl_max_min.rs +++ b/components/tidb_query_aggr/src/impl_max_min.rs @@ -184,7 +184,12 @@ where return Ok(()); } - if C::sort_compare(self.extremum.as_ref().unwrap(), value.as_ref().unwrap())? == E::ORD { + if C::sort_compare( + self.extremum.as_ref().unwrap(), + value.as_ref().unwrap(), + false, + )? == E::ORD + { self.extremum = value.map(|x| x.into_owned_value()); } Ok(()) diff --git a/components/tidb_query_datatype/src/codec/collation/collator/binary.rs b/components/tidb_query_datatype/src/codec/collation/collator/binary.rs index 6f183a215c7..653d0c415cd 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/binary.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/binary.rs @@ -24,7 +24,7 @@ impl Collator for CollatorBinary { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { + fn sort_compare(a: &[u8], b: &[u8], _force_no_pad: bool) -> Result { Ok(a.cmp(b)) } diff --git a/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs b/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs index 31685ca08d5..a767ca35bfe 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs @@ -43,9 +43,13 @@ impl Collator for T { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { - let sa = str::from_utf8(a)?.trim_end_matches(PADDING_SPACE); - let sb = str::from_utf8(b)?.trim_end_matches(PADDING_SPACE); + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = sa.trim_end_matches(PADDING_SPACE); + sb = sb.trim_end_matches(PADDING_SPACE); + } Ok(sa .chars() .map(Self::char_weight) diff --git a/components/tidb_query_datatype/src/codec/collation/collator/latin1_bin.rs b/components/tidb_query_datatype/src/codec/collation/collator/latin1_bin.rs index c70deb08cd1..a63a5aed7e2 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/latin1_bin.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/latin1_bin.rs @@ -28,10 +28,14 @@ impl Collator for CollatorLatin1Bin { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { - Ok(B(a) - .trim_end_with(|c| c == PADDING_SPACE) - .cmp(B(b).trim_end_with(|c| c == PADDING_SPACE))) + fn sort_compare(mut a: &[u8], mut b: &[u8], force_no_pad: bool) -> Result { + if !force_no_pad { + a = a.trim_end_with(|c| c == PADDING_SPACE); + } + if !force_no_pad { + b = b.trim_end_with(|c| c == PADDING_SPACE); + } + Ok(a.cmp(b)) } #[inline] diff --git a/components/tidb_query_datatype/src/codec/collation/collator/mod.rs b/components/tidb_query_datatype/src/codec/collation/collator/mod.rs index 913d1dced9f..4943772e850 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/mod.rs @@ -212,7 +212,7 @@ mod tests { hasher.finish() }; - let cmp = TT::sort_compare(sa, sb).unwrap(); + let cmp = TT::sort_compare(sa, sb, false).unwrap(); let ha = eval_hash(sa); let hb = eval_hash(sb); (cmp, ha, hb) @@ -448,7 +448,7 @@ mod tests { hasher.finish() }; - let cmp = CollatorLatin1Bin::sort_compare(sa.as_slice(), sb.as_slice()).unwrap(); + let cmp = CollatorLatin1Bin::sort_compare(sa.as_slice(), sb.as_slice(), false).unwrap(); let ha = eval_hash(sa.as_slice()); let hb = eval_hash(sb.as_slice()); diff --git a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_binary.rs b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_binary.rs index 959664b1854..e5333411cdb 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_binary.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_binary.rs @@ -26,9 +26,13 @@ impl Collator for CollatorUtf8Mb4Bin { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { - let sa = str::from_utf8(a)?.trim_end_matches(PADDING_SPACE); - let sb = str::from_utf8(b)?.trim_end_matches(PADDING_SPACE); + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = sa.trim_end_matches(PADDING_SPACE); + sb = sb.trim_end_matches(PADDING_SPACE); + } Ok(sa.as_bytes().cmp(sb.as_bytes())) } @@ -63,7 +67,7 @@ impl Collator for CollatorUtf8Mb4BinNoPadding { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { + fn sort_compare(a: &[u8], b: &[u8], _force_no_pad: bool) -> Result { str::from_utf8(a)?; str::from_utf8(b)?; Ok(a.cmp(b)) diff --git a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_general_ci.rs b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_general_ci.rs index 2cc9a738372..7b0f27d70d0 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_general_ci.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_general_ci.rs @@ -38,9 +38,13 @@ impl Collator for CollatorUtf8Mb4GeneralCi { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { - let sa = str::from_utf8(a)?.trim_end_matches(PADDING_SPACE); - let sb = str::from_utf8(b)?.trim_end_matches(PADDING_SPACE); + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = sa.trim_end_matches(PADDING_SPACE); + sb = sb.trim_end_matches(PADDING_SPACE); + } Ok(sa .chars() .map(Self::char_weight) diff --git a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_uca/mod.rs b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_uca/mod.rs index b90d28d0e11..cb653f5170d 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_uca/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/utf8mb4_uca/mod.rs @@ -53,9 +53,16 @@ impl Collator for CollatorUca { } #[inline] - fn sort_compare(a: &[u8], b: &[u8]) -> Result { - let mut ca = T::preprocess(str::from_utf8(a)?).chars(); - let mut cb = T::preprocess(str::from_utf8(b)?).chars(); + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = T::preprocess(sa); + sb = T::preprocess(sb); + } + + let mut ca = sa.chars(); + let mut cb = sb.chars(); let mut an = 0; let mut bn = 0; diff --git a/components/tidb_query_datatype/src/codec/collation/mod.rs b/components/tidb_query_datatype/src/codec/collation/mod.rs index 93cf0c8ca55..fe72a674e0b 100644 --- a/components/tidb_query_datatype/src/codec/collation/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/mod.rs @@ -121,7 +121,7 @@ pub trait Collator: 'static + std::marker::Send + std::marker::Sync + std::fmt:: } /// Compares `a` and `b` based on their SortKey. - fn sort_compare(a: &[u8], b: &[u8]) -> Result; + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result; /// Hashes `bstr` based on its SortKey directly. /// @@ -238,7 +238,7 @@ where { #[inline] fn eq(&self, other: &Self) -> bool { - C::sort_compare(self.inner.as_ref(), other.inner.as_ref()).unwrap() + C::sort_compare(self.inner.as_ref(), other.inner.as_ref(), false).unwrap() == std::cmp::Ordering::Equal } } @@ -251,7 +251,7 @@ where { #[inline] fn partial_cmp(&self, other: &Self) -> Option { - C::sort_compare(self.inner.as_ref(), other.inner.as_ref()).ok() + C::sort_compare(self.inner.as_ref(), other.inner.as_ref(), false).ok() } } @@ -261,7 +261,7 @@ where { #[inline] fn cmp(&self, other: &Self) -> Ordering { - C::sort_compare(self.inner.as_ref(), other.inner.as_ref()).unwrap() + C::sort_compare(self.inner.as_ref(), other.inner.as_ref(), false).unwrap() } } diff --git a/components/tidb_query_datatype/src/codec/data_type/scalar.rs b/components/tidb_query_datatype/src/codec/data_type/scalar.rs index 85197547964..397ffbe0619 100644 --- a/components/tidb_query_datatype/src/codec/data_type/scalar.rs +++ b/components/tidb_query_datatype/src/codec/data_type/scalar.rs @@ -387,7 +387,7 @@ impl<'a> ScalarValueRef<'a> { (ScalarValueRef::Bytes(Some(v1)), ScalarValueRef::Bytes(Some(v2))) => { match_template_collator! { TT, match field_type.collation()? { - Collation::TT => TT::sort_compare(v1, v2)? + Collation::TT => TT::sort_compare(v1, v2, false)? } } } diff --git a/components/tidb_query_expr/src/impl_compare.rs b/components/tidb_query_expr/src/impl_compare.rs index 54925ad2072..cd978c5e559 100644 --- a/components/tidb_query_expr/src/impl_compare.rs +++ b/components/tidb_query_expr/src/impl_compare.rs @@ -54,7 +54,7 @@ pub fn compare_bytes( (None, None) => F::compare_null(), (None, _) | (_, None) => F::compare_partial_null(), (Some(lhs), Some(rhs)) => { - let ord = C::sort_compare(lhs, rhs)?; + let ord = C::sort_compare(lhs, rhs, false)?; Some(F::compare_order(ord) as i64) } }) diff --git a/components/tidb_query_expr/src/impl_like.rs b/components/tidb_query_expr/src/impl_like.rs index bd00c1d888b..f81e47e85e0 100644 --- a/components/tidb_query_expr/src/impl_like.rs +++ b/components/tidb_query_expr/src/impl_like.rs @@ -47,7 +47,7 @@ pub fn like( } if let Some((_, toff)) = CS::decode_one(&target[tx..]) { if let Ok(std::cmp::Ordering::Equal) = - C::sort_compare(&target[tx..tx + toff], &pattern[px..px + poff]) + C::sort_compare(&target[tx..tx + toff], &pattern[px..px + poff], true) { tx += toff; px += poff; @@ -200,17 +200,27 @@ mod tests { Some(0), ), (r#"Ⱕ"#, r#"ⱕ"#, '\\', Collation::Utf8Mb40900AiCi, Some(1)), + ( + r#"a a"#, + r#"a a"#, + '\\', + Collation::Utf8Mb4UnicodeCi, + Some(1), + ), ]; for (target, pattern, escape, collation, expected) in cases { + let ret_ft = FieldTypeBuilder::new() + .tp(FieldTypeTp::LongLong) + .collation(collation) + .build(); + let arg_ft = FieldTypeBuilder::new() + .tp(FieldTypeTp::String) + .collation(collation) + .build(); let output = RpnFnScalarEvaluator::new() - .return_field_type( - FieldTypeBuilder::new() - .tp(FieldTypeTp::LongLong) - .collation(collation) - .build(), - ) - .push_param(target.to_owned().into_bytes()) - .push_param(pattern.to_owned().into_bytes()) + .return_field_type(ret_ft.clone()) + .push_param_with_field_type(target.to_owned().into_bytes(), arg_ft.clone()) + .push_param_with_field_type(pattern.to_owned().into_bytes(), arg_ft) .push_param(escape as i64) .evaluate(ScalarFuncSig::LikeSig) .unwrap(); @@ -335,6 +345,18 @@ mod tests { Collation::Utf8Mb4Bin, Some(1), ), + // This can happen when the new collation is not enabled, and TiDB + // doesn't push down the collation information. Though the two collations + // are the same, we still use the binary order. + ( + r#"测试A"#, + r#"测_a"#, + '\\', + Collation::Binary, + Collation::Utf8Mb4UnicodeCi, + Collation::Utf8Mb4UnicodeCi, + Some(0), + ), ]; for (target, pattern, escape, collation, target_collation, pattern_collation, expected) in cases diff --git a/components/tidb_query_expr/src/impl_string.rs b/components/tidb_query_expr/src/impl_string.rs index 1b633582a34..d0aeb1a9b1e 100644 --- a/components/tidb_query_expr/src/impl_string.rs +++ b/components/tidb_query_expr/src/impl_string.rs @@ -644,7 +644,7 @@ fn field_bytes(args: &[Option]) -> Result> { if arg.is_none() { continue; } - match C::sort_compare(val, arg.unwrap()) { + match C::sort_compare(val, arg.unwrap(), false) { Ok(Ordering::Equal) => return Ok(Some(pos as i64)), _ => continue, } @@ -781,7 +781,7 @@ pub fn substring_index( #[inline] pub fn strcmp(left: BytesRef, right: BytesRef) -> Result> { use std::cmp::Ordering::*; - Ok(Some(match C::sort_compare(left, right)? { + Ok(Some(match C::sort_compare(left, right, false)? { Less => -1, Equal => 0, Greater => 1, @@ -818,7 +818,7 @@ pub fn find_in_set(s: BytesRef, str_list: BytesRef) -> Result Date: Thu, 22 Aug 2024 14:48:13 +0800 Subject: [PATCH 035/144] OWNERS: Auto Sync OWNERS files from community membership (#17399) Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- OWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWNERS b/OWNERS index e5d8ff9cf89..3bc3e5e32e7 100644 --- a/OWNERS +++ b/OWNERS @@ -56,7 +56,6 @@ reviewers: - Fullstop000 - gozssky - haojinming - - hi-rustin - HuSharp - jayzhan211 - Jibbow @@ -69,6 +68,7 @@ reviewers: - MrCroxx - nolouch - rleungx + - Rustin170506 - tier-cap - v01dstar - wjhuang2016 From 109939ee5e4c39c3aee4dc44081f4a497e01f7c4 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Thu, 22 Aug 2024 20:31:42 +0800 Subject: [PATCH 036/144] In-memory Engine: add "ime" log prefix (#17404) ref tikv/tikv#16141 This commit adds the prefix "ime" to all In-Memory Engine log entries, making it easier to identify and debug related issues. Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/hybrid_engine/src/observer.rs | 13 ++-- .../src/background.rs | 70 +++++++++---------- .../range_cache_memory_engine/src/config.rs | 2 +- .../range_cache_memory_engine/src/engine.rs | 10 +-- .../src/range_manager.rs | 48 +++++++------ .../src/range_stats.rs | 6 +- .../range_cache_memory_engine/src/read.rs | 2 +- .../src/region_label.rs | 18 ++--- .../src/write_batch.rs | 10 +-- 9 files changed, 93 insertions(+), 86 deletions(-) diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer.rs index 8a2c837f17d..a9afdfc3c6a 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer.rs @@ -10,6 +10,7 @@ use raftstore::coprocessor::{ BoxRoleObserver, Cmd, CmdBatch, CmdObserver, Coprocessor, CoprocessorHost, ObserveLevel, ObserverContext, QueryObserver, RegionState, RoleObserver, }; +use tikv_util::info; #[derive(Clone)] pub struct Observer { @@ -79,8 +80,8 @@ impl Observer { )) { let range = CacheRange::from_region(ctx.region()); - tikv_util::info!( - "evict range due to apply commands"; + info!( + "ime evict range due to apply commands"; "region_id" => ctx.region().get_id(), "is_ingest_sst" => apply.pending_handle_ssts.is_some(), "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), @@ -99,8 +100,8 @@ impl Observer { if !state.new_regions.is_empty() { let cmd_type = cmd.request.get_admin_request().get_cmd_type(); assert!(cmd_type == AdminCmdType::BatchSplit || cmd_type == AdminCmdType::Split); - tikv_util::info!( - "in-memory-engine handle region split"; + info!( + "ime handle region split"; "region_id" => ctx.region().get_id(), "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), "region" => ?state.modified_region.as_ref().unwrap(), @@ -134,8 +135,8 @@ impl Observer { } let range = CacheRange::from_region(region); - tikv_util::info!( - "evict region due to leader step down"; + info!( + "ime evict region due to leader step down"; "region_id" => region.get_id(), "epoch" => ?region.get_region_epoch(), "start_key" => ?log_wrappers::Value(®ion.start_key), diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 90c8e943264..92c50aa9794 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -185,13 +185,13 @@ impl PdRangeHintService { for key_range in &label_rule.data { match parse_range(key_range) { Ok((start, end)) => { - info!("Requested to cache range"; + info!("ime requested to cache range"; "start" => ?log_wrappers::Value(&start), "end" => ?log_wrappers::Value(&end)); range_manager_load_cb(&start, &end); } Err(e) => { - error!("Unable to convert key_range rule to cache range"; "err" => ?e); + error!("ime unable to convert key_range rule to cache range"; "err" => ?e); } } } @@ -267,7 +267,7 @@ impl BgWorkManager { let region_info_provider = self.region_info_provider.clone(); range_hint_service.start(self.worker.remote(), move |start: &[u8], end: &[u8]| { let Some(ref info_provider) = region_info_provider else { - warn!("[IME] region info provider is none, skip load pinned range."); + warn!("ime region info provider is none, skip load pinned range."); return; }; @@ -275,7 +275,7 @@ impl BgWorkManager { Ok(r) => r, Err(e) => { warn!( - "get regions in range failed"; "err" => ?e, + "ime get regions in range failed"; "err" => ?e, "start" => ?log_wrappers::Value(start), "end" => ?log_wrappers::Value(end) ); @@ -290,7 +290,7 @@ impl BgWorkManager { let mut engine = core.write(); for r in regions { if let Err(e) = engine.mut_range_manager().load_region(r.clone()) { - warn!("load region by label failed"; "err" => ?e, "region" => ?r); + warn!("ime load region by label failed"; "err" => ?e, "region" => ?r); } } // TODO (afeinberg): This does not actually load the range. The load @@ -320,7 +320,7 @@ impl BgWorkManager { Ok(Ok(ts)) => ts, err => { error!( - "schedule range cache engine gc failed "; + "ime schedule range cache engine gc failed "; "timeout_duration" => ?tso_timeout, "error" => ?err, ); @@ -331,7 +331,7 @@ impl BgWorkManager { let safe_point = TimeStamp::compose(safe_point, 0).into_inner(); if let Err(e) = scheduler.schedule(BackgroundTask::Gc(GcTask {safe_point})) { error!( - "schedule range cache engine gc failed"; + "ime schedule range cache engine gc failed"; "err" => ?e, ); } @@ -339,7 +339,7 @@ impl BgWorkManager { recv(load_evict_ticker) -> _ => { if let Err(e) = scheduler.schedule(BackgroundTask::TopRegionsLoadEvict) { error!( - "schedule load evict failed"; + "ime schedule load evict failed"; "err" => ?e, ); } @@ -347,7 +347,7 @@ impl BgWorkManager { recv(rx) -> r => { if let Err(e) = r { error!( - "receive error in range cache engien gc ticker"; + "ime receive error in range cache engien gc ticker"; "err" => ?e, ); } @@ -425,7 +425,7 @@ impl BackgroundRunnerCore { let safe_point = safe_point.min(min_snapshot).min(historical_safe_point); if safe_point <= region_meta.safe_point() { info!( - "safe point not large enough"; + "ime safe point not large enough"; "prev" => region_meta.safe_point(), "current" => safe_point, ); @@ -434,7 +434,7 @@ impl BackgroundRunnerCore { // todo: change it to debug! info!( - "safe point update"; + "ime safe point update"; "prev" => region_meta.safe_point(), "current" => safe_point, "range" => ?range, @@ -461,7 +461,7 @@ impl BackgroundRunnerCore { let duration = start.saturating_elapsed(); RANGE_GC_TIME_HISTOGRAM.observe(duration.as_secs_f64()); info!( - "range gc complete"; + "ime range gc complete"; "range" => ?range, "gc_duration" => ?duration, "total_version" => filter.metrics.total, @@ -542,7 +542,7 @@ impl BackgroundRunnerCore { delete_range_scheduler.schedule_force(BackgroundTask::DeleteRegions(remove_regions)) { error!( - "schedule delete range failed"; + "ime schedule delete range failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -595,7 +595,7 @@ impl BackgroundRunnerCore { delete_range_scheduler.schedule_force(BackgroundTask::DeleteRegions(remove_regions)) { error!( - "schedule delete range failed"; + "ime schedule delete range failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -610,7 +610,7 @@ impl BackgroundRunnerCore { /// excess memory usage. fn evict_on_soft_limit_reached(&self, delete_range_scheduler: &Scheduler) { if self.range_stats_manager.is_none() { - warn!("range stats manager is not initialized, cannot evict on soft limit reached"); + warn!("ime range stats manager is not initialized, cannot evict on soft limit reached"); return; } let range_stats_manager = self.range_stats_manager.as_ref().unwrap(); @@ -646,7 +646,7 @@ impl BackgroundRunnerCore { .evict_region(®ion, EvictReason::MemoryLimitReached); if !deleteable_regions.is_empty() { info!( - "evict on soft limit reached"; + "ime evict on soft limit reached"; "region_to_evict" => ?region, "regions_evicted" => ?&deleteable_regions, "approx_size" => approx_size, @@ -663,7 +663,7 @@ impl BackgroundRunnerCore { .schedule_force(BackgroundTask::DeleteRegions(regions_to_delete)) { error!( - "schedule deletet range failed"; + "ime schedule deletet range failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -697,7 +697,7 @@ impl BackgroundRunnerCore { let mut regions_to_remove = Vec::with_capacity(256); range_stats_manager.collect_changed_ranges(&mut regions_to_add, &mut regions_to_remove); let mut regions_to_delete = Vec::with_capacity(regions_to_remove.len()); - info!("load_evict"; "ranges_to_add" => ?®ions_to_add, "may_evict" => ?®ions_to_remove); + info!("ime load_evict"; "ranges_to_add" => ?®ions_to_add, "may_evict" => ?®ions_to_remove); for evict_region in regions_to_remove { if self.memory_controller.reached_soft_limit() { let mut core = self.engine.write(); @@ -705,7 +705,7 @@ impl BackgroundRunnerCore { .mut_range_manager() .evict_region(&evict_region, EvictReason::AutoEvict); info!( - "load_evict: soft limit reached"; + "ime load_evict: soft limit reached"; "region_to_evict" => ?&evict_region, "evicted_regions" => ?&deleteable_regions, ); @@ -718,7 +718,7 @@ impl BackgroundRunnerCore { .schedule_force(BackgroundTask::DeleteRegions(regions_to_delete)) { error!( - "schedule deletet range failed"; + "ime schedule deletet range failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -727,11 +727,11 @@ impl BackgroundRunnerCore { for region in regions_to_add { let mut core = self.engine.write(); if let Err(e) = core.mut_range_manager().load_region(region.clone()) { - error!("error loading range"; "cache_range" => ?region, "err" => ?e); + error!("ime error loading range"; "cache_range" => ?region, "err" => ?e); } } range_stats_manager.set_checking_top_regions(false); - info!("load_evict complete"); + info!("ime load_evict complete"); } } @@ -891,7 +891,7 @@ impl Runnable for BackgroundRunner { }; info!( - "start a new round of gc for range cache engine"; + "ime start a new round of gc for range cache engine"; "safe_point" => t.safe_point, "oldest_sequence" => seqno, ); @@ -945,14 +945,14 @@ impl Runnable for BackgroundRunner { if is_canceled { info!( - "snapshot load canceled"; + "ime snapshot load canceled"; "region" => ?region, ); core.on_snapshot_load_failed(®ion, &delete_range_scheduler, false); return; } - info!("Loading region"; "region" => ?®ion); + info!("ime Loading region"; "region" => ?®ion); let start = Instant::now(); let iter_opt = IterOptions::new( Some(KeyBuilder::from_slice(®ion_range.start, 0, 0)), @@ -988,7 +988,7 @@ impl Runnable for BackgroundRunner { core.memory_controller.acquire(mem_size) { warn!( - "stop loading snapshot due to memory reaching hard limit"; + "ime stop loading snapshot due to memory reaching hard limit"; "region" => ?region, "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), ); @@ -1003,7 +1003,7 @@ impl Runnable for BackgroundRunner { } } Err(e) => { - error!("creating rocksdb iterator failed"; "cf" => cf, "err" => %e); + error!("ime creating rocksdb iterator failed"; "cf" => cf, "err" => %e); break 'load_snapshot None; } } @@ -1014,7 +1014,7 @@ impl Runnable for BackgroundRunner { Ok(Ok(ts)) => ts, err => { error!( - "get timestamp failed, skip gc loaded range"; + "ime get timestamp failed, skip gc loaded range"; "timeout_duration" => ?tso_timeout, "error" => ?err, ); @@ -1054,16 +1054,16 @@ impl Runnable for BackgroundRunner { let duration = start.saturating_elapsed(); RANGE_LOAD_TIME_HISTOGRAM.observe(duration.as_secs_f64()); info!( - "Loading region finished"; + "ime Loading region finished"; "region" => ?region, "duration(sec)" => ?duration, ); } else { - info!("Loading region canceled";"region" => ?region); + info!("ime Loading region canceled";"region" => ?region); } } else { info!( - "snapshot load failed"; + "ime snapshot load failed"; "region" => ?region, ); core.on_snapshot_load_failed(®ion, &delete_range_scheduler, true); @@ -1074,7 +1074,7 @@ impl Runnable for BackgroundRunner { BackgroundTask::MemoryCheckAndEvict => { let mem_usage = self.core.memory_controller.mem_usage(); info!( - "start memory usage check and evict"; + "ime start memory usage check and evict"; "mem_usage(MB)" => ReadableSize(mem_usage as u64).as_mb() ); if mem_usage > self.core.memory_controller.soft_limit_threshold() { @@ -1107,7 +1107,7 @@ impl Runnable for BackgroundRunner { let f = async move { info!( - "begin to cleanup tombstones in lock cf"; + "ime begin to cleanup tombstones in lock cf"; "seqno" => snapshot_seqno, ); @@ -1163,7 +1163,7 @@ impl Runnable for BackgroundRunner { } info!( - "cleanup tombstones in lock cf"; + "ime cleanup tombstones in lock cf"; "seqno" => snapshot_seqno, "total" => total, "removed" => removed, @@ -1390,7 +1390,7 @@ impl Filter { let v = iter.value(); if let Err(e) = self.filter_key(k.as_bytes(), v.as_bytes()) { warn!( - "Something Wrong in memory engine GC"; + "ime Something Wrong in memory engine GC"; "error" => ?e, ); } diff --git a/components/range_cache_memory_engine/src/config.rs b/components/range_cache_memory_engine/src/config.rs index f7c0e52ab56..1124dd4028a 100644 --- a/components/range_cache_memory_engine/src/config.rs +++ b/components/range_cache_memory_engine/src/config.rs @@ -25,7 +25,7 @@ impl ConfigManager for RangeCacheConfigManager { .update(move |cfg: &mut RangeCacheEngineConfig| cfg.update(change))?; } info!( - "range cache config changed"; + "ime range cache config changed"; "change" => ?change, ); Ok(()) diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 939ac00c3cd..8548ef42dcb 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -259,7 +259,7 @@ impl RangeCacheMemoryEngine { range_cache_engine_context: RangeCacheEngineContext, region_info_provider: Option>, ) -> Self { - info!("init range cache memory engine";); + info!("ime init range cache memory engine"); let core = Arc::new(RwLock::new(RangeCacheMemoryEngineCore::new())); let skiplist_engine = { core.read().engine().clone() }; @@ -321,7 +321,7 @@ impl RangeCacheMemoryEngine { .schedule_task(BackgroundTask::DeleteRegions(deleteable_regions)) { error!( - "schedule delete region failed"; + "ime schedule delete region failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -347,7 +347,7 @@ impl RangeCacheMemoryEngine { if schedule_load { range_manager.update_region_state(region.id, RegionState::Loading); info!( - "range to load"; + "ime range to load"; "region" => ?region, "cached" => range_manager.regions().len(), ); @@ -374,7 +374,7 @@ impl RangeCacheMemoryEngine { .schedule_task(BackgroundTask::LoadRegion(region.clone(), rocks_snap)) { error!( - "schedule region load failed"; + "ime schedule region load failed"; "err" => ?e, "region" => ?region, ); @@ -444,7 +444,7 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { .schedule_task(BackgroundTask::SetRocksEngine(disk_engine)) { error!( - "schedule set rocks_engine failed"; + "ime schedule set rocks_engine failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index ed38edb7e4a..2f0cbbc4823 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -13,7 +13,7 @@ use std::{ use collections::HashMap; use engine_traits::{CacheRange, EvictReason, FailedReason}; use kvproto::metapb::Region; -use tikv_util::{info, time::Instant}; +use tikv_util::{info, time::Instant, warn}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; @@ -179,10 +179,10 @@ impl RangeMeta { pub(crate) fn set_state(&mut self, new_state: RegionState) { assert!(self.validate_update_region_state(new_state)); info!( - "update region meta state"; - "region_id" => self.region.id, + "ime update region meta state"; + "region_id" => self.region.id, "epoch" => self.region.get_region_epoch().version, - "curr_state" => ?self.state, + "curr_state" => ?self.state, "new_state" => ?new_state); self.state = new_state; } @@ -394,7 +394,9 @@ impl RegionManager { && cached_meta.region.get_region_epoch().version != region.get_region_epoch().version && !cached_meta.amend_pending_region(region) { - info!("remove outdated pending region"; "pending_region" => ?cached_meta.region, "new_region" => ?region); + info!("ime remove outdated pending region"; + "pending_region" => ?cached_meta.region, + "new_region" => ?region); self.remove_region(region.id); return None; } @@ -435,14 +437,14 @@ impl RegionManager { removed_regions.push(region_meta.region.id); return true; } - tikv_util::warn!("load region overlaps with existing region"; + warn!("ime load region overlaps with existing region"; "region" => ?region, "exist_meta" => ?region_meta); overlapped_region_state = Some(region_meta.state); false }); if !removed_regions.is_empty() { - info!("load region meet pending region with stale epoch, removed"; + info!("ime load region meet pending region with stale epoch, removed"; "region" => ?region, "stale_regions" => ?removed_regions); } for id in removed_regions { @@ -613,7 +615,7 @@ impl RegionManager { evict_reason: EvictReason, ) -> Vec { info!( - "try to evict region"; + "ime try to evict region"; "evict_region" => ?evict_region, "reason" => ?evict_reason, ); @@ -640,8 +642,8 @@ impl RegionManager { true }); if evict_ids.is_empty() { - info!("evict a region that is not cached"; - "reason" => ?evict_reason, + info!("ime evict a region that is not cached"; + "reason" => ?evict_reason, "region" => ?evict_region); } for rid in evict_ids { @@ -670,7 +672,7 @@ impl RegionManager { if prev_state == RegionState::Pending { let meta = self.remove_region(id); info!( - "evict overlap pending region in cache range engine"; + "ime evict overlap pending region in cache range engine"; "reason" => ?evict_reason, "target_region" => ?evict_region, "overlap_region" => ?meta.region, @@ -678,7 +680,8 @@ impl RegionManager { ); return None; } else if prev_state.is_evict() { - info!("region already evicted"; "region" => ?meta.region, "state" => ?prev_state); + info!("ime region already evicted"; + "region" => ?meta.region, "state" => ?prev_state); return None; } @@ -689,7 +692,7 @@ impl RegionManager { }; info!( - "evict overlap region in cache range engine"; + "ime evict overlap region in cache range engine"; "reason" => ?evict_reason, "target_region" => ?evict_region, "overlap_region" => ?meta.region, @@ -726,7 +729,7 @@ impl RegionManager { evict_info.reason, ); info!( - "range eviction done"; + "ime range eviction done"; "region" => ?r, ); } @@ -793,11 +796,12 @@ impl RegionManager { if let Some(region_meta) = self.region_meta(source_region.id) { // if region is evicting, skip handling split for simplicity. if region_meta.state.is_evict() { - info!("region is evicted, skip split"; "meta" => ?®ion_meta, "new_regions" => ?new_regions); + info!("ime region is evicted, skip split"; + "meta" => ?®ion_meta, "new_regions" => ?new_regions); return; } } else { - info!("split source region not cached"; "region_id" => source_region.id); + info!("ime split source region not cached"; "region_id" => source_region.id); return; } @@ -817,15 +821,15 @@ impl RegionManager { && (source_region.end_key.is_empty() || (source_region.end_key >= r.end_key && !r.end_key.as_slice().is_empty())) }); - info!("[IME] handle split region met pending region epoch stale"; - "cached" => ?region_meta, - "split_source" => ?source_region, + info!("ime handle split region met pending region epoch stale"; + "cached" => ?region_meta, + "split_source" => ?source_region, "cache_new_regions" => ?new_regions); } - info!("handle region split"; - "region_id" => source_region.id, - "meta" => ?region_meta, + info!("ime handle region split"; + "region_id" => source_region.id, + "meta" => ?region_meta, "new_regions" => ?new_regions); for r in new_regions { diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 88370596d7b..2de4bc5d2a0 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -151,7 +151,7 @@ impl RangeStatsManager { let curr_num_regions = self.max_num_regions(); let next_num_regions = curr_num_regions + room_to_grow / (self.expected_region_size * 3); - info!("increasing number of top regions to cache"; + info!("ime increasing number of top regions to cache"; "from" => curr_num_regions, "to" => next_num_regions, ); @@ -165,7 +165,7 @@ impl RangeStatsManager { .checked_sub(1.max(to_shrink_by / self.expected_region_size)) .unwrap_or(1) .max(1); - info!("decreasing number of top regions to cache"; + info!("ime decreasing number of top regions to cache"; "from" => curr_num_regions, "to" => next_num_regions, ); @@ -199,7 +199,7 @@ impl RangeStatsManager { regions_added_out: &mut Vec, regions_removed_out: &mut Vec, ) { - info!("collect_changed_ranges"; "num_regions" => self.max_num_regions()); + info!("ime collect_changed_ranges"; "num_regions" => self.max_num_regions()); let curr_top_regions = self .info_provider .get_top_regions(Some(NonZeroUsize::try_from(self.max_num_regions()).unwrap())) diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index 516ff312998..f763c0dfb19 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -117,7 +117,7 @@ impl Drop for RangeCacheSnapshot { .schedule_task(BackgroundTask::DeleteRegions(regions_removable)) { error!( - "schedule delete range failed"; + "ime schedule delete range failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); diff --git a/components/range_cache_memory_engine/src/region_label.rs b/components/range_cache_memory_engine/src/region_label.rs index 1a1e34e8fa7..36cf716ead3 100644 --- a/components/range_cache_memory_engine/src/region_label.rs +++ b/components/range_cache_memory_engine/src/region_label.rs @@ -76,7 +76,8 @@ impl RegionLabelRulesManager { match old_value.as_ref() { // If a watch fires twice on an identical label rule, ignore the second invocation. Some(old_value) if old_value == label_rule => { - info!("Identical region label rule added twice; ignoring."; "rule_id" => &label_rule.id) + info!("ime identical region label rule added twice; ignoring."; + "rule_id" => &label_rule.id) } _ => cb(label_rule), } @@ -205,7 +206,8 @@ impl RegionLabelService { .with_prev_kv(), ), ); - info!("pd meta client creating watch stream"; "path" => region_label_path, "rev" => %self.revision); + info!("ime pd meta client creating watch stream"; + "path" => region_label_path, "rev" => %self.revision); while let Some(grpc_response) = stream.next().await { match grpc_response { Ok(resp) => { @@ -217,7 +219,7 @@ impl RegionLabelService { event.get_kv().get_value(), ) { Ok(label_rule) => self.on_label_rule(&label_rule), - Err(e) => error!("parse put region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), + Err(e) => error!("ime parse put region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), } } EventEventType::Delete => { @@ -225,19 +227,19 @@ impl RegionLabelService { event.get_prev_kv().get_value() ) { Ok(label_rule) => self.manager.remove_region_label(&label_rule.id), - Err(e) => error!("parse delete region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), + Err(e) => error!("ime parse delete region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), } } }); } Err(PdError::DataCompacted(msg)) => { - error!("required revision has been compacted"; "err" => ?msg); + error!("ime required revision has been compacted"; "err" => ?msg); self.reload_all_region_labels().await; cancel.abort(); continue 'outer; } Err(err) => { - error!("failed to watch region labels"; "err" => ?err); + error!("ime failed to watch region labels"; "err" => ?err); let _ = GLOBAL_TIMER_HANDLE .delay(std::time::Instant::now() + RETRY_INTERVAL) .compat() @@ -264,14 +266,14 @@ impl RegionLabelService { Ok(label_rule) => self.on_label_rule(&label_rule), Err(e) => { - error!("parse label rule failed"; "name" => ?g.get_key(), "err" => ?e); + error!("ime parse label rule failed"; "name" => ?g.get_key(), "err" => ?e); } } } return; } Err(err) => { - error!("failed to get meta storage's region label rules"; "err" => ?err); + error!("ime failed to get meta storage's region label rules"; "err" => ?err); let _ = GLOBAL_TIMER_HANDLE .delay(std::time::Instant::now() + RETRY_INTERVAL) .compat() diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index b654b5313d6..8db3081d5d5 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -150,7 +150,7 @@ impl RangeCacheWriteBatch { .schedule_task(BackgroundTask::CleanLockTombstone(snapshot_seqno)) { error!( - "schedule lock tombstone cleanup failed"; + "ime schedule lock tombstone cleanup failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -250,7 +250,7 @@ impl RangeCacheWriteBatch { if !self.engine.enabled() { let region = self.current_region.as_ref().unwrap(); info!( - "range cache is disabled, evict the range"; + "ime range cache is disabled, evict the range"; "range_start" => log_wrappers::Value(®ion.start_key), "range_end" => log_wrappers::Value(®ion.end_key), ); @@ -261,7 +261,7 @@ impl RangeCacheWriteBatch { if !self.memory_acquire(memory_expect) { let region = self.current_region.as_ref().unwrap(); info!( - "memory acquire failed due to reaching hard limit"; + "ime memory acquire failed due to reaching hard limit"; "range_start" => log_wrappers::Value(®ion.start_key), "range_end" => log_wrappers::Value(®ion.end_key), ); @@ -283,7 +283,7 @@ impl RangeCacheWriteBatch { .schedule_task(BackgroundTask::MemoryCheckAndEvict) { error!( - "schedule memory check failed"; + "ime schedule memory check failed"; "err" => ?e, ); assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); @@ -298,7 +298,7 @@ impl RangeCacheWriteBatch { MemoryUsage::HardLimitReached(n) => { self.memory_usage_reach_hard_limit = true; warn!( - "the memory usage of in-memory engine reaches to hard limit"; + "ime the memory usage of in-memory engine reaches to hard limit"; "region" => ?self.current_region.as_ref().unwrap(), "memory_usage(MB)" => ReadableSize(n as u64).as_mb_f64(), ); From 04992724fcf81344919882b87fe6a02ee48b8c64 Mon Sep 17 00:00:00 2001 From: hhwyt Date: Fri, 23 Aug 2024 10:18:14 +0800 Subject: [PATCH 037/144] encryption: fix unexpected error code for wrong master-key(tikv#17410) (#17413) close tikv/tikv#17410 This PR fixes a bug encountered in the GCP KMS master-key rotation scenario. When decryption fails using the current master-key, the `KsmBackend` is expected to return a `WrongMasterKey` error rather than any other error type. The higher-level caller will only retry with the previous master-key if a `WrongMasterKey` error is received. Signed-off-by: hhwyt Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/encryption/src/master_key/kms.rs | 85 ++++++++++++++++----- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/components/encryption/src/master_key/kms.rs b/components/encryption/src/master_key/kms.rs index db3c62194fd..7c3f56ca0cd 100644 --- a/components/encryption/src/master_key/kms.rs +++ b/components/encryption/src/master_key/kms.rs @@ -141,7 +141,11 @@ impl KmsBackend { self.kms_provider.decrypt_data_key(&ciphertext_key), ) })) - .map_err(cloud_convert_error("decrypt encrypted key failed".into()))?; + .map_err(|e| { + Error::WrongMasterKey(box_err!(cloud_convert_error( + "decrypt encrypted key failed".into(), + )(e))) + })?; let data_key = DataKeyPair { encrypted: ciphertext_key, plaintext: PlainKey::new(plaintext, CryptographyType::AesGcm256) @@ -154,6 +158,12 @@ impl KmsBackend { } } } + + #[cfg(test)] + fn clear_state(&mut self) { + let mut opt_state = self.state.lock().unwrap(); + *opt_state = None; + } } impl Backend for KmsBackend { @@ -173,7 +183,10 @@ impl Backend for KmsBackend { #[cfg(test)] mod fake { use async_trait::async_trait; - use cloud::{error::Result, kms::KmsProvider}; + use cloud::{ + error::{Error as CloudError, KmsError, Result}, + kms::KmsProvider, + }; use super::*; @@ -183,12 +196,14 @@ mod fake { #[derive(Debug)] pub struct FakeKms { plaintext_key: PlainKey, + should_decrypt_data_key_fail: bool, } impl FakeKms { - pub fn new(plaintext_key: Vec) -> Self { + pub fn new(plaintext_key: Vec, should_decrypt_data_key_fail: bool) -> Self { Self { plaintext_key: PlainKey::new(plaintext_key, CryptographyType::AesGcm256).unwrap(), + should_decrypt_data_key_fail, } } } @@ -204,7 +219,13 @@ mod fake { } async fn decrypt_data_key(&self, _ciphertext: &EncryptedKey) -> Result> { - Ok(vec![1u8, 32]) + if self.should_decrypt_data_key_fail { + Err(CloudError::KmsError(KmsError::WrongMasterKey(box_err!( + "wrong master key" + )))) + } else { + Ok(vec![1u8, 32]) + } } fn name(&self) -> &str { @@ -241,21 +262,36 @@ mod tests { assert_eq!(state2.cached(&encrypted2), true); } + const PLAIN_TEXT_HEX: &str = "25431587e9ecffc7c37f8d6d52a9bc3310651d46fb0e3bad2726c8f2db653749"; + const CIPHER_TEXT_HEX: &str = + "84e5f23f95648fa247cb28eef53abec947dbf05ac953734618111583840bd980"; + const PLAINKEY_HEX: &str = "c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139"; + const IV_HEX: &str = "cafabd9672ca6c79a2fbdc22"; + + #[cfg(test)] + fn prepare_data_for_encrypt() -> (Iv, Vec, Vec, Vec) { + let iv = Vec::from_hex(IV_HEX).unwrap(); + let iv = Iv::from_slice(iv.as_slice()).unwrap(); + let pt = Vec::from_hex(PLAIN_TEXT_HEX).unwrap(); + let plainkey = Vec::from_hex(PLAINKEY_HEX).unwrap(); + let ct = Vec::from_hex(CIPHER_TEXT_HEX).unwrap(); + (iv, pt, plainkey, ct) + } + + #[cfg(test)] + fn prepare_kms_backend(plainkey: Vec, should_decrypt_data_key_fail: bool) -> KmsBackend { + KmsBackend::new(Box::new(FakeKms::new( + plainkey, + should_decrypt_data_key_fail, + ))) + .unwrap() + } + #[test] fn test_kms_backend() { - // See more http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip - let pt = Vec::from_hex("25431587e9ecffc7c37f8d6d52a9bc3310651d46fb0e3bad2726c8f2db653749") - .unwrap(); - let ct = Vec::from_hex("84e5f23f95648fa247cb28eef53abec947dbf05ac953734618111583840bd980") - .unwrap(); - let plainkey = - Vec::from_hex("c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139") - .unwrap(); - - let iv = Vec::from_hex("cafabd9672ca6c79a2fbdc22").unwrap(); - - let backend = KmsBackend::new(Box::new(FakeKms::new(plainkey))).unwrap(); - let iv = Iv::from_slice(iv.as_slice()).unwrap(); + let (iv, pt, plainkey, ct) = prepare_data_for_encrypt(); + let backend = prepare_kms_backend(plainkey, false); + let encrypted_content = backend.encrypt_content(&pt, iv).unwrap(); assert_eq!(encrypted_content.get_content(), ct.as_slice()); let plaintext = backend.decrypt_content(&encrypted_content).unwrap(); @@ -293,4 +329,19 @@ mod tests { Error::Other(_) ); } + + #[test] + fn test_kms_backend_wrong_key() { + let (iv, pt, plainkey, ..) = prepare_data_for_encrypt(); + let mut backend = prepare_kms_backend(plainkey, true); + + let encrypted_content = backend.encrypt_content(&pt, iv).unwrap(); + // Clear the cached state to ensure that the subsequent + // backend.decrypt_content() invocation bypasses the cache and triggers the + // mocked FakeKMS::decrypt_data_key() function. + backend.clear_state(); + + let err = backend.decrypt_content(&encrypted_content).unwrap_err(); + assert_matches!(err, Error::WrongMasterKey(_)); + } } From 444270cf9736e7496138605341ac565331727f03 Mon Sep 17 00:00:00 2001 From: glorv Date: Sat, 24 Aug 2024 01:21:14 +0800 Subject: [PATCH 038/144] storage: support online config for flow-control module (#17396) close tikv/tikv#17395 support online config for flow-control module Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- src/storage/config.rs | 4 - src/storage/config_manager.rs | 7 +- src/storage/txn/flow_controller/mod.rs | 9 + .../singleton_flow_controller.rs | 157 ++++++++++++------ .../flow_controller/tablet_flow_controller.rs | 49 +++--- 5 files changed, 140 insertions(+), 86 deletions(-) diff --git a/src/storage/config.rs b/src/storage/config.rs index dae89a20039..a3291d7b3d2 100644 --- a/src/storage/config.rs +++ b/src/storage/config.rs @@ -254,13 +254,9 @@ impl Config { #[serde(rename_all = "kebab-case")] pub struct FlowControlConfig { pub enable: bool, - #[online_config(skip)] pub soft_pending_compaction_bytes_limit: ReadableSize, - #[online_config(skip)] pub hard_pending_compaction_bytes_limit: ReadableSize, - #[online_config(skip)] pub memtables_threshold: u64, - #[online_config(skip)] pub l0_files_threshold: u64, } diff --git a/src/storage/config_manager.rs b/src/storage/config_manager.rs index 4ca38dc7ae4..b36f2f2209f 100644 --- a/src/storage/config_manager.rs +++ b/src/storage/config_manager.rs @@ -67,8 +67,11 @@ impl ConfigManager self.ttl_checker_scheduler .schedule(TtlCheckerTask::UpdatePollInterval(interval.into())) .unwrap(); - } else if let Some(ConfigValue::Module(mut flow_control)) = change.remove("flow_control") { - if let Some(v) = flow_control.remove("enable") { + } else if let Some(ConfigValue::Module(flow_control)) = change.remove("flow_control") { + // we first update the config here then trigger the side-effect of + // `flow-control.enable`. + self.flow_controller.update_config(flow_control.clone())?; + if let Some(v) = flow_control.get("enable") { let enable: bool = v.into(); let enable_str = if enable { "true" } else { "false" }; for cf in ALL_CFS { diff --git a/src/storage/txn/flow_controller/mod.rs b/src/storage/txn/flow_controller/mod.rs index c0faeac6328..59dc1274e09 100644 --- a/src/storage/txn/flow_controller/mod.rs +++ b/src/storage/txn/flow_controller/mod.rs @@ -4,6 +4,7 @@ pub mod tablet_flow_controller; use std::time::Duration; +use online_config::ConfigChange; pub use singleton_flow_controller::EngineFlowController; pub use tablet_flow_controller::TabletFlowController; @@ -48,6 +49,14 @@ impl FlowController { FlowController::Tablet(ref controller) => controller.unconsume(region_id, bytes), } } + + pub fn update_config(&self, change: ConfigChange) -> online_config::Result<()> { + match self { + FlowController::Singleton(ref controller) => controller.update_config(change), + FlowController::Tablet(ref controller) => controller.update_config(change), + } + } + pub fn enable(&self, enable: bool) { match self { FlowController::Singleton(ref controller) => controller.enable(enable), diff --git a/src/storage/txn/flow_controller/singleton_flow_controller.rs b/src/storage/txn/flow_controller/singleton_flow_controller.rs index e7b4f109570..61c05fbd8a2 100644 --- a/src/storage/txn/flow_controller/singleton_flow_controller.rs +++ b/src/storage/txn/flow_controller/singleton_flow_controller.rs @@ -6,7 +6,7 @@ use std::{ collections::VecDeque, ops::{Add, AddAssign, Sub, SubAssign}, sync::{ - atomic::{AtomicBool, AtomicU32, Ordering}, + atomic::{AtomicU32, Ordering}, mpsc::{self, Receiver, RecvTimeoutError, SyncSender}, Arc, }, @@ -20,8 +20,10 @@ use engine_rocks::FlowInfo; use engine_traits::{CfNamesExt, FlowControlFactorsExt}; use getset::{CopyGetters, Setters}; use num_traits::cast::{AsPrimitive, FromPrimitive}; +use online_config::{ConfigChange, OnlineConfig}; use rand::Rng; use tikv_util::{ + config::VersionTrack, sys::thread::StdThreadBuildWrapper, time::{Instant, Limiter}, }; @@ -74,9 +76,9 @@ enum Trend { pub struct EngineFlowController { discard_ratio: Arc, limiter: Arc, - enabled: Arc, tx: Option>, handle: Option>, + config_tracker: Arc>, } pub(super) enum Msg { @@ -109,9 +111,9 @@ impl EngineFlowController { Self { discard_ratio: Arc::new(AtomicU32::new(0)), limiter: Arc::new(Limiter::new(f64::INFINITY)), - enabled: Arc::new(AtomicBool::new(false)), tx: None, handle: None, + config_tracker: Arc::new(VersionTrack::default()), } } @@ -126,22 +128,21 @@ impl EngineFlowController { .build(), ); let discard_ratio = Arc::new(AtomicU32::new(0)); - let checker = FlowChecker::new(config, engine, discard_ratio.clone(), limiter.clone()); + let config_tracker = Arc::new(VersionTrack::new(config.clone())); + let checker = FlowChecker::new( + config_tracker.clone(), + engine, + discard_ratio.clone(), + limiter.clone(), + ); let (tx, rx) = mpsc::sync_channel(5); - tx.send(if config.enable { - Msg::Enable - } else { - Msg::Disable - }) - .unwrap(); - Self { discard_ratio, limiter, - enabled: Arc::new(AtomicBool::new(config.enable)), tx: Some(tx), handle: Some(checker.start(rx, flow_info_receiver)), + config_tracker, } } } @@ -172,7 +173,6 @@ impl EngineFlowController { } pub fn enable(&self, enable: bool) { - self.enabled.store(enable, Ordering::Relaxed); if let Some(tx) = &self.tx { if enable { tx.send(Msg::Enable).unwrap(); @@ -183,7 +183,11 @@ impl EngineFlowController { } pub fn enabled(&self) -> bool { - self.enabled.load(Ordering::Relaxed) + self.config_tracker.value().enable + } + + pub fn update_config(&self, config_change: ConfigChange) -> online_config::Result<()> { + self.config_tracker.update(|cfg| cfg.update(config_change)) } #[cfg(test)] @@ -489,10 +493,7 @@ impl FlowControlFactorStore for E { #[derive(CopyGetters, Setters)] pub(super) struct FlowChecker { - pub soft_pending_compaction_bytes_limit: u64, - hard_pending_compaction_bytes_limit: u64, - memtables_threshold: u64, - l0_files_threshold: u64, + config_tracker: Arc>, // CfFlowChecker for each CF. cf_checkers: HashMap, @@ -520,7 +521,7 @@ pub(super) struct FlowChecker { impl FlowChecker { pub fn new( - config: &FlowControlConfig, + config: Arc>, engine: E, discard_ratio: Arc, limiter: Arc, @@ -530,7 +531,7 @@ impl FlowChecker { pub fn new_with_region_id( region_id: u64, - config: &FlowControlConfig, + config_tracker: Arc>, engine: E, discard_ratio: Arc, limiter: Arc, @@ -544,10 +545,7 @@ impl FlowChecker { Self { region_id, - soft_pending_compaction_bytes_limit: config.soft_pending_compaction_bytes_limit.0, - hard_pending_compaction_bytes_limit: config.hard_pending_compaction_bytes_limit.0, - memtables_threshold: config.memtables_threshold, - l0_files_threshold: config.l0_files_threshold, + config_tracker, engine, discard_ratio, limiter, @@ -561,15 +559,12 @@ impl FlowChecker { } } - pub fn on_flow_info_msg( - &mut self, - enabled: bool, - flow_info: Result, - ) { + pub fn on_flow_info_msg(&mut self, flow_info: Result) { + let current_cfg = self.config_tracker.value().clone(); match flow_info { Ok(FlowInfo::L0(cf, l0_bytes, ..)) => { self.collect_l0_consumption_stats(&cf, l0_bytes); - if enabled { + if current_cfg.enable { self.on_l0_change(cf) } } @@ -577,29 +572,29 @@ impl FlowChecker { if diff_bytes > 0 { // Intra L0 merges some deletion records, so regard it as a L0 compaction. self.collect_l0_consumption_stats(&cf, diff_bytes); - if enabled { + if current_cfg.enable { self.on_l0_change(cf); } } } Ok(FlowInfo::Flush(cf, flush_bytes, ..)) => { self.collect_l0_production_stats(&cf, flush_bytes); - if enabled { + if current_cfg.enable { self.on_memtable_change(&cf); self.on_l0_change(cf) } } Ok(FlowInfo::Compaction(cf, ..)) => { - if enabled { + if current_cfg.enable { self.on_pending_compaction_bytes_change(cf); } } Ok(FlowInfo::BeforeUnsafeDestroyRange(..)) => { - if !enabled { + if !current_cfg.enable { return; } self.wait_for_destroy_range_finish = true; - let soft = (self.soft_pending_compaction_bytes_limit as f64).log2(); + let soft = (current_cfg.soft_pending_compaction_bytes_limit.0 as f64).log2(); for cf_checker in self.cf_checkers.values_mut() { if let Some(long_term_pending_bytes) = cf_checker.long_term_pending_bytes.as_ref() @@ -612,13 +607,14 @@ impl FlowChecker { } } Ok(FlowInfo::AfterUnsafeDestroyRange(..)) => { - if !enabled { + if !current_cfg.enable { return; } self.wait_for_destroy_range_finish = false; for (cf, cf_checker) in &mut self.cf_checkers { if let Some(before) = cf_checker.pending_bytes_before_unsafe_destroy_range { - let soft = (self.soft_pending_compaction_bytes_limit as f64).log2(); + let soft = + (current_cfg.soft_pending_compaction_bytes_limit.0 as f64).log2(); let after = (self.engine.pending_compaction_bytes(self.region_id, cf) as f64) .log2(); @@ -649,17 +645,13 @@ impl FlowChecker { .spawn_wrapper(move || { let mut checker = self; let mut deadline = std::time::Instant::now(); - let mut enabled = true; loop { match rx.try_recv() { Ok(Msg::Close) => break, Ok(Msg::Disable) => { - enabled = false; checker.reset_statistics(); } - Ok(Msg::Enable) => { - enabled = true; - } + Ok(Msg::Enable) => {} Err(_) => {} } @@ -672,7 +664,7 @@ impl FlowChecker { SCHED_WRITE_FLOW_GAUGE.set(rate as i64); deadline = std::time::Instant::now() + TICK_DURATION; } else { - checker.on_flow_info_msg(enabled, msg); + checker.on_flow_info_msg(msg); } } }) @@ -745,8 +737,9 @@ impl FlowChecker { pending_compaction_bytes: u64, cf: String, ) { - let hard = (self.hard_pending_compaction_bytes_limit as f64).log2(); - let soft = (self.soft_pending_compaction_bytes_limit as f64).log2(); + let control_cfg = self.config_tracker.value().clone(); + let hard = (control_cfg.hard_pending_compaction_bytes_limit.0 as f64).log2(); + let soft = (control_cfg.soft_pending_compaction_bytes_limit.0 as f64).log2(); // Because pending compaction bytes changes dramatically, take the // logarithm of pending compaction bytes to make the values fall into // a relative small range @@ -828,10 +821,11 @@ impl FlowChecker { let prev = checker.last_num_memtables.get_recent(); checker.last_num_memtables.observe(num_memtables); + let memtables_threshold = self.config_tracker.value().memtables_threshold; // do special check on start, see the comment of the variable definition for // detail. if checker.on_start_memtable { - if num_memtables < self.memtables_threshold + if num_memtables < memtables_threshold || checker.last_num_memtables.trend() == Trend::Increasing { // the write is accumulating, still need to throttle @@ -850,8 +844,7 @@ impl FlowChecker { let checker = self.cf_checkers.get_mut(cf).unwrap(); let is_throttled = self.limiter.speed_limit() != f64::INFINITY; - let should_throttle = - checker.last_num_memtables.get_avg() > self.memtables_threshold as f64; + let should_throttle = checker.last_num_memtables.get_avg() > memtables_threshold as f64; let throttle = if !is_throttled && should_throttle { SCHED_THROTTLE_ACTION_COUNTER .with_label_values(&[cf, "memtable_init"]) @@ -864,7 +857,7 @@ impl FlowChecker { self.throttle_cf = Some(cf.to_string()); x as f64 } - } else if is_throttled && (!should_throttle || num_memtables < self.memtables_threshold) { + } else if is_throttled && (!should_throttle || num_memtables < memtables_threshold) { // should not throttle memtable if checker.memtable_init_speed { checker.memtable_init_speed = false; @@ -958,11 +951,12 @@ impl FlowChecker { fn on_l0_change(&mut self, cf: String) { let checker = self.cf_checkers.get_mut(&cf).unwrap(); let num_l0_files = checker.long_term_num_l0_files.get_recent(); + let l0_files_threshold = self.config_tracker.value().l0_files_threshold; // do special check on start, see the comment of the variable definition for // detail. if checker.on_start_l0_files { - if num_l0_files < self.l0_files_threshold + if num_l0_files < l0_files_threshold || checker.long_term_num_l0_files.trend() == Trend::Increasing { // the write is accumulating, still need to throttle @@ -999,7 +993,7 @@ impl FlowChecker { } let is_throttled = self.limiter.speed_limit() != f64::INFINITY; - let should_throttle = checker.long_term_num_l0_files.get_recent() > self.l0_files_threshold; + let should_throttle = checker.long_term_num_l0_files.get_recent() > l0_files_threshold; let throttle = if !is_throttled && should_throttle { SCHED_THROTTLE_ACTION_COUNTER @@ -1055,6 +1049,7 @@ pub(super) mod tests { use engine_rocks::RocksCfOptions; use engine_traits::{CfOptionsExt, Result}; + use online_config::ConfigValue; use super::{super::FlowController, *}; @@ -1128,10 +1123,16 @@ pub(super) mod tests { assert_eq!(flow_controller.consume(region_id, 1000), Duration::ZERO); // disable flow controller - flow_controller.enable(false); + let change = std::collections::HashMap::from_iter([( + "enable".to_string(), + ConfigValue::Bool(false), + )]); + flow_controller.update_config(change).unwrap(); assert_eq!(flow_controller.enabled(), false); // re-enable flow controller - flow_controller.enable(true); + let change = + std::collections::HashMap::from_iter([("enable".to_string(), ConfigValue::Bool(true))]); + flow_controller.update_config(change).unwrap(); assert_eq!(flow_controller.enabled(), true); assert_eq!(flow_controller.should_drop(region_id), false); assert_eq!(flow_controller.is_unlimited(region_id), true); @@ -1192,6 +1193,26 @@ pub(super) mod tests { assert_eq!(flow_controller.is_unlimited(region_id), false); assert_ne!(flow_controller.consume(region_id, 2000), Duration::ZERO); + // increase the threshold. + let change = std::collections::HashMap::from_iter([( + "memtables_threshold".to_string(), + ConfigValue::U64(10), + )]); + flow_controller.update_config(change).unwrap(); + send_flow_info(tx, region_id); + assert_eq!(flow_controller.should_drop(region_id), false); + assert_eq!(flow_controller.is_unlimited(region_id), true); + + // decrease the threshold. + let change = std::collections::HashMap::from_iter([( + "memtables_threshold".to_string(), + ConfigValue::U64(5), + )]); + flow_controller.update_config(change).unwrap(); + send_flow_info(tx, region_id); + assert_eq!(flow_controller.should_drop(region_id), false); + assert_eq!(flow_controller.is_unlimited(region_id), false); + // not throttle once the number of memtables falls below the threshold stub.0.num_memtables.store(1, Ordering::Relaxed); send_flow_info(tx, region_id); @@ -1239,6 +1260,16 @@ pub(super) mod tests { assert_eq!(flow_controller.should_drop(region_id), false); assert_eq!(flow_controller.is_unlimited(region_id), false); assert_ne!(flow_controller.consume(region_id, 2000), Duration::ZERO); + + // increase the threshold. + let change = std::collections::HashMap::from_iter([( + "l0_files_threshold".to_string(), + ConfigValue::U64(50), + )]); + flow_controller.update_config(change).unwrap(); + send_flow_info(tx, region_id); + assert_eq!(flow_controller.should_drop(region_id), false); + assert_eq!(flow_controller.is_unlimited(region_id), true); } #[test] @@ -1260,7 +1291,7 @@ pub(super) mod tests { // exceeds the threshold stub.0 .pending_compaction_bytes - .store(1000 * 1024 * 1024 * 1024, Ordering::Relaxed); + .store(500 * 1024 * 1024 * 1024, Ordering::Relaxed); send_flow_info(tx, region_id); // on start check forbids flow control assert!(flow_controller.discard_ratio(region_id) < f64::EPSILON); @@ -1272,10 +1303,26 @@ pub(super) mod tests { stub.0 .pending_compaction_bytes - .store(1000 * 1024 * 1024 * 1024, Ordering::Relaxed); + .store(500 * 1024 * 1024 * 1024, Ordering::Relaxed); send_flow_info(tx, region_id); assert!(flow_controller.discard_ratio(region_id) > f64::EPSILON); + // increase the threshold. + let change = std::collections::HashMap::from_iter([( + "soft_pending_compaction_bytes_limit".to_string(), + ConfigValue::Size(600 * 1024 * 1024 * 1024), + )]); + flow_controller.update_config(change).unwrap(); + send_flow_info(tx, region_id); + assert!(flow_controller.discard_ratio(region_id) < f64::EPSILON); + + // reset to default value. + let change = std::collections::HashMap::from_iter([( + "soft_pending_compaction_bytes_limit".to_string(), + ConfigValue::Size(192 * 1024 * 1024 * 1024), + )]); + flow_controller.update_config(change).unwrap(); + stub.0 .pending_compaction_bytes .store(1024 * 1024 * 1024, Ordering::Relaxed); diff --git a/src/storage/txn/flow_controller/tablet_flow_controller.rs b/src/storage/txn/flow_controller/tablet_flow_controller.rs index eee28997332..ee6fdb02bbc 100644 --- a/src/storage/txn/flow_controller/tablet_flow_controller.rs +++ b/src/storage/txn/flow_controller/tablet_flow_controller.rs @@ -3,7 +3,7 @@ // #[PerformanceCriticalPath] use std::{ sync::{ - atomic::{AtomicBool, AtomicU32, Ordering}, + atomic::{AtomicU32, Ordering}, mpsc::{self, Receiver, RecvTimeoutError, SyncSender}, Arc, RwLock, }, @@ -14,8 +14,9 @@ use std::{ use collections::{HashMap, HashMapEntry}; use engine_rocks::FlowInfo; use engine_traits::{CfNamesExt, FlowControlFactorsExt, TabletRegistry, DATA_CFS}; +use online_config::{ConfigChange, OnlineConfig}; use rand::Rng; -use tikv_util::{sys::thread::StdThreadBuildWrapper, time::Limiter}; +use tikv_util::{config::VersionTrack, sys::thread::StdThreadBuildWrapper, time::Limiter}; use super::singleton_flow_controller::{ FlowChecker, FlowControlFactorStore, Msg, RATIO_SCALE_FACTOR, TICK_DURATION, @@ -61,11 +62,11 @@ impl FlowControlFactorStore type Limiters = Arc, Arc)>>>; pub struct TabletFlowController { - enabled: Arc, tx: Option>, handle: Option>, limiters: Limiters, global_discard_ratio: Arc, + config_tracker: Arc>, } impl Drop for TabletFlowController { @@ -93,17 +94,11 @@ impl TabletFlowController { flow_info_receiver: Receiver, ) -> Self { let (tx, rx) = mpsc::sync_channel(5); - tx.send(if config.enable { - Msg::Enable - } else { - Msg::Disable - }) - .unwrap(); + let config_tracker = Arc::new(VersionTrack::new(config.clone())); let flow_checkers = Arc::new(RwLock::new(HashMap::default())); let limiters: Limiters = Arc::new(RwLock::new(HashMap::default())); let global_discard_ratio = Arc::new(AtomicU32::new(0)); Self { - enabled: Arc::new(AtomicBool::new(config.enable)), tx: Some(tx), limiters: limiters.clone(), handle: Some(FlowInfoDispatcher::start( @@ -112,10 +107,11 @@ impl TabletFlowController { registry, flow_checkers, limiters, - config.clone(), + config_tracker.clone(), global_discard_ratio.clone(), )), global_discard_ratio, + config_tracker, } } @@ -134,14 +130,13 @@ impl FlowInfoDispatcher { registry: TabletRegistry, flow_checkers: Arc>>>>, limiters: Limiters, - config: FlowControlConfig, + config: Arc>, global_discard_ratio: Arc, ) -> JoinHandle<()> { Builder::new() .name(thd_name!("flow-checker")) .spawn_wrapper(move || { let mut deadline = std::time::Instant::now(); - let mut enabled = config.enable; let engine = TabletFlowFactorStore::new(registry.clone()); let mut pending_compaction_checker = CompactionPendingBytesChecker::new( config.clone(), @@ -152,15 +147,12 @@ impl FlowInfoDispatcher { match rx.try_recv() { Ok(Msg::Close) => break, Ok(Msg::Disable) => { - enabled = false; let mut checkers = flow_checkers.as_ref().write().unwrap(); for checker in (*checkers).values_mut() { checker.reset_statistics(); } } - Ok(Msg::Enable) => { - enabled = true; - } + Ok(Msg::Enable) => {} Err(_) => {} } @@ -171,11 +163,11 @@ impl FlowInfoDispatcher { | Ok(FlowInfo::Flush(_cf, _, region_id)) => { let mut checkers = flow_checkers.as_ref().write().unwrap(); if let Some(checker) = checkers.get_mut(®ion_id) { - checker.on_flow_info_msg(enabled, msg); + checker.on_flow_info_msg(msg); } } Ok(FlowInfo::Compaction(cf, region_id)) => { - if !enabled { + if !config.value().enable { continue; } let mut checkers = flow_checkers.as_ref().write().unwrap(); @@ -194,7 +186,7 @@ impl FlowInfoDispatcher { | Ok(FlowInfo::AfterUnsafeDestroyRange(region_id)) => { let mut checkers = flow_checkers.as_ref().write().unwrap(); if let Some(checker) = checkers.get_mut(®ion_id) { - checker.on_flow_info_msg(enabled, msg); + checker.on_flow_info_msg(msg); } } Ok(FlowInfo::Created(region_id)) => { @@ -225,7 +217,7 @@ impl FlowInfoDispatcher { ); e.insert(FlowChecker::new_with_region_id( region_id, - &config, + config.clone(), engine, limiter.1.clone(), limiter.0.clone(), @@ -340,8 +332,11 @@ impl TabletFlowController { 0 } + pub fn update_config(&self, config_change: ConfigChange) -> online_config::Result<()> { + self.config_tracker.update(|cfg| cfg.update(config_change)) + } + pub fn enable(&self, enable: bool) { - self.enabled.store(enable, Ordering::Relaxed); if let Some(tx) = &self.tx { if enable { tx.send(Msg::Enable).unwrap(); @@ -352,7 +347,7 @@ impl TabletFlowController { } pub fn enabled(&self) -> bool { - self.enabled.load(Ordering::Relaxed) + self.config_tracker.value().enable } #[cfg(test)] @@ -378,12 +373,16 @@ struct CompactionPendingBytesChecker } impl CompactionPendingBytesChecker { - pub fn new(config: FlowControlConfig, discard_ratio: Arc, engine: E) -> Self { + pub fn new( + config: Arc>, + discard_ratio: Arc, + engine: E, + ) -> Self { CompactionPendingBytesChecker { pending_compaction_bytes: HashMap::default(), checker: FlowChecker::new_with_region_id( 0, // global checker - &config, + config, engine, discard_ratio, Arc::new( From 6fac4c33adce1767550a63f7c41eee332588c23a Mon Sep 17 00:00:00 2001 From: wuhuizuo Date: Mon, 26 Aug 2024 14:21:15 +0800 Subject: [PATCH 039/144] chore: update OWNERS_ALIASES (#17400) Signed-off-by: wuhuizuo Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- OWNERS_ALIASES | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index cd4a74373a9..aa71e7f7ac8 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -2,13 +2,12 @@ aliases: sig-critical-approvers-config-components: - easonn7 - - kevin-xianliu - zhangjinpeng87 sig-critical-approvers-config-src: - easonn7 - - kevin-xianliu - cfzjywxk - zhangjinpeng87 sig-critical-approvers-config-cdc: - BenMeadowcroft - - kevin-xianliu + - flowbehappy + - yudongusa From ec0216f16deddcb77aa36415e1920f46475f4e91 Mon Sep 17 00:00:00 2001 From: Shirly Date: Mon, 26 Aug 2024 16:57:15 +0800 Subject: [PATCH 040/144] compaction-filter: consider mvcc-delete as redundant key to trigger rocksdb compaction (#17431) close tikv/tikv#17269 compaction-filter: consider mvcc.delete as redundant key to trigger Rocksdb compaction Signed-off-by: Shirly --- components/engine_rocks/src/properties.rs | 1 + components/engine_traits/src/misc.rs | 15 ++++++++++++++- components/raftstore/src/store/worker/compact.rs | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/components/engine_rocks/src/properties.rs b/components/engine_rocks/src/properties.rs index b9032e53f8f..01ca0447a06 100644 --- a/components/engine_rocks/src/properties.rs +++ b/components/engine_rocks/src/properties.rs @@ -567,6 +567,7 @@ pub fn get_range_stats( num_entries, num_versions: props.num_versions, num_rows: props.num_rows, + num_deletes: props.num_deletes, }) } diff --git a/components/engine_traits/src/misc.rs b/components/engine_traits/src/misc.rs index fe5a3c0f696..5e1b1347751 100644 --- a/components/engine_traits/src/misc.rs +++ b/components/engine_traits/src/misc.rs @@ -57,12 +57,25 @@ pub trait StatisticsReporter { #[derive(Default)] pub struct RangeStats { - // The number of entries + // The number of entries in write cf. pub num_entries: u64, // The number of MVCC versions of all rows (num_entries - tombstones). pub num_versions: u64, // The number of rows. pub num_rows: u64, + // The number of MVCC deletes of all rows. + pub num_deletes: u64, +} + +impl RangeStats { + /// The number of redundant keys in the range. + /// It's calculated by `num_entries - num_versions + num_deleted`. + pub fn redundant_keys(&self) -> u64 { + // Consider the number of `mvcc_deletes` as the number of redundant keys. + self.num_entries + .saturating_sub(self.num_rows) + .saturating_add(self.num_deletes) + } } pub trait MiscExt: CfNamesExt + FlowControlFactorsExt + WriteBatchExt { diff --git a/components/raftstore/src/store/worker/compact.rs b/components/raftstore/src/store/worker/compact.rs index 4dfe180ceb8..0c1fc74ddab 100644 --- a/components/raftstore/src/store/worker/compact.rs +++ b/components/raftstore/src/store/worker/compact.rs @@ -445,7 +445,7 @@ pub fn need_compact(range_stats: &RangeStats, compact_threshold: &CompactThresho // We trigger region compaction when their are to many tombstones as well as // redundant keys, both of which can severly impact scan operation: let estimate_num_del = range_stats.num_entries - range_stats.num_versions; - let redundant_keys = range_stats.num_entries - range_stats.num_rows; + let redundant_keys = range_stats.redundant_keys(); (redundant_keys >= compact_threshold.redundant_rows_threshold && redundant_keys * 100 >= compact_threshold.redundant_rows_percent_threshold * range_stats.num_entries) From 888d407dbef89994a763000c57346249e8a8c729 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:07:45 +0800 Subject: [PATCH 041/144] In-memory engine: collect cop detail and use it to determine top regions (#17423) ref tikv/tikv#16141 collect cop detail and use it to determine top regions Signed-off-by: SpadeA-Tang --- components/backup/src/endpoint.rs | 7 +- components/pd_client/src/lib.rs | 38 ++++++ .../raftstore-v2/src/worker/pd/region.rs | 5 +- .../src/coprocessor/region_info_accessor.rs | 110 ++++++++++++++++-- components/raftstore/src/store/worker/pd.rs | 12 +- .../src/store/worker/split_controller.rs | 6 +- .../range_cache_memory_engine/src/engine.rs | 2 + .../range_cache_memory_engine/src/lib.rs | 5 + .../src/memory_controller.rs | 1 + components/server/src/server.rs | 1 + components/server/src/server2.rs | 4 + components/test_raftstore-v2/src/server.rs | 1 + components/test_raftstore/src/server.rs | 7 +- src/coprocessor/metrics.rs | 7 +- src/server/gc_worker/gc_worker.rs | 8 +- src/storage/metrics.rs | 7 +- tests/failpoints/cases/test_gc_metrics.rs | 4 +- .../raftstore/test_region_info_accessor.rs | 2 +- .../storage/test_region_info_accessor.rs | 32 +++-- 19 files changed, 222 insertions(+), 37 deletions(-) diff --git a/components/backup/src/endpoint.rs b/components/backup/src/endpoint.rs index 96a9216292b..c1a7189afb3 100644 --- a/components/backup/src/endpoint.rs +++ b/components/backup/src/endpoint.rs @@ -1348,9 +1348,10 @@ pub mod tests { impl MockRegionInfoProvider { pub fn new(encode_key: bool) -> Self { MockRegionInfoProvider { - regions: Arc::new(Mutex::new(RegionCollector::new(Arc::new(RwLock::new( - HashSet::default(), - ))))), + regions: Arc::new(Mutex::new(RegionCollector::new( + Arc::new(RwLock::new(HashSet::default())), + 0, + ))), cancel: None, need_encode_key: encode_key, } diff --git a/components/pd_client/src/lib.rs b/components/pd_client/src/lib.rs index 76bb8c77216..1b19a6322bd 100644 --- a/components/pd_client/src/lib.rs +++ b/components/pd_client/src/lib.rs @@ -52,6 +52,9 @@ pub struct RegionStat { pub read_bytes: u64, pub read_keys: u64, pub query_stats: QueryStats, + // Now, this info is not sent to PD (maybe in the future). It is needed here to make it + // collected by region collector. + pub cop_detail: RegionWriteCfCopDetail, pub approximate_size: u64, pub approximate_keys: u64, pub last_report_ts: UnixSecs, @@ -564,3 +567,38 @@ fn check_update_service_safe_point_resp( } Ok(()) } + +// Record the coprocessor details for region level. +#[derive(Clone, Debug, Default)] +pub struct RegionWriteCfCopDetail { + // How many times the `next` is called when handling cop request + pub next: usize, + // How many times the `prev` is called when handling cop request + pub prev: usize, + // How many keys that's visible to user + pub processed_keys: usize, +} + +impl RegionWriteCfCopDetail { + pub fn new(next: usize, prev: usize, processed_keys: usize) -> Self { + Self { + next, + prev, + processed_keys, + } + } + + pub fn add(&mut self, other: &RegionWriteCfCopDetail) { + self.next += other.next; + self.prev += other.prev; + self.processed_keys += other.processed_keys; + } + + pub fn sub(&self, other: &RegionWriteCfCopDetail) -> Self { + Self::new( + self.next - other.next, + self.prev - other.prev, + self.processed_keys - other.processed_keys, + ) + } +} diff --git a/components/raftstore-v2/src/worker/pd/region.rs b/components/raftstore-v2/src/worker/pd/region.rs index 7e74405dced..be207e1ab16 100644 --- a/components/raftstore-v2/src/worker/pd/region.rs +++ b/components/raftstore-v2/src/worker/pd/region.rs @@ -5,7 +5,9 @@ use std::{sync::Arc, time::Duration}; use collections::HashMap; use engine_traits::{KvEngine, RaftEngine}; use kvproto::{metapb, pdpb}; -use pd_client::{metrics::PD_HEARTBEAT_COUNTER_VEC, BucketStat, PdClient, RegionStat}; +use pd_client::{ + metrics::PD_HEARTBEAT_COUNTER_VEC, BucketStat, PdClient, RegionStat, RegionWriteCfCopDetail, +}; use raftstore::store::{ReadStats, WriteStats}; use resource_metering::RawRecords; use slog::{debug, error, info}; @@ -160,6 +162,7 @@ where read_bytes: read_bytes_delta, read_keys: read_keys_delta, query_stats: query_stats.0, + cop_detail: RegionWriteCfCopDetail::default(), approximate_size, approximate_keys, last_report_ts, diff --git a/components/raftstore/src/coprocessor/region_info_accessor.rs b/components/raftstore/src/coprocessor/region_info_accessor.rs index 60d1239f453..3cc60c04d1a 100644 --- a/components/raftstore/src/coprocessor/region_info_accessor.rs +++ b/components/raftstore/src/coprocessor/region_info_accessor.rs @@ -297,15 +297,21 @@ pub struct RegionCollector { // together in a struct exposing add, delete, and get_top_regions methods. region_activity: RegionActivityMap, region_leaders: Arc>>, + // It is calculated as '(next + prev) / processed_keys' + mvcc_amplification_threshold: usize, } impl RegionCollector { - pub fn new(region_leaders: Arc>>) -> Self { + pub fn new( + region_leaders: Arc>>, + mvcc_amplification_threshold: usize, + ) -> Self { Self { region_leaders, regions: HashMap::default(), region_activity: HashMap::default(), region_ranges: BTreeMap::default(), + mvcc_amplification_threshold, } } @@ -569,7 +575,7 @@ impl RegionCollector { /// /// Otherwise, return the top `count` regions for which this node is the /// leader from `self.region_activity`. Top regions are determined by - /// comparing `read_keys` in each region's most recent + /// comparing `next + prev` in each region's most recent /// region stat. /// /// Note: this function is `O(N log(N))` with respect to size of @@ -578,11 +584,15 @@ impl RegionCollector { /// approximately `300_000``. pub fn handle_get_top_regions(&mut self, count: usize, callback: Callback) { let compare_fn = |a: &RegionActivity, b: &RegionActivity| { - let a = a.region_stat.read_keys; - let b = b.region_stat.read_keys; + let a = a.region_stat.cop_detail.next + a.region_stat.cop_detail.prev; + let b = b.region_stat.cop_detail.next + b.region_stat.cop_detail.prev; b.cmp(&a) }; - let top_regions = if count == 0 { + + // Only used to log. + let mut max_qps = 0; + let mut max_next_prev = 0; + let mut top_regions = if count == 0 { self.regions .values() .map(|ri| { @@ -600,8 +610,15 @@ impl RegionCollector { .map(|(r, ra)| { ( r, - ra.map(|ra| ra.region_stat.approximate_size) - .unwrap_or_default(), + ra.map(|ra| { + max_qps = u64::max(ra.region_stat.query_stats.coprocessor, max_qps); + max_next_prev = usize::max( + ra.region_stat.cop_detail.prev + ra.region_stat.cop_detail.next, + max_next_prev, + ); + ra.region_stat.clone() + }) + .unwrap_or_default(), ) }) .collect::>() @@ -610,6 +627,11 @@ impl RegionCollector { self.region_activity .iter() .filter_map(|(id, ac)| { + max_qps = u64::max(ac.region_stat.query_stats.coprocessor, max_qps); + max_next_prev = usize::max( + ac.region_stat.cop_detail.prev + ac.region_stat.cop_detail.next, + max_next_prev, + ); self.regions .get(id) .filter(|ri| ri.role == StateRole::Leader) @@ -617,10 +639,70 @@ impl RegionCollector { }) .sorted_by(|(_, activity_0), (_, activity_1)| compare_fn(activity_0, activity_1)) .take(count) - .map(|(ri, ac)| (ri.region.clone(), ac.region_stat.approximate_size)) + .map(|(ri, ac)| (ri.region.clone(), ac.region_stat.clone())) .collect::>() }; - callback(top_regions) + + // TODO(SpadeA): remove it when auto load/evict is stable + { + let debug: Vec<_> = top_regions + .iter() + .map(|(r, s)| { + format!( + "region_id={}, read_keys={}, cop={}, cop_detail={:?}", + r.get_id(), + s.read_keys, + s.query_stats.coprocessor, + s.cop_detail, + ) + }) + .collect_vec(); + + info!( + "ime get top k regions before filter"; + "count" => count, + "max_qps" => max_qps, + "regions" => ?debug, + ); + } + + top_regions.retain(|(_, s)| { + s.cop_detail.next + s.cop_detail.prev >= max_next_prev / 10 + && s.cop_detail.processed_keys != 0 + && (s.cop_detail.next + s.cop_detail.prev) / s.cop_detail.processed_keys + >= self.mvcc_amplification_threshold + }); + + // TODO(SpadeA): remove it when auto load/evict is stable + { + let debug: Vec<_> = top_regions + .iter() + .map(|(r, s)| { + format!( + "region_id={}, read_keys={}, cop={}, cop_detail={:?}", + r.get_id(), + s.read_keys, + s.query_stats.coprocessor, + s.cop_detail, + ) + }) + .collect_vec(); + + info!( + "ime get top k regions after filter"; + "count" => count, + "read_count" => debug.len(), + "max_qps" => max_qps, + "regions" => ?debug, + ); + } + + callback( + top_regions + .into_iter() + .map(|(r, stat)| (r, stat.approximate_size)) + .collect_vec(), + ) } fn handle_raftstore_event(&mut self, event: RaftStoreEvent) { @@ -768,12 +850,13 @@ impl RegionInfoAccessor { pub fn new( host: &mut CoprocessorHost, region_stats_manager_enabled_cb: RegionStatsManagerEnabledCb, + mvcc_amplification_threshold: usize, ) -> Self { let region_leaders = Arc::new(RwLock::new(HashSet::default())); let worker = WorkerBuilder::new("region-collector-worker").create(); let scheduler = worker.start_with_timer( "region-collector-worker", - RegionCollector::new(region_leaders.clone()), + RegionCollector::new(region_leaders.clone(), mvcc_amplification_threshold), ); register_region_event_listener(host, scheduler.clone(), region_stats_manager_enabled_cb); @@ -803,6 +886,11 @@ impl RegionInfoAccessor { .unwrap(); rx.recv().unwrap() } + + #[cfg(any(test, feature = "testexport"))] + pub fn scheduler(&self) -> &Scheduler { + &self.scheduler + } } /// Top regions result: region and its approximate size. @@ -1033,7 +1121,7 @@ mod tests { use super::*; fn new_region_collector() -> RegionCollector { - RegionCollector::new(Arc::new(RwLock::new(HashSet::default()))) + RegionCollector::new(Arc::new(RwLock::new(HashSet::default())), 0) } fn new_region(id: u64, start_key: &[u8], end_key: &[u8], version: u64) -> Region { diff --git a/components/raftstore/src/store/worker/pd.rs b/components/raftstore/src/store/worker/pd.rs index e95ac635ba4..4f4d6b85034 100644 --- a/components/raftstore/src/store/worker/pd.rs +++ b/components/raftstore/src/store/worker/pd.rs @@ -35,7 +35,7 @@ use kvproto::{ raft_serverpb::RaftMessage, replication_modepb::{RegionReplicationStatus, StoreDrAutoSyncStatus}, }; -use pd_client::{metrics::*, BucketStat, Error, PdClient, RegionStat}; +use pd_client::{metrics::*, BucketStat, Error, PdClient, RegionStat, RegionWriteCfCopDetail}; use prometheus::local::LocalHistogram; use raft::eraftpb::ConfChangeType; use resource_metering::{Collector, CollectorGuard, CollectorRegHandle, RawRecords}; @@ -291,10 +291,12 @@ pub struct PeerStat { pub read_bytes: u64, pub read_keys: u64, pub query_stats: QueryStats, + pub cop_detail: RegionWriteCfCopDetail, // last_region_report_attributes records the state of the last region heartbeat pub last_region_report_read_bytes: u64, pub last_region_report_read_keys: u64, pub last_region_report_query_stats: QueryStats, + pub last_region_report_cop_detail: RegionWriteCfCopDetail, pub last_region_report_written_bytes: u64, pub last_region_report_written_keys: u64, pub last_region_report_ts: UnixSecs, @@ -1601,6 +1603,7 @@ where peer_stat .query_stats .add_query_stats(®ion_info.query_stats.0); + peer_stat.cop_detail.add(®ion_info.cop_detail); self.store_stat .engine_total_query_num .add_query_stats(®ion_info.query_stats.0); @@ -2031,6 +2034,7 @@ where written_keys_delta, last_report_ts, query_stats, + cop_detail, cpu_usage, ) = { let region_id = hb_task.region.get_id(); @@ -2049,12 +2053,16 @@ where let query_stats = peer_stat .query_stats .sub_query_stats(&peer_stat.last_region_report_query_stats); + let cop_detail = peer_stat + .cop_detail + .sub(&peer_stat.last_region_report_cop_detail); let mut last_report_ts = peer_stat.last_region_report_ts; peer_stat.last_region_report_written_bytes = hb_task.written_bytes; peer_stat.last_region_report_written_keys = hb_task.written_keys; peer_stat.last_region_report_read_bytes = peer_stat.read_bytes; peer_stat.last_region_report_read_keys = peer_stat.read_keys; peer_stat.last_region_report_query_stats = peer_stat.query_stats.clone(); + peer_stat.last_region_report_cop_detail = peer_stat.cop_detail.clone(); let unix_secs_now = UnixSecs::now(); peer_stat.last_region_report_ts = unix_secs_now; @@ -2085,6 +2093,7 @@ where written_keys_delta, last_report_ts, query_stats.0, + cop_detail, cpu_usage, ) }; @@ -2100,6 +2109,7 @@ where read_bytes: read_bytes_delta, read_keys: read_keys_delta, query_stats, + cop_detail, approximate_size, approximate_keys, last_report_ts, diff --git a/components/raftstore/src/store/worker/split_controller.rs b/components/raftstore/src/store/worker/split_controller.rs index 32362ef4b8c..0a6a19acc91 100644 --- a/components/raftstore/src/store/worker/split_controller.rs +++ b/components/raftstore/src/store/worker/split_controller.rs @@ -14,7 +14,7 @@ use kvproto::{ metapb::{self, Peer}, pdpb::QueryKind, }; -use pd_client::{BucketMeta, BucketStat}; +use pd_client::{BucketMeta, BucketStat, RegionWriteCfCopDetail}; use rand::Rng; use resource_metering::RawRecords; use tikv_util::{ @@ -333,6 +333,7 @@ impl Recorder { pub struct RegionInfo { pub sample_num: usize, pub query_stats: QueryStats, + pub cop_detail: RegionWriteCfCopDetail, pub peer: Peer, pub key_ranges: Vec, pub flow: FlowStatistics, @@ -343,6 +344,7 @@ impl RegionInfo { RegionInfo { sample_num, query_stats: QueryStats::default(), + cop_detail: RegionWriteCfCopDetail::default(), key_ranges: Vec::with_capacity(sample_num), peer: Peer::default(), flow: FlowStatistics::default(), @@ -444,6 +446,7 @@ impl ReadStats { end: Option<&[u8]>, write: &FlowStatistics, data: &FlowStatistics, + write_cf_cop_detail: &RegionWriteCfCopDetail, ) { let num = self.sample_num; let region_info = self @@ -452,6 +455,7 @@ impl ReadStats { .or_insert_with(|| RegionInfo::new(num)); region_info.flow.add(write); region_info.flow.add(data); + region_info.cop_detail.add(write_cf_cop_detail); // the bucket of the follower only have the version info and not needs to be // recorded the hot bucket. if let Some(buckets) = buckets diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 8548ef42dcb..aa15d0d7c00 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -572,6 +572,7 @@ pub mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), + mvcc_amplification_threshold: 10, })); let mem_controller = Arc::new(MemoryController::new(config.clone(), skiplist.clone())); @@ -627,6 +628,7 @@ pub mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), + mvcc_amplification_threshold: 10, })); let mem_controller = Arc::new(MemoryController::new(config.clone(), skiplist.clone())); diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index 87a319d3e34..f2fe1ca9ba7 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -59,6 +59,9 @@ pub struct RangeCacheEngineConfig { pub soft_limit_threshold: Option, pub hard_limit_threshold: Option, pub expected_region_size: Option, + // used in getting top regions to filter those with less mvcc amplification. Here, we define + // mvcc amplification to be '(next + prev) / processed_keys'. + pub mvcc_amplification_threshold: usize, } impl Default for RangeCacheEngineConfig { @@ -71,6 +74,7 @@ impl Default for RangeCacheEngineConfig { soft_limit_threshold: None, hard_limit_threshold: None, expected_region_size: None, + mvcc_amplification_threshold: 10, } } } @@ -128,6 +132,7 @@ impl RangeCacheEngineConfig { soft_limit_threshold: Some(ReadableSize::gb(1)), hard_limit_threshold: Some(ReadableSize::gb(2)), expected_region_size: Some(ReadableSize::mb(20)), + mvcc_amplification_threshold: 10, } } } diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index ee1fe4dd557..ae9a322d55d 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -131,6 +131,7 @@ mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Default::default(), + mvcc_amplification_threshold: 10, })); let mc = MemoryController::new(config, skiplist_engine.clone()); assert_eq!(mc.acquire(100), MemoryUsage::NormalUsage(100)); diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 017e6192f14..08d3779d9fd 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -430,6 +430,7 @@ where let region_info_accessor = RegionInfoAccessor::new( coprocessor_host.as_mut().unwrap(), region_stats_manager_enabled_cb, + config.range_cache_engine.mvcc_amplification_threshold, ); // Initialize concurrency manager diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index f91e20f5687..7cb6c354f0c 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -1518,6 +1518,10 @@ impl TikvServer { let region_info_accessor = RegionInfoAccessor::new( &mut coprocessor_host, Arc::new(|| false), // Not applicable to v2. + self.core + .config + .range_cache_engine + .mvcc_amplification_threshold, ); let cdc_worker = Box::new(LazyWorker::new("cdc")); diff --git a/components/test_raftstore-v2/src/server.rs b/components/test_raftstore-v2/src/server.rs index af256608562..fafe049e643 100644 --- a/components/test_raftstore-v2/src/server.rs +++ b/components/test_raftstore-v2/src/server.rs @@ -422,6 +422,7 @@ impl ServerCluster { let region_info_accessor = RegionInfoAccessor::new( &mut coprocessor_host, Arc::new(|| false), // Not applicable to v2 + cfg.range_cache_engine.mvcc_amplification_threshold, ); let sim_router = SimulateTransport::new(raft_router.clone()); diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index 4b750a2da17..0c12efefb20 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -308,8 +308,11 @@ impl ServerCluster { Arc::new(|| false) }; let mut coprocessor_host = CoprocessorHost::new(router.clone(), cfg.coprocessor.clone()); - let region_info_accessor = - RegionInfoAccessor::new(&mut coprocessor_host, enable_region_stats_mgr_cb); + let region_info_accessor = RegionInfoAccessor::new( + &mut coprocessor_host, + enable_region_stats_mgr_cb, + cfg.range_cache_engine.mvcc_amplification_threshold, + ); let raft_router = ServerRaftStoreRouter::new(router.clone(), local_reader); let sim_router = SimulateTransport::new(raft_router.clone()); diff --git a/src/coprocessor/metrics.rs b/src/coprocessor/metrics.rs index e06d4007ab9..897fd4cb202 100644 --- a/src/coprocessor/metrics.rs +++ b/src/coprocessor/metrics.rs @@ -4,7 +4,7 @@ use std::{cell::RefCell, mem, sync::Arc}; use collections::HashMap; use kvproto::{metapb, pdpb::QueryKind}; -use pd_client::BucketMeta; +use pd_client::{BucketMeta, RegionWriteCfCopDetail}; use prometheus::*; use prometheus_static_metric::*; use raftstore::store::{util::build_key_range, ReadStats}; @@ -309,6 +309,11 @@ pub fn tls_collect_read_flow( end, &statistics.write.flow_stats, &statistics.data.flow_stats, + &RegionWriteCfCopDetail::new( + statistics.write.next, + statistics.write.prev, + statistics.write.processed_keys, + ), ); }); } diff --git a/src/server/gc_worker/gc_worker.rs b/src/server/gc_worker/gc_worker.rs index 6c213dce004..05096a16db1 100644 --- a/src/server/gc_worker/gc_worker.rs +++ b/src/server/gc_worker/gc_worker.rs @@ -1873,7 +1873,7 @@ mod tests { let sp_provider = MockSafePointProvider(200); let mut host = CoprocessorHost::::default(); - let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false)); + let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0); let mut gc_config = GcConfig::default(); gc_config.num_threads = 2; @@ -1988,7 +1988,7 @@ mod tests { r1.mut_peers()[0].set_store_id(store_id); let mut host = CoprocessorHost::::default(); - let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false)); + let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0); host.on_region_changed(&r1, RegionChangeEvent::Create, StateRole::Leader); let db = engine.kv_engine().unwrap().as_inner().clone(); @@ -2052,7 +2052,7 @@ mod tests { r1.mut_peers()[0].set_store_id(store_id); let mut host = CoprocessorHost::::default(); - let ri_provider = Arc::new(RegionInfoAccessor::new(&mut host, Arc::new(|| false))); + let ri_provider = Arc::new(RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0)); host.on_region_changed(&r1, RegionChangeEvent::Create, StateRole::Leader); // Init env end... @@ -2153,7 +2153,7 @@ mod tests { r1.mut_peers()[0].set_store_id(1); let mut host = CoprocessorHost::::default(); - let ri_provider = Arc::new(RegionInfoAccessor::new(&mut host, Arc::new(|| false))); + let ri_provider = Arc::new(RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0)); host.on_region_changed(&r1, RegionChangeEvent::Create, StateRole::Leader); let db = engine.kv_engine().unwrap().as_inner().clone(); diff --git a/src/storage/metrics.rs b/src/storage/metrics.rs index 4978b1e06a7..46e4aa62b86 100644 --- a/src/storage/metrics.rs +++ b/src/storage/metrics.rs @@ -7,7 +7,7 @@ use std::{cell::RefCell, mem, sync::Arc}; use collections::HashMap; use engine_traits::{PerfContext, PerfContextExt, PerfContextKind, PerfLevel}; use kvproto::{kvrpcpb::KeyRange, metapb, pdpb::QueryKind}; -use pd_client::BucketMeta; +use pd_client::{BucketMeta, RegionWriteCfCopDetail}; use prometheus::*; use prometheus_static_metric::*; use raftstore::store::{util::build_key_range, ReadStats}; @@ -84,6 +84,11 @@ pub fn tls_collect_read_flow( end, &statistics.write.flow_stats, &statistics.data.flow_stats, + &RegionWriteCfCopDetail::new( + statistics.write.next, + statistics.write.prev, + statistics.write.processed_keys, + ), ); }); } diff --git a/tests/failpoints/cases/test_gc_metrics.rs b/tests/failpoints/cases/test_gc_metrics.rs index 2d4d3fc173d..62cf29a0107 100644 --- a/tests/failpoints/cases/test_gc_metrics.rs +++ b/tests/failpoints/cases/test_gc_metrics.rs @@ -158,7 +158,7 @@ fn test_txn_gc_keys_handled() { let sp_provider = MockSafePointProvider(200); let mut host = CoprocessorHost::::default(); - let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false)); + let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0); let auto_gc_cfg = AutoGcConfig::new(sp_provider, ri_provider, 1); let safe_point = Arc::new(AtomicU64::new(500)); @@ -303,7 +303,7 @@ fn test_raw_gc_keys_handled() { let sp_provider = MockSafePointProvider(200); let mut host = CoprocessorHost::::default(); - let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false)); + let ri_provider = RegionInfoAccessor::new(&mut host, Arc::new(|| false), 0); let auto_gc_cfg = AutoGcConfig::new(sp_provider, ri_provider, store_id); let safe_point = Arc::new(AtomicU64::new(500)); diff --git a/tests/integrations/raftstore/test_region_info_accessor.rs b/tests/integrations/raftstore/test_region_info_accessor.rs index 2f37d7f379b..c02a655d649 100644 --- a/tests/integrations/raftstore/test_region_info_accessor.rs +++ b/tests/integrations/raftstore/test_region_info_accessor.rs @@ -188,7 +188,7 @@ fn test_node_cluster_region_info_accessor() { .wl() .post_create_coprocessor_host(Box::new(move |id, host| { if id == 1 { - let c = RegionInfoAccessor::new(host, Arc::new(|| false)); + let c = RegionInfoAccessor::new(host, Arc::new(|| false), 0); tx.send(c).unwrap(); } })); diff --git a/tests/integrations/storage/test_region_info_accessor.rs b/tests/integrations/storage/test_region_info_accessor.rs index c79d1148c8a..1bac3d7c42e 100644 --- a/tests/integrations/storage/test_region_info_accessor.rs +++ b/tests/integrations/storage/test_region_info_accessor.rs @@ -12,7 +12,11 @@ use collections::HashMap; use engine_rocks::RocksEngine; use kvproto::metapb::Region; use more_asserts::{assert_gt, assert_le}; -use raftstore::coprocessor::{RegionInfoAccessor, RegionInfoProvider}; +use pd_client::{RegionStat, RegionWriteCfCopDetail}; +use raftstore::coprocessor::{ + region_info_accessor::{RaftStoreEvent, RegionActivity, RegionInfoQuery}, + RegionInfoAccessor, RegionInfoProvider, +}; use test_raftstore::*; use tikv_util::HandyRwLock; @@ -77,7 +81,7 @@ fn test_region_collection_seek_region() { .sim .wl() .post_create_coprocessor_host(Box::new(move |id, host| { - let p = RegionInfoAccessor::new(host, Arc::new(|| false)); + let p = RegionInfoAccessor::new(host, Arc::new(|| false), 0); tx.send((id, p)).unwrap() })); @@ -151,7 +155,7 @@ fn test_region_collection_get_regions_in_range() { .sim .wl() .post_create_coprocessor_host(Box::new(move |id, host| { - let p = RegionInfoAccessor::new(host, Arc::new(|| false)); + let p = RegionInfoAccessor::new(host, Arc::new(|| false), 0); tx.send((id, p)).unwrap() })); @@ -196,18 +200,28 @@ fn test_region_collection_get_top_regions() { .sim .wl() .post_create_coprocessor_host(Box::new(move |id, host| { - let p = RegionInfoAccessor::new(host, Arc::new(|| true)); + let p = RegionInfoAccessor::new(host, Arc::new(|| true), 0); tx.send((id, p)).unwrap() })); cluster.run(); let region_info_providers: HashMap<_, _> = rx.try_iter().collect(); assert_eq!(region_info_providers.len(), 3); let regions = prepare_cluster(&mut cluster); - let mut regions = regions.into_iter().map(|r| r.get_id()).collect::>(); - regions.sort(); + let mut region_ids = regions.iter().map(|r| r.get_id()).collect::>(); + region_ids.sort(); let mut all_results = BTreeSet::::new(); for node_id in cluster.get_node_ids() { let engine = ®ion_info_providers[&node_id]; + for r in ®ions { + let mut region_stat = RegionStat::default(); + region_stat.cop_detail = RegionWriteCfCopDetail::new(10, 10, 10); + let _ = engine.scheduler().schedule(RegionInfoQuery::RaftStoreEvent( + RaftStoreEvent::UpdateRegionActivity { + region: r.clone(), + activity: RegionActivity { region_stat }, + }, + )); + } let result = engine .get_top_regions(NonZeroUsize::new(10)) @@ -217,7 +231,7 @@ fn test_region_collection_get_top_regions() { .collect::>(); for region_id in &result { - assert!(regions.contains(region_id)); + assert!(region_ids.contains(region_id)); } let len = result.len(); if engine.region_leaders().read().unwrap().contains(&node_id) { @@ -234,7 +248,7 @@ fn test_region_collection_get_top_regions() { .collect::>(); all_results.extend(result.iter()); } - assert_eq!(all_results.into_iter().collect::>(), regions); + assert_eq!(all_results.into_iter().collect::>(), region_ids); for (_, p) in region_info_providers { p.stop(); @@ -250,7 +264,7 @@ fn test_region_collection_find_region_by_key() { .sim .wl() .post_create_coprocessor_host(Box::new(move |id, host| { - let p = RegionInfoAccessor::new(host, Arc::new(|| false)); + let p = RegionInfoAccessor::new(host, Arc::new(|| false), 0); tx.send((id, p)).unwrap() })); From 36aad165727d61bc4332c1fb10e866dc8ac4137e Mon Sep 17 00:00:00 2001 From: glorv Date: Mon, 26 Aug 2024 19:54:16 +0800 Subject: [PATCH 042/144] Revert "In-memory Engine: do not evict range on applying snapshot (#17430) close tikv/tikv#17405 Revert #17237 because cache region can be loaded even when current peer is not leader so we should handle apply snapshot event. Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../engine_traits/src/range_cache_engine.rs | 1 + components/hybrid_engine/src/observer.rs | 41 ++++++++++++++----- .../range_cache_memory_engine/src/metrics.rs | 4 ++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index fa632f3d0f8..1a157aefb95 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -50,6 +50,7 @@ pub enum EvictReason { DeleteRange, Merge, Disabled, + ApplySnapshot, } /// RangeCacheEngine works as a range cache caching some ranges (in Memory or diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer.rs index a9afdfc3c6a..6c1f457f64d 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer.rs @@ -6,9 +6,9 @@ use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngineExt, Regi use kvproto::{metapb::Region, raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; use raft::StateRole; use raftstore::coprocessor::{ - AdminObserver, ApplyCtxInfo, BoxAdminObserver, BoxCmdObserver, BoxQueryObserver, - BoxRoleObserver, Cmd, CmdBatch, CmdObserver, Coprocessor, CoprocessorHost, ObserveLevel, - ObserverContext, QueryObserver, RegionState, RoleObserver, + AdminObserver, ApplyCtxInfo, ApplySnapshotObserver, BoxAdminObserver, BoxApplySnapshotObserver, + BoxCmdObserver, BoxQueryObserver, BoxRoleObserver, Cmd, CmdBatch, CmdObserver, Coprocessor, + CoprocessorHost, ObserveLevel, ObserverContext, QueryObserver, RegionState, RoleObserver, }; use tikv_util::info; @@ -44,14 +44,17 @@ impl Observer { coprocessor_host .registry .register_admin_observer(priority, BoxAdminObserver::new(self.clone())); + // Evict cache when a peer applies snapshot. + // Applying snapshot changes the data in rocksdb but not IME, + // so we trigger region eviction to keep compatibility. + coprocessor_host.registry.register_apply_snapshot_observer( + priority, + BoxApplySnapshotObserver::new(self.clone()), + ); // Evict cache when a leader steps down. coprocessor_host .registry .register_role_observer(priority, BoxRoleObserver::new(self.clone())); - - // NB: We do not evict the cache when applying a snapshot because - // the peer must be in the follower role during this process. - // The cache is already evicted when the leader steps down. } fn post_exec_cmd( @@ -129,15 +132,16 @@ impl Observer { } } - fn evict_range_on_leader_steps_down(&self, region: &Region) { + fn evict_region_range(&self, region: &Region, reason: EvictReason) { if !self.cache_engine.range_cache_engine_enabled() { return; } let range = CacheRange::from_region(region); info!( - "ime evict region due to leader step down"; + "ime evict region"; "region_id" => region.get_id(), + "reason" => ?reason, "epoch" => ?region.get_region_epoch(), "start_key" => ?log_wrappers::Value(®ion.start_key), "end_key" => ?log_wrappers::Value(®ion.end_key), @@ -147,7 +151,7 @@ impl Observer { .unwrap() .push(RegionEvent::Eviction { region: region.clone(), - reason: EvictReason::BecomeFollower, + reason, }); } } @@ -186,6 +190,21 @@ impl AdminObserver for Observer { } } +impl ApplySnapshotObserver for Observer { + fn post_apply_snapshot( + &self, + ctx: &mut ObserverContext<'_>, + _: u64, + _: &raftstore::store::SnapKey, + _: Option<&raftstore::store::Snapshot>, + ) { + // While currently, we evict cached region after leader step down. + // A region can may still be loaded when it's leader. E.g, to pre-load + // some hot regions before transfering leader. + self.evict_region_range(ctx.region(), EvictReason::ApplySnapshot) + } +} + impl RoleObserver for Observer { fn on_role_change( &self, @@ -195,7 +214,7 @@ impl RoleObserver for Observer { if let StateRole::Follower = change.state && change.initialized { - self.evict_range_on_leader_steps_down(ctx.region()) + self.evict_region_range(ctx.region(), EvictReason::BecomeFollower) } } } diff --git a/components/range_cache_memory_engine/src/metrics.rs b/components/range_cache_memory_engine/src/metrics.rs index b3379138b38..6d9769c1ba1 100644 --- a/components/range_cache_memory_engine/src/metrics.rs +++ b/components/range_cache_memory_engine/src/metrics.rs @@ -40,6 +40,7 @@ make_auto_flush_static_metric! { become_follower, memory_limit_reached, disabled, + apply_snapshot, } pub struct GcFilteredCountVec: LocalIntCounter { @@ -204,5 +205,8 @@ pub(crate) fn observe_eviction_duration(secs: f64, evict_reason: EvictReason) { EvictReason::Disabled => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC .disabled .observe(secs), + EvictReason::ApplySnapshot => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .apply_snapshot + .observe(secs), } } From 0a99919065f2ce079b2df31893eeb510e0f5db96 Mon Sep 17 00:00:00 2001 From: Ping Yu Date: Tue, 27 Aug 2024 18:03:18 +0800 Subject: [PATCH 043/144] dep: Update rusoto to support IMDSv2 (#17441) close tikv/tikv#16443 Update rusoto to support IMDSv2. Signed-off-by: Ping Yu --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5fc5f3fa93..8d3727d054a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4827,7 +4827,7 @@ dependencies = [ [[package]] name = "rusoto_core" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "base64 0.13.0", @@ -4851,7 +4851,7 @@ dependencies = [ [[package]] name = "rusoto_credential" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "chrono", @@ -4868,7 +4868,7 @@ dependencies = [ [[package]] name = "rusoto_kms" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "bytes", @@ -4881,7 +4881,7 @@ dependencies = [ [[package]] name = "rusoto_mock" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "chrono", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "rusoto_s3" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "bytes", @@ -4909,7 +4909,7 @@ dependencies = [ [[package]] name = "rusoto_signature" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "base64 0.13.0", "bytes", @@ -4931,7 +4931,7 @@ dependencies = [ [[package]] name = "rusoto_sts" version = "0.46.0" -source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#cc733208600bdb15a13940d6930c1fbd4ab604f2" +source = "git+https://github.com/tikv/rusoto?branch=gh1482-s3-addr-styles#2b142c1792062a7a3a8317610d78dd141ab4223d" dependencies = [ "async-trait", "bytes", @@ -7091,7 +7091,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "static_assertions", ] From 0247c4436370c30d1698a9e45c83f7a9f432af28 Mon Sep 17 00:00:00 2001 From: glorv Date: Tue, 27 Aug 2024 19:49:46 +0800 Subject: [PATCH 044/144] in-memory-engine: replace region with CacheRegion (#17440) ref tikv/tikv#16141 Previous in #17331, we refactor the RangeManager and use metapb::Region to store region info. As metapb::Region is very cumbersome, this PR replace it with `CacheRegion`, renaming from `CacheRange` and adding `id` and `epoch_version`. Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/engine_traits/src/engine.rs | 12 +- .../engine_traits/src/range_cache_engine.rs | 86 +++-- components/engine_traits/src/write_batch.rs | 6 +- components/hybrid_engine/src/engine.rs | 14 +- components/hybrid_engine/src/misc.rs | 23 +- components/hybrid_engine/src/observer.rs | 32 +- components/hybrid_engine/src/snapshot.rs | 14 +- components/hybrid_engine/src/write_batch.rs | 32 +- .../tests/failpoints/test_write_batch.rs | 8 +- components/raftstore/src/store/fsm/apply.rs | 9 +- components/raftstore/src/store/peer.rs | 6 +- components/raftstore/src/store/worker/read.rs | 14 +- .../src/background.rs | 225 ++++++------- .../range_cache_memory_engine/src/engine.rs | 63 ++-- .../range_cache_memory_engine/src/keys.rs | 6 +- .../src/prop_test.rs | 6 +- .../src/range_manager.rs | 295 ++++++++---------- .../range_cache_memory_engine/src/read.rs | 231 ++++++-------- .../src/region_label.rs | 6 +- .../src/test_util.rs | 2 +- .../src/write_batch.rs | 126 +++----- .../tests/failpoints/test_memory_engine.rs | 111 ++++--- components/test_raftstore-v2/src/util.rs | 34 +- components/test_raftstore/src/cluster.rs | 23 +- src/server/raftkv/mod.rs | 4 +- .../cases/test_range_cache_engine.rs | 119 +++---- 26 files changed, 657 insertions(+), 850 deletions(-) diff --git a/components/engine_traits/src/engine.rs b/components/engine_traits/src/engine.rs index 3d8240650f4..346c4011082 100644 --- a/components/engine_traits/src/engine.rs +++ b/components/engine_traits/src/engine.rs @@ -85,17 +85,13 @@ pub trait KvEngine: #[derive(Debug, Clone)] pub struct SnapshotContext { - pub range: Option, - pub region_id: u64, - // the version of region epoch. - pub epoch_version: u64, - + pub region: Option, pub read_ts: u64, } impl SnapshotContext { - pub fn set_range(&mut self, range: CacheRange) { - assert!(self.range.is_none()); - self.range = Some(range); + pub fn set_region(&mut self, region: CacheRegion) { + assert!(self.region.is_none()); + self.region = Some(region); } } diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 1a157aefb95..0046f6266fd 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -25,17 +25,17 @@ pub enum FailedReason { #[derive(Debug, PartialEq)] pub enum RegionEvent { Split { - source: Region, - new_regions: Vec, + source: CacheRegion, + new_regions: Vec, }, Eviction { - region: Region, + region: CacheRegion, reason: EvictReason, }, // range eviction triggered by delete_range // we should evict all cache regions that overlaps with this range EvictByRange { - range: CacheRange, + range: CacheRegion, reason: EvictReason, }, } @@ -66,9 +66,7 @@ pub trait RangeCacheEngine: // provide atomic write fn snapshot( &self, - region_id: u64, - region_epoch: u64, - range: CacheRange, + region: CacheRegion, read_ts: u64, seq_num: u64, ) -> result::Result; @@ -77,7 +75,7 @@ pub trait RangeCacheEngine: fn set_disk_engine(&mut self, disk_engine: Self::DiskEngine); // return the region containing the key - fn get_region_for_key(&self, key: &[u8]) -> Option; + fn get_region_for_key(&self, key: &[u8]) -> Option; type RangeHintService: RangeHintService; fn start_hint_service(&self, range_hint_service: Self::RangeHintService); @@ -105,37 +103,57 @@ pub trait RangeCacheEngineExt { /// as it continues to evolve to handle eviction, using stats. pub trait RangeHintService: Send + Sync {} -#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] -pub struct CacheRange { +#[derive(Clone, Eq, PartialEq)] +pub struct CacheRegion { + // target region id + pub id: u64, + // the version of target region epoch. we only track version but not + // conf_version because conf_version does not change the applied data. + pub epoch_version: u64, + // data start key of the region range, equals to data_key(region.start_key). pub start: Vec, + // data start key of the region range, equals to data_end_key(region.start_key). pub end: Vec, } -impl Debug for CacheRange { +impl Debug for CacheRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CacheRange") + f.debug_struct("CacheRegion") + .field("id", &self.id) + .field("epoch", &self.epoch_version) .field("range_start", &log_wrappers::Value(&self.start)) .field("range_end", &log_wrappers::Value(&self.end)) .finish() } } -impl CacheRange { - pub fn new(start: Vec, end: Vec) -> Self { - Self { start, end } +impl CacheRegion { + pub fn new>, T2: Into>>( + id: u64, + epoch_version: u64, + start: T1, + end: T2, + ) -> Self { + Self { + id, + epoch_version, + start: start.into(), + end: end.into(), + } } pub fn from_region(region: &Region) -> Self { Self { start: enc_start_key(region), end: enc_end_key(region), + id: region.id, + epoch_version: region.get_region_epoch().version, } } } -impl CacheRange { - // todo: need to consider ""? - pub fn contains_range(&self, other: &CacheRange) -> bool { +impl CacheRegion { + pub fn contains_range(&self, other: &CacheRegion) -> bool { self.start <= other.start && self.end >= other.end } @@ -144,49 +162,49 @@ impl CacheRange { } // Note: overlaps also includes "contains" - pub fn overlaps(&self, other: &CacheRange) -> bool { + pub fn overlaps(&self, other: &CacheRegion) -> bool { self.start < other.end && other.start < self.end } } #[cfg(test)] mod tests { - use super::CacheRange; + use super::CacheRegion; #[test] fn test_overlap() { - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k4".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k6".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k2".to_vec(), b"k4".to_vec()); assert!(r1.overlaps(&r2)); assert!(r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k7".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k6".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k2".to_vec(), b"k7".to_vec()); assert!(r1.overlaps(&r2)); assert!(r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k1".to_vec(), b"k4".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k6".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k1".to_vec(), b"k4".to_vec()); assert!(r1.overlaps(&r2)); assert!(r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k6".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k6".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k2".to_vec(), b"k6".to_vec()); assert!(r1.overlaps(&r2)); assert!(r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); - let r2 = CacheRange::new(b"k1".to_vec(), b"k6".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k6".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k1".to_vec(), b"k6".to_vec()); assert!(r1.overlaps(&r2)); assert!(r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - let r2 = CacheRange::new(b"k2".to_vec(), b"k3".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k2".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k2".to_vec(), b"k3".to_vec()); assert!(!r1.overlaps(&r2)); assert!(!r2.overlaps(&r1)); - let r1 = CacheRange::new(b"k1".to_vec(), b"k2".to_vec()); - let r2 = CacheRange::new(b"k3".to_vec(), b"k4".to_vec()); + let r1 = CacheRegion::new(1, 0, b"k1".to_vec(), b"k2".to_vec()); + let r2 = CacheRegion::new(2, 0, b"k3".to_vec(), b"k4".to_vec()); assert!(!r1.overlaps(&r2)); assert!(!r2.overlaps(&r1)); } diff --git a/components/engine_traits/src/write_batch.rs b/components/engine_traits/src/write_batch.rs index 7a2a222178e..31aff5c9a56 100644 --- a/components/engine_traits/src/write_batch.rs +++ b/components/engine_traits/src/write_batch.rs @@ -1,8 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use kvproto::metapb::Region; - -use crate::{errors::Result, options::WriteOptions}; +use crate::{errors::Result, options::WriteOptions, CacheRegion}; /// Engines that can create write batches pub trait WriteBatchExt: Sized { @@ -128,5 +126,5 @@ pub trait WriteBatch: Mutable { /// It declares that the following consecutive write will be within this /// region. - fn prepare_for_region(&mut self, _: &Region) {} + fn prepare_for_region(&mut self, _: CacheRegion) {} } diff --git a/components/hybrid_engine/src/engine.rs b/components/hybrid_engine/src/engine.rs index dd82f02d728..1253fae335c 100644 --- a/components/hybrid_engine/src/engine.rs +++ b/components/hybrid_engine/src/engine.rs @@ -75,7 +75,7 @@ where { let mut batch = self.write_batch(); if let Some(region) = self.range_cache_engine.get_region_for_key(key) { - batch.prepare_for_region(®ion); + batch.prepare_for_region(region); } f(&mut batch)?; let _ = batch.write()?; @@ -98,9 +98,7 @@ where None } else if let Some(ctx) = ctx { match self.range_cache_engine.snapshot( - ctx.region_id, - ctx.epoch_version, - ctx.range.unwrap(), + ctx.region.unwrap(), ctx.read_ts, disk_snap.sequence_number(), ) { @@ -213,7 +211,7 @@ mod tests { use std::sync::Arc; use engine_rocks::util::new_engine; - use engine_traits::{CacheRange, KvEngine, SnapshotContext, CF_DEFAULT, CF_LOCK, CF_WRITE}; + use engine_traits::{CacheRegion, KvEngine, SnapshotContext, CF_DEFAULT, CF_LOCK, CF_WRITE}; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use range_cache_memory_engine::{ config::RangeCacheConfigManager, test_util::new_region, RangeCacheEngineConfig, @@ -237,7 +235,7 @@ mod tests { RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config.clone())); let region = new_region(1, b"k00", b"k10"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); memory_engine.new_region(region.clone()); { let mut core = memory_engine.core().write(); @@ -249,10 +247,8 @@ mod tests { assert!(!s.range_cache_snapshot_available()); let mut snap_ctx = SnapshotContext { - region_id: 1, - epoch_version: 0, read_ts: 15, - range: Some(range.clone()), + region: Some(range.clone()), }; let s = hybrid_engine.snapshot(Some(snap_ctx.clone())); assert!(s.range_cache_snapshot_available()); diff --git a/components/hybrid_engine/src/misc.rs b/components/hybrid_engine/src/misc.rs index dcecdae1a7b..ef08e56c10a 100644 --- a/components/hybrid_engine/src/misc.rs +++ b/components/hybrid_engine/src/misc.rs @@ -1,7 +1,7 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. use engine_traits::{ - CacheRange, EvictReason, KvEngine, MiscExt, RangeCacheEngine, RegionEvent, Result, + CacheRegion, EvictReason, KvEngine, MiscExt, RangeCacheEngine, RegionEvent, Result, WriteBatchExt, }; @@ -41,7 +41,7 @@ where for r in ranges { self.range_cache_engine() .on_region_event(RegionEvent::EvictByRange { - range: CacheRange::new(r.start_key.to_vec(), r.end_key.to_vec()), + range: CacheRegion::new(0, 0, r.start_key.to_vec(), r.end_key.to_vec()), reason: EvictReason::DeleteRange, }); } @@ -155,7 +155,7 @@ where #[cfg(test)] pub mod tests { use engine_traits::{ - CacheRange, DeleteStrategy, MiscExt, Mutable, Range, RangeCacheEngine, WriteBatch, + CacheRegion, DeleteStrategy, MiscExt, Mutable, Range, RangeCacheEngine, WriteBatch, WriteBatchExt, WriteOptions, CF_DEFAULT, }; use range_cache_memory_engine::{test_util::new_region, RangeCacheEngineConfig}; @@ -180,14 +180,19 @@ pub mod tests { }, ) .unwrap(); + + let cache_r1 = CacheRegion::from_region(&r1); + let cache_r2 = CacheRegion::from_region(&r2); + let cache_r3 = CacheRegion::from_region(&r3); + let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_region(&r1); + write_batch.prepare_for_region(cache_r1.clone()); write_batch.put(b"zk02", b"val").unwrap(); write_batch.put(b"zk03", b"val").unwrap(); - write_batch.prepare_for_region(&r2); + write_batch.prepare_for_region(cache_r2.clone()); write_batch.put(b"zk22", b"val").unwrap(); write_batch.put(b"zk23", b"val").unwrap(); - write_batch.prepare_for_region(&r3); + write_batch.prepare_for_region(cache_r3.clone()); write_batch.put(b"zk42", b"val").unwrap(); write_batch.put(b"zk42", b"val").unwrap(); write_batch.write().unwrap(); @@ -203,15 +208,15 @@ pub mod tests { hybrid_engine .range_cache_engine() - .snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000) + .snapshot(cache_r1.clone(), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) + .snapshot(cache_r2.clone(), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(r3.id, 0, CacheRange::from_region(&r3), 1000, 1000) + .snapshot(cache_r3.clone(), 1000, 1000) .unwrap(); } } diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer.rs index 6c1f457f64d..57c559089ac 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; -use engine_traits::{CacheRange, EvictReason, KvEngine, RangeCacheEngineExt, RegionEvent}; +use engine_traits::{CacheRegion, EvictReason, KvEngine, RangeCacheEngineExt, RegionEvent}; use kvproto::{metapb::Region, raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; use raft::StateRole; use raftstore::coprocessor::{ @@ -82,20 +82,18 @@ impl Observer { AdminCmdType::PrepareMerge | AdminCmdType::CommitMerge )) { - let range = CacheRange::from_region(ctx.region()); + let cache_region = CacheRegion::from_region(ctx.region()); info!( "ime evict range due to apply commands"; - "region_id" => ctx.region().get_id(), + "region" => ?cache_region, "is_ingest_sst" => apply.pending_handle_ssts.is_some(), "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), - "start_key" => ?log_wrappers::Value(&ctx.region().start_key), - "end_key" => ?log_wrappers::Value(&ctx.region().end_key), ); self.pending_events .lock() .unwrap() .push(RegionEvent::Eviction { - region: ctx.region().clone(), + region: cache_region, reason: EvictReason::Merge, }); } @@ -115,8 +113,12 @@ impl Observer { .lock() .unwrap() .push(RegionEvent::Split { - source: ctx.region().clone(), - new_regions: state.new_regions.clone(), + source: CacheRegion::from_region(ctx.region()), + new_regions: state + .new_regions + .iter() + .map(CacheRegion::from_region) + .collect(), }); } } @@ -137,20 +139,18 @@ impl Observer { return; } - let range = CacheRange::from_region(region); + let cache_region = CacheRegion::from_region(region); info!( "ime evict region"; - "region_id" => region.get_id(), + "region" => ?cache_region, "reason" => ?reason, "epoch" => ?region.get_region_epoch(), - "start_key" => ?log_wrappers::Value(®ion.start_key), - "end_key" => ?log_wrappers::Value(®ion.end_key), ); self.pending_events .lock() .unwrap() .push(RegionEvent::Eviction { - region: region.clone(), + region: cache_region, reason, }); } @@ -295,7 +295,7 @@ mod tests { cache_engine.enabled.store(true, Ordering::Relaxed); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); - let expected = CacheRange::from_region(®ion); + let expected = CacheRegion::from_region(®ion); assert!(&cache_engine.region_events.lock().unwrap().is_empty()); } @@ -338,9 +338,9 @@ mod tests { cache_engine.enabled.store(true, Ordering::Relaxed); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); - let expected = CacheRange::from_region(®ion); + let cached_region = CacheRegion::from_region(®ion); let expected = RegionEvent::Eviction { - region, + region: cached_region, reason: EvictReason::Merge, }; assert_eq!(&cache_engine.region_events.lock().unwrap()[0], &expected); diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index b69837278ba..ba801331211 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -132,7 +132,7 @@ where mod tests { use engine_traits::{ - CacheRange, IterOptions, Iterable, Iterator, KvEngine, Mutable, SnapshotContext, + CacheRegion, IterOptions, Iterable, Iterator, KvEngine, Mutable, SnapshotContext, WriteBatch, WriteBatchExt, CF_DEFAULT, }; use range_cache_memory_engine::{ @@ -144,10 +144,10 @@ mod tests { #[test] fn test_iterator() { let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let cache_region = CacheRegion::from_region(®ion); let mut iter_opt = IterOptions::default(); - iter_opt.set_upper_bound(&range.end, 0); - iter_opt.set_lower_bound(&range.start, 0); + iter_opt.set_upper_bound(&cache_region.end, 0); + iter_opt.set_lower_bound(&cache_region.start, 0); let region_clone = region.clone(); let (_path, hybrid_engine) = hybrid_engine_for_tests( @@ -168,7 +168,7 @@ mod tests { assert!(!iter.seek_to_first().unwrap()); } let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_region(®ion); + write_batch.prepare_for_region(cache_region.clone()); write_batch .cache_write_batch .set_range_cache_status(RangeCacheStatus::Cached); @@ -176,9 +176,7 @@ mod tests { let seq = write_batch.write().unwrap(); assert!(seq > 0); let ctx = SnapshotContext { - region_id: 1, - epoch_version: 0, - range: Some(CacheRange::from_region(®ion)), + region: Some(cache_region.clone()), read_ts: 10, }; let snap = hybrid_engine.snapshot(Some(ctx)); diff --git a/components/hybrid_engine/src/write_batch.rs b/components/hybrid_engine/src/write_batch.rs index b8753bd89bc..2c718c3bd6d 100644 --- a/components/hybrid_engine/src/write_batch.rs +++ b/components/hybrid_engine/src/write_batch.rs @@ -3,9 +3,8 @@ use std::sync::atomic::{AtomicBool, Ordering}; use engine_traits::{ - is_data_cf, KvEngine, Mutable, Result, WriteBatch, WriteBatchExt, WriteOptions, + is_data_cf, CacheRegion, KvEngine, Mutable, Result, WriteBatch, WriteBatchExt, WriteOptions, }; -use kvproto::metapb::Region; use range_cache_memory_engine::{RangeCacheMemoryEngine, RangeCacheWriteBatch}; use crate::engine::HybridEngine; @@ -101,7 +100,7 @@ impl WriteBatch for HybridEngineWriteBatch { self.cache_write_batch.merge(other.cache_write_batch) } - fn prepare_for_region(&mut self, r: &Region) { + fn prepare_for_region(&mut self, r: CacheRegion) { self.cache_write_batch.prepare_for_region(r); } } @@ -153,7 +152,7 @@ mod tests { use std::time::Duration; use engine_traits::{ - CacheRange, KvEngine, Mutable, Peekable, RangeCacheEngine, SnapshotContext, WriteBatch, + CacheRegion, KvEngine, Mutable, Peekable, RangeCacheEngine, SnapshotContext, WriteBatch, WriteBatchExt, }; use range_cache_memory_engine::{ @@ -180,8 +179,9 @@ mod tests { }, ) .unwrap(); + let cache_region = CacheRegion::from_region(®ion); let mut write_batch = hybrid_engine.write_batch(); - write_batch.prepare_for_region(®ion); + write_batch.prepare_for_region(cache_region.clone()); write_batch .cache_write_batch .set_range_cache_status(RangeCacheStatus::Cached); @@ -191,9 +191,7 @@ mod tests { let actual: &[u8] = &hybrid_engine.get_value(b"zhello").unwrap().unwrap(); assert_eq!(b"world", &actual); let ctx = SnapshotContext { - region_id: 1, - epoch_version: 0, - range: Some(CacheRange::from_region(®ion)), + region: Some(cache_region.clone()), read_ts: 10, }; let snap = hybrid_engine.snapshot(Some(ctx)); @@ -243,6 +241,8 @@ mod tests { fn test_delete_range() { let region1 = new_region(1, b"k00", b"k10"); let region2 = new_region(2, b"k20", b"k30"); + let cache_region1 = CacheRegion::from_region(®ion1); + let cache_region2 = CacheRegion::from_region(®ion2); let region1_clone = region1.clone(); let region2_clone = region2.clone(); @@ -257,21 +257,21 @@ mod tests { .unwrap(); let mut wb = hybrid_engine.write_batch(); - wb.prepare_for_region(®ion1); + wb.prepare_for_region(cache_region1.clone()); wb.put(b"zk05", b"val").unwrap(); wb.put(b"zk08", b"val2").unwrap(); - wb.prepare_for_region(®ion2); + wb.prepare_for_region(cache_region1.clone()); wb.put(b"zk25", b"val3").unwrap(); wb.put(b"zk27", b"val4").unwrap(); wb.write().unwrap(); hybrid_engine .range_cache_engine() - .snapshot(region1.id, 0, CacheRange::from_region(®ion1), 1000, 1000) + .snapshot(cache_region1.clone(), 1000, 1000) .unwrap(); hybrid_engine .range_cache_engine() - .snapshot(region2.id, 0, CacheRange::from_region(®ion2), 1000, 1000) + .snapshot(cache_region2.clone(), 1000, 1000) .unwrap(); assert_eq!( 4, @@ -286,19 +286,19 @@ mod tests { let mut wb = hybrid_engine.write_batch(); // all ranges overlapped with it will be evicted - wb.prepare_for_region(®ion1); + wb.prepare_for_region(cache_region1.clone()); wb.delete_range(b"zk05", b"zk08").unwrap(); - wb.prepare_for_region(®ion2); + wb.prepare_for_region(cache_region2.clone()); wb.delete_range(b"zk20", b"zk21").unwrap(); wb.write().unwrap(); hybrid_engine .range_cache_engine() - .snapshot(region1.id, 0, CacheRange::from_region(®ion1), 1000, 1000) + .snapshot(cache_region1.clone(), 1000, 1000) .unwrap_err(); hybrid_engine .range_cache_engine() - .snapshot(region2.id, 0, CacheRange::from_region(®ion2), 1000, 1000) + .snapshot(cache_region2.clone(), 1000, 1000) .unwrap_err(); let m_engine = hybrid_engine.range_cache_engine(); diff --git a/components/hybrid_engine/tests/failpoints/test_write_batch.rs b/components/hybrid_engine/tests/failpoints/test_write_batch.rs index 227c95b0db3..1185bfb8e58 100644 --- a/components/hybrid_engine/tests/failpoints/test_write_batch.rs +++ b/components/hybrid_engine/tests/failpoints/test_write_batch.rs @@ -3,7 +3,7 @@ use std::sync::mpsc::sync_channel; use crossbeam::epoch; -use engine_traits::{Mutable, WriteBatch, WriteBatchExt}; +use engine_traits::{CacheRegion, Mutable, WriteBatch, WriteBatchExt}; use hybrid_engine::util::hybrid_engine_for_tests; use range_cache_memory_engine::{ decode_key, test_util::new_region, InternalKey, RangeCacheEngineConfig, ValueType, @@ -46,17 +46,17 @@ fn test_sequence_number_unique() { // while we block the batch loading of region3, it's new KVs are still directly // written into the skiplist. let mut wb = hybrid_engine.write_batch(); - wb.prepare_for_region(&r); + wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"zk", b"val").unwrap(); // seq 3 wb.delete(b"zk").unwrap(); // seq 4 wb.put(b"zk2", b"val").unwrap(); // seq 5 - wb.prepare_for_region(&r2); + wb.prepare_for_region(CacheRegion::from_region(&r2)); wb.put(b"zk6", b"val").unwrap(); // seq 6 wb.delete(b"zk5").unwrap(); // seq 7 wb.put(b"zk5", b"val2").unwrap(); // seq 8 - wb.prepare_for_region(&r3); + wb.prepare_for_region(CacheRegion::from_region(&r3)); wb.put(b"zk8", b"val").unwrap(); // seq 9 wb.put(b"zk7", b"val2").unwrap(); // seq 10 diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index d1ef08909ad..80c9ff2a434 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -29,9 +29,9 @@ use batch_system::{ use collections::{HashMap, HashMapEntry, HashSet}; use crossbeam::channel::{TryRecvError, TrySendError}; use engine_traits::{ - util::SequenceNumber, DeleteStrategy, KvEngine, Mutable, PerfContext, PerfContextKind, - RaftEngine, RaftEngineReadOnly, Range as EngineRange, Snapshot, SstMetaInfo, WriteBatch, - WriteOptions, ALL_CFS, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, + util::SequenceNumber, CacheRegion, DeleteStrategy, KvEngine, Mutable, PerfContext, + PerfContextKind, RaftEngine, RaftEngineReadOnly, Range as EngineRange, Snapshot, SstMetaInfo, + WriteBatch, WriteOptions, ALL_CFS, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, }; use fail::fail_point; use health_controller::types::LatencyInspector; @@ -542,7 +542,8 @@ where pub fn prepare_for(&mut self, delegate: &mut ApplyDelegate) { self.applied_batch .push_batch(&delegate.observe_info, delegate.region.get_id()); - self.kv_wb.prepare_for_region(&delegate.region); + let cache_region = CacheRegion::from_region(&delegate.region); + self.kv_wb.prepare_for_region(cache_region); } /// Commits all changes have done for delegate. `persistent` indicates diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index 8649384e6a5..c6b56a2c3db 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -19,7 +19,7 @@ use bytes::Bytes; use collections::{HashMap, HashSet}; use crossbeam::{atomic::AtomicCell, channel::TrySendError}; use engine_traits::{ - CacheRange, Engines, KvEngine, PerfContext, RaftEngine, Snapshot, SnapshotContext, WriteBatch, + CacheRegion, Engines, KvEngine, PerfContext, RaftEngine, Snapshot, SnapshotContext, WriteBatch, WriteOptions, CF_DEFAULT, CF_LOCK, CF_WRITE, }; use error_code::ErrorCodeExt; @@ -5015,9 +5015,7 @@ where let snap_ctx = if let Ok(read_ts) = decode_u64(&mut req.get_header().get_flag_data()) { Some(SnapshotContext { - range: Some(CacheRange::from_region(®ion)), - region_id: region.id, - epoch_version: region.get_region_epoch().version, + region: Some(CacheRegion::from_region(®ion)), read_ts, }) } else { diff --git a/components/raftstore/src/store/worker/read.rs b/components/raftstore/src/store/worker/read.rs index 4983694df52..7311512ab21 100644 --- a/components/raftstore/src/store/worker/read.rs +++ b/components/raftstore/src/store/worker/read.rs @@ -12,7 +12,7 @@ use std::{ }; use crossbeam::{atomic::AtomicCell, channel::TrySendError}; -use engine_traits::{CacheRange, KvEngine, Peekable, RaftEngine, SnapshotContext}; +use engine_traits::{CacheRegion, KvEngine, Peekable, RaftEngine, SnapshotContext}; use fail::fail_point; use kvproto::{ errorpb, @@ -1071,9 +1071,7 @@ where match self.pre_propose_raft_command(&req) { Ok(Some((mut delegate, policy))) => { if let Some(ref mut ctx) = snap_ctx { - ctx.region_id = delegate.region.id; - ctx.epoch_version = delegate.region.get_region_epoch().version; - ctx.set_range(CacheRange::from_region(&delegate.region)) + ctx.set_region(CacheRegion::from_region(&delegate.region)) } let mut snap_updated = false; @@ -2602,10 +2600,8 @@ mod tests { } let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: 15, - range: None, + region: None, }; let s = get_snapshot(Some(snap_ctx.clone()), &mut reader, cmd.clone(), &rx); @@ -2685,9 +2681,7 @@ mod tests { reader.release_snapshot_cache(); let snap_ctx = SnapshotContext { read_ts: 15, - range: None, - region_id: 0, - epoch_version: 0, + region: None, }; reader.propose_raft_command(Some(snap_ctx), read_id, task.request, task.callback); assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 92c50aa9794..49b8d842767 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -9,11 +9,10 @@ use crossbeam::{ }; use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_traits::{ - CacheRange, EvictReason, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, + CacheRegion, EvictReason, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, SnapshotMiscExt, CF_DEFAULT, CF_WRITE, DATA_CFS, }; use hex::FromHexError; -use kvproto::metapb::Region; use parking_lot::RwLock; use pd_client::{PdClient, RpcClient}; use raftstore::coprocessor::RegionInfoProvider; @@ -39,7 +38,7 @@ use crate::{ GC_FILTERED_STATIC, RANGE_CACHE_COUNT, RANGE_CACHE_MEMORY_USAGE, RANGE_GC_TIME_HISTOGRAM, RANGE_LOAD_TIME_HISTOGRAM, }, - range_manager::{RangeMeta, RegionState}, + range_manager::{CacheRegionMeta, RegionState}, range_stats::{RangeStatsManager, DEFAULT_EVICT_MIN_DURATION}, region_label::{ KeyRangeRule, LabelRule, RegionLabelAddedCb, RegionLabelRulesManager, @@ -77,9 +76,9 @@ fn parse_write(value: &[u8]) -> Result, String> { #[derive(Debug)] pub enum BackgroundTask { Gc(GcTask), - LoadRegion(Region, Arc), + LoadRegion(CacheRegion, Arc), MemoryCheckAndEvict, - DeleteRegions(Vec), + DeleteRegions(Vec), TopRegionsLoadEvict, CleanLockTombstone(u64), SetRocksEngine(RocksEngine), @@ -289,7 +288,8 @@ impl BgWorkManager { let mut engine = core.write(); for r in regions { - if let Err(e) = engine.mut_range_manager().load_region(r.clone()) { + let cache_region = CacheRegion::from_region(&r); + if let Err(e) = engine.mut_range_manager().load_region(cache_region) { warn!("ime load region by label failed"; "err" => ?e, "region" => ?r); } } @@ -372,7 +372,7 @@ impl BackgroundRunnerCore { /// /// Returns empty vector if there are no ranges cached or the previous gc is /// not finished. - fn regions_for_gc(&self) -> Vec { + fn regions_for_gc(&self) -> Vec { let core = self.engine.read(); // another gc task is running, skipped. if !core.range_manager().try_set_regions_in_gc(true) { @@ -384,7 +384,7 @@ impl BackgroundRunnerCore { .values() .filter_map(|m| { if m.get_state() == RegionState::Active { - Some(m.region().clone()) + Some(m.get_region().clone()) } else { None } @@ -394,18 +394,17 @@ impl BackgroundRunnerCore { pub(crate) fn gc_region( &self, - region: &Region, + region: &CacheRegion, safe_point: u64, oldest_seqno: u64, ) -> FilterMetrics { - let range = CacheRange::from_region(region); let (skiplist_engine, safe_point) = { let mut core = self.engine.write(); // We should also consider the ongoing snapshot of the historical ranges (ranges // that have been evicted). let historical_safe_point = core .range_manager() - .get_history_regions_min_ts(&range) + .get_history_regions_min_ts(region) .unwrap_or(u64::MAX); let Some(region_meta) = core.mut_range_manager().mut_region_meta(region.id) else { @@ -413,7 +412,7 @@ impl BackgroundRunnerCore { }; if region_meta.get_state() != RegionState::Active - || !range.contains_range(region_meta.get_range()) + || !region.contains_range(region_meta.get_region()) { return FilterMetrics::default(); } @@ -437,7 +436,7 @@ impl BackgroundRunnerCore { "ime safe point update"; "prev" => region_meta.safe_point(), "current" => safe_point, - "range" => ?range, + "region" => ?region, ); region_meta.set_safe_point(safe_point); region_meta.set_in_gc(true); @@ -451,7 +450,7 @@ impl BackgroundRunnerCore { skiplist_engine.cf_handle(CF_DEFAULT), skiplist_engine.cf_handle(CF_WRITE), ); - filter.filter_keys_in_range(&range); + filter.filter_keys_in_range(region); { let mut engine = self.engine.write(); @@ -462,7 +461,7 @@ impl BackgroundRunnerCore { RANGE_GC_TIME_HISTOGRAM.observe(duration.as_secs_f64()); info!( "ime range gc complete"; - "range" => ?range, + "region" => ?region, "gc_duration" => ?duration, "total_version" => filter.metrics.total, "filtered_version" => filter.metrics.filtered, @@ -494,7 +493,7 @@ impl BackgroundRunnerCore { // if `false` is returned, the load is canceled fn on_snapshot_load_finished( &self, - region: &Region, + region: &CacheRegion, delete_range_scheduler: &Scheduler, safe_point: u64, ) -> bool { @@ -505,7 +504,7 @@ impl BackgroundRunnerCore { // We still need to check whether the snapshot is canceled during the load let region_meta = core.mut_range_manager().mut_region_meta(region.id).unwrap(); let mut remove_regions = vec![]; - let mut on_region_meta = |meta: &mut RangeMeta| { + let mut on_region_meta = |meta: &mut CacheRegionMeta| { assert!( meta.get_state() == RegionState::Loading || meta.get_state() == RegionState::LoadingCanceled, @@ -518,18 +517,17 @@ impl BackgroundRunnerCore { } else { assert_eq!(meta.get_state(), RegionState::LoadingCanceled); meta.mark_evict(RegionState::Evicting, EvictReason::LoadFailed); - remove_regions.push(meta.region().clone()); + remove_regions.push(meta.get_region().clone()); } }; - if region_meta.region().get_region_epoch().version == region.get_region_epoch().version { + if region_meta.get_region().epoch_version == region.epoch_version { on_region_meta(region_meta); } else { // epoch version changed, should use scan to find all overlapped regions - let range = CacheRange::from_region(region); core.range_manager - .iter_overlapped_regions_mut(&range, |meta| { - assert!(range.contains_range(meta.get_range())); + .iter_overlapped_regions_mut(region, |meta| { + assert!(region.contains_range(meta.get_region())); on_region_meta(meta); }); } @@ -557,7 +555,7 @@ impl BackgroundRunnerCore { fn on_snapshot_load_failed( &self, - region: &Region, + region: &CacheRegion, delete_range_scheduler: &Scheduler, started: bool, ) { @@ -565,7 +563,7 @@ impl BackgroundRunnerCore { let region_meta = core.range_manager.mut_region_meta(region.id).unwrap(); let mut remove_regions = vec![]; - let mut mark_region_evicted = |meta: &mut RangeMeta| { + let mut mark_region_evicted = |meta: &mut CacheRegionMeta| { assert!( meta.get_state() == RegionState::Loading || meta.get_state() == RegionState::LoadingCanceled @@ -576,17 +574,16 @@ impl BackgroundRunnerCore { EvictReason::LoadFailedWithoutStart }; meta.mark_evict(RegionState::Evicting, reason); - remove_regions.push(meta.region().clone()); + remove_regions.push(meta.get_region().clone()); }; - if region_meta.region().get_region_epoch().version == region.get_region_epoch().version { + if region_meta.get_region().epoch_version == region.epoch_version { mark_region_evicted(region_meta); } else { // epoch version changed, should use scan to find all overlap regions - let range = CacheRange::from_region(region); core.range_manager - .iter_overlapped_regions_mut(&range, |meta| { - assert!(range.contains_range(meta.get_range())); + .iter_overlapped_regions_mut(region, |meta| { + assert!(region.contains_range(meta.get_region())); mark_region_evicted(meta); }); } @@ -640,14 +637,15 @@ impl BackgroundRunnerCore { if remaining == 0 { break; } + let cache_region = CacheRegion::from_region(®ion); let mut engine_wr = self.engine.write(); let deleteable_regions = engine_wr .mut_range_manager() - .evict_region(®ion, EvictReason::MemoryLimitReached); + .evict_region(&cache_region, EvictReason::MemoryLimitReached); if !deleteable_regions.is_empty() { info!( "ime evict on soft limit reached"; - "region_to_evict" => ?region, + "region_to_evict" => ?cache_region, "regions_evicted" => ?&deleteable_regions, "approx_size" => approx_size, "remaining" => remaining @@ -700,13 +698,14 @@ impl BackgroundRunnerCore { info!("ime load_evict"; "ranges_to_add" => ?®ions_to_add, "may_evict" => ?®ions_to_remove); for evict_region in regions_to_remove { if self.memory_controller.reached_soft_limit() { + let cache_region = CacheRegion::from_region(&evict_region); let mut core = self.engine.write(); let deleteable_regions = core .mut_range_manager() - .evict_region(&evict_region, EvictReason::AutoEvict); + .evict_region(&cache_region, EvictReason::AutoEvict); info!( "ime load_evict: soft limit reached"; - "region_to_evict" => ?&evict_region, + "region_to_evict" => ?&cache_region, "evicted_regions" => ?&deleteable_regions, ); regions_to_delete.extend(deleteable_regions); @@ -725,8 +724,9 @@ impl BackgroundRunnerCore { } } for region in regions_to_add { + let cache_region = CacheRegion::from_region(®ion); let mut core = self.engine.write(); - if let Err(e) = core.mut_range_manager().load_region(region.clone()) { + if let Err(e) = core.mut_range_manager().load_region(cache_region) { error!("ime error loading range"; "cache_range" => ?region, "err" => ?e); } } @@ -922,7 +922,6 @@ impl Runnable for BackgroundRunner { fail::fail_point!("before_start_loading_region"); fail::fail_point!("on_start_loading_region"); let mut is_canceled = false; - let region_range = CacheRange::from_region(®ion); let skiplist_engine = { let engine = core.engine.read(); let region_meta = engine.range_manager().region_meta(region.id).unwrap(); @@ -955,8 +954,8 @@ impl Runnable for BackgroundRunner { info!("ime Loading region"; "region" => ?®ion); let start = Instant::now(); let iter_opt = IterOptions::new( - Some(KeyBuilder::from_slice(®ion_range.start, 0, 0)), - Some(KeyBuilder::from_slice(®ion_range.end, 0, 0)), + Some(KeyBuilder::from_slice(®ion.start, 0, 0)), + Some(KeyBuilder::from_slice(®ion.end, 0, 0)), false, ); @@ -1040,7 +1039,7 @@ impl Runnable for BackgroundRunner { skiplist_engine.cf_handle(CF_DEFAULT), skiplist_engine.cf_handle(CF_WRITE), ); - filter.filter_keys_in_range(®ion_range); + filter.filter_keys_in_range(®ion); Some(safe_point) }; @@ -1209,7 +1208,7 @@ pub struct DeleteRangeRunner { // written by apply threads. In that case, we have to delay the delete range task to avoid race // condition between them. Periodically, these delayed ranges will be checked to see if it is // ready to be deleted. - delay_regions: Vec, + delay_regions: Vec, } impl DeleteRangeRunner { @@ -1220,11 +1219,10 @@ impl DeleteRangeRunner { } } - fn delete_regions(&mut self, regions: &[Region]) { + fn delete_regions(&mut self, regions: &[CacheRegion]) { let skiplist_engine = self.engine.read().engine(); for r in regions { - let range = CacheRange::from_region(r); - skiplist_engine.delete_range(&range); + skiplist_engine.delete_range(r); } self.engine .write() @@ -1250,17 +1248,14 @@ impl Runnable for DeleteRangeRunner { let mut regions_to_delete = vec![]; for r in regions { let region_meta = core.range_manager.region_meta(r.id).unwrap(); - assert_eq!( - region_meta.region().get_region_epoch().version, - r.get_region_epoch().version - ); + assert_eq!(region_meta.get_region().epoch_version, r.epoch_version); assert_eq!(region_meta.get_state(), RegionState::Evicting); // If the range is overlapped with ranges in `ranges_being_written`, the // range has to be delayed to delete. See comment on `delay_ranges`. if region_meta.is_in_gc() || core .range_manager - .is_overlapped_with_regions_being_written(region_meta.get_range()) + .is_overlapped_with_regions_being_written(region_meta.get_region()) { regions_to_delay.push(r); } else { @@ -1380,10 +1375,10 @@ impl Filter { } } - fn filter_keys_in_range(&mut self, range: &CacheRange) { + fn filter_keys_in_range(&mut self, region: &CacheRegion) { let mut iter = self.write_cf_handle.iterator(); let guard = &epoch::pin(); - let (start_key, end_key) = encode_key_for_boundary_with_mvcc(range); + let (start_key, end_key) = encode_key_for_boundary_with_mvcc(region); iter.seek(&start_key, guard); while iter.valid() && iter.key() < &end_key { let k = iter.key(); @@ -1545,11 +1540,12 @@ pub mod tests { use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, IterOptions, Iterable, Iterator, RangeCacheEngine, RegionEvent, SyncMutable, + CacheRegion, IterOptions, Iterable, Iterator, RangeCacheEngine, RegionEvent, SyncMutable, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use futures::future::ready; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; + use kvproto::metapb::Region; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use pd_client::PdClient; use tempfile::Builder; @@ -1821,7 +1817,7 @@ pub mod tests { ))); let memory_controller = engine.memory_controller(); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let cache_region = CacheRegion::from_region(®ion); engine.new_region(region.clone()); let (write, default) = { @@ -1891,11 +1887,11 @@ pub mod tests { delete_data(b"key2", 40, 18, &write, memory_controller.clone()); let snap = engine - .snapshot(1, 0, range.clone(), u64::MAX, u64::MAX) + .snapshot(cache_region.clone(), u64::MAX, u64::MAX) .unwrap(); let mut iter_opts = IterOptions::default(); - iter_opts.set_lower_bound(&range.start, 0); - iter_opts.set_upper_bound(&range.end, 0); + iter_opts.set_lower_bound(&cache_region.start, 0); + iter_opts.set_upper_bound(&cache_region.end, 0); let (worker, _) = BackgroundRunner::new( engine.core.clone(), @@ -1905,7 +1901,7 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - worker.core.gc_region(®ion, 40, 100); + worker.core.gc_region(&cache_region, 40, 100); let mut iter = snap.iterator_opt("write", iter_opts).unwrap(); iter.seek_to_first().unwrap(); @@ -1983,23 +1979,24 @@ pub mod tests { Arc::new(MockPdClient {}), ); + let cache_region = CacheRegion::from_region(®ion); // gc should not hanlde keys with larger seqno than oldest seqno - worker.core.gc_region(®ion, 13, 10); + worker.core.gc_region(&cache_region, 13, 10); assert_eq!(3, element_count(&default)); assert_eq!(3, element_count(&write)); // gc will not remove the latest mvcc put below safe point - worker.core.gc_region(®ion, 14, 100); + worker.core.gc_region(&cache_region, 14, 100); assert_eq!(2, element_count(&default)); assert_eq!(2, element_count(&write)); - worker.core.gc_region(®ion, 16, 100); + worker.core.gc_region(&cache_region, 16, 100); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); // rollback will not make the first older version be filtered rollback_data(b"key1", 17, 16, &write, memory_controller.clone()); - worker.core.gc_region(®ion, 17, 100); + worker.core.gc_region(&cache_region, 17, 100); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); let key = encode_key(b"key1", TimeStamp::new(15)); @@ -2011,7 +2008,7 @@ pub mod tests { // unlike in WriteCompactionFilter, the latest mvcc delete below safe point will // be filtered delete_data(b"key1", 19, 18, &write, memory_controller.clone()); - worker.core.gc_region(®ion, 19, 100); + worker.core.gc_region(&cache_region, 19, 100); assert_eq!(0, element_count(&write)); assert_eq!(0, element_count(&default)); } @@ -2027,10 +2024,10 @@ pub mod tests { let (write, default, region1, region2) = { let mut core = engine.core().write(); - let region1 = new_region(1, b"k00", b"k10"); + let region1 = CacheRegion::new(1, 0, b"zk00", b"zk10"); core.mut_range_manager().new_region(region1.clone()); - let region2 = new_region(2, b"k30", b"k40"); + let region2 = CacheRegion::new(2, 0, b"zk30", b"zk40"); core.mut_range_manager().new_region(region2.clone()); let engine = core.engine(); @@ -2211,7 +2208,9 @@ pub mod tests { Arc::new(MockPdClient {}), ); - let filter = worker.core.gc_region(®ion, 20, 200); + let filter = worker + .core + .gc_region(&CacheRegion::from_region(®ion), 20, 200); assert_eq!(1, filter.filtered); assert_eq!(1, element_count(&default)); assert_eq!(1, element_count(&write)); @@ -2310,31 +2309,31 @@ pub mod tests { Duration::from_secs(100), Arc::new(MockPdClient {}), ); - let range = CacheRange::from_region(®ion); - let s1 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX); - let s2 = engine.snapshot(1, 0, range.clone(), 11, u64::MAX); - let s3 = engine.snapshot(1, 0, range.clone(), 20, u64::MAX); + let cache_region = CacheRegion::from_region(®ion); + let s1 = engine.snapshot(cache_region.clone(), 10, u64::MAX); + let s2 = engine.snapshot(cache_region.clone(), 11, u64::MAX); + let s3 = engine.snapshot(cache_region.clone(), 20, u64::MAX); // nothing will be removed due to snapshot 5 - let filter = worker.core.gc_region(®ion, 30, 100); + let filter = worker.core.gc_region(&cache_region, 30, 100); assert_eq!(0, filter.filtered); assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); drop(s1); - let filter = worker.core.gc_region(®ion, 30, 100); + let filter = worker.core.gc_region(&cache_region, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(5, element_count(&default)); assert_eq!(5, element_count(&write)); drop(s2); - let filter = worker.core.gc_region(®ion, 30, 100); + let filter = worker.core.gc_region(&cache_region, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(4, element_count(&default)); assert_eq!(4, element_count(&write)); drop(s3); - let filter = worker.core.gc_region(®ion, 30, 100); + let filter = worker.core.gc_region(&cache_region, 30, 100); assert_eq!(1, filter.filtered); assert_eq!(3, element_count(&default)); assert_eq!(3, element_count(&write)); @@ -2424,22 +2423,19 @@ pub mod tests { memory_controller.clone(), ); - let range = CacheRange::from_region(®ion); - let snap1 = engine.snapshot(1, 0, range.clone(), 20, 1000).unwrap(); - let snap2 = engine.snapshot(1, 0, range.clone(), 22, 1000).unwrap(); - let _snap3 = engine.snapshot(1, 0, range.clone(), 60, 1000).unwrap(); + let cache_region = CacheRegion::from_region(®ion); + let snap1 = engine.snapshot(cache_region.clone(), 20, 1000).unwrap(); + let snap2 = engine.snapshot(cache_region.clone(), 22, 1000).unwrap(); + let _snap3 = engine.snapshot(cache_region.clone(), 60, 1000).unwrap(); - let mut new_regions = vec![ - new_region(1, "", "key5"), - new_region(2, "key5", "key8"), - new_region(3, "key8", "z"), + let new_regions = vec![ + CacheRegion::new(1, 1, "z", "zkey5"), + CacheRegion::new(2, 1, "zkey5", "zkey8"), + CacheRegion::new(3, 1, "zkey8", cache_region.end.clone()), ]; - for r in &mut new_regions { - r.mut_region_epoch().version = 1; - } let region2 = new_regions[1].clone(); engine.on_region_event(RegionEvent::Split { - source: region.clone(), + source: cache_region.clone(), new_regions, }); assert_eq!(engine.core.read().range_manager().regions().len(), 3); @@ -2465,7 +2461,7 @@ pub mod tests { .values() .filter_map(|m| { if m.get_state() == RegionState::Active { - Some(m.region().clone()) + Some(m.get_region().clone()) } else { None } @@ -2522,8 +2518,8 @@ pub mod tests { } let k = format!("zk{:08}", 15).into_bytes(); - let region1 = new_region(1, DATA_MIN_KEY, k.clone()); - let region2 = new_region(2, k, DATA_MAX_KEY); + let region1 = CacheRegion::new(1, 0, DATA_MIN_KEY, k.clone()); + let region2 = CacheRegion::new(2, 0, k, DATA_MAX_KEY); { let mut core = engine.core.write(); core.mut_range_manager() @@ -2533,8 +2529,8 @@ pub mod tests { .load_region(region2.clone()) .unwrap(); } - engine.prepare_for_apply(1, CacheRange::from_region(®ion1), ®ion1); - engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + engine.prepare_for_apply(1, ®ion1); + engine.prepare_for_apply(1, ®ion2); // concurrent write to rocksdb, but the key will not be loaded in the memory // engine @@ -2561,22 +2557,10 @@ pub mod tests { std::thread::sleep(Duration::from_secs(1)); let _ = engine - .snapshot( - region1.id, - 0, - CacheRange::from_region(®ion1), - u64::MAX, - u64::MAX, - ) + .snapshot(region1.clone(), u64::MAX, u64::MAX) .unwrap(); let _ = engine - .snapshot( - region2.id, - 0, - CacheRange::from_region(®ion2), - u64::MAX, - u64::MAX, - ) + .snapshot(region2.clone(), u64::MAX, u64::MAX) .unwrap(); let guard = &epoch::pin(); @@ -2717,7 +2701,8 @@ pub mod tests { Duration::from_millis(200), || !engine.core.read().range_manager().regions().is_empty(), ); - engine.prepare_for_apply(1, CacheRange::from_region(®ion), ®ion); + let cache_region = CacheRegion::from_region(®ion); + engine.prepare_for_apply(1, &cache_region); // Wait for the range to be loaded. test_util::eventually( @@ -2728,15 +2713,7 @@ pub mod tests { core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active }, ); - let _ = engine - .snapshot( - region.id, - 0, - CacheRange::from_region(®ion), - u64::MAX, - u64::MAX, - ) - .unwrap(); + let _ = engine.snapshot(cache_region, u64::MAX, u64::MAX).unwrap(); let (write, default) = { let core = engine.core().write(); @@ -2828,7 +2805,7 @@ pub mod tests { for r in [®ion1, ®ion2, ®ion3] { engine.load_region(r.clone()).unwrap(); - engine.prepare_for_apply(1, CacheRange::from_region(r), r); + engine.prepare_for_apply(1, &CacheRegion::from_region(r)); } // ensure all ranges are finshed @@ -2846,16 +2823,10 @@ pub mod tests { if exist { let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); let snap = engine - .snapshot( - region.id, - 0, - CacheRange::from_region(region), - read_ts, - u64::MAX, - ) + .snapshot(CacheRegion::from_region(region), read_ts, u64::MAX) .unwrap(); let mut count = 0; - let range = CacheRange::from_region(region); + let range = CacheRegion::from_region(region); for cf in DATA_CFS { let mut iter = IterOptions::default(); iter.set_lower_bound(&range.start, 0); @@ -2870,7 +2841,7 @@ pub mod tests { assert_eq!(count, expect_count); } else { engine - .snapshot(region.id, 0, CacheRange::from_region(region), 10, 10) + .snapshot(CacheRegion::from_region(region), 10, 10) .unwrap_err(); } }; @@ -2911,7 +2882,7 @@ pub mod tests { rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); // After loading range1, the memory usage should be 140*6=840 engine.load_region(region1.clone()).unwrap(); - engine.prepare_for_apply(1, CacheRange::from_region(®ion1), ®ion1); + engine.prepare_for_apply(1, &CacheRegion::from_region(®ion1)); let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); let key = construct_key(3, 10); @@ -2936,7 +2907,7 @@ pub mod tests { assert_eq!(config.value().hard_limit_threshold(), 2000); engine.load_region(region2.clone()).unwrap(); - engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); // ensure all ranges are finshed test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { @@ -2953,10 +2924,10 @@ pub mod tests { if exist { let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); let snap = engine - .snapshot(r.id, 0, CacheRange::from_region(r), read_ts, u64::MAX) + .snapshot(CacheRegion::from_region(r), read_ts, u64::MAX) .unwrap(); let mut count = 0; - let range = CacheRange::from_region(r); + let range = CacheRegion::from_region(r); for cf in DATA_CFS { let mut iter = IterOptions::default(); iter.set_lower_bound(&range.start, 0); @@ -2971,7 +2942,7 @@ pub mod tests { assert_eq!(count, expect_count); } else { engine - .snapshot(r.id, 0, CacheRange::from_region(r), 10, 10) + .snapshot(CacheRegion::from_region(r), 10, 10) .unwrap_err(); } }; diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index aa15d0d7c00..09fe4d6362e 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -17,7 +17,7 @@ use crossbeam_skiplist::{ }; use engine_rocks::RocksEngine; use engine_traits::{ - CacheRange, EvictReason, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, + CacheRegion, EvictReason, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use kvproto::metapb::Region; @@ -151,11 +151,11 @@ impl SkiplistEngine { count } - pub(crate) fn delete_range_cf(&self, cf: &str, range: &CacheRange) { + pub(crate) fn delete_range_cf(&self, cf: &str, region: &CacheRegion) { let (start, end) = if cf == CF_LOCK { - encode_key_for_boundary_without_mvcc(range) + encode_key_for_boundary_without_mvcc(region) } else { - encode_key_for_boundary_with_mvcc(range) + encode_key_for_boundary_with_mvcc(region) }; let handle = self.cf_handle(cf); @@ -170,9 +170,9 @@ impl SkiplistEngine { guard.flush(); } - pub(crate) fn delete_range(&self, range: &CacheRange) { + pub(crate) fn delete_range(&self, region: &CacheRegion) { DATA_CFS.iter().for_each(|&cf| { - self.delete_range_cf(cf, range); + self.delete_range_cf(cf, region); }); } } @@ -298,17 +298,22 @@ impl RangeCacheMemoryEngine { } pub fn new_region(&self, region: Region) { - self.core.write().range_manager.new_region(region); + let cache_region = CacheRegion::from_region(®ion); + self.core.write().range_manager.new_region(cache_region); } pub fn load_region(&self, region: Region) -> result::Result<(), LoadFailedReason> { - self.core.write().mut_range_manager().load_region(region) + let cache_region = CacheRegion::from_region(®ion); + self.core + .write() + .mut_range_manager() + .load_region(cache_region) } /// Evict a region from the in-memory engine. After this call, the region /// will not be readable, but the data of the region may not be deleted /// immediately due to some ongoing snapshots. - pub fn evict_region(&self, region: &Region, evict_reason: EvictReason) { + pub fn evict_region(&self, region: &CacheRegion, evict_reason: EvictReason) { let deleteable_regions = self .core .write() @@ -334,8 +339,7 @@ impl RangeCacheMemoryEngine { pub(crate) fn prepare_for_apply( &self, write_batch_id: u64, - range: CacheRange, - region: &Region, + region: &CacheRegion, ) -> RangeCacheStatus { let mut core = self.core.write(); let range_manager = core.mut_range_manager(); @@ -347,7 +351,7 @@ impl RangeCacheMemoryEngine { if schedule_load { range_manager.update_region_state(region.id, RegionState::Loading); info!( - "ime range to load"; + "ime region to load"; "region" => ?region, "cached" => range_manager.regions().len(), ); @@ -356,7 +360,7 @@ impl RangeCacheMemoryEngine { let mut result = RangeCacheStatus::NotInCache; if region_state == RegionState::Loading || region_state == RegionState::Active { - range_manager.record_in_region_being_written(write_batch_id, range); + range_manager.record_in_region_being_written(write_batch_id, region.clone()); if region_state == RegionState::Active { result = RangeCacheStatus::Cached; } else { @@ -420,20 +424,11 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { fn snapshot( &self, - region_id: u64, - region_epoch: u64, - range: CacheRange, + region: CacheRegion, read_ts: u64, seq_num: u64, ) -> result::Result { - RangeCacheSnapshot::new( - self.clone(), - region_id, - region_epoch, - range, - read_ts, - seq_num, - ) + RangeCacheSnapshot::new(self.clone(), region, read_ts, seq_num) } type DiskEngine = RocksEngine; @@ -457,7 +452,7 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { .start_bg_hint_service(range_hint_service) } - fn get_region_for_key(&self, key: &[u8]) -> Option { + fn get_region_for_key(&self, key: &[u8]) -> Option { self.core.read().range_manager().get_region_for_key(key) } @@ -485,8 +480,8 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { .read() .range_manager() .iter_overlapped_regions(&range, |meta| { - assert!(meta.get_range().overlaps(&range)); - regions.push(meta.region().clone()); + assert!(meta.get_region().overlaps(&range)); + regions.push(meta.get_region().clone()); true }); for r in regions { @@ -511,20 +506,20 @@ pub mod tests { use std::sync::Arc; use crossbeam::epoch; - use engine_traits::{CacheRange, CF_DEFAULT, CF_LOCK, CF_WRITE}; + use engine_traits::{CacheRegion, CF_DEFAULT, CF_LOCK, CF_WRITE}; use tikv_util::config::{ReadableSize, VersionTrack}; use super::SkiplistEngine; use crate::{ keys::{construct_key, construct_user_key, encode_key}, memory_controller::MemoryController, - range_manager::{RangeMeta, RegionManager, RegionState::*}, + range_manager::{CacheRegionMeta, RegionManager, RegionState::*}, test_util::new_region, InternalBytes, RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, ValueType, }; - fn count_region(mgr: &RegionManager, mut f: impl FnMut(&RangeMeta) -> bool) -> usize { + fn count_region(mgr: &RegionManager, mut f: impl FnMut(&CacheRegionMeta) -> bool) -> usize { mgr.regions().values().filter(|m| f(m)).count() } #[test] @@ -537,7 +532,7 @@ pub mod tests { let mut region2 = new_region(1, b"k1", b"k5"); region2.mut_region_epoch().version = 2; - engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); assert_eq!( count_region(engine.core.read().range_manager(), |m| { matches!(m.get_state(), Pending | Loading) @@ -550,7 +545,7 @@ pub mod tests { let mut region2 = new_region(1, b"k2", b"k5"); region2.mut_region_epoch().version = 2; - engine.prepare_for_apply(1, CacheRange::from_region(®ion2), ®ion2); + engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); assert_eq!( count_region(engine.core.read().range_manager(), |m| { matches!(m.get_state(), Pending | Loading) @@ -596,7 +591,7 @@ pub mod tests { let start = construct_user_key(1); let end = construct_user_key(10); - let range = CacheRange::new(start, end); + let range = CacheRegion::new(1, 0, start, end); skiplist.delete_range(&range); let mut iter = handle.iterator(); @@ -648,7 +643,7 @@ pub mod tests { insert_kv(b"k3", b"val3", 103); insert_kv(b"k4", b"val4", 104); - let range = CacheRange::new(b"k1".to_vec(), b"k4".to_vec()); + let range = CacheRegion::new(1, 0, b"k1".to_vec(), b"k4".to_vec()); skiplist.delete_range(&range); let mut iter = lock_handle.iterator(); diff --git a/components/range_cache_memory_engine/src/keys.rs b/components/range_cache_memory_engine/src/keys.rs index 5015d08c90d..383d78e191a 100644 --- a/components/range_cache_memory_engine/src/keys.rs +++ b/components/range_cache_memory_engine/src/keys.rs @@ -8,7 +8,7 @@ use std::{ }; use bytes::{BufMut, Bytes}; -use engine_traits::CacheRange; +use engine_traits::CacheRegion; use txn_types::{Key, TimeStamp}; use crate::{memory_controller::MemoryController, write_batch::MEM_CONTROLLER_OVERHEAD}; @@ -232,7 +232,7 @@ pub fn encode_seek_for_prev_key(key: &[u8], seq: u64) -> InternalBytes { // range keys deos not contain mvcc version and sequence number #[inline] -pub fn encode_key_for_boundary_with_mvcc(range: &CacheRange) -> (InternalBytes, InternalBytes) { +pub fn encode_key_for_boundary_with_mvcc(range: &CacheRegion) -> (InternalBytes, InternalBytes) { // Both encoded_start and encoded_end should be the smallest key in the // respective of user key (with mvcc version), so that the iterations cover all // versions of the range start and covers nothing of range end. @@ -252,7 +252,7 @@ pub fn encode_key_for_boundary_with_mvcc(range: &CacheRange) -> (InternalBytes, } #[inline] -pub fn encode_key_for_boundary_without_mvcc(range: &CacheRange) -> (InternalBytes, InternalBytes) { +pub fn encode_key_for_boundary_without_mvcc(range: &CacheRegion) -> (InternalBytes, InternalBytes) { // Both encoded_start and encoded_end should be the smallest key in the // respective of user key (without mvcc version), so that the iterations cover // all versions of the range start and covers nothing of range end. diff --git a/components/range_cache_memory_engine/src/prop_test.rs b/components/range_cache_memory_engine/src/prop_test.rs index 8045a43cc51..187941beb7a 100644 --- a/components/range_cache_memory_engine/src/prop_test.rs +++ b/components/range_cache_memory_engine/src/prop_test.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use crossbeam::epoch; use engine_rocks::{util::new_engine, RocksEngine}; use engine_traits::{ - CacheRange, CfName, Iterable, Iterator, Peekable, SyncMutable, CF_DEFAULT, CF_LOCK, CF_WRITE, + CacheRegion, CfName, Iterable, Iterator, Peekable, SyncMutable, CF_DEFAULT, CF_LOCK, CF_WRITE, }; use proptest::prelude::*; use tikv_util::config::{ReadableSize, VersionTrack}; @@ -190,11 +190,11 @@ fn test_rocksdb_skiplist_basic_operations(cf: CfName, operations: Vec Operation::DeleteRange(k1, k2) => { if k1 <= k2 { db_rocks.delete_range_cf(cf, &k1, &k2).unwrap(); - let range = CacheRange::new(k1.clone(), k2.clone()); + let range = CacheRegion::new(1, 0, k1.clone(), k2.clone()); skiplist.delete_range_cf(cf, &range); } else { db_rocks.delete_range_cf(cf, &k2, &k1).unwrap(); - let range = CacheRange::new(k2.clone(), k1.clone()); + let range = CacheRegion::new(1, 0, k2.clone(), k1.clone()); skiplist.delete_range_cf(cf, &range); } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 2f0cbbc4823..a2c9033b436 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -11,8 +11,7 @@ use std::{ }; use collections::HashMap; -use engine_traits::{CacheRange, EvictReason, FailedReason}; -use kvproto::metapb::Region; +use engine_traits::{CacheRegion, EvictReason, FailedReason}; use tikv_util::{info, time::Instant, warn}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; @@ -86,10 +85,9 @@ impl SnapshotList { } #[derive(Debug)] -pub struct RangeMeta { - region: Region, - // the data range of this region. - range: CacheRange, +pub struct CacheRegionMeta { + // the cached region meta. + region: CacheRegion, // active region snapshots. region_snapshot_list: SnapshotList, // the gc safe point. @@ -107,12 +105,10 @@ struct EvictInfo { reason: EvictReason, } -impl RangeMeta { - fn new(region: Region) -> Self { - let range = CacheRange::from_region(®ion); +impl CacheRegionMeta { + fn new(region: CacheRegion) -> Self { Self { region, - range, region_snapshot_list: SnapshotList::default(), safe_point: 0, state: RegionState::Pending, @@ -122,7 +118,7 @@ impl RangeMeta { } #[inline] - pub fn region(&self) -> &Region { + pub fn get_region(&self) -> &CacheRegion { &self.region } @@ -130,18 +126,13 @@ impl RangeMeta { // happen for pending region because otherwise we will always update // the region epoch with ApplyObserver(for loading/active regions) or // no need to update the epoch for evicting regions. - fn amend_pending_region(&mut self, region: &Region) -> bool { - assert!( - self.region.id == region.id - && self.region.get_region_epoch().version < region.get_region_epoch().version - ); - let new_range = CacheRange::from_region(region); - if !self.range.contains_range(&new_range) { + fn amend_pending_region(&mut self, region: &CacheRegion) -> bool { + assert!(self.region.id == region.id && self.region.epoch_version < region.epoch_version); + if !self.region.contains_range(region) { return false; } self.region = region.clone(); - self.range = new_range; true } @@ -154,10 +145,6 @@ impl RangeMeta { self.safe_point = safe_point; } - pub fn get_range(&self) -> &CacheRange { - &self.range - } - pub fn get_state(&self) -> RegionState { self.state } @@ -181,7 +168,7 @@ impl RangeMeta { info!( "ime update region meta state"; "region_id" => self.region.id, - "epoch" => self.region.get_region_epoch().version, + "epoch" => self.region.epoch_version, "curr_state" => ?self.state, "new_state" => ?new_state); self.state = new_state; @@ -210,12 +197,10 @@ impl RangeMeta { // Build a new RangeMeta from a existing meta, the new meta should inherit // the safe_point, state, in_gc and evict_info. // This method is currently only used for handling region split. - pub(crate) fn derive_from(region: Region, source_meta: &Self) -> Self { - let range = CacheRange::from_region(®ion); - assert!(source_meta.range.contains_range(&range)); + pub(crate) fn derive_from(region: CacheRegion, source_meta: &Self) -> Self { + assert!(source_meta.region.contains_range(®ion)); Self { region, - range, region_snapshot_list: SnapshotList::default(), safe_point: source_meta.safe_point, state: source_meta.state, @@ -265,7 +250,7 @@ pub struct RegionManager { // data_end_key --> region_id regions_by_range: BTreeMap, u64>, // region_id --> region_meta - regions: HashMap, + regions: HashMap, // we use this flag to ensure there is only 1 running gc task. is_gc_task_running: AtomicBool, // Outdated regions that are split but still hold some on going snapshots. @@ -273,7 +258,7 @@ pub struct RegionManager { // It's possible that multi region with the same end key are in `historical_regions`, // so we add epoch version into the key to ensure the uniqueness. // (data_end_key, epoch_version) --> region_id - historical_regions: BTreeMap, + historical_regions: BTreeMap, // Record the region ranges that are being written. // // It is used to avoid the conccurency issue between delete range and write to memory: after @@ -287,49 +272,49 @@ pub struct RegionManager { // the ranges of this batch. So, when the write batch is consumed by the in-memory engine, // all ranges of it are cleared from `ranges_being_written`. // write_batch_id --> Vec - regions_being_written: HashMap>, + regions_being_written: HashMap>, } impl RegionManager { - pub(crate) fn regions(&self) -> &HashMap { + pub(crate) fn regions(&self) -> &HashMap { &self.regions } // load a new region directly in the active state. // This fucntion is used for unit/integration tests only. - pub fn new_region(&mut self, region: Region) { - let mut range_meta = RangeMeta::new(region); + pub fn new_region(&mut self, region: CacheRegion) { + let mut range_meta = CacheRegionMeta::new(region); range_meta.state = RegionState::Active; self.new_region_meta(range_meta); } - fn new_region_meta(&mut self, meta: RangeMeta) { - assert!(!self.overlaps_with(&meta.range)); + fn new_region_meta(&mut self, meta: CacheRegionMeta) { + assert!(!self.overlaps_with(&meta.region)); let id = meta.region.id; - let data_end_key = meta.range.end.clone(); + let data_end_key = meta.region.end.clone(); self.regions.insert(id, meta); self.regions_by_range.insert(data_end_key, id); } - pub fn region_meta(&self, id: u64) -> Option<&RangeMeta> { + pub fn region_meta(&self, id: u64) -> Option<&CacheRegionMeta> { self.regions.get(&id) } - pub fn mut_region_meta(&mut self, id: u64) -> Option<&mut RangeMeta> { + pub fn mut_region_meta(&mut self, id: u64) -> Option<&mut CacheRegionMeta> { self.regions.get_mut(&id) } pub fn iter_overlapped_regions( &self, - range: &CacheRange, - mut f: impl FnMut(&RangeMeta) -> bool, + region: &CacheRegion, + mut f: impl FnMut(&CacheRegionMeta) -> bool, ) { for (_key, id) in self .regions_by_range - .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(®ion.start), Unbounded)) { let region_meta = &self.regions[id]; - if region_meta.range.start >= range.end { + if region_meta.region.start >= region.end { break; } if !f(region_meta) { @@ -340,15 +325,15 @@ impl RegionManager { pub fn iter_overlapped_regions_mut( &mut self, - range: &CacheRange, - mut f: impl FnMut(&mut RangeMeta), + region: &CacheRegion, + mut f: impl FnMut(&mut CacheRegionMeta), ) { for (_key, id) in self .regions_by_range - .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(®ion.start), Unbounded)) { let region_meta = self.regions.get_mut(id).unwrap(); - if region_meta.range.start >= range.end { + if region_meta.region.start >= region.end { break; } f(region_meta); @@ -367,14 +352,14 @@ impl RegionManager { } } - pub fn get_region_for_key(&self, key: &[u8]) -> Option { + pub fn get_region_for_key(&self, key: &[u8]) -> Option { if let Some((key, id)) = self .regions_by_range .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(key), Unbounded)) .next() { let meta = &self.regions[id]; - if &meta.range.start <= key { + if &meta.region.start <= key { return Some(meta.region.clone()); } } @@ -385,13 +370,13 @@ impl RegionManager { self.regions.contains_key(®ion_id) } - pub fn check_region_state(&mut self, region: &Region) -> Option { + pub fn check_region_state(&mut self, region: &CacheRegion) -> Option { use RegionState::*; let Some(cached_meta) = self.regions.get_mut(®ion.id) else { return None; }; if cached_meta.state == Pending - && cached_meta.region.get_region_epoch().version != region.get_region_epoch().version + && cached_meta.region.epoch_version != region.epoch_version && !cached_meta.amend_pending_region(region) { info!("ime remove outdated pending region"; @@ -407,14 +392,14 @@ impl RegionManager { self.regions.get_mut(&id).unwrap().state = state; } - fn overlaps_with(&self, range: &CacheRange) -> bool { + fn overlaps_with(&self, region: &CacheRegion) -> bool { let entry = self .regions_by_range - .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(&range.start), Unbounded)) + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(®ion.start), Unbounded)) .next(); if let Some((_key, id)) = entry { let meta = &self.regions[id]; - if meta.range.start < range.end { + if meta.region.start < region.end { return true; } } @@ -425,14 +410,13 @@ impl RegionManager { /// target region. If there are regions with `pending` state and whose /// epoch version is smaller than target region, the pending regions will /// be removed first. - fn check_overlap_with_region(&mut self, region: &Region) -> Option { - let region_range = CacheRange::from_region(region); + fn check_overlap_with_region(&mut self, region: &CacheRegion) -> Option { let mut removed_regions = vec![]; let mut overlapped_region_state = None; - self.iter_overlapped_regions(®ion_range, |region_meta| { + self.iter_overlapped_regions(region, |region_meta| { // pending region with out-dated epoch, should be removed. if region_meta.state == RegionState::Pending - && region_meta.region.get_region_epoch().version < region.get_region_epoch().version + && region_meta.region.epoch_version < region.epoch_version { removed_regions.push(region_meta.region.id); return true; @@ -469,7 +453,7 @@ impl RegionManager { return Err(FailedReason::NotCached); } - if meta.region.get_region_epoch().version != region_epoch { + if meta.region.epoch_version != region_epoch { return Err(FailedReason::EpochNotMatch); } @@ -489,10 +473,10 @@ impl RegionManager { pub(crate) fn remove_region_snapshot( &mut self, snapshot_meta: &RangeCacheSnapshotMeta, - ) -> Vec { + ) -> Vec { // fast path: in most case, region is not changed. - if let Some(region_meta) = self.regions.get_mut(&snapshot_meta.region_id) - && region_meta.region.get_region_epoch().version == snapshot_meta.epoch_version + if let Some(region_meta) = self.regions.get_mut(&snapshot_meta.region.id) + && region_meta.region.epoch_version == snapshot_meta.region.epoch_version { // epoch not changed region_meta @@ -507,7 +491,10 @@ impl RegionManager { // slow path: region not found or epoch version changes, must fell in the // history regions. - let hist_key = KeyAndVersion(snapshot_meta.range.end.clone(), snapshot_meta.epoch_version); + let hist_key = KeyAndVersion( + snapshot_meta.region.end.clone(), + snapshot_meta.region.epoch_version, + ); let meta = self.historical_regions.get_mut(&hist_key).unwrap(); meta.region_snapshot_list .remove_snapshot(snapshot_meta.snapshot_ts); @@ -515,7 +502,7 @@ impl RegionManager { let mut deletable_regions = vec![]; if meta.region_snapshot_list.is_empty() { self.historical_regions.remove(&hist_key).unwrap(); - self.iter_overlapped_regions(&snapshot_meta.range, |meta| { + self.iter_overlapped_regions(&snapshot_meta.region, |meta| { if matches!( meta.get_state(), RegionState::PendingEvict | RegionState::Evicting @@ -541,39 +528,39 @@ impl RegionManager { // so we don't check these two factors here for simplicity. #[inline] fn region_ready_to_evict( - meta: &RangeMeta, - historical_regions: &BTreeMap, + meta: &CacheRegionMeta, + historical_regions: &BTreeMap, ) -> bool { if meta.state != RegionState::PendingEvict { return false; } meta.region_snapshot_list.is_empty() - && !Self::overlaps_with_historical_regions(&meta.range, historical_regions) + && !Self::overlaps_with_historical_regions(&meta.region, historical_regions) } fn overlaps_with_historical_regions( - range: &CacheRange, - historical_regions: &BTreeMap, + region: &CacheRegion, + historical_regions: &BTreeMap, ) -> bool { for (_, meta) in historical_regions.range(( - Excluded(KeyAndVersion(range.start.clone(), u64::MAX)), + Excluded(KeyAndVersion(region.start.clone(), u64::MAX)), Unbounded, )) { - if meta.range.start < range.end { + if meta.region.start < region.end { return true; } } false } - pub(crate) fn get_history_regions_min_ts(&self, range: &CacheRange) -> Option { + pub(crate) fn get_history_regions_min_ts(&self, region: &CacheRegion) -> Option { self.historical_regions .range(( - Excluded(KeyAndVersion(range.start.clone(), u64::MAX)), + Excluded(KeyAndVersion(region.start.clone(), u64::MAX)), Unbounded, )) .filter_map(|(_, meta)| { - if meta.range.start < range.end { + if meta.region.start < region.end { meta.region_snapshot_list.min_snapshot_ts() } else { None @@ -582,14 +569,14 @@ impl RegionManager { .min() } - pub(crate) fn on_gc_region_finished(&mut self, region: &Region) { + pub(crate) fn on_gc_region_finished(&mut self, region: &CacheRegion) { let region_meta = self.regions.get_mut(®ion.id).unwrap(); - if region_meta.region.get_region_epoch().version == region.get_region_epoch().version { + if region_meta.region.epoch_version == region.epoch_version { region_meta.set_in_gc(false); } else { - let range = region_meta.range.clone(); - self.iter_overlapped_regions_mut(&range, |meta| { - assert!(range.contains_range(&meta.range)); + let cache_region = region_meta.region.clone(); + self.iter_overlapped_regions_mut(&cache_region, |meta| { + assert!(cache_region.contains_range(&meta.region)); meta.set_in_gc(false); }); } @@ -611,9 +598,9 @@ impl RegionManager { // range. So, conservatively, we evict all ranges overlap with it. pub(crate) fn evict_region( &mut self, - evict_region: &Region, + evict_region: &CacheRegion, evict_reason: EvictReason, - ) -> Vec { + ) -> Vec { info!( "ime try to evict region"; "evict_region" => ?evict_region, @@ -622,7 +609,7 @@ impl RegionManager { if let Some(meta) = self.regions.get(&evict_region.id) { // if epoch not changed, no need to do range scan. - if meta.region.get_region_epoch().version == evict_region.get_region_epoch().version { + if meta.region.epoch_version == evict_region.epoch_version { if let Some(region) = self.do_evict_region(evict_region.id, evict_region, evict_reason) { @@ -633,9 +620,8 @@ impl RegionManager { let mut deleteable_regions = vec![]; let mut evict_ids = vec![]; - let evict_range = CacheRange::from_region(evict_region); - self.iter_overlapped_regions(&evict_range, |meta| { - if evict_range.start >= meta.range.end { + self.iter_overlapped_regions(evict_region, |meta| { + if evict_region.start >= meta.region.end { return false; } evict_ids.push(meta.region.id); @@ -658,13 +644,13 @@ impl RegionManager { fn do_evict_region( &mut self, id: u64, - evict_region: &Region, + evict_region: &CacheRegion, evict_reason: EvictReason, - ) -> Option { + ) -> Option { let meta = self.regions.get_mut(&id).unwrap(); let prev_state = meta.state; assert!( - meta.range.overlaps(&CacheRange::from_region(evict_region)), + meta.region.overlaps(evict_region), "meta: {:?}, evict_region: {:?}", meta, evict_region @@ -709,19 +695,16 @@ impl RegionManager { None } - fn remove_region(&mut self, id: u64) -> RangeMeta { + fn remove_region(&mut self, id: u64) -> CacheRegionMeta { let meta = self.regions.remove(&id).unwrap(); - self.regions_by_range.remove(&meta.range.end); + self.regions_by_range.remove(&meta.region.end); meta } - pub fn on_delete_regions(&mut self, regions: &[Region]) { + pub fn on_delete_regions(&mut self, regions: &[CacheRegion]) { for r in regions { let meta = self.remove_region(r.id); - assert_eq!( - meta.region.get_region_epoch().version, - r.get_region_epoch().version - ); + assert_eq!(meta.region.epoch_version, r.epoch_version); let evict_info = meta.evict_info.unwrap(); observe_eviction_duration( @@ -742,23 +725,23 @@ impl RegionManager { .is_ok() } - pub(crate) fn is_overlapped_with_regions_being_written(&self, range: &CacheRange) -> bool { + pub(crate) fn is_overlapped_with_regions_being_written(&self, region: &CacheRegion) -> bool { self.regions_being_written.iter().any(|(_, ranges)| { ranges .iter() - .any(|range_being_written| range_being_written.overlaps(range)) + .any(|range_being_written| range_being_written.overlaps(region)) }) } pub(crate) fn record_in_region_being_written( &mut self, write_batch_id: u64, - range: CacheRange, + region: CacheRegion, ) { self.regions_being_written .entry(write_batch_id) .or_default() - .push(range); + .push(region); } pub(crate) fn clear_regions_in_being_written( @@ -772,9 +755,9 @@ impl RegionManager { } } - pub fn load_region(&mut self, region: Region) -> Result<(), LoadFailedReason> { + pub fn load_region(&mut self, cache_region: CacheRegion) -> Result<(), LoadFailedReason> { use RegionState::*; - if let Some(state) = self.check_overlap_with_region(®ion) { + if let Some(state) = self.check_overlap_with_region(&cache_region) { let reason = match state { Pending | Loading => LoadFailedReason::PendingRange, Active => LoadFailedReason::Overlapped, @@ -782,7 +765,7 @@ impl RegionManager { }; return Err(reason); } - let meta = RangeMeta::new(region); + let meta = CacheRegionMeta::new(cache_region); self.new_region_meta(meta); Ok(()) } @@ -790,8 +773,8 @@ impl RegionManager { // return `true` is the region is evicted. pub(crate) fn split_region( &mut self, - source_region: &Region, - mut new_regions: Vec, + source_region: &CacheRegion, + mut new_regions: Vec, ) { if let Some(region_meta) = self.region_meta(source_region.id) { // if region is evicting, skip handling split for simplicity. @@ -807,20 +790,12 @@ impl RegionManager { let region_meta = self.remove_region(source_region.id); assert!(!region_meta.state.is_evict()); - if region_meta.region.get_region_epoch().version != source_region.get_region_epoch().version - { + if region_meta.region.epoch_version != source_region.epoch_version { // for pending regions, we keep regions that still fall in this range if epoch // version changed. assert_eq!(region_meta.state, RegionState::Pending); - assert!( - region_meta.region.get_region_epoch().version - < source_region.get_region_epoch().version - ); - new_regions.retain(|r| { - r.start_key <= source_region.start_key - && (source_region.end_key.is_empty() - || (source_region.end_key >= r.end_key && !r.end_key.as_slice().is_empty())) - }); + assert!(region_meta.region.epoch_version < source_region.epoch_version); + new_regions.retain(|r| region_meta.region.overlaps(r)); info!("ime handle split region met pending region epoch stale"; "cached" => ?region_meta, "split_source" => ?source_region, @@ -833,7 +808,7 @@ impl RegionManager { "new_regions" => ?new_regions); for r in new_regions { - let meta = RangeMeta::derive_from(r, ®ion_meta); + let meta = CacheRegionMeta::derive_from(r, ®ion_meta); self.new_region_meta(meta); } @@ -842,8 +817,8 @@ impl RegionManager { if !region_meta.region_snapshot_list.is_empty() { self.historical_regions.insert( KeyAndVersion( - region_meta.range.end.clone(), - region_meta.region.get_region_epoch().version, + region_meta.region.end.clone(), + region_meta.region.epoch_version, ), region_meta, ); @@ -867,15 +842,15 @@ pub enum RangeCacheStatus { #[cfg(test)] mod tests { - use engine_traits::{CacheRange, EvictReason, FailedReason}; + use engine_traits::{CacheRegion, EvictReason, FailedReason}; use super::*; - use crate::{range_manager::LoadFailedReason, test_util::new_region}; + use crate::range_manager::LoadFailedReason; #[test] fn test_range_manager() { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, "k00", b"k10"); + let r1 = CacheRegion::new(1, 0, "k00", b"k10"); range_mgr.new_region(r1.clone()); range_mgr.set_safe_point(r1.id, 5); @@ -884,33 +859,29 @@ mod tests { FailedReason::TooOldRead ); range_mgr.region_snapshot(r1.id, 0, 8).unwrap(); - let snapshot1 = RangeCacheSnapshotMeta::new(1, 0, CacheRange::from_region(&r1), 8, 1); + let snapshot1 = RangeCacheSnapshotMeta::new(r1.clone(), 8, 1); range_mgr.region_snapshot(r1.id, 0, 10).unwrap(); - let snapshot2 = RangeCacheSnapshotMeta::new(1, 0, CacheRange::from_region(&r1), 10, 2); + let snapshot2 = RangeCacheSnapshotMeta::new(r1.clone(), 10, 2); assert_eq!( range_mgr.region_snapshot(2, 0, 8).unwrap_err(), FailedReason::NotCached ); - let mut r_evict = new_region(2, b"k03", b"k06"); - let mut r_left = new_region(1, b"k00", b"k03"); - let mut r_right = new_region(3, b"k06", b"k10"); - for r in [&mut r_evict, &mut r_left, &mut r_right] { - r.mut_region_epoch().version = 2; - } + let r_evict = CacheRegion::new(2, 2, b"k03", b"k06"); + let r_left = CacheRegion::new(1, 2, b"k00", b"k03"); + let r_right = CacheRegion::new(3, 2, b"k06", b"k10"); range_mgr.split_region(&r1, vec![r_left.clone(), r_evict.clone(), r_right.clone()]); range_mgr.evict_region(&r_evict, EvictReason::AutoEvict); - let range1 = CacheRange::from_region(&r1); let meta1 = range_mgr .historical_regions - .get(&KeyAndVersion(range1.end.clone(), 0)) + .get(&KeyAndVersion(r1.end.clone(), 0)) .unwrap(); assert_eq!( range_mgr.regions.get(&r_evict.id).unwrap().state, RegionState::PendingEvict, ); assert_eq!( - range_mgr.regions_by_range.get(&range1.end).unwrap(), + range_mgr.regions_by_range.get(&r1.end).unwrap(), &r_right.id ); let meta2 = range_mgr.regions.get(&r_left.id).unwrap(); @@ -919,8 +890,7 @@ mod tests { // evict a range with accurate match range_mgr.region_snapshot(r_left.id, 2, 10).unwrap(); - let snapshot3 = - RangeCacheSnapshotMeta::new(r_left.id, 2, CacheRange::from_region(&r1), 10, 3); + let snapshot3 = RangeCacheSnapshotMeta::new(r_left.clone(), 10, 3); range_mgr.evict_region(&r_left, EvictReason::AutoEvict); assert_eq!( range_mgr.regions.get(&r_left.id).unwrap().state, @@ -946,11 +916,10 @@ mod tests { #[test] fn test_range_load() { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - let mut r2 = new_region(2, b"k10", b"k20"); - r2.mut_region_epoch().version = 2; - let r3 = new_region(3, b"k20", b"k30"); - let r4 = new_region(4, b"k25", b"k35"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let mut r2 = CacheRegion::new(2, 2, b"k10", b"k20"); + let r3 = CacheRegion::new(3, 0, b"k20", b"k30"); + let r4 = CacheRegion::new(4, 0, b"k25", b"k35"); range_mgr.new_region(r1.clone()); range_mgr.load_region(r2.clone()).unwrap(); @@ -963,7 +932,7 @@ mod tests { ); // load r2 with an outdated epoch. - r2.mut_region_epoch().version = 1; + r2.epoch_version = 1; assert_eq!( range_mgr.load_region(r2).unwrap_err(), LoadFailedReason::PendingRange, @@ -978,31 +947,30 @@ mod tests { #[test] fn test_range_load_overlapped() { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - // let r2 = new_region(2, b"k20", b"k30"); - let r3 = new_region(3, b"k40", b"k50"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); range_mgr.evict_region(&r1, EvictReason::AutoEvict); range_mgr.load_region(r3).unwrap(); - let r = new_region(4, b"k00", b"k05"); + let r = CacheRegion::new(4, 0, b"k00", b"k05"); assert_eq!( range_mgr.load_region(r).unwrap_err(), LoadFailedReason::Evicting ); - let r = new_region(4, b"k05", b"k15"); + let r = CacheRegion::new(4, 0, b"k05", b"k15"); assert_eq!( range_mgr.load_region(r).unwrap_err(), LoadFailedReason::Evicting ); - let r = new_region(4, b"k35", b"k45"); + let r = CacheRegion::new(4, 0, b"k35", b"k45"); assert_eq!( range_mgr.load_region(r).unwrap_err(), LoadFailedReason::PendingRange ); - let r = new_region(4, b"k45", b"k55"); + let r = CacheRegion::new(4, 0, b"k45", b"k55"); assert_eq!( range_mgr.load_region(r).unwrap_err(), LoadFailedReason::PendingRange @@ -1013,9 +981,9 @@ mod tests { fn test_evict_regions() { { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - let r2 = new_region(2, b"k20", b"k30"); - let r3 = new_region(3, b"k40", b"k50"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); + let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); range_mgr.new_region(r2.clone()); range_mgr.new_region(r3.clone()); @@ -1023,8 +991,7 @@ mod tests { range_mgr.contains_region(r2.id); range_mgr.contains_region(r3.id); - let mut r4 = new_region(4, b"k00", b"k05"); - r4.mut_region_epoch().version = 2; + let r4 = CacheRegion::new(4, 2, b"k00", b"k05"); assert_eq!( range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r1] @@ -1033,9 +1000,9 @@ mod tests { { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - let r2 = new_region(2, b"k20", b"k30"); - let r3 = new_region(3, b"k40", b"k50"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); + let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); range_mgr.new_region(r2.clone()); range_mgr.new_region(r3.clone()); @@ -1043,7 +1010,7 @@ mod tests { assert!(range_mgr.contains_region(r2.id)); assert!(range_mgr.contains_region(r3.id)); - let r4 = new_region(4, b"k", b"k51"); + let r4 = CacheRegion::new(4, 0, b"k", b"k51"); assert_eq!( range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r1, r2, r3] @@ -1058,14 +1025,14 @@ mod tests { { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - let r2 = new_region(2, b"k20", b"k30"); - let r3 = new_region(3, b"k40", b"k50"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); + let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); range_mgr.new_region(r2.clone()); range_mgr.new_region(r3.clone()); - let r4 = new_region(4, b"k25", b"k55"); + let r4 = CacheRegion::new(4, 0, b"k25", b"k55"); assert_eq!( range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r2, r3] @@ -1082,14 +1049,14 @@ mod tests { { let mut range_mgr = RegionManager::default(); - let r1 = new_region(1, b"k00", b"k10"); - let r2 = new_region(2, b"k30", b"k40"); - let r3 = new_region(3, b"k50", b"k60"); + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + let r2 = CacheRegion::new(2, 0, b"k30", b"k40"); + let r3 = CacheRegion::new(3, 0, b"k50", b"k60"); range_mgr.new_region(r1.clone()); range_mgr.new_region(r2.clone()); range_mgr.new_region(r3.clone()); - let r4 = new_region(4, b"k25", b"k75"); + let r4 = CacheRegion::new(4, 0, b"k25", b"k75"); assert_eq!( range_mgr.evict_region(&r4, EvictReason::AutoEvict), vec![r2, r3] diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index f763c0dfb19..8c58ce623db 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -8,7 +8,7 @@ use crossbeam::epoch::{self}; use crossbeam_skiplist::{base::OwnedIter, SkipList}; use engine_rocks::{raw::SliceTransform, util::FixedSuffixSliceTransform}; use engine_traits::{ - CacheRange, CfNamesExt, DbVector, Error, FailedReason, IterMetricsCollector, IterOptions, + CacheRegion, CfNamesExt, DbVector, Error, FailedReason, IterMetricsCollector, IterOptions, Iterable, Iterator, MetricsExt, Peekable, ReadOptions, Result, Snapshot, SnapshotMiscExt, CF_DEFAULT, }; @@ -43,9 +43,7 @@ enum Direction { #[derive(Clone, Debug)] pub struct RangeCacheSnapshotMeta { - pub(crate) range: CacheRange, - pub(crate) epoch_version: u64, - pub(crate) region_id: u64, + pub(crate) region: CacheRegion, pub(crate) snapshot_ts: u64, // Sequence number is shared between RangeCacheEngine and disk KvEnigne to // provide atomic write @@ -53,17 +51,9 @@ pub struct RangeCacheSnapshotMeta { } impl RangeCacheSnapshotMeta { - pub(crate) fn new( - region_id: u64, - epoch_version: u64, - range: CacheRange, - snapshot_ts: u64, - sequence_number: u64, - ) -> Self { + pub(crate) fn new(region: CacheRegion, snapshot_ts: u64, sequence_number: u64) -> Self { Self { - range, - epoch_version, - region_id, + region, snapshot_ts, sequence_number, } @@ -80,23 +70,15 @@ pub struct RangeCacheSnapshot { impl RangeCacheSnapshot { pub fn new( engine: RangeCacheMemoryEngine, - region_id: u64, - region_epoch: u64, - range: CacheRange, + region: CacheRegion, read_ts: u64, seq_num: u64, ) -> result::Result { let mut core = engine.core.write(); core.range_manager - .region_snapshot(region_id, region_epoch, read_ts)?; + .region_snapshot(region.id, region.epoch_version, read_ts)?; Ok(RangeCacheSnapshot { - snapshot_meta: RangeCacheSnapshotMeta::new( - region_id, - region_epoch, - range, - read_ts, - seq_num, - ), + snapshot_meta: RangeCacheSnapshotMeta::new(region, read_ts, seq_num), skiplist_engine: core.engine.clone(), engine: engine.clone(), }) @@ -146,15 +128,15 @@ impl Iterable for RangeCacheSnapshot { } let (lower_bound, upper_bound) = (lower_bound.unwrap(), upper_bound.unwrap()); - if lower_bound < self.snapshot_meta.range.start - || upper_bound > self.snapshot_meta.range.end + if lower_bound < self.snapshot_meta.region.start + || upper_bound > self.snapshot_meta.region.end { return Err(Error::Other(box_err!( "the bounderies required [{}, {}] exceeds the range of the snapshot [{}, {}]", log_wrappers::Value(&lower_bound), log_wrappers::Value(&upper_bound), - log_wrappers::Value(&self.snapshot_meta.range.start), - log_wrappers::Value(&self.snapshot_meta.range.end) + log_wrappers::Value(&self.snapshot_meta.region.start), + log_wrappers::Value(&self.snapshot_meta.region.end) ))); } @@ -190,12 +172,12 @@ impl Peekable for RangeCacheSnapshot { key: &[u8], ) -> Result> { fail::fail_point!("on_range_cache_get_value"); - if !self.snapshot_meta.range.contains_key(key) { + if !self.snapshot_meta.region.contains_key(key) { return Err(Error::Other(box_err!( "key {} not in range[{}, {}]", log_wrappers::Value(key), - log_wrappers::Value(&self.snapshot_meta.range.start), - log_wrappers::Value(&self.snapshot_meta.range.end) + log_wrappers::Value(&self.snapshot_meta.region.start), + log_wrappers::Value(&self.snapshot_meta.region.end) ))); } let mut iter = self.skiplist_engine.data[cf_to_id(cf)].owned_iter(); @@ -686,12 +668,11 @@ mod tests { raw::DBStatisticsTickerType, util::new_engine_opt, RocksDbOptions, RocksStatistics, }; use engine_traits::{ - CacheRange, EvictReason, FailedReason, IterMetricsCollector, IterOptions, Iterable, + CacheRegion, EvictReason, FailedReason, IterMetricsCollector, IterOptions, Iterable, Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, RegionEvent, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, }; use keys::DATA_PREFIX_KEY; - use kvproto::metapb::Region; use tempfile::Builder; use tikv_util::config::VersionTrack; @@ -740,8 +721,8 @@ mod tests { } }; - let range = CacheRange::from_region(®ion); - let s1 = engine.snapshot(1, 0, range.clone(), 5, u64::MAX).unwrap(); + let cache_region = CacheRegion::from_region(®ion); + let s1 = engine.snapshot(cache_region.clone(), 5, u64::MAX).unwrap(); { let mut core = engine.core.write(); @@ -749,22 +730,22 @@ mod tests { } assert_eq!( engine - .snapshot(region.id, 0, CacheRange::from_region(®ion), 5, u64::MAX) + .snapshot(cache_region.clone(), 5, u64::MAX) .unwrap_err(), FailedReason::TooOldRead ); - let s2 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); + let s2 = engine.snapshot(cache_region.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(5, 1); verify_snapshot_count(10, 1); - let s3 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); + let s3 = engine.snapshot(cache_region.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(10, 2); drop(s1); verify_snapshot_count(5, 0); drop(s2); verify_snapshot_count(10, 1); - let s4 = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); + let s4 = engine.snapshot(cache_region.clone(), 10, u64::MAX).unwrap(); verify_snapshot_count(10, 2); drop(s4); verify_snapshot_count(10, 1); @@ -898,7 +879,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -910,7 +891,7 @@ mod tests { put_key_val(&sl, "c", "vall", 10, 5); } - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -937,7 +918,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let cache_region = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -951,7 +932,7 @@ mod tests { let opts = ReadOptions::default(); { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 60).unwrap(); + let snapshot = engine.snapshot(cache_region.clone(), 10, 60).unwrap(); for i in 1..10 { for mvcc in 1..50 { let k = construct_key(i, mvcc); @@ -973,7 +954,7 @@ mod tests { // all deletions { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); + let snapshot = engine.snapshot(cache_region.clone(), 10, u64::MAX).unwrap(); for i in 1..10 { for mvcc in 1..50 { let k = construct_key(i, mvcc); @@ -989,7 +970,7 @@ mod tests { // some deletions { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 105).unwrap(); + let snapshot = engine.snapshot(cache_region.clone(), 10, 105).unwrap(); for mvcc in 1..50 { for i in 1..7 { let k = construct_key(i, mvcc); @@ -1018,7 +999,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); let step: i32 = 2; @@ -1031,7 +1012,7 @@ mod tests { } let mut iter_opt = IterOptions::default(); - let snapshot = engine.snapshot(1, 0, range.clone(), 10, u64::MAX).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); // boundaries are not set assert!(snapshot.iterator_opt("lock", iter_opt.clone()).is_err()); @@ -1048,7 +1029,7 @@ mod tests { // Not restricted by bounds, no deletion (seq_num 150) { - let snapshot = engine.snapshot(1, 0, range.clone(), 100, 150).unwrap(); + let snapshot = engine.snapshot(range.clone(), 100, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); verify_key_values( @@ -1084,7 +1065,7 @@ mod tests { // Not restricted by bounds, some deletions (seq_num 230) { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 230).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 230).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); verify_key_values( @@ -1128,7 +1109,7 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_first().unwrap()); @@ -1169,7 +1150,7 @@ mod tests { // with bounds, some deletions (seq_num 215) { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 215).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 215).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt).unwrap(); // sequence can see the deletion @@ -1206,7 +1187,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); let step: i32 = 2; @@ -1226,7 +1207,7 @@ mod tests { // Not restricted by bounds, no deletion (seq_num 150) { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); verify_key_values( @@ -1265,7 +1246,7 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); { - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 150).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt).unwrap(); assert!(iter.seek_to_last().unwrap()); @@ -1311,7 +1292,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -1339,7 +1320,7 @@ mod tests { // seq num 1 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 1).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 1).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va1"); @@ -1367,7 +1348,7 @@ mod tests { // seq num 2 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 2).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 2).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va1"); @@ -1380,7 +1361,7 @@ mod tests { // seq num 5 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 5).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 5).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"vb2"); @@ -1391,7 +1372,7 @@ mod tests { // seq num 6 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 6).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 6).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); assert_eq!(iter.value(), b"va4"); @@ -1435,7 +1416,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -1463,7 +1444,7 @@ mod tests { // seq num 1 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 1).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 1).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc1"); @@ -1481,7 +1462,7 @@ mod tests { // seq num 2 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 2).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 2).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc1"); @@ -1494,7 +1475,7 @@ mod tests { // seq num 5 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 5).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 5).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vb2"); @@ -1505,7 +1486,7 @@ mod tests { // seq num 6 { - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 6).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 6).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_last().unwrap(); assert_eq!(iter.value(), b"vc4"); @@ -1530,7 +1511,7 @@ mod tests { fn test_iter_user_skip() { let mut iter_opt = IterOptions::default(); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -1554,7 +1535,7 @@ mod tests { put_key_val(&sl, "b", v.as_str(), 10, s + i); } - let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("b", 10); @@ -1591,7 +1572,7 @@ mod tests { delete_key(&sl, "b", 10, s + i); } - let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("a", 10); @@ -1620,7 +1601,7 @@ mod tests { } let v = construct_value(50, 50); put_key_val(&sl, "b", v.as_str(), 10, 50); - let snapshot = engine.snapshot(1, 0, range.clone(), 10, 50).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, 50).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); let k = construct_mvcc_key("b", 10); @@ -1655,7 +1636,7 @@ mod tests { let v = construct_value(50, 50); put_key_val(&sl, "b", v.as_str(), 10, s + 50); - let snapshot = engine.snapshot(1, 0, range.clone(), 10, s + seq).unwrap(); + let snapshot = engine.snapshot(range.clone(), 10, s + seq).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(!iter.seek_to_first().unwrap()); assert!(!iter.valid().unwrap()); @@ -1674,7 +1655,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"k000", b"k100"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -1700,9 +1681,7 @@ mod tests { iter_opt.set_upper_bound(&upper_bound, 0); iter_opt.set_lower_bound(&lower_bound, 0); iter_opt.set_prefix_same_as_start(true); - let snapshot = engine - .snapshot(1, 0, range.clone(), u64::MAX, u64::MAX) - .unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, u64::MAX).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); // prefix seek, forward @@ -1747,7 +1726,7 @@ mod tests { fill_data_in_skiplist(sl.clone(), (1..60).step_by(1), 1..2, 1); }); - let evict_range = CacheRange::new(construct_user_key(20), construct_user_key(40)); + let evict_range = CacheRegion::new(1, 0, construct_user_key(20), construct_user_key(40)); sl_engine.delete_range(&evict_range); sl_engine.data.iter().for_each(|sl| { let mut iter = sl.owned_iter(); @@ -1770,7 +1749,7 @@ mod tests { }); } - fn verify_evict_region_deleted(engine: &RangeCacheMemoryEngine, region: &Region) { + fn verify_evict_region_deleted(engine: &RangeCacheMemoryEngine, region: &CacheRegion) { test_util::eventually( Duration::from_millis(100), Duration::from_millis(2000), @@ -1785,12 +1764,12 @@ mod tests { }, ); let write_handle = engine.core.read().engine.cf_handle("write"); - let start_key = encode_seek_key(®ion.start_key, u64::MAX); + let start_key = encode_seek_key(®ion.start, u64::MAX); let mut iter = write_handle.iterator(); let guard = &epoch::pin(); iter.seek(&start_key, guard); - let end = encode_seek_key(®ion.end_key, u64::MAX); + let end = encode_seek_key(®ion.end, u64::MAX); assert!(iter.key() > &end || !iter.valid()); } @@ -1800,7 +1779,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, construct_region_key(0), construct_region_key(30)); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); let guard = &epoch::pin(); @@ -1817,38 +1796,31 @@ mod tests { } } - let mut new_regions = vec![ - new_region(1, construct_region_key(0), construct_region_key(10)), - new_region(2, construct_region_key(10), construct_region_key(20)), - new_region(3, construct_region_key(20), construct_region_key(30)), + let new_regions = vec![ + CacheRegion::new(1, 1, construct_user_key(0), construct_user_key(10)), + CacheRegion::new(2, 1, construct_user_key(10), construct_user_key(20)), + CacheRegion::new(3, 1, construct_user_key(20), construct_user_key(30)), ]; - new_regions.iter_mut().for_each(|r| { - r.mut_region_epoch().version = 1; - }); engine.on_region_event(RegionEvent::Split { - source: region.clone(), + source: CacheRegion::from_region(®ion), new_regions: new_regions.clone(), }); let evict_region = new_regions[1].clone(); engine.evict_region(&evict_region, EvictReason::AutoEvict); assert_eq!( - engine.snapshot(1, 0, range.clone(), 10, 200).unwrap_err(), + engine.snapshot(range.clone(), 10, 200).unwrap_err(), FailedReason::EpochNotMatch ); assert_eq!( - engine - .snapshot(2, 1, CacheRange::from_region(&evict_region), 10, 200) - .unwrap_err(), + engine.snapshot(evict_region.clone(), 10, 200).unwrap_err(), FailedReason::NotCached ); let r_left = new_regions[0].clone(); let r_right = new_regions[2].clone(); - let snap_left = engine - .snapshot(r_left.id, 1, CacheRange::from_region(&r_left), 10, 200) - .unwrap(); + let snap_left = engine.snapshot(r_left, 10, 200).unwrap(); let mut iter_opt = IterOptions::default(); let lower_bound = construct_user_key(0); @@ -1859,9 +1831,7 @@ mod tests { iter.seek_to_first().unwrap(); verify_key_values(&mut iter, (0..10).step_by(1), 10..11, true, true); - let snap_right = engine - .snapshot(r_right.id, 1, CacheRange::from_region(&r_right), 10, 200) - .unwrap(); + let snap_right = engine.snapshot(r_right, 10, 200).unwrap(); let lower_bound = construct_user_key(20); let upper_bound = construct_user_key(30); iter_opt.set_upper_bound(&upper_bound, 0); @@ -1900,21 +1870,17 @@ mod tests { } } - let range = CacheRange::from_region(®ion); - let s1 = engine.snapshot(1, 0, range.clone(), 10, 10); - let s2 = engine.snapshot(1, 0, range, 20, 20); + let cache_region = CacheRegion::from_region(®ion); + let s1 = engine.snapshot(cache_region.clone(), 10, 10); + let s2 = engine.snapshot(cache_region.clone(), 20, 20); - let mut new_regions = vec![ - new_region(1, construct_region_key(0), construct_region_key(10)), - new_region(2, construct_region_key(10), construct_region_key(20)), - new_region(3, construct_region_key(20), construct_region_key(30)), + let new_regions = vec![ + CacheRegion::new(1, 1, construct_user_key(0), construct_user_key(10)), + CacheRegion::new(2, 1, construct_user_key(10), construct_user_key(20)), + CacheRegion::new(3, 1, construct_user_key(20), construct_user_key(30)), ]; - new_regions.iter_mut().for_each(|r| { - r.mut_region_epoch().version = 1; - }); - engine.on_region_event(RegionEvent::Split { - source: region.clone(), + source: cache_region.clone(), new_regions: new_regions.clone(), }); @@ -1922,25 +1888,9 @@ mod tests { engine.evict_region(&evict_region, EvictReason::AutoEvict); let r_left = new_regions[0].clone(); - let s3 = engine - .snapshot( - r_left.id, - r_left.get_region_epoch().version, - CacheRange::from_region(&r_left), - 20, - 20, - ) - .unwrap(); + let s3 = engine.snapshot(r_left.clone(), 20, 20).unwrap(); let r_right = new_regions[2].clone(); - let s4 = engine - .snapshot( - r_right.id, - r_right.get_region_epoch().version, - CacheRange::from_region(&r_left), - 20, - 20, - ) - .unwrap(); + let s4 = engine.snapshot(r_right, 20, 20).unwrap(); drop(s3); engine.evict_region(&r_left, EvictReason::AutoEvict); @@ -1988,7 +1938,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -2008,7 +1958,7 @@ mod tests { let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); while iter.valid().unwrap() { @@ -2033,7 +1983,7 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); { @@ -2071,7 +2021,7 @@ mod tests { } let statistics = engine.statistics(); - let snapshot = engine.snapshot(1, 0, range.clone(), u64::MAX, 100).unwrap(); + let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); assert_eq!(PERF_CONTEXT.with(|c| c.borrow().get_read_bytes), 0); let key = construct_mvcc_key("a", 10); snapshot.get_value_cf("write", &key).unwrap(); @@ -2158,18 +2108,16 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); let mut wb = engine.write_batch(); - wb.prepare_for_region(®ion); + wb.prepare_for_region(range.clone()); put_entries(&mut wb); wb.set_sequence_number(wb_sequence).unwrap(); wb.write().unwrap(); - let snap = engine - .snapshot(1, 0, range.clone(), 100, snap_sequence) - .unwrap(); + let snap = engine.snapshot(range.clone(), 100, snap_sequence).unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -2226,7 +2174,8 @@ mod tests { let mut wb = engine.write_batch(); let region = new_region(1, b"", b"z"); - wb.prepare_for_region(®ion); + let cache_region = CacheRegion::from_region(®ion); + wb.prepare_for_region(cache_region); wb.put(b"zb", b"f").unwrap(); wb.set_sequence_number(200).unwrap(); @@ -2289,8 +2238,8 @@ mod tests { }); // For sequence number 102 - let range = CacheRange::new(b"".to_vec(), b"z".to_vec()); - let snap = engine.snapshot(1, 0, range.clone(), 100, 102).unwrap(); + let range = CacheRegion::new(1, 0, b"".to_vec(), b"z".to_vec()); + let snap = engine.snapshot(range.clone(), 100, 102).unwrap(); let mut iter_opt = IterOptions::default(); iter_opt.set_upper_bound(&range.end, 0); iter_opt.set_lower_bound(&range.start, 0); @@ -2332,7 +2281,7 @@ mod tests { assert!(!iter.valid().unwrap()); // For sequence number 104 - let snap = engine.snapshot(1, 0, range.clone(), 100, 104).unwrap(); + let snap = engine.snapshot(range.clone(), 100, 104).unwrap(); let mut iter = snap.iterator_opt("default", iter_opt.clone()).unwrap(); iter.seek(b"c").unwrap(); assert_eq!(iter.key(), b"c"); @@ -2370,7 +2319,7 @@ mod tests { assert!(!iter.valid().unwrap()); // For sequence number 108 - let snap = engine.snapshot(1, 0, range.clone(), 100, 108).unwrap(); + let snap = engine.snapshot(range.clone(), 100, 108).unwrap(); let mut iter = snap.iterator_opt("default", iter_opt.clone()).unwrap(); iter.seek(b"c").unwrap(); assert_eq!(iter.key(), b"c"); diff --git a/components/range_cache_memory_engine/src/region_label.rs b/components/range_cache_memory_engine/src/region_label.rs index 36cf716ead3..9e0d5cc8d66 100644 --- a/components/range_cache_memory_engine/src/region_label.rs +++ b/components/range_cache_memory_engine/src/region_label.rs @@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration}; use dashmap::DashMap; -use engine_traits::CacheRange; +use engine_traits::CacheRegion; use futures::{ compat::Future01CompatExt, stream::{self, StreamExt}, @@ -50,13 +50,13 @@ pub struct KeyRangeRule { pub end_key: String, } -impl TryFrom<&KeyRangeRule> for CacheRange { +impl TryFrom<&KeyRangeRule> for CacheRegion { type Error = Box; fn try_from(key_range: &KeyRangeRule) -> Result { let start_key = data_key(&hex::decode(&key_range.start_key)?); let end_key = data_end_key(&hex::decode(&key_range.end_key)?); - Ok(CacheRange::new(start_key, end_key)) + Ok(CacheRegion::new(0, 0, start_key, end_key)) } } pub type RegionLabelAddedCb = Arc; diff --git a/components/range_cache_memory_engine/src/test_util.rs b/components/range_cache_memory_engine/src/test_util.rs index 4f68378a03a..8c5ecefe7cc 100644 --- a/components/range_cache_memory_engine/src/test_util.rs +++ b/components/range_cache_memory_engine/src/test_util.rs @@ -174,7 +174,7 @@ pub fn new_region>, T2: Into>>(id: u64, start: T1, end: region.id = id; region.start_key = start.into(); region.end_key = end.into(); - // push a dummy peer to avoid CacheRange::from_region panic. + // push a dummy peer to avoid CacheRegion::from_region panic. region.mut_peers().push(Peer::default()); region } diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 8db3081d5d5..66b06dae283 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -8,10 +8,9 @@ use std::{ use bytes::Bytes; use crossbeam::epoch; use engine_traits::{ - CacheRange, EvictReason, MiscExt, Mutable, RangeCacheEngine, Result, WriteBatch, WriteBatchExt, - WriteOptions, CF_DEFAULT, + CacheRegion, EvictReason, MiscExt, Mutable, RangeCacheEngine, Result, WriteBatch, + WriteBatchExt, WriteOptions, CF_DEFAULT, }; -use kvproto::metapb::Region; use tikv_util::{box_err, config::ReadableSize, error, info, time::Instant, warn}; use crate::{ @@ -64,7 +63,7 @@ pub struct RangeCacheWriteBatch { memory_usage_reach_hard_limit: bool, region_save_point: usize, current_region_evicted: bool, - current_region: Option, + current_region: Option, // record the total durations of the prepare work for write in the write batch prepare_for_write_duration: Duration, @@ -249,22 +248,14 @@ impl RangeCacheWriteBatch { if !self.engine.enabled() { let region = self.current_region.as_ref().unwrap(); - info!( - "ime range cache is disabled, evict the range"; - "range_start" => log_wrappers::Value(®ion.start_key), - "range_end" => log_wrappers::Value(®ion.end_key), - ); + info!("ime range cache is disabled, evict the range"; "region" => ?region); self.evict_current_region(EvictReason::Disabled); return; } let memory_expect = entry_size(); if !self.memory_acquire(memory_expect) { let region = self.current_region.as_ref().unwrap(); - info!( - "ime memory acquire failed due to reaching hard limit"; - "range_start" => log_wrappers::Value(®ion.start_key), - "range_end" => log_wrappers::Value(®ion.end_key), - ); + info!("ime memory acquire failed due to reaching hard limit"; "region" => ?region); self.evict_current_region(EvictReason::MemoryLimitReached); return; } @@ -497,12 +488,11 @@ impl WriteBatch for RangeCacheWriteBatch { Ok(()) } - fn prepare_for_region(&mut self, region: &Region) { + fn prepare_for_region(&mut self, region: CacheRegion) { let time = Instant::now(); - self.current_region = Some(region.clone()); // TODO: remote range. - let range = CacheRange::from_region(region); - self.set_range_cache_status(self.engine.prepare_for_apply(self.id, range, region)); + self.set_range_cache_status(self.engine.prepare_for_apply(self.id, ®ion)); + self.current_region = Some(region); self.memory_usage_reach_hard_limit = false; self.region_save_point = self.buffer.len(); self.current_region_evicted = false; @@ -555,7 +545,7 @@ mod tests { use crossbeam_skiplist::SkipList; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, FailedReason, Peekable, RangeCacheEngine, WriteBatch, DATA_CFS, + CacheRegion, FailedReason, Peekable, RangeCacheEngine, WriteBatch, DATA_CFS, }; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use tempfile::Builder; @@ -595,7 +585,7 @@ mod tests { } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_region(&r); + wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"aaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); assert_eq!(wb.write().unwrap(), 1); @@ -618,7 +608,7 @@ mod tests { } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_region(&r); + wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"aaa", b"bbb").unwrap(); wb.set_save_point(); wb.put(b"aaa", b"ccc").unwrap(); @@ -646,18 +636,18 @@ mod tests { } let mut wb = RangeCacheWriteBatch::from(&engine); wb.range_cache_status = RangeCacheStatus::Cached; - wb.prepare_for_region(&r); + wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"zaaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); _ = wb.write(); wb.clear(); - wb.prepare_for_region(&r); + wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"zbbb", b"ccc").unwrap(); wb.delete(b"zaaa").unwrap(); wb.set_sequence_number(2).unwrap(); _ = wb.write(); let snapshot = engine - .snapshot(r.id, 0, CacheRange::from_region(&r), u64::MAX, 3) + .snapshot(CacheRegion::from_region(&r), u64::MAX, 3) .unwrap(); assert_eq!( snapshot.get_value(&b"zbbb"[..]).unwrap().unwrap(), @@ -687,7 +677,7 @@ mod tests { let mut r1_new = new_region(1, b"k01".to_vec(), b"k06".to_vec()); r1_new.mut_region_epoch().version = 2; let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r1_new); + wb.prepare_for_region(CacheRegion::from_region(&r1_new)); assert!(engine.core().read().range_manager().regions().is_empty()); wb.put(b"zk01", b"val1").unwrap(); wb.put(b"zk03", b"val1").unwrap(); @@ -704,12 +694,13 @@ mod tests { engine.load_region(r1.clone()).unwrap(); let mut r1_new = new_region(1, b"k01".to_vec(), b"k05".to_vec()); r1_new.mut_region_epoch().version = 2; + let cache_r1_new = CacheRegion::from_region(&r1_new); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r1_new); + wb.prepare_for_region(cache_r1_new.clone()); { let core = engine.core.read(); let region_meta = core.range_manager().region_meta(1).unwrap(); - assert_eq!(region_meta.region(), &r1_new); + assert_eq!(region_meta.get_region(), &cache_r1_new); assert_eq!(region_meta.get_state(), RegionState::Loading); } wb.put(b"zk02", b"val1").unwrap(); @@ -725,9 +716,7 @@ mod tests { core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active }, ); - let snapshot = engine - .snapshot(r1.id, 2, CacheRange::from_region(&r1_new), u64::MAX, 6) - .unwrap(); + let snapshot = engine.snapshot(cache_r1_new.clone(), u64::MAX, 6).unwrap(); for i in 1..5 { let res = snapshot.get_value(format!("zk0{}", i).as_bytes()).unwrap(); if i % 2 == 0 { @@ -741,7 +730,7 @@ mod tests { assert_eq!(skip_engine.node_count(), 2); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r1_new); + wb.prepare_for_region(cache_r1_new.clone()); wb.put(b"zk01", b"val2").unwrap(); wb.set_sequence_number(6).unwrap(); wb.write().unwrap(); @@ -757,7 +746,7 @@ mod tests { .set_state(RegionState::PendingEvict); } let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r1_new); + wb.prepare_for_region(cache_r1_new.clone()); wb.put(b"zk02", b"val2").unwrap(); wb.set_sequence_number(7).unwrap(); wb.write().unwrap(); @@ -804,23 +793,23 @@ mod tests { core.mut_range_manager().set_safe_point(r.id, 10); } let _ = engine - .snapshot(r.id, 0, CacheRange::from_region(r), 1000, 1000) + .snapshot(CacheRegion::from_region(r), 1000, 1000) .unwrap(); } let memory_controller = engine.memory_controller(); let val1: Vec = vec![0; 150]; let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(®ions[0]); + wb.prepare_for_region(CacheRegion::from_region(®ions[0])); // memory required: // 4(key) + 8(sequencen number) + 150(value) + 16(2 Arc = vec![3; 300]; - wb.prepare_for_region(®ions[4]); + wb.prepare_for_region(CacheRegion::from_region(®ions[4])); wb.put(b"zk41", &val4).unwrap(); // We should have allocated 740 as calculated above @@ -862,62 +851,35 @@ mod tests { assert_eq!(1246, memory_controller.mem_usage()); let snap1 = engine - .snapshot( - regions[0].id, - 0, - CacheRange::from_region(®ions[0]), - 1000, - 1010, - ) + .snapshot(CacheRegion::from_region(®ions[0]), 1000, 1010) .unwrap(); assert_eq!(snap1.get_value(b"zk01").unwrap().unwrap(), &val1); let snap2 = engine - .snapshot( - regions[1].id, - 0, - CacheRange::from_region(®ions[1]), - 1000, - 1010, - ) + .snapshot(CacheRegion::from_region(®ions[1]), 1000, 1010) .unwrap(); assert_eq!(snap2.get_value(b"zk11").unwrap().unwrap(), &val1); assert_eq!( engine - .snapshot( - regions[2].id, - 0, - CacheRange::from_region(®ions[2]), - 1000, - 1000 - ) + .snapshot(CacheRegion::from_region(®ions[2]), 1000, 1000) .unwrap_err(), FailedReason::NotCached ); let snap4 = engine - .snapshot( - regions[3].id, - 0, - CacheRange::from_region(®ions[3]), - 1000, - 1010, - ) + .snapshot(CacheRegion::from_region(®ions[3]), 1000, 1010) .unwrap(); assert_eq!(snap4.get_value(b"zk32").unwrap().unwrap(), &val3); let _snap5 = engine - .snapshot( - regions[4].id, - 0, - CacheRange::from_region(®ions[4]), - 1000, - 1010, - ) + .snapshot(CacheRegion::from_region(®ions[4]), 1000, 1010) .unwrap(); drop(snap1); - engine.evict_region(®ions[0], EvictReason::AutoEvict); + engine.evict_region( + &CacheRegion::from_region(®ions[0]), + EvictReason::AutoEvict, + ); wait_evict_done(&engine); flush_epoch(); assert_eq!(972, memory_controller.mem_usage()); @@ -941,16 +903,16 @@ mod tests { core.mut_range_manager().set_safe_point(r.id, 10); } let _ = engine - .snapshot(r.id, 0, CacheRange::from_region(r), 1000, 1000) + .snapshot(CacheRegion::from_region(r), 1000, 1000) .unwrap(); } let val1: Vec = (0..150).map(|_| 0).collect(); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r2); + wb.prepare_for_region(CacheRegion::from_region(&r2)); wb.put(b"zkk11", &val1).unwrap(); let snap1 = engine - .snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000) + .snapshot(CacheRegion::from_region(&r1), 1000, 1000) .unwrap(); // disable the range cache @@ -965,16 +927,16 @@ mod tests { assert!(snap1.get_value(b"zkk00").unwrap().is_none()); let mut wb = RangeCacheWriteBatch::from(&engine); - wb.prepare_for_region(&r1); + wb.prepare_for_region(CacheRegion::from_region(&r1)); // put should trigger the evict and it won't write into range cache wb.put(b"zkk01", &val1).unwrap(); wb.write_impl(1000).unwrap(); // new snapshot will fail to create as it's evicted already - let snap1 = engine.snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000); + let snap1 = engine.snapshot(CacheRegion::from_region(&r1), 1000, 1000); assert_eq!(snap1.unwrap_err(), FailedReason::NotCached); let snap2 = engine - .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) + .snapshot(CacheRegion::from_region(&r2), 1000, 1000) .unwrap(); // if no new write, the range cache can still be used. assert_eq!(snap2.get_value(b"zkk11").unwrap().unwrap(), &val1); @@ -985,10 +947,10 @@ mod tests { config_change.insert(String::from("enabled"), ConfigValue::Bool(true)); config_manager.dispatch(config_change).unwrap(); - let snap1 = engine.snapshot(r1.id, 0, CacheRange::from_region(&r1), 1000, 1000); + let snap1 = engine.snapshot(CacheRegion::from_region(&r1), 1000, 1000); assert_eq!(snap1.unwrap_err(), FailedReason::NotCached); let snap2 = engine - .snapshot(r2.id, 0, CacheRange::from_region(&r2), 1000, 1000) + .snapshot(CacheRegion::from_region(&r2), 1000, 1000) .unwrap(); assert_eq!(snap2.get_value(b"zkk11").unwrap().unwrap(), &val1); } diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 9f02caaf2b9..87730c16877 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -8,10 +8,10 @@ use std::{ use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRange, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, WriteBatchExt, + CacheRegion, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; -use keys::data_key; +use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; use kvproto::metapb::Region; use range_cache_memory_engine::{ decode_key, encode_key_for_boundary_without_mvcc, encoding_for_filter, @@ -65,7 +65,7 @@ fn test_gc_worker() { let (write, default) = { let mut core = engine.core().write(); core.mut_range_manager() - .new_region(new_region(1, b"", b"z")); + .new_region(CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY)); let engine = core.engine(); (engine.cf_handle(CF_WRITE), engine.cf_handle(CF_DEFAULT)) }; @@ -161,7 +161,7 @@ fn test_clean_up_tombstone() { let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config.clone())); let region = new_region(1, b"".to_vec(), b"z".to_vec()); - + let cache_region = CacheRegion::from_region(®ion); let (tx, rx) = sync_channel(0); fail::cfg_callback("clean_lock_tombstone_done", move || { tx.send(true).unwrap(); @@ -170,7 +170,7 @@ fn test_clean_up_tombstone() { engine.new_region(region.clone()); let mut wb = engine.write_batch(); - wb.prepare_for_region(®ion); + wb.prepare_for_region(cache_region.clone()); wb.put_cf("lock", b"k", b"val").unwrap(); wb.put_cf("lock", b"k1", b"val").unwrap(); wb.put_cf("lock", b"k2", b"val").unwrap(); @@ -182,7 +182,7 @@ fn test_clean_up_tombstone() { wb.write().unwrap(); let mut wb = engine.write_batch(); - wb.prepare_for_region(®ion); + wb.prepare_for_region(cache_region.clone()); wb.put_cf("lock", b"k", b"val").unwrap(); // seq 120 wb.put_cf("lock", b"k1", b"val").unwrap(); // seq 121 wb.put_cf("lock", b"k2", b"val").unwrap(); // seq 122 @@ -256,7 +256,7 @@ fn test_evict_with_loading_range() { let engine_clone = engine.clone(); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); - engine_clone.evict_region(&r, EvictReason::AutoEvict); + engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict); }) .unwrap(); @@ -270,11 +270,14 @@ fn test_evict_with_loading_range() { engine.load_region(r2.clone()).unwrap(); engine.load_region(r3.clone()).unwrap(); + let cache_region1 = CacheRegion::from_region(&r1); + let cache_region2 = CacheRegion::from_region(&r2); + let cache_region3 = CacheRegion::from_region(&r3); let mut wb = engine.write_batch(); // prepare range to trigger loading - wb.prepare_for_region(&r1); - wb.prepare_for_region(&r2); - wb.prepare_for_region(&r3); + wb.prepare_for_region(cache_region1.clone()); + wb.prepare_for_region(cache_region2.clone()); + wb.prepare_for_region(cache_region3.clone()); wb.set_sequence_number(10).unwrap(); wb.write().unwrap(); @@ -290,15 +293,9 @@ fn test_evict_with_loading_range() { .unwrap(); let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); - engine - .snapshot(r1.id, 0, CacheRange::from_region(&r1), read_ts, 100) - .unwrap_err(); - engine - .snapshot(r2.id, 0, CacheRange::from_region(&r2), read_ts, 100) - .unwrap_err(); - engine - .snapshot(r3.id, 0, CacheRange::from_region(&r3), read_ts, 100) - .unwrap(); + engine.snapshot(cache_region1, read_ts, 100).unwrap_err(); + engine.snapshot(cache_region2, read_ts, 100).unwrap_err(); + engine.snapshot(cache_region3, read_ts, 100).unwrap(); } #[test] @@ -332,12 +329,12 @@ fn test_cached_write_batch_cleared_when_load_failed() { let mut wb = engine.write_batch(); // range1 starts to load - wb.prepare_for_region(&r1); + wb.prepare_for_region(CacheRegion::from_region(&r1)); rx.recv_timeout(Duration::from_secs(5)).unwrap(); wb.put(b"zk05", b"val").unwrap(); wb.put(b"zk06", b"val").unwrap(); - wb.prepare_for_region(&r2); + wb.prepare_for_region(CacheRegion::from_region(&r2)); wb.put(b"zk25", b"val").unwrap(); wb.set_sequence_number(100).unwrap(); wb.write().unwrap(); @@ -401,31 +398,35 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { }) .unwrap(); + let cache_region1 = CacheRegion::from_region(&r1); + let cache_region2 = CacheRegion::from_region(&r2); + let cache_region3 = CacheRegion::from_region(&r3); + engine.new_region(r1.clone()); engine.new_region(r2.clone()); engine.load_region(r3.clone()).unwrap(); let engine_clone = engine.clone(); let (range_prepared_tx, range_prepared_rx) = sync_channel(0); - let region1_clone = r1.clone(); - let region2_clone = r2.clone(); - let region3_clone = r3.clone(); + let region1_clone = cache_region1.clone(); + let region2_clone = cache_region2.clone(); + let region3_clone = cache_region3.clone(); let handle = std::thread::spawn(move || { let mut wb = engine_clone.write_batch(); - wb.prepare_for_region(®ion1_clone); + wb.prepare_for_region(region1_clone); wb.put_cf(CF_LOCK, b"zk02", b"val").unwrap(); wb.put_cf(CF_LOCK, b"zk03", b"val").unwrap(); wb.put_cf(CF_LOCK, b"zk04", b"val").unwrap(); wb.set_sequence_number(100).unwrap(); let mut wb2 = engine_clone.write_batch(); - wb2.prepare_for_region(®ion2_clone); + wb2.prepare_for_region(region2_clone); wb.put_cf(CF_LOCK, b"zk22", b"val").unwrap(); wb.put_cf(CF_LOCK, b"zk23", b"val").unwrap(); wb2.set_sequence_number(200).unwrap(); let mut wb3 = engine_clone.write_batch(); - wb3.prepare_for_region(®ion3_clone); + wb3.prepare_for_region(region3_clone); wb3.set_sequence_number(300).unwrap(); range_prepared_tx.send(true).unwrap(); @@ -441,12 +442,12 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { // Now, three ranges are in write status, delete range will not be performed // until they leave the write status - engine.evict_region(&r1, EvictReason::AutoEvict); - engine.evict_region(&r2, EvictReason::AutoEvict); + engine.evict_region(&cache_region1, EvictReason::AutoEvict); + engine.evict_region(&cache_region2, EvictReason::AutoEvict); let verify_data = |r: &Region, expected_num: u64| { let handle = engine.core().read().engine().cf_handle(CF_LOCK); - let (start, end) = encode_key_for_boundary_without_mvcc(&CacheRange::from_region(r)); + let (start, end) = encode_key_for_boundary_without_mvcc(&CacheRegion::from_region(r)); let mut iter = handle.iterator(); let guard = &epoch::pin(); let mut count = 0; @@ -489,7 +490,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { snapshot_load_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - engine.evict_region(&r3, EvictReason::AutoEvict); + engine.evict_region(&CacheRegion::from_region(&r3), EvictReason::AutoEvict); fail::cfg("before_clear_ranges_in_being_written", "pause").unwrap(); write_batch_consume_rx @@ -520,17 +521,17 @@ fn test_double_delete_range_schedule() { ))); engine.set_disk_engine(rocks_engine); - let r1 = new_region(1, b"k00".to_vec(), b"k10".to_vec()); - let r2 = new_region(2, b"k20".to_vec(), b"k30".to_vec()); - let r3 = new_region(3, b"k40".to_vec(), b"k50".to_vec()); + let r1 = new_region(1, b"k00", b"k10"); + let r2 = new_region(2, b"k20", b"k30"); + let r3 = new_region(3, b"k40", b"k50"); let (snapshot_load_tx, snapshot_load_rx) = sync_channel(0); let engine_clone = engine.clone(); - let r = new_region(4, b"k00".to_vec(), b"k60".to_vec()); + let r = new_region(4, b"k00", b"k60"); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); // evict all ranges. So the loading ranges will also be evicted and a delete // range task will be scheduled. - engine_clone.evict_region(&r, EvictReason::AutoEvict); + engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict); }) .unwrap(); @@ -545,15 +546,15 @@ fn test_double_delete_range_schedule() { engine.load_region(r3.clone()).unwrap(); let snap1 = engine - .snapshot(r1.id, 0, CacheRange::from_region(&r1), 100, 100) + .snapshot(CacheRegion::from_region(&r1), 100, 100) .unwrap(); let snap2 = engine - .snapshot(r2.id, 0, CacheRange::from_region(&r2), 100, 100) + .snapshot(CacheRegion::from_region(&r2), 100, 100) .unwrap(); let mut wb = engine.write_batch(); // prepare range to trigger loading - wb.prepare_for_region(&r3); + wb.prepare_for_region(CacheRegion::from_region(&r3)); wb.set_sequence_number(10).unwrap(); wb.write().unwrap(); @@ -615,10 +616,10 @@ fn test_load_with_gc() { .unwrap(); let region = new_region(1, b"", b"z"); - let range = CacheRange::from_region(®ion); + let range = CacheRegion::from_region(®ion); engine.load_region(region.clone()).unwrap(); let mut wb = engine.write_batch(); - wb.prepare_for_region(®ion); + wb.prepare_for_region(range.clone()); wb.set_sequence_number(100).unwrap(); wb.write().unwrap(); @@ -640,10 +641,8 @@ fn test_load_with_gc() { } // ensure the safe point of the engine - engine - .snapshot(region.id, 0, range.clone(), 6, 100) - .unwrap_err(); - engine.snapshot(region.id, 0, range, 7, 100).unwrap(); + engine.snapshot(range.clone(), 6, 100).unwrap_err(); + engine.snapshot(range, 7, 100).unwrap(); } // test in-memory-engine can handle region split event after load region task @@ -671,6 +670,7 @@ fn test_region_split_before_batch_loading_start() { fail::cfg("on_start_loading_region", "pause").unwrap(); let region = new_region(1, b"k00", b"k30"); + let cache_region = CacheRegion::from_region(®ion); // write some data into rocksdb to trigger batch loading. for i in 0..30 { @@ -690,11 +690,11 @@ fn test_region_split_before_batch_loading_start() { // use write batch to trigger scheduling pending region loading task. let mut wb = engine.write_batch(); - wb.prepare_for_region(®ion); + wb.prepare_for_region(cache_region.clone()); wb.set_sequence_number(10).unwrap(); - wb.put(b"k00", b"val2").unwrap(); - wb.put(b"k10", b"val2").unwrap(); - wb.put(b"k20", b"val2").unwrap(); + wb.put(b"zk00", b"val2").unwrap(); + wb.put(b"zk10", b"val2").unwrap(); + wb.put(b"zk20", b"val2").unwrap(); wb.write().unwrap(); assert_eq!( engine @@ -711,16 +711,13 @@ fn test_region_split_before_batch_loading_start() { rx.recv().unwrap(); // split source region into multiple new regions. - let mut new_regions = vec![ - new_region(1, b"k00", b"k10"), - new_region(2, b"k10", b"k20"), - new_region(3, b"k20", b"k30"), + let new_regions = vec![ + CacheRegion::new(1, 2, b"zk00", b"zk10"), + CacheRegion::new(2, 2, b"zk10", b"zk20"), + CacheRegion::new(3, 2, b"zk20", b"zk30"), ]; - for r in &mut new_regions { - r.mut_region_epoch().version = 2; - } let event = RegionEvent::Split { - source: region.clone(), + source: cache_region.clone(), new_regions: new_regions.clone(), }; engine.on_region_event(event); diff --git a/components/test_raftstore-v2/src/util.rs b/components/test_raftstore-v2/src/util.rs index 0efad0505e8..5d87a3f5b02 100644 --- a/components/test_raftstore-v2/src/util.rs +++ b/components/test_raftstore-v2/src/util.rs @@ -198,17 +198,31 @@ pub fn wait_for_synced( .get(&node_id) .unwrap() .clone(); - let leader = cluster.leader_of_region(region_id).unwrap(); - let epoch = cluster.get_region_epoch(region_id); - let mut ctx = Context::default(); - ctx.set_region_id(region_id); - ctx.set_peer(leader); - ctx.set_region_epoch(epoch); - let snap_ctx = SnapContext { - pb_ctx: &ctx, - ..Default::default() + + let mut count = 0; + let snapshot = loop { + count += 1; + let leader = cluster.leader_of_region(region_id).unwrap(); + let epoch = cluster.get_region_epoch(region_id); + let mut ctx = Context::default(); + ctx.set_region_id(region_id); + ctx.set_peer(leader); + ctx.set_region_epoch(epoch); + let snap_ctx = SnapContext { + pb_ctx: &ctx, + ..Default::default() + }; + match storage.snapshot(snap_ctx) { + Ok(s) => break s, + Err(e) => { + if count <= 5 { + continue; + } + panic!("all retry failed: {:?}", e); + } + } }; - let snapshot = storage.snapshot(snap_ctx).unwrap(); + let txn_ext = snapshot.txn_ext.clone().unwrap(); for retry in 0..10 { if txn_ext.is_max_ts_synced() { diff --git a/components/test_raftstore/src/cluster.rs b/components/test_raftstore/src/cluster.rs index d417a4b88df..0167c9b6629 100644 --- a/components/test_raftstore/src/cluster.rs +++ b/components/test_raftstore/src/cluster.rs @@ -19,7 +19,7 @@ use encryption_export::DataKeyManager; use engine_rocks::{RocksCompactedEvent, RocksEngine, RocksStatistics}; use engine_test::raft::RaftTestEngine; use engine_traits::{ - CacheRange, Engines, Iterable, KvEngine, ManualCompactionOptions, Mutable, Peekable, + CacheRegion, Engines, Iterable, KvEngine, ManualCompactionOptions, Mutable, Peekable, RaftEngineReadOnly, SnapshotContext, SyncMutable, WriteBatch, CF_DEFAULT, CF_RAFT, }; use file_system::IoRateLimiter; @@ -1025,12 +1025,7 @@ where } else { let ctx = SnapshotContext { read_ts: u64::MAX, - range: Some(CacheRange::new( - DATA_MIN_KEY.to_vec(), - DATA_MAX_KEY.to_vec(), - )), - region_id: 0, - epoch_version: 0, + region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), }; self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) } @@ -1042,12 +1037,7 @@ where } else { let ctx = SnapshotContext { read_ts: u64::MAX, - range: Some(CacheRange::new( - DATA_MIN_KEY.to_vec(), - DATA_MAX_KEY.to_vec(), - )), - region_id: 0, - epoch_version: 0, + region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), }; self.get_cf_with_snap_ctx(cf, key, true, ctx) } @@ -1059,12 +1049,7 @@ where } else { let ctx = SnapshotContext { read_ts: u64::MAX, - range: Some(CacheRange::new( - DATA_MIN_KEY.to_vec(), - DATA_MAX_KEY.to_vec(), - )), - region_id: 0, - epoch_version: 0, + region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), }; self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) } diff --git a/src/server/raftkv/mod.rs b/src/server/raftkv/mod.rs index 4d3d2712431..5c7f5228c5f 100644 --- a/src/server/raftkv/mod.rs +++ b/src/server/raftkv/mod.rs @@ -650,10 +650,8 @@ where // When range cache engine is enabled, we need snapshot context to determine // whether we should use range cache engine snapshot for this request. ctx.start_ts.map(|ts| SnapshotContext { - region_id: 0, - epoch_version: 0, + region: None, read_ts: ts.into_inner(), - range: None, }) } else { None diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index 883bccb0843..e14ed2c6f82 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -7,11 +7,11 @@ use std::{ use engine_rocks::RocksSstWriterBuilder; use engine_traits::{ - CacheRange, EvictReason, RangeCacheEngine, SnapshotContext, SstWriter, SstWriterBuilder, + CacheRegion, EvictReason, RangeCacheEngine, SnapshotContext, SstWriter, SstWriterBuilder, CF_DEFAULT, CF_WRITE, }; use file_system::calc_crc32_bytes; -use keys::data_key; +use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; use kvproto::{ import_sstpb::SstMeta, raft_cmdpb::{CmdType, RaftCmdRequest, RaftRequestHeader, Request}, @@ -37,16 +37,15 @@ fn test_basic_put_get() { let region = cluster.get_region(b"k"); let rid = region.id; let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(region); + core.mut_range_manager() + .new_region(CacheRegion::from_region(®ion)); core.mut_range_manager().set_safe_point(rid, 1000); } cluster.put(b"k05", b"val").unwrap(); let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: 1001, - range: None, + region: None, }; let (tx, rx) = sync_channel(1); fail::cfg_callback("on_range_cache_get_value", move || { @@ -95,9 +94,15 @@ fn test_load() { let r2 = cluster.get_region(&split_key2); let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().load_region(r).unwrap(); - core.mut_range_manager().load_region(r1).unwrap(); - core.mut_range_manager().load_region(r2).unwrap(); + core.mut_range_manager() + .load_region(CacheRegion::from_region(&r)) + .unwrap(); + core.mut_range_manager() + .load_region(CacheRegion::from_region(&r1)) + .unwrap(); + core.mut_range_manager() + .load_region(CacheRegion::from_region(&r2)) + .unwrap(); } // put key to trigger load task @@ -131,10 +136,8 @@ fn test_load() { .unwrap(); let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: 20, - range: None, + region: None, }; for i in 0..30 { @@ -192,7 +195,9 @@ fn test_load_with_split() { // Load the whole range as if it is not splitted. Loading process should handle // it correctly. let cache_range = new_region(1, "", ""); - core.mut_range_manager().load_region(cache_range).unwrap(); + core.mut_range_manager() + .load_region(CacheRegion::from_region(&cache_range)) + .unwrap(); } rx.recv_timeout(Duration::from_secs(5)).unwrap(); @@ -226,10 +231,8 @@ fn test_load_with_split() { .unwrap(); let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: 20, - range: None, + region: None, }; for i in 0..30 { @@ -291,7 +294,7 @@ fn test_load_with_split2() { // try to load a region with old epoch and bigger range, // it should be updated to the real region range. core.mut_range_manager() - .load_region(new_region(r_split.id, "", "")) + .load_region(CacheRegion::new(r_split.id, 0, DATA_MIN_KEY, DATA_MAX_KEY)) .unwrap(); } @@ -314,8 +317,8 @@ fn test_load_with_split2() { let range_cache_engine = cluster.get_range_cache_engine(1); let core = range_cache_engine.core().read(); let meta = core.range_manager().region_meta(r_split.id).unwrap(); - let split_range = CacheRange::from_region(&r_split); - assert_eq!(&split_range, meta.get_range()); + let split_range = CacheRegion::from_region(&r_split); + assert_eq!(&split_range, meta.get_region()); } fail::remove("on_handle_put"); @@ -327,10 +330,8 @@ fn test_load_with_split2() { }) .unwrap(); let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: 20, - range: None, + region: None, }; let _ = cluster @@ -375,7 +376,7 @@ fn test_load_with_eviction() { let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. - let cache_range = new_region(1, "", ""); + let cache_range = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); core.mut_range_manager().load_region(cache_range).unwrap(); } @@ -403,7 +404,7 @@ fn test_load_with_eviction() { let range_cache_engine = cluster.get_range_cache_engine(1); let mut tried_count = 0; while range_cache_engine - .snapshot(1, 0, CacheRange::from_region(&r), u64::MAX, u64::MAX) + .snapshot(CacheRegion::from_region(&r), u64::MAX, u64::MAX) .is_err() && tried_count < 5 { @@ -412,7 +413,7 @@ fn test_load_with_eviction() { } // Now, the range ["", "") should be cached let region = new_region(1, b"k10", ""); - range_cache_engine.evict_region(®ion, EvictReason::AutoEvict); + range_cache_engine.evict_region(&CacheRegion::from_region(®ion), EvictReason::AutoEvict); } fail::remove("on_write_impl"); @@ -426,10 +427,8 @@ fn test_load_with_eviction() { .unwrap(); let snap_ctx = SnapshotContext { - region_id: 0, - epoch_version: 0, read_ts: u64::MAX, - range: None, + region: None, }; let val = cluster .get_cf_with_snap_ctx(CF_DEFAULT, b"k01", false, snap_ctx.clone()) @@ -452,7 +451,7 @@ fn test_evictions_after_transfer_leader() { let r = cluster.get_region(b""); cluster.must_transfer_leader(r.id, new_peer(1, 1)); - let cache_region = new_region(1, "", ""); + let cache_region = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); @@ -462,24 +461,12 @@ fn test_evictions_after_transfer_leader() { }; range_cache_engine - .snapshot( - cache_region.id, - 0, - CacheRange::from_region(&cache_region), - 100, - 100, - ) + .snapshot(cache_region.clone(), 100, 100) .unwrap(); cluster.must_transfer_leader(r.id, new_peer(2, 2)); range_cache_engine - .snapshot( - cache_region.id, - 0, - CacheRange::from_region(&cache_region), - 100, - 100, - ) + .snapshot(cache_region, 100, 100) .unwrap_err(); } @@ -491,41 +478,31 @@ fn test_eviction_after_merge() { cluster.must_split(&r, b"key1"); let r = cluster.get_region(b""); - let range1 = CacheRange::from_region(&r); + let range1 = CacheRegion::from_region(&r); let r2 = cluster.get_region(b"key1"); - let range2 = CacheRange::from_region(&r2); + let range2 = CacheRegion::from_region(&r2); let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(r.clone()); - core.mut_range_manager().new_region(r2.clone()); + core.mut_range_manager().new_region(range1.clone()); + core.mut_range_manager().new_region(range2.clone()); drop(core); range_cache_engine }; range_cache_engine - .snapshot(r.id, r.get_region_epoch().version, range1.clone(), 100, 100) + .snapshot(range1.clone(), 100, 100) .unwrap(); range_cache_engine - .snapshot( - r2.id, - r2.get_region_epoch().version, - range2.clone(), - 100, - 100, - ) + .snapshot(range2.clone(), 100, 100) .unwrap(); let pd_client = Arc::clone(&cluster.pd_client); pd_client.must_merge(r.get_id(), r2.get_id()); - range_cache_engine - .snapshot(r.id, r.get_region_epoch().version, range1, 100, 100) - .unwrap_err(); - range_cache_engine - .snapshot(r2.id, r2.get_region_epoch().version, range2, 100, 100) - .unwrap_err(); + range_cache_engine.snapshot(range1, 100, 100).unwrap_err(); + range_cache_engine.snapshot(range2, 100, 100).unwrap_err(); } #[test] @@ -544,23 +521,17 @@ fn test_eviction_after_ingest_sst() { // Add region r to cache. let region = cluster.get_region(b""); - let range = CacheRange::from_region(®ion); + let cache_region = CacheRegion::from_region(®ion); let range_cache_engine = { let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(region.clone()); + core.mut_range_manager().new_region(cache_region.clone()); drop(core); range_cache_engine }; range_cache_engine - .snapshot( - region.id, - region.get_region_epoch().version, - range.clone(), - 100, - 100, - ) + .snapshot(cache_region.clone(), 100, 100) .unwrap(); // Ingest the sst file. @@ -601,12 +572,6 @@ fn test_eviction_after_ingest_sst() { assert!(!resp.get_header().has_error(), "{:?}", resp); range_cache_engine - .snapshot( - region.id, - region.get_region_epoch().version, - range, - 100, - 100, - ) + .snapshot(cache_region, 100, 100) .unwrap_err(); } From 222e0a43215c68d4e6485cd24f8e902560ebb983 Mon Sep 17 00:00:00 2001 From: hhwyt Date: Wed, 28 Aug 2024 14:01:47 +0800 Subject: [PATCH 045/144] encryption: add test for temporary KMS service unavailable (#17445) ref tikv/tikv#17410 This commit adds a new test to verify TiKV's recovery after temporary unavailability of the KMS service. Signed-off-by: hhwyt Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 1 + Cargo.toml | 2 + components/encryption/Cargo.toml | 1 + components/encryption/src/lib.rs | 2 + components/encryption/src/master_key/kms.rs | 85 ++++++++++++--------- components/encryption/src/master_key/mod.rs | 2 + tests/failpoints/cases/test_encryption.rs | 23 ++++++ 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d3727d054a..d5c72f70bc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6468,6 +6468,7 @@ dependencies = [ "crossbeam", "crypto", "dashmap", + "encryption", "encryption_export", "engine_panic", "engine_rocks", diff --git a/Cargo.toml b/Cargo.toml index 3cef40497bf..a3b2977206d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ testexport = [ "engine_rocks/testexport", "engine_panic/testexport", "hybrid_engine/testexport", + "encryption/testexport", ] test-engine-kv-rocksdb = ["engine_test/test-engine-kv-rocksdb"] test-engine-raft-raft-engine = ["engine_test/test-engine-raft-raft-engine"] @@ -80,6 +81,7 @@ crc64fast = "0.1" crossbeam = { workspace = true } crypto = { workspace = true } dashmap = "5" +encryption = { workspace = true } encryption_export = { workspace = true } engine_panic = { workspace = true } engine_rocks = { workspace = true } diff --git a/components/encryption/Cargo.toml b/components/encryption/Cargo.toml index 73a4f61bb95..2968ea4be30 100644 --- a/components/encryption/Cargo.toml +++ b/components/encryption/Cargo.toml @@ -10,6 +10,7 @@ failpoints = ["fail/failpoints"] # openssl/vendored is necssary in order to conditionally building SM4 encryption # support, as SM4 is disabled on various openssl distributions, such as Rocky Linux 9. sm4 = ["openssl/vendored"] +testexport = [] [dependencies] async-trait = "0.1" diff --git a/components/encryption/src/lib.rs b/components/encryption/src/lib.rs index 6c145c5e9be..c31e734ba9a 100644 --- a/components/encryption/src/lib.rs +++ b/components/encryption/src/lib.rs @@ -11,6 +11,8 @@ mod file_dict_file; mod io; mod manager; mod master_key; +#[cfg(any(test, feature = "testexport"))] +pub use master_key::fake; mod metrics; use std::{io::ErrorKind, path::Path}; diff --git a/components/encryption/src/master_key/kms.rs b/components/encryption/src/master_key/kms.rs index 7c3f56ca0cd..b50cf1aac4b 100644 --- a/components/encryption/src/master_key/kms.rs +++ b/components/encryption/src/master_key/kms.rs @@ -63,7 +63,7 @@ impl KmsBackend { }) } - fn encrypt_content(&self, plaintext: &[u8], iv: Iv) -> Result { + pub fn encrypt_content(&self, plaintext: &[u8], iv: Iv) -> Result { let mut opt_state = self.state.lock().unwrap(); if opt_state.is_none() { let runtime = self.runtime.lock().unwrap(); @@ -98,7 +98,7 @@ impl KmsBackend { // On decrypt failure, the rule is to return WrongMasterKey error in case it is // possible that a wrong master key has been used, or other error otherwise. - fn decrypt_content(&self, content: &EncryptedContent) -> Result> { + pub fn decrypt_content(&self, content: &EncryptedContent) -> Result> { let vendor_name = self.kms_provider.name(); match content.metadata.get(MetadataKey::KmsVendor.as_str()) { Some(val) if val.as_slice() == vendor_name.as_bytes() => (), @@ -159,8 +159,8 @@ impl KmsBackend { } } - #[cfg(test)] - fn clear_state(&mut self) { + #[cfg(any(test, feature = "testexport"))] + pub fn clear_state(&mut self) { let mut opt_state = self.state.lock().unwrap(); *opt_state = None; } @@ -180,13 +180,15 @@ impl Backend for KmsBackend { } } -#[cfg(test)] -mod fake { +#[cfg(any(test, feature = "testexport"))] +pub mod fake { use async_trait::async_trait; use cloud::{ error::{Error as CloudError, KmsError, Result}, kms::KmsProvider, }; + use fail::fail_point; + use hex::FromHex; use super::*; @@ -208,9 +210,21 @@ mod fake { } } + fn check_fail_point(fail_point_name: &str) -> Result<()> { + fail_point!(fail_point_name, |val| { + val.and_then(|x| x.parse::().ok()) + .filter(|&fail| fail) + .map(|_| Err(CloudError::ApiTimeout(box_err!("api timeout")))) + .unwrap_or(Ok(())) + }); + Ok(()) + } + #[async_trait] impl KmsProvider for FakeKms { async fn generate_data_key(&self) -> Result { + check_fail_point("kms_api_timeout_encrypt")?; + Ok(DataKeyPair { encrypted: EncryptedKey::new(FAKE_DATA_KEY_ENCRYPTED.to_vec())?, plaintext: PlainKey::new(self.plaintext_key.clone(), CryptographyType::AesGcm256) @@ -219,12 +233,14 @@ mod fake { } async fn decrypt_data_key(&self, _ciphertext: &EncryptedKey) -> Result> { + check_fail_point("kms_api_timeout_decrypt")?; + if self.should_decrypt_data_key_fail { Err(CloudError::KmsError(KmsError::WrongMasterKey(box_err!( "wrong master key" )))) } else { - Ok(vec![1u8, 32]) + Ok(hex::decode(PLAINKEY_HEX).unwrap()) } } @@ -232,14 +248,40 @@ mod fake { FAKE_VENDOR_NAME } } + + // See more http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + const PLAIN_TEXT_HEX: &str = "25431587e9ecffc7c37f8d6d52a9bc3310651d46fb0e3bad2726c8f2db653749"; + const CIPHER_TEXT_HEX: &str = + "84e5f23f95648fa247cb28eef53abec947dbf05ac953734618111583840bd980"; + const PLAINKEY_HEX: &str = "c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139"; + const IV_HEX: &str = "cafabd9672ca6c79a2fbdc22"; + + pub fn prepare_data_for_encrypt() -> (Iv, Vec, Vec, Vec) { + let iv = Vec::from_hex(IV_HEX).unwrap(); + let iv = Iv::from_slice(iv.as_slice()).unwrap(); + let pt = Vec::from_hex(PLAIN_TEXT_HEX).unwrap(); + let plainkey = Vec::from_hex(PLAINKEY_HEX).unwrap(); + let ct = Vec::from_hex(CIPHER_TEXT_HEX).unwrap(); + (iv, pt, plainkey, ct) + } + + pub fn prepare_kms_backend( + plainkey: Vec, + should_decrypt_data_key_fail: bool, + ) -> KmsBackend { + KmsBackend::new(Box::new(FakeKms::new( + plainkey, + should_decrypt_data_key_fail, + ))) + .unwrap() + } } #[cfg(test)] mod tests { - use hex::FromHex; use matches::assert_matches; - use super::{fake::FakeKms, *}; + use super::{fake::*, *}; #[test] fn test_state() { @@ -262,31 +304,6 @@ mod tests { assert_eq!(state2.cached(&encrypted2), true); } - const PLAIN_TEXT_HEX: &str = "25431587e9ecffc7c37f8d6d52a9bc3310651d46fb0e3bad2726c8f2db653749"; - const CIPHER_TEXT_HEX: &str = - "84e5f23f95648fa247cb28eef53abec947dbf05ac953734618111583840bd980"; - const PLAINKEY_HEX: &str = "c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139"; - const IV_HEX: &str = "cafabd9672ca6c79a2fbdc22"; - - #[cfg(test)] - fn prepare_data_for_encrypt() -> (Iv, Vec, Vec, Vec) { - let iv = Vec::from_hex(IV_HEX).unwrap(); - let iv = Iv::from_slice(iv.as_slice()).unwrap(); - let pt = Vec::from_hex(PLAIN_TEXT_HEX).unwrap(); - let plainkey = Vec::from_hex(PLAINKEY_HEX).unwrap(); - let ct = Vec::from_hex(CIPHER_TEXT_HEX).unwrap(); - (iv, pt, plainkey, ct) - } - - #[cfg(test)] - fn prepare_kms_backend(plainkey: Vec, should_decrypt_data_key_fail: bool) -> KmsBackend { - KmsBackend::new(Box::new(FakeKms::new( - plainkey, - should_decrypt_data_key_fail, - ))) - .unwrap() - } - #[test] fn test_kms_backend() { let (iv, pt, plainkey, ct) = prepare_data_for_encrypt(); diff --git a/components/encryption/src/master_key/mod.rs b/components/encryption/src/master_key/mod.rs index a674cd3a685..329cff033e8 100644 --- a/components/encryption/src/master_key/mod.rs +++ b/components/encryption/src/master_key/mod.rs @@ -28,6 +28,8 @@ mod metadata; use self::metadata::*; mod kms; +#[cfg(any(test, feature = "testexport"))] +pub use self::kms::fake; pub use self::kms::KmsBackend; #[derive(Default, Debug, Clone)] diff --git a/tests/failpoints/cases/test_encryption.rs b/tests/failpoints/cases/test_encryption.rs index eba0a515893..e230fad2f83 100644 --- a/tests/failpoints/cases/test_encryption.rs +++ b/tests/failpoints/cases/test_encryption.rs @@ -51,3 +51,26 @@ fn create_file_info(id: u64, method: EncryptionMethod) -> FileInfo { ..Default::default() } } + +#[test] +fn test_kms_provider_temporary_unavailable() { + #[cfg(any(test, feature = "testexport"))] + use encryption::fake::*; + + // Simulate temporary unavailable with a timeout error during encryption. + // Expect the backend to handle the timeout gracefully and succeed on the + // subsequent retry. + fail::cfg("kms_api_timeout_encrypt", "1*return(true)").unwrap(); + let (iv, pt, plainkey, ..) = prepare_data_for_encrypt(); + let mut backend = prepare_kms_backend(plainkey, false); + let encrypted_content = backend.encrypt_content(&pt, iv).unwrap(); + // Clear the cached state to ensure that the subsequent + // backend.decrypt_content() invocation bypasses the cache and triggers the + // mocked FakeKMS::decrypt_data_key() function. + backend.clear_state(); + + // Same as above. + fail::cfg("kms_api_timeout_decrypt", "1*return(true)").unwrap(); + let pt_decrypt = backend.decrypt_content(&encrypted_content).unwrap(); + assert_eq!(pt_decrypt, pt); +} From a19d5b314ab188948d6d3606fc4350d155d6ebbc Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 3 Sep 2024 10:54:37 +0800 Subject: [PATCH 046/144] test_util: renew tests certs (#17472) close tikv/tikv#17471 Add a script to renew certificates and fix the flaky test `test_security_status_service_without_cn` . Signed-off-by: Neil Shen --- components/test_util/data/.gitignore | 2 + components/test_util/data/ca.pem | 37 +++++++------- components/test_util/data/generate_certs.sh | 40 +++++++++++++++ components/test_util/data/key.pem | 55 +++++++++++---------- components/test_util/data/server.pem | 38 +++++++------- 5 files changed, 105 insertions(+), 67 deletions(-) create mode 100644 components/test_util/data/.gitignore create mode 100755 components/test_util/data/generate_certs.sh diff --git a/components/test_util/data/.gitignore b/components/test_util/data/.gitignore new file mode 100644 index 00000000000..0773e460402 --- /dev/null +++ b/components/test_util/data/.gitignore @@ -0,0 +1,2 @@ +ca.key +server.csr diff --git a/components/test_util/data/ca.pem b/components/test_util/data/ca.pem index e130a8eece9..05015192501 100644 --- a/components/test_util/data/ca.pem +++ b/components/test_util/data/ca.pem @@ -1,22 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIUdZFW8VQoZZzek8cA+5GGu6ZInjowDQYJKoZIhvcNAQEL -BQAwVzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0Jl -aWppbmcxEDAOBgNVBAoTB1BpbmdDQVAxEjAQBgNVBAMTCU15IG93biBDQTAeFw0x -OTA5MDIwNjEyMDBaFw0yNDA4MzEwNjEyMDBaMFcxCzAJBgNVBAYTAkNOMRAwDgYD -VQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRAwDgYDVQQKEwdQaW5nQ0FQ -MRIwEAYDVQQDEwlNeSBvd24gQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDcDtQ7UX+xlVY0vpklp1uUmPoFsN0U6fqRzHU+LvYS5AM5RPJMVLiKBiSi -zGsB+XPmXZ8H7rZZ+osZsEmDIF3HdyiSNpPNzRJKxsz4KVRzfoKZXL9D41TpuE27 -+7tN6qGytYrnAy8cHMA0S1TnQ0biOFTcXZrwh5lvlIcx7ceUamGuEl94tblxSSJl -2SkpHkKIDv0kcgoGmmh4y8SzAtmnwcCjkCSoITvvwKklp5830pFKOnpN9uZJzkXa -tuUSpSji/JG79nQfH91LtL7xMprORVtg9YAa3aJm0Uf33WFvaCTSrt//7CVK8nqK -xayS3u7dNH3GV9b81OGtlR76leFlAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjAS -BgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBS3hxTaN9B7eF8xr0DKLZ3b5vFn -rDAfBgNVHSMEGDAWgBS3hxTaN9B7eF8xr0DKLZ3b5vFnrDANBgkqhkiG9w0BAQsF -AAOCAQEAi9WiEvTQQjmb7ekXHf1tKwdLNu5akQXIwTKeZSWRSeMgqVQcoyTZMPBX -ythl6K3175RUIMtCwO4uZTOpRU1mTl0pIjoEcJGHYX91zyA5BjWahXZttvt7/hyX -UwJN9clBXLfZTCp1ysLCtarLcip4WxWNsxEwXFUisE2gbu3F9ELHAbRSVUe/CwC6 -8BkY+G+fovazjGoTV4NadJVFRzTR/zsWkBNllBOBTrop8FH23ePVh3hXafzJlcip -bDbRxNqSzNtLr88mwswklgiIHXF6PY2TkyscsXVkHPAswZnrv4lLov7M3VjL8ITA -uYm4Me5Tmj+6pb+Foky15+ehmicQbA== +MIIDITCCAgmgAwIBAgIUVe4Q3uw8yW0seqG9yQMfXrSXLHswDQYJKoZIhvcNAQEL +BQAwFzEVMBMGA1UEAwwMdGlrdl90ZXN0X2NhMCAXDTI0MDMyNzAwMDAwMFoYDzIx +MjQwMzI3MDAwMDAwWjAXMRUwEwYDVQQDDAx0aWt2X3Rlc3RfY2EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+cR9jZ0LtX4ztcupCEyrR8CNmw1TkIsOQ +rPhP43FkdggQN2vqkM9ZtKxlcODuNul748saEFoK1AGv4MgxgKcbt6sTucdz4oC4 +O1rM31eicU630PblPNU8Bstvlta2jCZAbERBhiAm1C3zQncodyVr9Oa2Ff9SRXcW +7icpv4CTsesPi19nF+EhBAuCifeI3Vj1Uvd5wvsK/m0D0gpp3Vp7CNYwHLv9gfPu +Jui0Q8NM5ENBcIfUBK8zOvr8a5glqV36KUA4m7yDXyYHIR2SrD/y3XDc6cbRgxKS +qbQMbc67H2XJHWjHgp7gv9rdU9HGxfv49j+TnxwYNPb3aflBgk1JAgMBAAGjYzBh +MB0GA1UdDgQWBBS+Qw4MGLTrjFTO2xlGwlj+yy1o7zAfBgNVHSMEGDAWgBS+Qw4M +GLTrjFTO2xlGwlj+yy1o7zASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAQEAezNpYWbkxvIv/MfWxpbF+TBA1ssWT1xyuwUu +P9EdXj72XKnpkmZXxysyCSZR1ZH9XwuqHgQkegxQMKMeiv5UQLouTFEa5LUJxlQw +A3O1Ky1r6dv6p/JkOAbMxh+VoWAFCW5Ioo81rwZLGu3DS3+gsauDBpevIqLlL29H +FAQ+JO33pzuAP+PBHnO0Zi3ddvgDNULpHQhC8BUR9fI/NsxKuS4QwPGK1fnd/Qvg +w5aP0PZ8CNheIvVy4qkeUsh2kS7vghMpwa/KkCGurmwg2C6sgCTDKJVgkTOEutx4 +5LfVfuwAmWWnrqWwLtAyJI5SAUhXLtSu2DeyC5ppP5DFRBP3qw== -----END CERTIFICATE----- diff --git a/components/test_util/data/generate_certs.sh b/components/test_util/data/generate_certs.sh new file mode 100755 index 00000000000..08156aa5e68 --- /dev/null +++ b/components/test_util/data/generate_certs.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +set -euo pipefail + +SCRIPT_PATH="$(realpath "$0")" +CERT_DIR="$(dirname "$SCRIPT_PATH")" +CA_KEY="$CERT_DIR/ca.key" +CA_CERT="$CERT_DIR/ca.pem" +SERVER_KEY="$CERT_DIR/key.pem" +SERVER_CSR="$CERT_DIR/server.csr" +SERVER_CERT="$CERT_DIR/server.pem" +VALID_DAYS=3650 +RSA_KEY_SIZE=2048 + +# CA certs. +openssl genrsa -out "$CA_KEY" "$RSA_KEY_SIZE" +openssl req -new -x509 -days "$VALID_DAYS" -key "$CA_KEY" -out "$CA_CERT" \ + -subj "/CN=tikv_test_ca" \ + -addext "basicConstraints = critical,CA:TRUE,pathlen:0" \ + -addext "keyUsage = cRLSign, keyCertSign" +echo "CA certificate:" +openssl x509 -text -in "$CA_CERT" -noout + +# Server certs. +openssl genrsa -out "$SERVER_KEY" "$RSA_KEY_SIZE" +openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" \ + -extensions v3_ca \ + -subj "/CN=tikv-server" \ + -addext "basicConstraints = critical, CA:FALSE" \ + -addext "keyUsage = critical, digitalSignature, keyEncipherment" \ + -addext "extendedKeyUsage = serverAuth, clientAuth" \ + -addext "subjectAltName = IP.1:172.16.5.40, IP.2:127.0.0.1" +openssl x509 -req -days "$VALID_DAYS" \ + -CA "$CA_CERT" -CAkey "$CA_KEY" -CAcreateserial \ + -copy_extensions copyall \ + -in "$SERVER_CSR" -out "$SERVER_CERT" +echo "Server certificate:" +openssl x509 -text -in "$SERVER_CERT" -noout diff --git a/components/test_util/data/key.pem b/components/test_util/data/key.pem index c7f9fa8c340..61ab0c3f029 100644 --- a/components/test_util/data/key.pem +++ b/components/test_util/data/key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAsRpq/E/VC82YxsC5LlKFvI9HJuchMtKskn53anW4rNE3sfN0 -WDS6qCyxNumUVBqO98J18xxbz/XkV7aP6TcXZrNgEqw07PZWTDoyZVi+n9HXyWwl -BeiE2WWrCESqsar+cXV5UE3oE7Y4CT56tMN+awKqnf1zLyRl9DlqSg1/GabheVzz -fGhdqddqdpAZcaOHH8UMEWdnZ4qTFaaGNRlrRy3W0VjzgIocQorpvvtZkQM5iCxx -z9wuF9/6gGdopTA0J2SvZKa+oI/867NLpN5Hx+cn/ThHhCTh1N34Ulloa0aiou72 -mGgyMIdQxYAsRnG62EHn+9aPtegIjQd13Be9/wIDAQABAoIBAHJ8v3iIKxNMP10M -rSlS032HqdluRLnUExdIhe3eWBnvze9NkIKM47Vf3te+u9J6sL1dil40kO2o6YoC -TJnYsVoEzzCC/lvJCxSP8pAthF1QjAx7yps9KtRWsu/PZAEipwW1iUzub/5+J09i -gnRkhE6tFJq5g0KQZxAwJZPlkaqEcZIOObfh9zD9hutvCPmXBtB600EbQU4XzyjP -KaU08LtNZVm4mhKMuhXuFt8LBkjjfuw6zNcjsvgMkyflFTLc/SgWWIpq1ALHQCsq -OiFfTPyuLy+8tGTbawvRIqiHHRd23XttPcfkdfWbNVTSBfodTOhXGFaVYbJ6EVA4 -OzVzftECgYEAz/D99wpWbjU8vye5cjKjZCY/+QnY0t76YsUmfD9+fQNBDSQnKCKj -6nO6oYFQ9RI/vPMfrNX0sqo5hKfufNBCr/MILDXR6vtcEuaqd84DgaPVPRjHef6v -paYUi0Enb3gF3LXYggTN1mz9leEW8BablTN/DLP5AAvMfM/XSkVzlIsCgYEA2gjc -mcUDL1smAvriFVmpD4IrPzaZ9kINOfFNqkp/+y7S0BZGeS5ESSodrs0CIojttp3o -9GL7QLhZ9DehJWfh2qfA5mvzKGzUeM2oapR2Ts/m3voS4ErPTm+cTBOjRe3gGSSN -4sAJ5LA071RfNjEZBSktow//WX/oWrhIyovnxt0CgYBxyge/4xlO77URSdSySEGf -MUs6pYfQRRKxb/9SaJB4KoqzfUAsN2CJkNDlRlWd9mGIrWZ89wwTpREapabdCD4l -+JFVWBJKS0ikUzOfoc3LaHLtHx0xhgxqUkrVtU62MfDLSXt0Etrs5vGRzf32Xfi/ -mdGBiw7MVqiM+FNwojbQZwKBgDly5E1P78rmhVl7qV5exYDkl2iMhnywYrPFtOUN -xDL2320csWz0l+F/S1rngYx/78KSUPMzsWgYKvuCPN+SQ5xNXzJXdzZLlqBN7/ZF -L/cMKJTP53FZxM2x8sjI09h1GPsG+quoVfL/yrLU1FF/FkyZ0QCKEooOfbaJoARe -YK+xAoGAfT0P200WsLKRl73XYJZNYQl5+h5s7Sk9J8QuPwFWqm/mGwYKTLI042jg -lsAym4krAR0c1CHTW3aHRimYpYbi7/kztZU1zUQgcGL+79afer3ZuFF7mGzR+I/r -yOQ2dEfmVASfl/fMh1qyExpcCaMuejaODWyILlxOwvnywHWMSCU= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCzMRjAbG2MVTMs +x7Rr+eeIi4jNyhvaQ8LcTB08BdgY8618blS037dB/85GxKTfZMdJZkCygbSsyiVJ +owqyucsT6IKYnZ/kDxfXXYEBIQcOYLnAEU1NNnQLPYSTth7xjnSKvg78gH+wY2LP +4z6QD64XboKa/fmVuByO/QlnZntkr4kiH6O5rJyt1Hm+OzVRYs5RumGU0Mpn3Bjd +xmGqB7+Wldbu2ECfOFFDaC/uizWVr1OD5lsdVau20ZEwZN37udRXsBc0qTp+CaA0 +sTFNCfqq9/Z3SVOGmWldvVOfF33+n9N+n1yyeZ8TlZ3JB2daKoDHDxLY0KKZtu6D +M9RlcMdJAgMBAAECggEAExOZ//pLG1KCtTS5h3k+ZfH86XOnzW/DUfKkdhxlKhrf +EE0qpWrftp4GFtCegM3YzX6eSqK2WmLW32UFIYvYC9GH/bliKURWFG526mjauHQh +sknlQeAXMI8nCxaraqnwzEh5jfYcIeoiveECaxHQRdxU+S0qof7Mw4g6tRBa+Jft +TUW1aa/m6p8s19xTKebtpCj+p1zwUdU8t4fw8eq5qFn4t1jlWaaCLgJv4OAE52IB +81LEJjG0vevVIvifsm+2t58IOqYJhEo0qMw2X0AMQDEOJZPeW1puFg4cdvh1bar6 +RDxVhX0IkDKz7w62VoGb0ZptZkO3vrG8OXN2TI+L0QKBgQC30ASVENK2l7Jo+n5m +Qxf7s4ZoJ9jjWjO8N+Mkd5/Cu+xePlv5EmcBZCDONSmAdtaZXDs9DVO8E4yFXecJ +fidQnvRhhRxrG/LEEwHNzR8lMlm5tc4wx7g2y844Qjan71O8gawUd6eZyRmVDnmk +st6DLUwyWTkwaa7VkDaGFFqjVQKBgQD5kIS0fiq1hhOzrPt6U2FCHybrNnWCyFN5 +ISYJpl1vn7YqFV2wgXwn+A9bcDi7DMK8hx1b49Xx2lwo9n7Cb5Pd0ykhdjo12hUQ +WBqiFEjInsQ84RvivyTzlrvBduVMRtWA8lxp4gFjXFf/avHzoRkM21IfU46Q9QNn +Y8rKTFJ8JQKBgGRgv6/b0QYPj0lOyen0Z8t3PUXxxLpbTvdRGcSXYvJIB4tryHQa +/Y8/675QP8q8mvKC8IKlnX2Ou2U1Y27GqpeXRmNe+qbvS0KSEqEdjA2XEnKc+u2e +k1WxNHt6hThuNK8zrRI8SZVswYCpt/oeB+9gtESmftmWTPipWW0c/mZFAoGBAIbK +pLJr9ptmmFuSUZ1nTX+OHdIq7ts9YcBpxAawQYUZqSUftyOvPCTGWV0Uxr9YjBGR +lKzd6N8hBmflgt93rlDATVXSamxNptTWEUR7WjhpcCpFl28nuEiMoEpE8mH5XDWy +MXHK7N8CsFC3LYld+I62Iqvi0HzAqR79ijkrcd21AoGBAIc+y9eKyMxFfHkz/pZH +cupJiF21Y3+cw7h2TRNvqSLvHTp3enCDo7WG0R0K74BHIvwTDcZxsxThm6KwB+y9 +WIuKQC064e5ASjdF1dfwFFlNpwphL2kebWuzIkpEVtCcGJPUuJ704R7tD3y8q4BN +aSrpjjRGIVr6mLcxXGgHJa5R +-----END PRIVATE KEY----- diff --git a/components/test_util/data/server.pem b/components/test_util/data/server.pem index 09200bd82f6..42deadba2db 100644 --- a/components/test_util/data/server.pem +++ b/components/test_util/data/server.pem @@ -1,22 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIDlTCCAn2gAwIBAgIUGKdjy/Uqp64ZiwqMwpTMGP5tKT0wDQYJKoZIhvcNAQEL -BQAwVzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0Jl -aWppbmcxEDAOBgNVBAoTB1BpbmdDQVAxEjAQBgNVBAMTCU15IG93biBDQTAgFw0x -OTA5MDIwNjEzMDBaGA8yMTE5MDgwOTA2MTMwMFowFjEUMBIGA1UEAxMLdGlrdi1z -ZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxGmr8T9ULzZjG -wLkuUoW8j0cm5yEy0qySfndqdbis0Tex83RYNLqoLLE26ZRUGo73wnXzHFvP9eRX -to/pNxdms2ASrDTs9lZMOjJlWL6f0dfJbCUF6ITZZasIRKqxqv5xdXlQTegTtjgJ -Pnq0w35rAqqd/XMvJGX0OWpKDX8ZpuF5XPN8aF2p12p2kBlxo4cfxQwRZ2dnipMV -poY1GWtHLdbRWPOAihxCium++1mRAzmILHHP3C4X3/qAZ2ilMDQnZK9kpr6gj/zr -s0uk3kfH5yf9OEeEJOHU3fhSWWhrRqKi7vaYaDIwh1DFgCxGcbrYQef71o+16AiN -B3XcF73/AgMBAAGjgZcwgZQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsG -AQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTw7yUYqbAv -BJw3zZctLUfUi0vyqzAfBgNVHSMEGDAWgBS3hxTaN9B7eF8xr0DKLZ3b5vFnrDAV -BgNVHREEDjAMhwSsEAUohwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCBljfge2fC -5X+tt1v7AkWoH5xpymEVvuIWWJmT/6FNTn1rdnIaxWCQzJbBCXjZS/75lKnwfrTB -ZK7iMv1GQaBevT/qm+7GcApsr5nFrI/MvzrvY+XRqvU8gsRhUjHYI+JPLGWxhzZD -pQdJTAGvsDLHu1VVdHR2KsE4M8ceGq58f7zPSq/suf+8SYEOFP8zfuXX1HfUrFVe -69ZQw8PZh4EYL0PYtE5BYfe9iJyFNNtZiejiribMQz/NtNkKM3M+Hm40ULGuwHXq -bKDjDq1PvmpVb/kKO/xADTIAbqproXETZ4W2keI3hwm6NxysvEbYV9+puQBXQqwT -KOt9Lo4ofSAF +MIIDVTCCAj2gAwIBAgIUUCvVn7LZjm7FD+xeAd5g1oKFSrIwDQYJKoZIhvcNAQEL +BQAwFzEVMBMGA1UEAwwMdGlrdl90ZXN0X2NhMCAXDTI0MDMyNzAwMDAwMFoYDzIx +MjQwMzI3MDAwMDAwWjAWMRQwEgYDVQQDDAt0aWt2LXNlcnZlcjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALMxGMBsbYxVMyzHtGv554iLiM3KG9pDwtxM +HTwF2BjzrXxuVLTft0H/zkbEpN9kx0lmQLKBtKzKJUmjCrK5yxPogpidn+QPF9dd +gQEhBw5gucARTU02dAs9hJO2HvGOdIq+DvyAf7BjYs/jPpAPrhdugpr9+ZW4HI79 +CWdme2SviSIfo7msnK3Ueb47NVFizlG6YZTQymfcGN3GYaoHv5aV1u7YQJ84UUNo +L+6LNZWvU4PmWx1Vq7bRkTBk3fu51FewFzSpOn4JoDSxMU0J+qr39ndJU4aZaV29 +U58Xff6f036fXLJ5nxOVnckHZ1oqgMcPEtjQopm27oMz1GVwx0kCAwEAAaOBlzCB +lDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwFQYDVR0RBA4wDIcErBAFKIcEfwAAATAdBgNVHQ4EFgQU +Z4ACSrFMAFHP3iQAlZihuxlTk64wHwYDVR0jBBgwFoAUvkMODBi064xUztsZRsJY +/sstaO8wDQYJKoZIhvcNAQELBQADggEBALxhZMiXDQvUJCtSGPaCJhvs51O7Sb+8 +xrByuQrtXhcNVsOcq+0OjT/roUzD0x5mf75cTcJm6XZuzg2BPgN7wQU5GPuhOcJv +XFx4uoRDNBzN5FlxZu+ln4Qqw/M/4zsRwD3qkp/J50RpbCOmf1x/b1M6+s1uQcT5 +6sMErUXnOzvY5ey4vCJFiveYu5Z7GIHPB8xlhJtiu3T8FN1o3Us75evFk7hHfJjf +zU1Efd6W9RU/bEPAPvqnLBkSHdx7Urw0hNHlW2IDjaX1zIV5Ibeiw61olyQAiXjy +N3VJrMbuSTRv5BZxp4sKwnan4dAtfXvSSle36pYhN5UTjD72NNlLe8A= -----END CERTIFICATE----- From c159b691ac687f177ec92bf89d362ce014187878 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:20:16 +0800 Subject: [PATCH 047/144] In-memory engine: consider mvcc suffix in prop test (#17455) close tikv/tikv#17456 consider mvcc suffix in prop test Signed-off-by: SpadeA-Tang Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/prop_test.rs | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/components/range_cache_memory_engine/src/prop_test.rs b/components/range_cache_memory_engine/src/prop_test.rs index 187941beb7a..aaccf2b3578 100644 --- a/components/range_cache_memory_engine/src/prop_test.rs +++ b/components/range_cache_memory_engine/src/prop_test.rs @@ -9,6 +9,7 @@ use engine_traits::{ }; use proptest::prelude::*; use tikv_util::config::{ReadableSize, VersionTrack}; +use txn_types::{Key, TimeStamp}; use super::engine::SkiplistHandle; use crate::{ @@ -16,6 +17,9 @@ use crate::{ InternalBytes, RangeCacheEngineConfig, }; +// This fixed mvcc suffix is used for CF_WRITE and CF_DEFAULT in prop test. +const MVCC_SUFFIX: u64 = 10; + #[derive(Clone)] enum Operation { Put(Vec, Vec), @@ -158,15 +162,27 @@ fn test_rocksdb_skiplist_basic_operations(cf: CfName, operations: Vec (handle, key, value, guard) }; + // Delete range in SkiplistEngine considers MVCC suffix for CF_DEFAULT and + // CF_WRITE, so we append the suffix for them. for op in operations { match op { - Operation::Put(k, v) => { + Operation::Put(mut k, v) => { + if cf != CF_LOCK { + k = Key::from_raw(&k) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + } db_rocks.put_cf(cf, &k, &v).unwrap(); let (handle, key, value, guard) = skiplist_args(k, Some(v)); handle.insert(key, value.unwrap(), &guard) } - Operation::Get(k) => { + Operation::Get(mut k) => { + if cf != CF_LOCK { + k = Key::from_raw(&k) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + } let res_rocks = db_rocks.get_value_cf(cf, &k).unwrap(); let (handle, key, _value, guard) = skiplist_args(k, None); let res_skiplist = handle.get(&key, &guard); @@ -175,28 +191,45 @@ fn test_rocksdb_skiplist_basic_operations(cf: CfName, operations: Vec res_skiplist.map(|e| e.value().as_slice()) ); } - Operation::Delete(k) => { + Operation::Delete(mut k) => { + if cf != CF_LOCK { + k = Key::from_raw(&k) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + } db_rocks.delete_cf(cf, &k).unwrap(); let (handle, key, _value, guard) = skiplist_args(k, None); handle.remove(&key, &guard) } - Operation::Scan(k, limit) => { + Operation::Scan(mut k, limit) => { + if cf != CF_LOCK { + k = Key::from_raw(&k) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + } let res_rocks = scan_rocksdb(&db_rocks, cf, &k, limit); let (handle, key, _value, _guard) = skiplist_args(k, None); let res_titan = scan_skiplist(handle, &key, limit); assert_eq!(res_rocks, res_titan); } - Operation::DeleteRange(k1, k2) => { - if k1 <= k2 { - db_rocks.delete_range_cf(cf, &k1, &k2).unwrap(); - let range = CacheRegion::new(1, 0, k1.clone(), k2.clone()); - skiplist.delete_range_cf(cf, &range); - } else { - db_rocks.delete_range_cf(cf, &k2, &k1).unwrap(); - let range = CacheRegion::new(1, 0, k2.clone(), k1.clone()); - skiplist.delete_range_cf(cf, &range); + Operation::DeleteRange(mut k1, mut k2) => { + if k1 > k2 { + (k1, k2) = (k2, k1); } + + let range = CacheRegion::new(1, 0, k1.clone(), k2.clone()); + skiplist.delete_range_cf(cf, &range); + + if cf != CF_LOCK { + k1 = Key::from_raw(&k1) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + k2 = Key::from_raw(&k2) + .append_ts(TimeStamp::new(MVCC_SUFFIX)) + .into_encoded(); + } + db_rocks.delete_range_cf(cf, &k1, &k2).unwrap(); } } } @@ -209,3 +242,15 @@ proptest! { test_rocksdb_skiplist_basic_operations(cf, operations); } } + +#[test] +fn test_case1() { + let de = |data| hex::decode(data).unwrap(); + let cf = CF_WRITE; + let operations = [ + Operation::Put(de("E2"), de("38CC98E09D9CB1D1")), + Operation::DeleteRange(de(""), de("E2")), + Operation::Scan(de("2C0F698A"), 3), + ]; + test_rocksdb_skiplist_basic_operations(cf, operations.to_vec()); +} From d907f15ae5faac1f884cc41820ada7be267b1a9d Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:54:41 +0800 Subject: [PATCH 048/144] In-memory engine: introduce stop load limit threshold (#17443) ref tikv/tikv#16141, close tikv/tikv#17442 Introduce stop load limit threshold Signed-off-by: SpadeA-Tang Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 130 +++++++++++++----- .../range_cache_memory_engine/src/engine.rs | 2 + .../range_cache_memory_engine/src/lib.rs | 24 ++++ .../src/memory_controller.rs | 11 ++ .../tests/failpoints/test_memory_engine.rs | 3 +- .../integrations/config/test_config_client.rs | 5 + 6 files changed, 142 insertions(+), 33 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 49b8d842767..13b93bf8a7f 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -688,7 +688,7 @@ impl BackgroundRunnerCore { } let curr_memory_usage = self.memory_controller.mem_usage(); - let threshold = self.memory_controller.soft_limit_threshold(); + let threshold = self.memory_controller.stop_load_limit_threshold(); range_stats_manager.adjust_max_num_regions(curr_memory_usage, threshold); let mut regions_to_add = Vec::with_capacity(256); @@ -937,7 +937,7 @@ impl Runnable for BackgroundRunner { engine.engine.clone() }; - if core.memory_controller.reached_soft_limit() { + if core.memory_controller.reached_stop_load_limit() { // We are running out of memory, so cancel the load. is_canceled = true; } @@ -2749,9 +2749,101 @@ pub mod tests { pd_server.stop(); } + fn verify_load( + region: &Region, + engine: &RangeCacheMemoryEngine, + exist: bool, + expect_count: usize, + ) { + if exist { + let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); + let snap = engine + .snapshot(CacheRegion::from_region(region), read_ts, u64::MAX) + .unwrap(); + let mut count = 0; + let range = CacheRegion::from_region(region); + for cf in DATA_CFS { + let mut iter = IterOptions::default(); + iter.set_lower_bound(&range.start, 0); + iter.set_upper_bound(&range.end, 0); + let mut iter = snap.iterator_opt(cf, iter).unwrap(); + let _ = iter.seek_to_first(); + while iter.valid().unwrap() { + let _ = iter.next(); + count += 1; + } + } + assert_eq!(count, expect_count); + } else { + engine + .snapshot(CacheRegion::from_region(region), 10, 10) + .unwrap_err(); + } + } + + #[test] + fn test_snapshot_load_reaching_stop_limit() { + let mut config = RangeCacheEngineConfig::config_for_test(); + config.stop_load_limit_threshold = Some(ReadableSize(500)); + config.soft_limit_threshold = Some(ReadableSize(1000)); + config.hard_limit_threshold = Some(ReadableSize(1500)); + let config = Arc::new(VersionTrack::new(config)); + let mut engine = + RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config)); + let path = Builder::new() + .prefix("test_snapshot_load_reaching_limit") + .tempdir() + .unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + engine.set_disk_engine(rocks_engine.clone()); + let mem_controller = engine.memory_controller(); + + let region1 = new_region(1, construct_region_key(1), construct_region_key(3)); + // Memory for one put is 17(key) + 3(val) + 8(Seqno) + 16(Memory controller in + // key and val) + 96(Node overhead) = 140 + let key = construct_key(1, 10); + rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); + + let key = construct_key(2, 10); + rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); + // After loading range1, the memory usage should be 140*6=840 + + let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); + let key = construct_key(3, 10); + rocks_engine.put_cf(CF_DEFAULT, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); + rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); + + for r in [®ion1, ®ion2] { + engine.load_region(r.clone()).unwrap(); + engine.prepare_for_apply(1, &CacheRegion::from_region(r)); + } + + // ensure all ranges are finshed + test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { + !engine + .core + .read() + .range_manager() + .regions() + .values() + .any(|m| matches!(m.get_state(), Pending | Loading)) + }); + + verify_load(®ion1, &engine, true, 6); + verify_load(®ion2, &engine, false, 0); + assert_eq!(mem_controller.mem_usage(), 846); + } + #[test] - fn test_snapshot_load_reaching_limit() { + fn test_snapshot_load_reaching_hard_limit() { let mut config = RangeCacheEngineConfig::config_for_test(); + config.stop_load_limit_threshold = Some(ReadableSize(1000)); config.soft_limit_threshold = Some(ReadableSize(1000)); config.hard_limit_threshold = Some(ReadableSize(1500)); let config = Arc::new(VersionTrack::new(config)); @@ -2819,35 +2911,9 @@ pub mod tests { .any(|m| matches!(m.get_state(), Pending | Loading)) }); - let verify = |region: &Region, exist, expect_count| { - if exist { - let read_ts = TimeStamp::compose(TimeStamp::physical_now(), 0).into_inner(); - let snap = engine - .snapshot(CacheRegion::from_region(region), read_ts, u64::MAX) - .unwrap(); - let mut count = 0; - let range = CacheRegion::from_region(region); - for cf in DATA_CFS { - let mut iter = IterOptions::default(); - iter.set_lower_bound(&range.start, 0); - iter.set_upper_bound(&range.end, 0); - let mut iter = snap.iterator_opt(cf, iter).unwrap(); - let _ = iter.seek_to_first(); - while iter.valid().unwrap() { - let _ = iter.next(); - count += 1; - } - } - assert_eq!(count, expect_count); - } else { - engine - .snapshot(CacheRegion::from_region(region), 10, 10) - .unwrap_err(); - } - }; - verify(®ion1, true, 6); - verify(®ion2, false, 0); - verify(®ion3, false, 3); + verify_load(®ion1, &engine, true, 6); + verify_load(®ion2, &engine, false, 0); + verify_load(®ion3, &engine, false, 3); assert_eq!(mem_controller.mem_usage(), 1551); } diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 09fe4d6362e..84ebaf031c4 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -564,6 +564,7 @@ pub mod tests { enabled: true, gc_interval: Default::default(), load_evict_interval: Default::default(), + stop_load_limit_threshold: Some(ReadableSize(300)), soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), @@ -620,6 +621,7 @@ pub mod tests { enabled: true, gc_interval: Default::default(), load_evict_interval: Default::default(), + stop_load_limit_threshold: Some(ReadableSize(300)), soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index f2fe1ca9ba7..101562bfce9 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -56,6 +56,10 @@ pub struct RangeCacheEngineConfig { pub enabled: bool, pub gc_interval: ReadableDuration, pub load_evict_interval: ReadableDuration, + // TODO(SpadeA): ultimately we only expose one memory limit to user. + // When memory usage reaches this amount, no further load will be performed. + pub stop_load_limit_threshold: Option, + // When memory usage reaches this amount, we start to pick some ranges to evict. pub soft_limit_threshold: Option, pub hard_limit_threshold: Option, pub expected_region_size: Option, @@ -69,6 +73,7 @@ impl Default for RangeCacheEngineConfig { Self { enabled: false, gc_interval: ReadableDuration(Duration::from_secs(180)), + stop_load_limit_threshold: None, // Each load/evict operation should run within five minutes. load_evict_interval: ReadableDuration(Duration::from_secs(300)), soft_limit_threshold: None, @@ -95,6 +100,20 @@ impl RangeCacheEngineConfig { )); } + if self.stop_load_limit_threshold.is_none() { + self.stop_load_limit_threshold = self.soft_limit_threshold; + } + + if self.stop_load_limit_threshold.as_ref().unwrap() + > self.soft_limit_threshold.as_ref().unwrap() + { + return Err(Error::InvalidArgument(format!( + "stop-load-limit-threshold {:?} is larger to soft-limit-threshold {:?}", + self.stop_load_limit_threshold.as_ref().unwrap(), + self.soft_limit_threshold.as_ref().unwrap() + ))); + } + if self.soft_limit_threshold.as_ref().unwrap() >= self.hard_limit_threshold.as_ref().unwrap() { @@ -108,6 +127,10 @@ impl RangeCacheEngineConfig { Ok(()) } + pub fn stop_load_limit_threshold(&self) -> usize { + self.stop_load_limit_threshold.map_or(0, |r| r.0 as usize) + } + pub fn soft_limit_threshold(&self) -> usize { self.soft_limit_threshold.map_or(0, |r| r.0 as usize) } @@ -129,6 +152,7 @@ impl RangeCacheEngineConfig { gc_interval: ReadableDuration(Duration::from_secs(180)), load_evict_interval: ReadableDuration(Duration::from_secs(300)), /* Should run within * five minutes */ + stop_load_limit_threshold: Some(ReadableSize::gb(1)), soft_limit_threshold: Some(ReadableSize::gb(1)), hard_limit_threshold: Some(ReadableSize::gb(2)), expected_region_size: Some(ReadableSize::mb(20)), diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index ae9a322d55d..6ceba104c14 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -85,11 +85,21 @@ impl MemoryController { self.allocated.fetch_sub(n, Ordering::Relaxed); } + #[inline] + pub(crate) fn reached_stop_load_limit(&self) -> bool { + self.mem_usage() >= self.config.value().stop_load_limit_threshold() + } + #[inline] pub(crate) fn reached_soft_limit(&self) -> bool { self.mem_usage() >= self.config.value().soft_limit_threshold() } + #[inline] + pub(crate) fn stop_load_limit_threshold(&self) -> usize { + self.config.value().stop_load_limit_threshold() + } + #[inline] pub(crate) fn soft_limit_threshold(&self) -> usize { self.config.value().soft_limit_threshold() @@ -128,6 +138,7 @@ mod tests { enabled: true, gc_interval: Default::default(), load_evict_interval: Default::default(), + stop_load_limit_threshold: Some(ReadableSize(300)), soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Default::default(), diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 87730c16877..814f92fdbe0 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -305,7 +305,8 @@ fn test_cached_write_batch_cleared_when_load_failed() { let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); let mut config = RangeCacheEngineConfig::config_for_test(); - config.soft_limit_threshold = Some(ReadableSize(20)); + config.stop_load_limit_threshold = Some(ReadableSize(20)); + config.soft_limit_threshold = Some(ReadableSize(30)); config.hard_limit_threshold = Some(ReadableSize(40)); let config = Arc::new(VersionTrack::new(config)); let mut engine = diff --git a/tests/integrations/config/test_config_client.rs b/tests/integrations/config/test_config_client.rs index 9f126fcea82..10946db796e 100644 --- a/tests/integrations/config/test_config_client.rs +++ b/tests/integrations/config/test_config_client.rs @@ -58,6 +58,10 @@ fn test_update_config() { let mut range_cache_config_change = HashMap::new(); range_cache_config_change.insert("range_cache_engine.enabled".to_owned(), "true".to_owned()); + range_cache_config_change.insert( + "range_cache_engine.stop-load-limit-threshold".to_owned(), + "8GB".to_owned(), + ); range_cache_config_change.insert( "range_cache_engine.soft-limit-threshold".to_owned(), "10GB".to_owned(), @@ -68,6 +72,7 @@ fn test_update_config() { ); cfg_controller.update(range_cache_config_change).unwrap(); cfg.range_cache_engine.enabled = true; + cfg.range_cache_engine.stop_load_limit_threshold = Some(ReadableSize::gb(8)); cfg.range_cache_engine.soft_limit_threshold = Some(ReadableSize::gb(10)); cfg.range_cache_engine.hard_limit_threshold = Some(ReadableSize::gb(15)); assert_eq!(cfg_controller.get_current(), cfg); From 6e3e9aea0aedec8f880ed959b87cc17b8b0af565 Mon Sep 17 00:00:00 2001 From: hhwyt Date: Wed, 4 Sep 2024 10:32:57 +0800 Subject: [PATCH 049/144] encryption: remove duplicate comments (#17462) ref tikv/tikv#17410 Comments Signed-off-by: hhwyt Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/encryption/src/master_key/kms.rs | 8 ++++---- tests/failpoints/cases/test_encryption.rs | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/components/encryption/src/master_key/kms.rs b/components/encryption/src/master_key/kms.rs index b50cf1aac4b..c22bb3c03ea 100644 --- a/components/encryption/src/master_key/kms.rs +++ b/components/encryption/src/master_key/kms.rs @@ -159,6 +159,9 @@ impl KmsBackend { } } + // Used to clear the cached state to ensure that the next + // backend.decrypt_content() invocation bypasses the cache and invokes the + // KmsProvider::decrypt_data_key() function. #[cfg(any(test, feature = "testexport"))] pub fn clear_state(&mut self) { let mut opt_state = self.state.lock().unwrap(); @@ -353,11 +356,8 @@ mod tests { let mut backend = prepare_kms_backend(plainkey, true); let encrypted_content = backend.encrypt_content(&pt, iv).unwrap(); - // Clear the cached state to ensure that the subsequent - // backend.decrypt_content() invocation bypasses the cache and triggers the - // mocked FakeKMS::decrypt_data_key() function. - backend.clear_state(); + backend.clear_state(); let err = backend.decrypt_content(&encrypted_content).unwrap_err(); assert_matches!(err, Error::WrongMasterKey(_)); } diff --git a/tests/failpoints/cases/test_encryption.rs b/tests/failpoints/cases/test_encryption.rs index e230fad2f83..bd0b6a49c25 100644 --- a/tests/failpoints/cases/test_encryption.rs +++ b/tests/failpoints/cases/test_encryption.rs @@ -64,11 +64,8 @@ fn test_kms_provider_temporary_unavailable() { let (iv, pt, plainkey, ..) = prepare_data_for_encrypt(); let mut backend = prepare_kms_backend(plainkey, false); let encrypted_content = backend.encrypt_content(&pt, iv).unwrap(); - // Clear the cached state to ensure that the subsequent - // backend.decrypt_content() invocation bypasses the cache and triggers the - // mocked FakeKMS::decrypt_data_key() function. - backend.clear_state(); + backend.clear_state(); // Same as above. fail::cfg("kms_api_timeout_decrypt", "1*return(true)").unwrap(); let pt_decrypt = backend.decrypt_content(&encrypted_content).unwrap(); From 3ca20467241c587bbf13c373c19710adf9bda83d Mon Sep 17 00:00:00 2001 From: Connor Date: Thu, 5 Sep 2024 12:55:36 +0800 Subject: [PATCH 050/144] storage: Fix unexpected flow control after unsafe destroy range (#17458) close tikv/tikv#17304 Fix unexpected flow control after unsafe destroy range Flow controller detects pending compaction bytes jump before and after unsafe destroy range. If there is a jump, the controller enters a state that would ignore the high pending compaction bytes until it falls back to normal. Previously, the controller may not enter the state if the pending compaction bytes is lower than the threshold while long term average pending bytes is still high. Then it would trigger flow control mistakenly. Signed-off-by: Connor1996 Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../singleton_flow_controller.rs | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/storage/txn/flow_controller/singleton_flow_controller.rs b/src/storage/txn/flow_controller/singleton_flow_controller.rs index 61c05fbd8a2..2d36b9d15b0 100644 --- a/src/storage/txn/flow_controller/singleton_flow_controller.rs +++ b/src/storage/txn/flow_controller/singleton_flow_controller.rs @@ -593,14 +593,24 @@ impl FlowChecker { if !current_cfg.enable { return; } + if self.wait_for_destroy_range_finish { + // Concurrent unsafe destroy range, ignore the second one + info!("concurrent unsafe destroy range, ignore"); + return; + } self.wait_for_destroy_range_finish = true; let soft = (current_cfg.soft_pending_compaction_bytes_limit.0 as f64).log2(); - for cf_checker in self.cf_checkers.values_mut() { + for (cf, cf_checker) in &mut self.cf_checkers { if let Some(long_term_pending_bytes) = cf_checker.long_term_pending_bytes.as_ref() { let v = long_term_pending_bytes.get_avg(); if v <= soft { + info!( + "before unsafe destroy range"; + "cf" => cf, + "pending_bytes" => v + ); cf_checker.pending_bytes_before_unsafe_destroy_range = Some(v); } } @@ -625,9 +635,13 @@ impl FlowChecker { SCHED_THROTTLE_ACTION_COUNTER .with_label_values(&[cf, "pending_bytes_jump"]) .inc(); - } else { - cf_checker.pending_bytes_before_unsafe_destroy_range = None; } + info!( + "after unsafe destroy range"; + "cf" => cf, + "before" => before, + "after" => after + ); } } } @@ -771,7 +785,17 @@ impl FlowChecker { let pending_compaction_bytes = long_term_pending_bytes.get_avg(); let ignore = if let Some(before) = checker.pending_bytes_before_unsafe_destroy_range { + // It assumes that the long term average will eventually come down below the + // soft limit. If the general traffic flow increases during destroy, the long + // term average may never come down and the flow control will be turned off for + // a long time, which would be a rather rare case, so just ignore it. if pending_compaction_bytes <= before && !self.wait_for_destroy_range_finish { + info!( + "pending compaction bytes is back to normal"; + "cf" => &cf, + "pending_compaction_bytes" => pending_compaction_bytes, + "before" => before + ); checker.pending_bytes_before_unsafe_destroy_range = None; } true @@ -1346,6 +1370,14 @@ pub(super) mod tests { stub.0 .pending_compaction_bytes .store(10000000 * 1024 * 1024 * 1024, Ordering::Relaxed); + send_flow_info(tx, region_id); + assert!(flow_controller.discard_ratio(region_id) < f64::EPSILON); + + // after unsafe destroy range, pending compaction bytes may jump back to a lower + // value + stub.0 + .pending_compaction_bytes + .store(100 * 1024 * 1024 * 1024, Ordering::Relaxed); tx.send(FlowInfo::Compaction("default".to_string(), region_id)) .unwrap(); tx.send(FlowInfo::AfterUnsafeDestroyRange(region_id)) @@ -1358,13 +1390,23 @@ pub(super) mod tests { flow_controller.discard_ratio(region_id) ); - // unfreeze the control + // the long term average pending compaction bytes is still high, shouldn't + // unfreeze the jump control + stub.0 + .pending_compaction_bytes + .store(100 * 1024 * 1024 * 1024, Ordering::Relaxed); + send_flow_info(tx, region_id); + assert!(flow_controller.discard_ratio(region_id) < f64::EPSILON); + + // the long term average pending compaction bytes falls below the threshold, + // should unfreeze the jump control stub.0 .pending_compaction_bytes .store(1024 * 1024, Ordering::Relaxed); send_flow_info(tx, region_id); assert!(flow_controller.discard_ratio(region_id) < f64::EPSILON); + // exceeds the threshold, should perform throttle stub.0 .pending_compaction_bytes .store(1000000000 * 1024 * 1024 * 1024, Ordering::Relaxed); From 070cbd53a569f643e190a50d11bd790827441e69 Mon Sep 17 00:00:00 2001 From: glorv Date: Thu, 5 Sep 2024 17:15:37 +0800 Subject: [PATCH 051/144] in-memory-region: fix the inconsistency caused by updating region range (#17486) close tikv/tikv#17483, close tikv/tikv#17484 The PR fix the bug by `amend_pending_region` that causes inconsistency between regions and regions_by_range because it may change the region range in metadata but not update the key of regions_by_range. This PR change the original `amend_pending_region` by first remove the old region and add a new one. BTW, this PR also add a `Drop` implementation for `RegionManager` in test environment to check the consistency between regions and regions_by_range to find this kind of bug easier. Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/range_manager.rs | 63 +++++++++++++------ .../src/write_batch.rs | 40 ++++++++++++ 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index a2c9033b436..b6a7d02266d 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -122,18 +122,18 @@ impl CacheRegionMeta { &self.region } - // update region info due to epoch version changes. This can only - // happen for pending region because otherwise we will always update - // the region epoch with ApplyObserver(for loading/active regions) or - // no need to update the epoch for evicting regions. - fn amend_pending_region(&mut self, region: &CacheRegion) -> bool { - assert!(self.region.id == region.id && self.region.epoch_version < region.epoch_version); - if !self.region.contains_range(region) { - return false; - } - - self.region = region.clone(); - true + // check whether we can replace the current outdated pending region with the new + // one. + fn can_be_updated_to(&self, region: &CacheRegion) -> bool { + assert!( + self.region.id == region.id && self.region.epoch_version < region.epoch_version, + "current: {:?}, new: {:?}", + &self.region, + region + ); + // if the new region's range is contained by the current region, we can directly + // update to the new one. + self.region.contains_range(region) } pub(crate) fn safe_point(&self) -> u64 { @@ -280,6 +280,13 @@ impl RegionManager { &self.regions } + #[cfg(test)] + pub(crate) fn region_meta_by_end_key(&self, key: &[u8]) -> Option<&CacheRegionMeta> { + self.regions_by_range + .get(key) + .and_then(|id| self.regions.get(id)) + } + // load a new region directly in the active state. // This fucntion is used for unit/integration tests only. pub fn new_region(&mut self, region: CacheRegion) { @@ -375,14 +382,23 @@ impl RegionManager { let Some(cached_meta) = self.regions.get_mut(®ion.id) else { return None; }; - if cached_meta.state == Pending - && cached_meta.region.epoch_version != region.epoch_version - && !cached_meta.amend_pending_region(region) + if cached_meta.state == Pending && cached_meta.region.epoch_version != region.epoch_version { + let meta = self.remove_region(region.id); + if meta.can_be_updated_to(region) { + info!("ime update outdated pending region"; + "current_meta" => ?meta, + "new_region" => ?region); + // the new region's range is smaller than removed region, so it is impossible to + // be overlapped with other existing regions. + self.load_region(region.clone()).unwrap(); + + return Some(RegionState::Pending); + } + info!("ime remove outdated pending region"; - "pending_region" => ?cached_meta.region, + "pending_region" => ?meta.region, "new_region" => ?region); - self.remove_region(region.id); return None; } Some(cached_meta.state) @@ -697,7 +713,7 @@ impl RegionManager { fn remove_region(&mut self, id: u64) -> CacheRegionMeta { let meta = self.regions.remove(&id).unwrap(); - self.regions_by_range.remove(&meta.region.end); + self.regions_by_range.remove(&meta.region.end).unwrap(); meta } @@ -826,6 +842,17 @@ impl RegionManager { } } +#[cfg(test)] +impl Drop for RegionManager { + fn drop(&mut self) { + // check regions and regions by range matches with each other. + for (key, id) in &self.regions_by_range { + let meta = self.regions.get(id).unwrap(); + assert_eq!(key, &meta.region.end); + } + } +} + #[derive(Debug, PartialEq)] pub enum LoadFailedReason { Overlapped, diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 66b06dae283..57b92f16dd1 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -954,4 +954,44 @@ mod tests { .unwrap(); assert_eq!(snap2.get_value(b"zkk11").unwrap().unwrap(), &val1); } + + #[test] + fn test_write_batch_update_outdated_pending_region() { + let path = Builder::new() + .prefix("test_write_batch_update_outdated_pending_region") + .tempdir() + .unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( + Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), + )); + engine.set_disk_engine(rocks_engine.clone()); + + let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); + + engine + .core() + .write() + .mut_range_manager() + .load_region(r1) + .unwrap(); + + // load a region with a newer epoch and small range, should trigger replace. + let r_new = CacheRegion::new(1, 1, b"k00", b"k05"); + let mut wb = RangeCacheWriteBatch::from(&engine); + wb.prepare_for_region(r_new.clone()); + + { + let core = engine.core().read(); + let cache_meta = core.range_manager.region_meta(1).unwrap(); + assert_eq!(cache_meta.get_region(), &r_new); + let meta_by_range = core + .range_manager + .region_meta_by_end_key(&r_new.end) + .unwrap(); + assert_eq!(meta_by_range.get_region(), &r_new); + } + } } From 7e8d4ad96e02f12472c1562d1846724202a4d256 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 6 Sep 2024 17:39:59 +0800 Subject: [PATCH 052/144] In-memory Engine: Reduce `HybridEngine` scope (#17359) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In TiKV, the `KvEngine` trait provides the write path abstraction (`WriteBatch`) and read path abstraction (`Snapshot`). The `HybridEngine` implements the `KvEngine` trait, allowing it to be integrated into TiKV. However, as described in issue #17181, there is a major downside: all components and features in TiKV use the `HybridEngine`, which can introduce unexpected compatibility issues (e.g., BR restore failures with checksum errors). This is not worthwhile because the `HybridEngine` is designed specifically for accelerating coprocessor read speed in scenarios with many MVCC workloads. This PR shrinks the `HybridEngine` scope from being globally enabled to only being enabled in the coprocessor. The changes include: - Adding a new observer, `WriteBatchObserver`, to observe write requests via raftstore coprocessor hooks. - Adding a new observer, `SnapshotObserver`, to observe snapshot (and `read_ts`) via raftstore coprocessor hooks. - Adding a new method to the `RaftKv` struct called `async_in_memory_snapshot`, which takes snapshots from the `HybridEngine`. This PR also introduces an architectural change, transforming the in-memory engine from functioning as an `KvEngine` to acting as an MVCC-aware cache. Conceptually, the in-memory engine is shifted from the storage engine layer to the MVCC layer. This adjustment better aligns with its purpose of improving MVCC performance by caching recent versions, rather than serving as a full-fledged storage engine. ┌──────────────┐ ┌──────────────┐ │ Copr/Storage │ │ Copr/Storage │ ├──────────────┤ ├──────────────┤ │ MVCC │ │ MVCC │ ├──────────────┤ │ ┌──────────┐ │ │ Raftstore │ ───> │ │ IME │ │ ├──────────────┤ ├─┴──────────┴─┤ │ IME │ │ Raftstore │ │┌────────────┐│ ├──────────────┤ ││ RocksDB ││ │ RocksDB │ └┴────────────┴┘ └──────────────┘ Additionally, this PR brings two unexpected benefits*: - Reduced TiKV binary size: From 1.7GB to 1.2GB. - Faster build time: From 32 minutes to 20 minutes. *: Results were obtained using the `make release` command. Signed-off-by: Neil Shen --- Cargo.lock | 2 + components/backup-stream/tests/suite.rs | 3 +- components/cdc/tests/mod.rs | 11 +- components/engine_panic/src/lib.rs | 1 - .../engine_panic/src/range_cache_engine.rs | 15 - components/engine_rocks/src/lib.rs | 1 - .../engine_rocks/src/range_cache_engine.rs | 14 - components/engine_traits/src/engine.rs | 1 - .../engine_traits/src/range_cache_engine.rs | 2 - components/engine_traits/src/write_batch.rs | 23 +- components/hybrid_engine/src/engine.rs | 67 +-- components/hybrid_engine/src/lib.rs | 2 +- .../src/{observer.rs => observer/eviction.rs} | 49 +- components/hybrid_engine/src/observer/mod.rs | 9 + .../hybrid_engine/src/observer/snapshot.rs | 46 ++ .../hybrid_engine/src/observer/write_batch.rs | 136 +++++ .../hybrid_engine/src/range_cache_engine.rs | 4 - components/hybrid_engine/src/snapshot.rs | 33 +- .../raftstore/src/coprocessor/dispatcher.rs | 49 +- components/raftstore/src/coprocessor/mod.rs | 5 + .../src/coprocessor/read_write/mod.rs | 7 + .../src/coprocessor/read_write/snapshot.rs | 16 + .../src/coprocessor/read_write/write_batch.rs | 182 +++++++ components/raftstore/src/store/fsm/apply.rs | 15 +- components/raftstore/src/store/peer.rs | 22 +- .../raftstore/src/store/region_snapshot.rs | 59 ++- components/raftstore/src/store/worker/read.rs | 46 +- .../range_cache_memory_engine/src/lib.rs | 1 + .../range_cache_memory_engine/src/read.rs | 1 + .../src/write_batch.rs | 2 +- components/resolved_ts/tests/mod.rs | 3 +- components/server/src/common.rs | 58 +-- components/server/src/server.rs | 167 +++--- components/test_backup/src/disk_snap.rs | 3 +- components/test_backup/src/lib.rs | 3 +- components/test_coprocessor/Cargo.toml | 2 + components/test_coprocessor/src/dag.rs | 11 +- components/test_coprocessor/src/fixture.rs | 29 +- components/test_coprocessor/src/store.rs | 27 +- components/test_coprocessor/src/table.rs | 8 + components/test_raftstore-v2/src/server.rs | 6 + components/test_raftstore/src/cluster.rs | 86 ++-- components/test_raftstore/src/node.rs | 106 ++-- components/test_raftstore/src/server.rs | 294 ++++++----- .../test_raftstore/src/transport_simulate.rs | 46 +- components/test_raftstore/src/util.rs | 140 ++--- components/test_storage/src/assert_storage.rs | 23 +- components/test_storage/src/util.rs | 11 +- components/tikv_kv/src/btree_engine.rs | 6 + components/tikv_kv/src/lib.rs | 26 + components/tikv_kv/src/mock_engine.rs | 6 + components/tikv_kv/src/rocksdb_engine.rs | 6 + src/coprocessor/endpoint.rs | 29 +- src/server/gc_worker/gc_worker.rs | 12 + src/server/raftkv/mod.rs | 263 +++++----- src/server/raftkv2/mod.rs | 6 + src/storage/mod.rs | 6 + tests/benches/misc/raftkv/mod.rs | 2 + tests/benches/raftstore/mod.rs | 25 +- tests/failpoints/cases/test_bootstrap.rs | 5 +- .../cases/test_cmd_epoch_checker.rs | 5 +- tests/failpoints/cases/test_merge.rs | 3 +- .../cases/test_range_cache_engine.rs | 480 +++++++++--------- tests/failpoints/cases/test_rawkv.rs | 3 +- .../cases/test_replica_stale_read.rs | 15 +- tests/failpoints/cases/test_sst_recovery.rs | 7 +- tests/failpoints/cases/test_stale_read.rs | 5 +- .../failpoints/cases/test_unsafe_recovery.rs | 7 +- tests/failpoints/cases/test_witness.rs | 5 +- tests/integrations/coprocessor/test_select.rs | 76 ++- tests/integrations/import/util.rs | 19 +- .../integrations/raftstore/test_bootstrap.rs | 6 +- .../raftstore/test_clear_stale_data.rs | 2 +- .../raftstore/test_compact_after_delete.rs | 4 +- .../raftstore/test_compact_lock_cf.rs | 12 +- .../raftstore/test_compact_log.rs | 13 +- .../raftstore/test_early_apply.rs | 13 +- .../integrations/raftstore/test_flashback.rs | 12 +- .../raftstore/test_joint_consensus.rs | 13 +- .../integrations/raftstore/test_lease_read.rs | 8 - tests/integrations/raftstore/test_multi.rs | 46 +- tests/integrations/raftstore/test_prevote.rs | 20 +- .../raftstore/test_region_change_observer.rs | 3 +- .../raftstore/test_region_heartbeat.rs | 3 +- .../raftstore/test_region_info_accessor.rs | 6 +- .../raftstore/test_replication_mode.rs | 9 +- tests/integrations/raftstore/test_single.rs | 8 - tests/integrations/raftstore/test_snap.rs | 6 +- .../raftstore/test_split_region.rs | 28 +- .../integrations/raftstore/test_stale_peer.rs | 8 +- tests/integrations/raftstore/test_stats.rs | 24 +- .../integrations/raftstore/test_tombstone.rs | 7 +- .../integrations/raftstore/test_transport.rs | 3 +- .../raftstore/test_update_region_size.rs | 7 +- tests/integrations/raftstore/test_witness.rs | 5 +- .../resource_metering/test_read_keys.rs | 10 +- tests/integrations/server/kv_service.rs | 4 +- tests/integrations/server/lock_manager.rs | 35 +- tests/integrations/server_encryption.rs | 3 +- .../integrations/storage/test_raft_storage.rs | 7 +- tests/integrations/storage/test_raftkv.rs | 3 +- .../storage/test_region_info_accessor.rs | 5 +- 102 files changed, 1797 insertions(+), 1400 deletions(-) delete mode 100644 components/engine_panic/src/range_cache_engine.rs delete mode 100644 components/engine_rocks/src/range_cache_engine.rs rename components/hybrid_engine/src/{observer.rs => observer/eviction.rs} (89%) create mode 100644 components/hybrid_engine/src/observer/mod.rs create mode 100644 components/hybrid_engine/src/observer/snapshot.rs create mode 100644 components/hybrid_engine/src/observer/write_batch.rs create mode 100644 components/raftstore/src/coprocessor/read_write/mod.rs create mode 100644 components/raftstore/src/coprocessor/read_write/snapshot.rs create mode 100644 components/raftstore/src/coprocessor/read_write/write_batch.rs diff --git a/Cargo.lock b/Cargo.lock index d5c72f70bc5..36ca62879e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5930,11 +5930,13 @@ name = "test_coprocessor" version = "0.0.1" dependencies = [ "api_version", + "codec", "collections", "concurrency_manager", "engine_rocks", "futures 0.3.15", "kvproto", + "pd_client", "protobuf", "resource_metering", "test_storage", diff --git a/components/backup-stream/tests/suite.rs b/components/backup-stream/tests/suite.rs index ba6c350ccd6..843bc5e4c9a 100644 --- a/components/backup-stream/tests/suite.rs +++ b/components/backup-stream/tests/suite.rs @@ -21,7 +21,6 @@ use backup_stream::{ utils, BackupStreamGrpcService, BackupStreamResolver, Endpoint, GetCheckpointResult, RegionCheckpointOperation, RegionSet, Task, }; -use engine_rocks::RocksEngine; use futures::{executor::block_on, AsyncWriteExt, Future, Stream, StreamExt}; use grpcio::{ChannelBuilder, Server, ServerBuilder}; use kvproto::{ @@ -264,7 +263,7 @@ impl MetaStore for ErrorStore { pub struct Suite { pub endpoints: HashMap>, pub meta_store: ErrorStore, - pub cluster: Cluster>, + pub cluster: Cluster, tikv_cli: HashMap, log_backup_cli: HashMap, obs: HashMap, diff --git a/components/cdc/tests/mod.rs b/components/cdc/tests/mod.rs index ce52455a8af..31b1db087a4 100644 --- a/components/cdc/tests/mod.rs +++ b/components/cdc/tests/mod.rs @@ -134,7 +134,7 @@ fn create_event_feed( } pub struct TestSuiteBuilder { - cluster: Option>>, + cluster: Option>, memory_quota: Option, } @@ -147,10 +147,7 @@ impl TestSuiteBuilder { } #[must_use] - pub fn cluster( - mut self, - cluster: Cluster>, - ) -> TestSuiteBuilder { + pub fn cluster(mut self, cluster: Cluster) -> TestSuiteBuilder { self.cluster = Some(cluster); self } @@ -167,7 +164,7 @@ impl TestSuiteBuilder { pub fn build_with_cluster_runner(self, mut runner: F) -> TestSuite where - F: FnMut(&mut Cluster>), + F: FnMut(&mut Cluster), { init(); let memory_quota = self.memory_quota.unwrap_or(usize::MAX); @@ -257,7 +254,7 @@ impl TestSuiteBuilder { } pub struct TestSuite { - pub cluster: Cluster>, + pub cluster: Cluster, pub endpoints: HashMap>, pub obs: HashMap, tikv_cli: HashMap, diff --git a/components/engine_panic/src/lib.rs b/components/engine_panic/src/lib.rs index 0b0c107f873..93555f5ba5f 100644 --- a/components/engine_panic/src/lib.rs +++ b/components/engine_panic/src/lib.rs @@ -46,6 +46,5 @@ pub use crate::flow_control_factors::*; pub mod table_properties; pub use crate::table_properties::*; pub mod checkpoint; -pub mod range_cache_engine; mod raft_engine; diff --git a/components/engine_panic/src/range_cache_engine.rs b/components/engine_panic/src/range_cache_engine.rs deleted file mode 100644 index 1b5e3cc61df..00000000000 --- a/components/engine_panic/src/range_cache_engine.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. - -use engine_traits::{EvictReason, RangeCacheEngineExt, RegionEvent}; - -use crate::PanicEngine; - -impl RangeCacheEngineExt for PanicEngine { - fn range_cache_engine_enabled(&self) -> bool { - panic!() - } - - fn on_region_event(&self, event: RegionEvent) { - panic!() - } -} diff --git a/components/engine_rocks/src/lib.rs b/components/engine_rocks/src/lib.rs index 86afd386c7c..28c7c97d0a8 100644 --- a/components/engine_rocks/src/lib.rs +++ b/components/engine_rocks/src/lib.rs @@ -46,7 +46,6 @@ mod logger; pub use crate::logger::*; mod misc; pub use crate::misc::*; -pub mod range_cache_engine; pub mod range_properties; mod snapshot; pub use crate::snapshot::*; diff --git a/components/engine_rocks/src/range_cache_engine.rs b/components/engine_rocks/src/range_cache_engine.rs deleted file mode 100644 index cce2498126b..00000000000 --- a/components/engine_rocks/src/range_cache_engine.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. - -use engine_traits::{RangeCacheEngineExt, RegionEvent}; - -use crate::RocksEngine; - -impl RangeCacheEngineExt for RocksEngine { - fn range_cache_engine_enabled(&self) -> bool { - false - } - - #[inline] - fn on_region_event(&self, _: RegionEvent) {} -} diff --git a/components/engine_traits/src/engine.rs b/components/engine_traits/src/engine.rs index 346c4011082..a3aff48543c 100644 --- a/components/engine_traits/src/engine.rs +++ b/components/engine_traits/src/engine.rs @@ -33,7 +33,6 @@ pub trait KvEngine: + Debug + Unpin + Checkpointable - + RangeCacheEngineExt + 'static { /// A consistent read-only snapshot of the database diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 0046f6266fd..0b958668f75 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -88,8 +88,6 @@ pub trait RangeCacheEngine: } pub trait RangeCacheEngineExt { - fn range_cache_engine_enabled(&self) -> bool; - // TODO(SpadeA): try to find a better way to reduce coupling degree of range // cache engine and kv engine fn on_region_event(&self, event: RegionEvent); diff --git a/components/engine_traits/src/write_batch.rs b/components/engine_traits/src/write_batch.rs index 31aff5c9a56..a53b2faf9aa 100644 --- a/components/engine_traits/src/write_batch.rs +++ b/components/engine_traits/src/write_batch.rs @@ -39,10 +39,16 @@ pub trait Mutable: Send { /// Delete a range of key/values in a given column family fn delete_range_cf(&mut self, cf: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()>; - fn put_msg(&mut self, key: &[u8], m: &M) -> Result<()> { + fn put_msg(&mut self, key: &[u8], m: &M) -> Result<()> + where + Self: Sized, + { self.put(key, &m.write_to_bytes()?) } - fn put_msg_cf(&mut self, cf: &str, key: &[u8], m: &M) -> Result<()> { + fn put_msg_cf(&mut self, cf: &str, key: &[u8], m: &M) -> Result<()> + where + Self: Sized, + { self.put_cf(cf, key, &m.write_to_bytes()?) } } @@ -73,8 +79,13 @@ pub trait WriteBatch: Mutable { /// Commit the WriteBatch to disk with the given options fn write_opt(&mut self, opts: &WriteOptions) -> Result; - // TODO: it should be `FnOnce`. - fn write_callback_opt(&mut self, opts: &WriteOptions, mut cb: impl FnMut(u64)) -> Result { + /// Commit the WriteBatch to disk with the given options and call the + /// callback. The callback is called multiple times with the sequence number + /// of the write. + fn write_callback_opt(&mut self, opts: &WriteOptions, mut cb: impl FnMut(u64)) -> Result + where + Self: Sized, + { let seq = self.write_opt(opts)?; cb(seq); Ok(seq) @@ -122,7 +133,9 @@ pub trait WriteBatch: Mutable { fn rollback_to_save_point(&mut self) -> Result<()>; /// Merge another WriteBatch to itself - fn merge(&mut self, src: Self) -> Result<()>; + fn merge(&mut self, src: Self) -> Result<()> + where + Self: Sized; /// It declares that the following consecutive write will be within this /// region. diff --git a/components/hybrid_engine/src/engine.rs b/components/hybrid_engine/src/engine.rs index 1253fae335c..cddb3a15d37 100644 --- a/components/hybrid_engine/src/engine.rs +++ b/components/hybrid_engine/src/engine.rs @@ -50,6 +50,40 @@ where } } +pub fn new_in_memory_snapshot( + range_cache_engine: &EC, + ctx: SnapshotContext, + sequence_number: u64, +) -> Option { + match range_cache_engine.snapshot(ctx.region.unwrap(), ctx.read_ts, sequence_number) { + Ok(snap) => { + SNAPSHOT_TYPE_COUNT_STATIC.range_cache_engine.inc(); + Some(snap) + } + Err(FailedReason::TooOldRead) => { + RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC + .too_old_read + .inc(); + SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); + None + } + Err(FailedReason::NotCached) => { + RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC + .not_cached + .inc(); + SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); + None + } + Err(FailedReason::EpochNotMatch) => { + RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC + .epoch_not_match + .inc(); + SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); + None + } + } +} + impl HybridEngine where EK: KvEngine, @@ -97,43 +131,14 @@ where let range_cache_snap = if !self.range_cache_engine.enabled() { None } else if let Some(ctx) = ctx { - match self.range_cache_engine.snapshot( - ctx.region.unwrap(), - ctx.read_ts, - disk_snap.sequence_number(), - ) { - Ok(snap) => { - SNAPSHOT_TYPE_COUNT_STATIC.range_cache_engine.inc(); - Some(snap) - } - Err(FailedReason::TooOldRead) => { - RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC - .too_old_read - .inc(); - None - } - Err(FailedReason::NotCached) => { - RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC - .not_cached - .inc(); - None - } - Err(FailedReason::EpochNotMatch) => { - RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC - .epoch_not_match - .inc(); - None - } - } + new_in_memory_snapshot(&self.range_cache_engine, ctx, disk_snap.sequence_number()) } else { RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC .no_read_ts .inc(); + SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); None }; - if range_cache_snap.is_none() { - SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); - } HybridEngineSnapshot::new(disk_snap, range_cache_snap) } diff --git a/components/hybrid_engine/src/lib.rs b/components/hybrid_engine/src/lib.rs index ba30a4f4b26..5d21b00e2b1 100644 --- a/components/hybrid_engine/src/lib.rs +++ b/components/hybrid_engine/src/lib.rs @@ -29,5 +29,5 @@ mod ttl_properties; pub mod util; mod write_batch; -pub use engine::HybridEngine; +pub use engine::{new_in_memory_snapshot, HybridEngine}; pub use snapshot::HybridEngineSnapshot; diff --git a/components/hybrid_engine/src/observer.rs b/components/hybrid_engine/src/observer/eviction.rs similarity index 89% rename from components/hybrid_engine/src/observer.rs rename to components/hybrid_engine/src/observer/eviction.rs index 57c559089ac..cf9ac7e02e6 100644 --- a/components/hybrid_engine/src/observer.rs +++ b/components/hybrid_engine/src/observer/eviction.rs @@ -13,7 +13,7 @@ use raftstore::coprocessor::{ use tikv_util::info; #[derive(Clone)] -pub struct Observer { +pub struct EvictionObserver { // observer is per thread so there is no need to use mutex here, // but current inteface only provides `&self` but not `&mut self`, // so we use mutex to workaround this restriction. @@ -22,9 +22,9 @@ pub struct Observer { cache_engine: Arc, } -impl Observer { +impl EvictionObserver { pub fn new(cache_engine: Arc) -> Self { - Observer { + EvictionObserver { pending_events: Arc::default(), cache_engine, } @@ -64,9 +64,6 @@ impl Observer { state: &RegionState, apply: &mut ApplyCtxInfo<'_>, ) { - if !self.cache_engine.range_cache_engine_enabled() { - return; - } // Evict caches for successfully executed ingest commands and admin // commands that change region range. // @@ -124,10 +121,6 @@ impl Observer { } fn on_flush_cmd(&self) { - if !self.cache_engine.range_cache_engine_enabled() { - return; - } - let events = std::mem::take(&mut *self.pending_events.lock().unwrap()); for e in events { self.cache_engine.on_region_event(e); @@ -135,10 +128,6 @@ impl Observer { } fn evict_region_range(&self, region: &Region, reason: EvictReason) { - if !self.cache_engine.range_cache_engine_enabled() { - return; - } - let cache_region = CacheRegion::from_region(region); info!( "ime evict region"; @@ -156,9 +145,9 @@ impl Observer { } } -impl Coprocessor for Observer {} +impl Coprocessor for EvictionObserver {} -impl QueryObserver for Observer { +impl QueryObserver for EvictionObserver { fn post_exec_query( &self, ctx: &mut ObserverContext<'_>, @@ -174,7 +163,7 @@ impl QueryObserver for Observer { } } -impl AdminObserver for Observer { +impl AdminObserver for EvictionObserver { fn post_exec_admin( &self, ctx: &mut ObserverContext<'_>, @@ -190,7 +179,7 @@ impl AdminObserver for Observer { } } -impl ApplySnapshotObserver for Observer { +impl ApplySnapshotObserver for EvictionObserver { fn post_apply_snapshot( &self, ctx: &mut ObserverContext<'_>, @@ -205,7 +194,7 @@ impl ApplySnapshotObserver for Observer { } } -impl RoleObserver for Observer { +impl RoleObserver for EvictionObserver { fn on_role_change( &self, ctx: &mut ObserverContext<'_>, @@ -219,7 +208,7 @@ impl RoleObserver for Observer { } } -impl CmdObserver for Observer { +impl CmdObserver for EvictionObserver { fn on_flush_applied_cmd_batch( &self, _max_level: ObserveLevel, @@ -233,8 +222,6 @@ impl CmdObserver for Observer { #[cfg(test)] mod tests { - use std::sync::atomic::{AtomicBool, Ordering}; - use engine_traits::{RegionEvent, SstMetaInfo}; use kvproto::{ import_sstpb::SstMeta, @@ -246,13 +233,9 @@ mod tests { #[derive(Default)] struct MockRangeCacheEngine { - enabled: AtomicBool, region_events: Arc>>, } impl RangeCacheEngineExt for MockRangeCacheEngine { - fn range_cache_engine_enabled(&self) -> bool { - self.enabled.load(Ordering::Relaxed) - } fn on_region_event(&self, event: RegionEvent) { self.region_events.lock().unwrap().push(event); } @@ -269,7 +252,7 @@ mod tests { #[test] fn test_do_not_evict_range_region_split() { let cache_engine = Arc::new(MockRangeCacheEngine::default()); - let observer = Observer::new(cache_engine.clone()); + let observer = EvictionObserver::new(cache_engine.clone()); let mut region = Region::default(); region.set_id(1); @@ -290,9 +273,6 @@ mod tests { let cmd = Cmd::new(0, 0, request, response); // Must not evict range for region split. - // - // Enable range cache engine. - cache_engine.enabled.store(true, Ordering::Relaxed); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); let expected = CacheRegion::from_region(®ion); @@ -302,7 +282,7 @@ mod tests { #[test] fn test_evict_range_ingest_sst() { let cache_engine = Arc::new(MockRangeCacheEngine::default()); - let observer = Observer::new(cache_engine.clone()); + let observer = EvictionObserver::new(cache_engine.clone()); let mut region = Region::default(); region.set_id(1); @@ -329,13 +309,6 @@ mod tests { let response = RaftCmdResponse::default(); let cmd = Cmd::new(0, 0, request, response); - // Must not evict range when range cache engine is disabled. - observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); - observer.on_flush_cmd(); - assert!(cache_engine.region_events.lock().unwrap().is_empty()); - - // Enable range cache engine. - cache_engine.enabled.store(true, Ordering::Relaxed); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); observer.on_flush_cmd(); let cached_region = CacheRegion::from_region(®ion); diff --git a/components/hybrid_engine/src/observer/mod.rs b/components/hybrid_engine/src/observer/mod.rs new file mode 100644 index 00000000000..fb35590185c --- /dev/null +++ b/components/hybrid_engine/src/observer/mod.rs @@ -0,0 +1,9 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +mod eviction; +mod snapshot; +mod write_batch; + +pub use eviction::EvictionObserver; +pub use snapshot::{HybridSnapshotObserver, RangeCacheSnapshotPin}; +pub use write_batch::RegionCacheWriteBatchObserver; diff --git a/components/hybrid_engine/src/observer/snapshot.rs b/components/hybrid_engine/src/observer/snapshot.rs new file mode 100644 index 00000000000..377cb856131 --- /dev/null +++ b/components/hybrid_engine/src/observer/snapshot.rs @@ -0,0 +1,46 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use engine_traits::{KvEngine, SnapshotContext}; +use raftstore::coprocessor::{ + dispatcher::BoxSnapshotObserver, CoprocessorHost, ObservedSnapshot, SnapshotObserver, +}; +use range_cache_memory_engine::{RangeCacheMemoryEngine, RangeCacheSnapshot}; + +use crate::new_in_memory_snapshot; + +/// RangeCacheSnapshotPin pins data of a RangeCacheMemoryEngine during taking +/// snapshot. It prevents the data from being evicted or deleted from the cache. +// TODO: Remove it, theoretically it can be remove if we don't need an +// in-memory engine snapshot when a region is removed or splitted. +pub struct RangeCacheSnapshotPin { + pub snap: Option, +} + +impl ObservedSnapshot for RangeCacheSnapshotPin {} + +#[derive(Clone)] +pub struct HybridSnapshotObserver { + cache_engine: RangeCacheMemoryEngine, +} + +impl HybridSnapshotObserver { + pub fn new(cache_engine: RangeCacheMemoryEngine) -> Self { + HybridSnapshotObserver { cache_engine } + } + + pub fn register_to(&self, coprocessor_host: &mut CoprocessorHost) { + coprocessor_host + .registry + .register_snapshot_observer(BoxSnapshotObserver::new(self.clone())); + } +} + +impl SnapshotObserver for HybridSnapshotObserver { + fn on_snapshot(&self, ctx: SnapshotContext, sequence_number: u64) -> Box { + // Taking a snapshot to pin data in the cache engine which prevents the + // data from being evicted or deleted from the cache. + // The data should be released when the snapshot is dropped. + let snap = new_in_memory_snapshot(&self.cache_engine, ctx, sequence_number); + Box::new(RangeCacheSnapshotPin { snap }) + } +} diff --git a/components/hybrid_engine/src/observer/write_batch.rs b/components/hybrid_engine/src/observer/write_batch.rs new file mode 100644 index 00000000000..822adcc7224 --- /dev/null +++ b/components/hybrid_engine/src/observer/write_batch.rs @@ -0,0 +1,136 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use engine_traits::{is_data_cf, CacheRegion, KvEngine, Mutable, Result, WriteBatch, WriteOptions}; +use raftstore::coprocessor::{ + dispatcher::BoxWriteBatchObserver, Coprocessor, CoprocessorHost, ObservableWriteBatch, + WriteBatchObserver, +}; +use range_cache_memory_engine::{RangeCacheMemoryEngine, RangeCacheWriteBatch}; + +#[derive(Clone)] +pub struct RegionCacheWriteBatchObserver { + cache_engine: RangeCacheMemoryEngine, +} + +impl RegionCacheWriteBatchObserver { + pub fn new(cache_engine: RangeCacheMemoryEngine) -> Self { + RegionCacheWriteBatchObserver { cache_engine } + } + + pub fn register_to(&self, coprocessor_host: &mut CoprocessorHost) { + coprocessor_host + .registry + .register_write_batch_observer(BoxWriteBatchObserver::new(self.clone())); + } +} + +impl Coprocessor for RegionCacheWriteBatchObserver {} + +impl WriteBatchObserver for RegionCacheWriteBatchObserver { + fn create_observable_write_batch(&self) -> Box { + Box::new(HybridObservableWriteBatch { + cache_write_batch: RangeCacheWriteBatch::from(&self.cache_engine), + }) + } +} + +struct HybridObservableWriteBatch { + cache_write_batch: RangeCacheWriteBatch, +} + +impl ObservableWriteBatch for HybridObservableWriteBatch { + fn write_opt_seq(&mut self, opts: &WriteOptions, seq_num: u64) { + self.cache_write_batch.set_sequence_number(seq_num).unwrap(); + self.cache_write_batch.write_opt(opts).unwrap(); + } + fn post_write(&mut self) { + self.cache_write_batch.maybe_compact_lock_cf(); + } +} + +/// Implements the `WriteBatch` trait for `HybridObservableWriteBatch`. +/// +/// The following methods are not implemented because they are not used +/// through the interface `Box`. +/// +/// - `write`, `write_opt`, `write_callback_opt`, `merge` +/// +/// Implements the remaining methods of the `WriteBatch` trait by delegating +/// the calls to the `cache_write_batch` field. +impl WriteBatch for HybridObservableWriteBatch { + fn write(&mut self) -> Result { + unimplemented!("write") + } + fn write_opt(&mut self, opts: &WriteOptions) -> Result { + unimplemented!("write_opt") + } + fn write_callback_opt(&mut self, opts: &WriteOptions, cb: impl FnMut(u64)) -> Result + where + Self: Sized, + { + unimplemented!("write_callback_opt") + } + fn merge(&mut self, other: Self) -> Result<()> + where + Self: Sized, + { + unimplemented!("merge") + } + + fn data_size(&self) -> usize { + self.cache_write_batch.data_size() + } + fn count(&self) -> usize { + self.cache_write_batch.count() + } + fn is_empty(&self) -> bool { + self.cache_write_batch.is_empty() + } + fn should_write_to_engine(&self) -> bool { + self.cache_write_batch.should_write_to_engine() + } + fn clear(&mut self) { + self.cache_write_batch.clear() + } + fn set_save_point(&mut self) { + self.cache_write_batch.set_save_point() + } + fn pop_save_point(&mut self) -> Result<()> { + self.cache_write_batch.pop_save_point() + } + fn rollback_to_save_point(&mut self) -> Result<()> { + self.cache_write_batch.rollback_to_save_point() + } + fn prepare_for_region(&mut self, region: CacheRegion) { + self.cache_write_batch.prepare_for_region(region); + } +} + +impl Mutable for HybridObservableWriteBatch { + fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()> { + self.cache_write_batch.put(key, value) + } + fn put_cf(&mut self, cf: &str, key: &[u8], value: &[u8]) -> Result<()> { + if is_data_cf(cf) { + self.cache_write_batch.put_cf(cf, key, value)?; + } + Ok(()) + } + fn delete(&mut self, key: &[u8]) -> Result<()> { + self.cache_write_batch.delete(key) + } + fn delete_cf(&mut self, cf: &str, key: &[u8]) -> Result<()> { + self.cache_write_batch.delete_cf(cf, key) + } + fn delete_range(&mut self, begin_key: &[u8], end_key: &[u8]) -> Result<()> { + // delete_range in range cache engine means eviction -- all ranges overlapped + // with [begin_key, end_key] will be evicted. + self.cache_write_batch.delete_range(begin_key, end_key) + } + fn delete_range_cf(&mut self, cf: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()> { + // delete_range in range cache engine means eviction -- all ranges overlapped + // with [begin_key, end_key] will be evicted. + self.cache_write_batch + .delete_range_cf(cf, begin_key, end_key) + } +} diff --git a/components/hybrid_engine/src/range_cache_engine.rs b/components/hybrid_engine/src/range_cache_engine.rs index 1fabcfee5ac..cf8730a5345 100644 --- a/components/hybrid_engine/src/range_cache_engine.rs +++ b/components/hybrid_engine/src/range_cache_engine.rs @@ -9,10 +9,6 @@ where EK: KvEngine, EC: RangeCacheEngine, { - fn range_cache_engine_enabled(&self) -> bool { - true - } - #[inline] fn on_region_event(&self, event: RegionEvent) { self.range_cache_engine().on_region_event(event); diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index ba801331211..7a07e95dbf9 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -1,13 +1,21 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. -use std::fmt::{self, Debug, Formatter}; +use std::{ + any::Any, + fmt::{self, Debug, Formatter}, +}; use engine_traits::{ is_data_cf, CfNamesExt, IterOptions, Iterable, KvEngine, Peekable, RangeCacheEngine, ReadOptions, Result, Snapshot, SnapshotMiscExt, CF_DEFAULT, }; +use raftstore::coprocessor::ObservedSnapshot; +use range_cache_memory_engine::RangeCacheMemoryEngine; -use crate::{db_vector::HybridDbVector, engine_iterator::HybridEngineIterator}; +use crate::{ + db_vector::HybridDbVector, engine_iterator::HybridEngineIterator, + observer::RangeCacheSnapshotPin, +}; pub struct HybridEngineSnapshot where @@ -43,6 +51,27 @@ where } } +impl HybridEngineSnapshot +where + EK: KvEngine, +{ + pub fn from_observed_snapshot( + disk_snap: EK::Snapshot, + snap_pin: Option>, + ) -> Self { + let mut range_cache_snap = None; + if let Some(snap_pin) = snap_pin { + let snap_any: Box = snap_pin; + let range_cache_snap_pin: Box = snap_any.downcast().unwrap(); + range_cache_snap = range_cache_snap_pin.snap; + } + HybridEngineSnapshot { + disk_snap, + range_cache_snap, + } + } +} + impl Snapshot for HybridEngineSnapshot where EK: KvEngine, diff --git a/components/raftstore/src/coprocessor/dispatcher.rs b/components/raftstore/src/coprocessor/dispatcher.rs index 7e25feff788..2ac4d62731d 100644 --- a/components/raftstore/src/coprocessor/dispatcher.rs +++ b/components/raftstore/src/coprocessor/dispatcher.rs @@ -3,7 +3,7 @@ // #[PerformanceCriticalPath] called by Fsm on_ready_compute_hash use std::{borrow::Cow, marker::PhantomData, mem, ops::Deref}; -use engine_traits::{CfName, KvEngine}; +use engine_traits::{CfName, KvEngine, SnapshotContext, WriteBatch}; use kvproto::{ metapb::{Region, RegionEpoch}, pdpb::CheckPolicy, @@ -12,6 +12,7 @@ use kvproto::{ }; use protobuf::Message; use raft::eraftpb; +use read_write::WriteBatchObserver; use tikv_util::box_try; use super::{split_observer::SplitObserver, *}; @@ -295,6 +296,17 @@ impl_box_observer!( RegionHeartbeatObserver, WrappedRegionHeartbeatObserver ); +impl_box_observer!( + BoxWriteBatchObserver, + WriteBatchObserver, + WrappedBoxWriteBatchObserver +); +impl_box_observer!( + BoxSnapshotObserver, + SnapshotObserver, + WrappedBoxSnapshotObserver +); + /// Registry contains all registered coprocessors. #[derive(Clone)] pub struct Registry @@ -314,6 +326,11 @@ where update_safe_ts_observers: Vec>, message_observers: Vec>, region_heartbeat_observers: Vec>, + // For now, `write_batch_observer` and `snapshot_observer` can only have one + // observer solely because of simplicity. However, it is possible to have + // multiple observers in the future if needed. + write_batch_observer: Option, + snapshot_observer: Option, // TODO: add endpoint } @@ -333,6 +350,8 @@ impl Default for Registry { update_safe_ts_observers: Default::default(), message_observers: Default::default(), region_heartbeat_observers: Default::default(), + write_batch_observer: None, + snapshot_observer: None, } } } @@ -413,6 +432,14 @@ impl Registry { ) { push!(priority, qo, self.region_heartbeat_observers); } + + pub fn register_write_batch_observer(&mut self, write_batch_observer: BoxWriteBatchObserver) { + self.write_batch_observer = Some(write_batch_observer); + } + + pub fn register_snapshot_observer(&mut self, snapshot_observer: BoxSnapshotObserver) { + self.snapshot_observer = Some(snapshot_observer); + } } /// A macro that loops over all observers and returns early when error is found @@ -886,6 +913,26 @@ impl CoprocessorHost { } } + pub fn on_create_apply_write_batch(&self, wb: WB) -> WriteBatchWrapper { + let observable_wb = self + .registry + .write_batch_observer + .as_ref() + .map(|observer| observer.inner().create_observable_write_batch()); + WriteBatchWrapper::new(wb, observable_wb) + } + + pub fn on_snapshot( + &self, + ctx: SnapshotContext, + seqno: u64, + ) -> Option> { + self.registry + .snapshot_observer + .as_ref() + .map(move |observer| observer.inner().on_snapshot(ctx, seqno)) + } + pub fn shutdown(&self) { for entry in &self.registry.admin_observers { entry.observer.inner().stop(); diff --git a/components/raftstore/src/coprocessor/mod.rs b/components/raftstore/src/coprocessor/mod.rs index 1cbbdab5ab5..7b4d8909c71 100644 --- a/components/raftstore/src/coprocessor/mod.rs +++ b/components/raftstore/src/coprocessor/mod.rs @@ -31,6 +31,7 @@ pub mod region_info_accessor; mod split_check; pub mod split_observer; use kvproto::raft_serverpb::RaftMessage; +mod read_write; pub use self::{ config::{Config, ConsistencyCheckMethod}, @@ -42,6 +43,10 @@ pub use self::{ StoreHandle, }, error::{Error, Result}, + read_write::{ + ObservableWriteBatch, ObservedSnapshot, SnapshotObserver, WriteBatchObserver, + WriteBatchWrapper, + }, region_info_accessor::{ Callback as RegionInfoCallback, RangeKey, RegionCollector, RegionInfo, RegionInfoAccessor, RegionInfoProvider, SeekRegionCallback, diff --git a/components/raftstore/src/coprocessor/read_write/mod.rs b/components/raftstore/src/coprocessor/read_write/mod.rs new file mode 100644 index 00000000000..8c55177f01f --- /dev/null +++ b/components/raftstore/src/coprocessor/read_write/mod.rs @@ -0,0 +1,7 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +mod snapshot; +mod write_batch; + +pub use snapshot::*; +pub use write_batch::*; diff --git a/components/raftstore/src/coprocessor/read_write/snapshot.rs b/components/raftstore/src/coprocessor/read_write/snapshot.rs new file mode 100644 index 00000000000..c982ba5894e --- /dev/null +++ b/components/raftstore/src/coprocessor/read_write/snapshot.rs @@ -0,0 +1,16 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::any::Any; + +use engine_traits::SnapshotContext; + +/// ObservedSnapshot is a trait that represents data that are observed during +/// taking snapshot. +/// It inherits from Any to allow downcasting to concrete types. +pub trait ObservedSnapshot: Any + Send + Sync {} + +/// SnapshotObserver is a trait that observes the snapshot process. +pub trait SnapshotObserver: Send { + /// on_snapshot is called when raftstore is taking RegionSnapshot. + fn on_snapshot(&self, ctx: SnapshotContext, sequence_number: u64) -> Box; +} diff --git a/components/raftstore/src/coprocessor/read_write/write_batch.rs b/components/raftstore/src/coprocessor/read_write/write_batch.rs new file mode 100644 index 00000000000..28bed821825 --- /dev/null +++ b/components/raftstore/src/coprocessor/read_write/write_batch.rs @@ -0,0 +1,182 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::sync::atomic::{AtomicBool, Ordering}; + +use engine_traits::{CacheRegion, Mutable, Result, WriteBatch, WriteOptions, CF_DEFAULT}; + +pub trait WriteBatchObserver: Send { + fn create_observable_write_batch(&self) -> Box; +} + +/// It observes write operations of an `engine_trait::WriteBatch`, and provides +/// additional methods to specify which region the write operations belong to. +// TODO: May be we can unified it with `CmdObserver`? +pub trait ObservableWriteBatch: WriteBatch + Send { + // It declares that the following consecutive write will be within this + // region. + // TODO: move `prepare_for_region` from `WriteBatch` to here. + // fn prepare_for_region(&mut self, _: CacheRegion); + + /// Commit the WriteBatch with the given options and sequence number. + fn write_opt_seq(&mut self, opts: &WriteOptions, seq_num: u64); + /// It is called after a write operation is finished. + fn post_write(&mut self); +} + +pub struct WriteBatchWrapper { + write_batch: WB, + observable_write_batch: Option>, +} + +impl WriteBatchWrapper { + pub fn new( + write_batch: WB, + observable_write_batch: Option>, + ) -> Self { + Self { + write_batch, + observable_write_batch, + } + } +} + +impl WriteBatch for WriteBatchWrapper { + fn write(&mut self) -> Result { + self.write_opt(&WriteOptions::default()) + } + + fn write_opt(&mut self, opts: &WriteOptions) -> Result { + self.write_callback_opt(opts, |_| ()) + } + + fn write_callback_opt(&mut self, opts: &WriteOptions, mut cb: impl FnMut(u64)) -> Result { + let called = AtomicBool::new(false); + let res = self.write_batch.write_callback_opt(opts, |s| { + if !called.fetch_or(true, Ordering::SeqCst) { + if let Some(w) = self.observable_write_batch.as_mut() { + w.write_opt_seq(opts, s); + } + } + cb(s); + }); + if let Some(w) = self.observable_write_batch.as_mut() { + w.post_write(); + } + res + } + + fn data_size(&self) -> usize { + self.write_batch.data_size() + } + + fn count(&self) -> usize { + self.write_batch.count() + } + + fn is_empty(&self) -> bool { + self.write_batch.is_empty() + } + + fn should_write_to_engine(&self) -> bool { + self.write_batch.should_write_to_engine() + } + + fn clear(&mut self) { + if let Some(w) = self.observable_write_batch.as_mut() { + w.clear() + } + self.write_batch.clear(); + } + + fn set_save_point(&mut self) { + if let Some(w) = self.observable_write_batch.as_mut() { + w.set_save_point() + } + self.write_batch.set_save_point() + } + + fn pop_save_point(&mut self) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.pop_save_point()?; + } + self.write_batch.pop_save_point() + } + + fn rollback_to_save_point(&mut self) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.rollback_to_save_point()?; + } + self.write_batch.rollback_to_save_point() + } + + fn merge(&mut self, _: Self) -> Result<()> { + unimplemented!("WriteBatchWrapper does not support merge") + } + + fn prepare_for_region(&mut self, region: CacheRegion) { + if let Some(w) = self.observable_write_batch.as_mut() { + w.prepare_for_region(region) + } + } +} + +impl Mutable for WriteBatchWrapper { + fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.put_cf(CF_DEFAULT, key, value)?; + } + self.write_batch.put(key, value) + } + + fn put_cf(&mut self, cf: &str, key: &[u8], value: &[u8]) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.put_cf(cf, key, value)?; + } + self.write_batch.put_cf(cf, key, value) + } + + fn delete(&mut self, key: &[u8]) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.delete_cf(CF_DEFAULT, key)?; + } + self.write_batch.delete(key) + } + + fn delete_cf(&mut self, cf: &str, key: &[u8]) -> Result<()> { + if let Some(w) = self.observable_write_batch.as_mut() { + w.delete_cf(cf, key)?; + } + self.write_batch.delete_cf(cf, key) + } + + fn delete_range(&mut self, begin_key: &[u8], end_key: &[u8]) -> Result<()> { + // delete_range in range cache engine means eviction -- all ranges overlapped + // with [begin_key, end_key] will be evicted. + if let Some(w) = self.observable_write_batch.as_mut() { + w.delete_range_cf(CF_DEFAULT, begin_key, end_key)?; + } + self.write_batch.delete_range(begin_key, end_key) + } + + fn delete_range_cf(&mut self, cf: &str, begin_key: &[u8], end_key: &[u8]) -> Result<()> { + // delete_range in range cache engine means eviction -- all ranges overlapped + // with [begin_key, end_key] will be evicted. + if let Some(w) = self.observable_write_batch.as_mut() { + w.delete_range_cf(cf, begin_key, end_key)?; + } + self.write_batch.delete_range_cf(cf, begin_key, end_key) + } + + // Override the default methods `put_msg` and `put_msg_cf` to prevent + // potential loss of put observations if WB also overrides them. + fn put_msg(&mut self, key: &[u8], m: &M) -> Result<()> { + // It's okay to call `self.put` even though it does not strictly + // follow the `put_msg` semantics, as there are no implementors + // that override it. + self.put(key, &m.write_to_bytes()?) + } + fn put_msg_cf(&mut self, cf: &str, key: &[u8], m: &M) -> Result<()> { + // See put_msg. + self.put_cf(cf, key, &m.write_to_bytes()?) + } +} diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index 80c9ff2a434..1a1644d07ff 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -79,7 +79,7 @@ use crate::{ bytes_capacity, coprocessor::{ ApplyCtxInfo, Cmd, CmdBatch, CmdObserveInfo, CoprocessorHost, ObserveHandle, ObserveLevel, - RegionState, + RegionState, WriteBatchWrapper, }, store::{ cmd_resp, @@ -406,7 +406,7 @@ where exec_log_index: u64, exec_log_term: u64, - kv_wb: EK::WriteBatch, + kv_wb: WriteBatchWrapper, kv_wb_last_bytes: u64, kv_wb_last_keys: u64, @@ -492,6 +492,7 @@ where priority: Priority, ) -> ApplyContext { let kv_wb = engine.write_batch_with_cap(DEFAULT_APPLY_WB_SIZE); + let kv_wb = host.on_create_apply_write_batch(kv_wb); ApplyContext { tag, @@ -619,7 +620,9 @@ where let data_size = self.kv_wb().data_size(); if data_size > APPLY_WB_SHRINK_SIZE { // Control the memory usage for the WriteBatch. - self.kv_wb = self.engine.write_batch_with_cap(DEFAULT_APPLY_WB_SIZE); + let kv_wb = self.engine.write_batch_with_cap(DEFAULT_APPLY_WB_SIZE); + let kv_wb = self.host.on_create_apply_write_batch(kv_wb); + self.kv_wb = kv_wb; } else { // Clear data, reuse the WriteBatch, this can reduce memory allocations and // deallocations. @@ -721,12 +724,12 @@ where } #[inline] - pub fn kv_wb(&self) -> &EK::WriteBatch { + pub fn kv_wb(&self) -> &WriteBatchWrapper { &self.kv_wb } #[inline] - pub fn kv_wb_mut(&mut self) -> &mut EK::WriteBatch { + pub fn kv_wb_mut(&mut self) -> &mut WriteBatchWrapper { &mut self.kv_wb } @@ -1204,7 +1207,7 @@ where self.metrics.written_keys += apply_ctx.delta_keys(); } - fn write_apply_state(&self, wb: &mut EK::WriteBatch) { + fn write_apply_state(&self, wb: &mut WriteBatchWrapper) { wb.put_msg_cf( CF_RAFT, &keys::apply_state_key(self.region.get_id()), diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index c6b56a2c3db..c63627ed7a3 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -4963,9 +4963,9 @@ where Ok(propose_index) } - fn handle_read>( + fn handle_read( &self, - reader: &mut E, + ctx: &mut PollContext, req: RaftCmdRequest, check_epoch: bool, read_index: Option, @@ -5022,7 +5022,17 @@ where None }; - let mut resp = reader.execute(&req, &Arc::new(region), read_index, snap_ctx, None); + let mut reader = PollContextReader { + engines: &ctx.engines, + }; + let mut resp = reader.execute( + &req, + &Arc::new(region), + read_index, + snap_ctx, + None, + &ctx.coprocessor_host, + ); if let Some(snap) = resp.snapshot.as_mut() { snap.txn_ext = Some(self.txn_ext.clone()); snap.bucket_meta = self @@ -6007,7 +6017,11 @@ where } } -impl ReadExecutor for PollContext +struct PollContextReader<'a, EK, ER> { + engines: &'a Engines, +} + +impl<'a, EK, ER> ReadExecutor for PollContextReader<'a, EK, ER> where EK: KvEngine, ER: RaftEngine, diff --git a/components/raftstore/src/store/region_snapshot.rs b/components/raftstore/src/store/region_snapshot.rs index 3456d4c3add..f8f426aaad2 100644 --- a/components/raftstore/src/store/region_snapshot.rs +++ b/components/raftstore/src/store/region_snapshot.rs @@ -2,10 +2,11 @@ // #[PerformanceCriticalPath] use std::{ + fmt, num::NonZeroU64, sync::{ atomic::{AtomicU64, Ordering}, - Arc, + Arc, Mutex, }, }; @@ -23,6 +24,7 @@ use tikv_util::{ }; use crate::{ + coprocessor::ObservedSnapshot, store::{util, PeerStorage, TxnExt}, Error, Result, }; @@ -30,7 +32,6 @@ use crate::{ /// Snapshot of a region. /// /// Only data within a region can be accessed. -#[derive(Debug)] pub struct RegionSnapshot { snap: Arc, region: Arc, @@ -41,6 +42,22 @@ pub struct RegionSnapshot { // `None` means the snapshot does not provide peer related transaction extensions. pub txn_ext: Option>, pub bucket_meta: Option>, + + observed_snap: Option>>>>, +} + +impl fmt::Debug for RegionSnapshot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RegionSnapshot") + .field("region", &self.region) + .field("apply_index", &self.apply_index) + .field("from_v2", &self.from_v2) + .field("term", &self.term) + .field("txn_extra_op", &self.txn_extra_op) + .field("txn_ext", &self.txn_ext) + .field("bucket_meta", &self.bucket_meta) + .finish() + } } impl RegionSnapshot @@ -74,6 +91,43 @@ where txn_extra_op: TxnExtraOp::Noop, txn_ext: None, bucket_meta: None, + observed_snap: None, + } + } + + pub fn set_observed_snapshot(&mut self, observed_snap: Box) { + self.observed_snap = Some(Arc::new(Mutex::new(Some(observed_snap)))); + } + + /// Replace underlying snapshot with its observed snapshot. + /// + /// One use case is to allow callers to build a `RegionSnapshot` with an + /// optimized snapshot. See RaftKv::async_in_memory_snapshot for an example. + /// + /// # Panics + /// + /// It panics, if it has been cloned before this calling `replace_snapshot` + /// or if `snap_fn` panics, the panic is propagated to the caller. + pub fn replace_snapshot(mut self, snap_fn: F) -> RegionSnapshot + where + Sp: Snapshot, + F: FnOnce(S, Option>) -> Sp, + { + let mut observed = None; + if let Some(observed_snap) = self.observed_snap.take() { + observed = observed_snap.lock().unwrap().take(); + } + let inner = Arc::into_inner(self.snap).unwrap(); + RegionSnapshot { + snap: Arc::new(snap_fn(inner, observed)), + region: self.region, + apply_index: self.apply_index, + from_v2: self.from_v2, + term: self.term, + txn_extra_op: self.txn_extra_op, + txn_ext: self.txn_ext, + bucket_meta: self.bucket_meta, + observed_snap: None, } } @@ -196,6 +250,7 @@ where txn_extra_op: self.txn_extra_op, txn_ext: self.txn_ext.clone(), bucket_meta: self.bucket_meta.clone(), + observed_snap: self.observed_snap.clone(), } } } diff --git a/components/raftstore/src/store/worker/read.rs b/components/raftstore/src/store/worker/read.rs index 7311512ab21..b3d8044e8bf 100644 --- a/components/raftstore/src/store/worker/read.rs +++ b/components/raftstore/src/store/worker/read.rs @@ -12,7 +12,9 @@ use std::{ }; use crossbeam::{atomic::AtomicCell, channel::TrySendError}; -use engine_traits::{CacheRegion, KvEngine, Peekable, RaftEngine, SnapshotContext}; +use engine_traits::{ + CacheRegion, KvEngine, Peekable, RaftEngine, SnapshotContext, SnapshotMiscExt, +}; use fail::fail_point; use kvproto::{ errorpb, @@ -34,6 +36,7 @@ use txn_types::{TimeStamp, WriteBatchFlags}; use super::metrics::*; use crate::{ + coprocessor::CoprocessorHost, errors::RAFTSTORE_IS_BUSY, store::{ cmd_resp, @@ -113,6 +116,7 @@ pub trait ReadExecutor { read_index: Option, snap_ctx: Option, local_read_ctx: Option>, + host: &CoprocessorHost, ) -> ReadResponse<::Snapshot> { let requests = msg.get_requests(); let mut response = ReadResponse { @@ -138,10 +142,21 @@ pub trait ReadExecutor { } } CmdType::Snap => { - let snapshot = RegionSnapshot::from_snapshot( + let mut snapshot = RegionSnapshot::from_snapshot( self.get_snapshot(snap_ctx.clone(), &local_read_ctx), region.clone(), ); + if let Some(snap_ctx) = snap_ctx.as_ref() { + // We only observe snapshot when it has snapshot context. + // + // Currently, the snapshot context is set when caller + // wants an in-memory engine snapshot which requires + // the snapshot and some metadata in the context. + let seqno = snapshot.get_snapshot().sequence_number(); + if let Some(observed_snap) = host.on_snapshot(snap_ctx.clone(), seqno) { + snapshot.set_observed_snapshot(observed_snap); + } + } response.snapshot = Some(snapshot); Response::default() } @@ -921,6 +936,7 @@ where snap_cache: SnapCache, // A channel to raftstore. router: C, + host: CoprocessorHost, } impl LocalReader @@ -928,12 +944,18 @@ where E: KvEngine, C: ProposalRouter + CasualRouter, { - pub fn new(kv_engine: E, store_meta: StoreMetaDelegate, router: C) -> Self { + pub fn new( + kv_engine: E, + store_meta: StoreMetaDelegate, + router: C, + host: CoprocessorHost, + ) -> Self { Self { local_reader: LocalReaderCore::new(store_meta), kv_engine, snap_cache: SnapCache::new(), router, + host, } } @@ -1020,7 +1042,14 @@ where } let region = Arc::clone(&delegate.region); - let mut response = delegate.execute(req, ®ion, None, snap_ctx, Some(local_read_ctx)); + let mut response = delegate.execute( + req, + ®ion, + None, + snap_ctx, + Some(local_read_ctx), + &self.host, + ); if let Some(snap) = response.snapshot.as_mut() { snap.bucket_meta = delegate.bucket_meta.clone(); } @@ -1049,7 +1078,8 @@ where let region = Arc::clone(&delegate.region); // Getting the snapshot - let mut response = delegate.execute(req, ®ion, None, None, Some(local_read_ctx)); + let mut response = + delegate.execute(req, ®ion, None, None, Some(local_read_ctx), &self.host); if let Some(snap) = response.snapshot.as_mut() { snap.bucket_meta = delegate.bucket_meta.clone(); } @@ -1233,6 +1263,7 @@ where kv_engine: self.kv_engine.clone(), snap_cache: self.snap_cache.clone(), router: self.router.clone(), + host: self.host.clone(), } } } @@ -1366,7 +1397,9 @@ mod tests { let path = Builder::new().prefix(path).tempdir().unwrap(); let db = engine_test::kv::new_engine(path.path().to_str().unwrap(), ALL_CFS).unwrap(); let (ch, rx, _) = MockRouter::new(); - let mut reader = LocalReader::new(db.clone(), StoreMetaDelegate::new(store_meta, db), ch); + let host = CoprocessorHost::default(); + let mut reader = + LocalReader::new(db.clone(), StoreMetaDelegate::new(store_meta, db), ch, host); reader.local_reader.store_id = Cell::new(Some(store_id)); (path, reader, rx) } @@ -2497,6 +2530,7 @@ mod tests { engine.clone(), StoreMetaDelegate::new(store_meta, engine), ch, + CoprocessorHost::default(), ); reader.local_reader.store_id = Cell::new(Some(store_id)); (path, reader, rx, memory_engine) diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index 101562bfce9..0fffad89317 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -40,6 +40,7 @@ pub use keys::{ }; pub use metrics::flush_range_cache_engine_statistics; pub use range_manager::{RangeCacheStatus, RegionState}; +pub use read::RangeCacheSnapshot; pub use statistics::Statistics as RangeCacheMemoryEngineStatistics; use txn_types::TimeStamp; pub use write_batch::RangeCacheWriteBatch; diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index 8c58ce623db..bb50ed110a3 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -524,6 +524,7 @@ impl Iterator for RangeCacheIterator { } fn seek(&mut self, key: &[u8]) -> Result { + fail::fail_point!("on_range_cache_iterator_seek"); let begin = Instant::now(); self.direction = Direction::Forward; if let Some(ref mut extractor) = self.prefix_extractor { diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 57b92f16dd1..e3b97bd4fa1 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -172,7 +172,7 @@ impl RangeCacheWriteBatch { // the RocksDB, which will be incremented automatically for each key, so // that all keys have unique sequence numbers. fn write_impl(&mut self, mut seq: u64) -> Result<()> { - fail::fail_point!("on_write_impl"); + fail::fail_point!("on_range_cache_write_batch_write_impl"); let guard = &epoch::pin(); let start = Instant::now(); let mut lock_modification: u64 = 0; diff --git a/components/resolved_ts/tests/mod.rs b/components/resolved_ts/tests/mod.rs index 5547fef461a..90592de582b 100644 --- a/components/resolved_ts/tests/mod.rs +++ b/components/resolved_ts/tests/mod.rs @@ -3,7 +3,6 @@ use std::{sync::*, time::Duration}; use collections::HashMap; -use engine_rocks::RocksEngine; use grpcio::{ChannelBuilder, Environment}; use kvproto::{import_sstpb_grpc::ImportSstClient, kvrpcpb::*, tikvpb::TikvClient}; use online_config::ConfigValue; @@ -19,7 +18,7 @@ pub fn init() { } pub struct TestSuite { - pub cluster: Cluster>, + pub cluster: Cluster, tikv_cli: HashMap, import_cli: HashMap, diff --git a/components/server/src/common.rs b/components/server/src/common.rs index 8d48a3ece12..d8ebded71ed 100644 --- a/components/server/src/common.rs +++ b/components/server/src/common.rs @@ -695,48 +695,24 @@ impl Stop for LazyWorker { } } -pub trait KvEngineBuilder: KvEngine { - fn build( - range_cache_engine_context: RangeCacheEngineContext, - disk_engine: RocksEngine, - pd_client: Option>, - region_info_provider: Option>, - ) -> Self; -} - -impl KvEngineBuilder for RocksEngine { - fn build( - _: RangeCacheEngineContext, - disk_engine: RocksEngine, - _pd_client: Option>, - _region_info_provider: Option>, - ) -> Self { - disk_engine - } -} - -impl KvEngineBuilder for HybridEngine { - fn build( - range_cache_engine_context: RangeCacheEngineContext, - disk_engine: RocksEngine, - pd_client: Option>, - region_info_provider: Option>, - ) -> Self { - // todo(SpadeA): add config for it - let mut memory_engine = RangeCacheMemoryEngine::with_region_info_provider( - range_cache_engine_context, - region_info_provider, - ); - memory_engine.set_disk_engine(disk_engine.clone()); - if let Some(pd_client) = pd_client.as_ref() { - memory_engine.start_hint_service( - ::RangeHintService::from( - pd_client.clone(), - ), - ) - } - HybridEngine::new(disk_engine, memory_engine) +pub fn build_hybrid_engine( + range_cache_engine_context: RangeCacheEngineContext, + disk_engine: RocksEngine, + pd_client: Option>, + region_info_provider: Option>, +) -> HybridEngine { + // todo(SpadeA): add config for it + let mut memory_engine = RangeCacheMemoryEngine::with_region_info_provider( + range_cache_engine_context, + region_info_provider, + ); + memory_engine.set_disk_engine(disk_engine.clone()); + if let Some(pd_client) = pd_client.as_ref() { + memory_engine.start_hint_service( + ::RangeHintService::from(pd_client.clone()), + ) } + HybridEngine::new(disk_engine, memory_engine) } pub trait ConfiguredRaftEngine: RaftEngine { diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 08d3779d9fd..283c180461e 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -34,14 +34,20 @@ use engine_rocks::{ }; use engine_rocks_helper::sst_recovery::{RecoveryRunner, DEFAULT_CHECK_INTERVAL}; use engine_traits::{ - Engines, KvEngine, RaftEngine, SingletonFactory, TabletContext, TabletRegistry, CF_DEFAULT, - CF_WRITE, + Engines, KvEngine, MiscExt, RaftEngine, SingletonFactory, TabletContext, TabletRegistry, + CF_DEFAULT, CF_WRITE, }; use file_system::{get_io_rate_limiter, BytesFetcher, MetricsManager as IoMetricsManager}; use futures::executor::block_on; use grpcio::{EnvBuilder, Environment}; use health_controller::HealthController; -use hybrid_engine::{observer::Observer as HybridEngineObserver, HybridEngine}; +use hybrid_engine::{ + observer::{ + EvictionObserver as HybridEngineObserver, HybridSnapshotObserver, + RegionCacheWriteBatchObserver, + }, + HybridEngine, +}; use kvproto::{ brpb::create_backup, cdcpb::create_change_data, deadlock::create_deadlock, debugpb::create_debug, diagnosticspb::create_diagnostics, import_sstpb::create_import_sst, @@ -133,8 +139,8 @@ use tokio::runtime::Builder; use crate::{ common::{ - ConfiguredRaftEngine, DiskUsageChecker, EngineMetricsManager, EnginesResourceInfo, - KvEngineBuilder, TikvServerCore, + build_hybrid_engine, ConfiguredRaftEngine, DiskUsageChecker, EngineMetricsManager, + EnginesResourceInfo, TikvServerCore, }, memory::*, setup::*, @@ -143,16 +149,15 @@ use crate::{ }; #[inline] -fn run_impl( +fn run_impl( config: TikvConfig, service_event_tx: TikvMpsc::Sender, service_event_rx: TikvMpsc::Receiver, ) where - EK: KvEngine + KvEngineBuilder, CER: ConfiguredRaftEngine, F: KvFormat, { - let mut tikv = TikvServer::::init(config, service_event_tx.clone()); + let mut tikv = TikvServer::::init(config, service_event_tx.clone()); // Must be called after `TikvServer::init`. let memory_limit = tikv.core.config.memory_usage_limit.unwrap().0; let high_water = (tikv.core.config.memory_usage_high_water * memory_limit as f64) as u64; @@ -164,8 +169,8 @@ fn run_impl( tikv.core.init_encryption(); let fetcher = tikv.core.init_io_utility(); let listener = tikv.core.init_flow_receiver(); - let (engines, engines_info) = tikv.init_raw_engines(listener); - tikv.init_engines(engines.clone()); + let (engines, engines_info, in_memory_engine) = tikv.init_raw_engines(listener); + tikv.init_engines(engines.clone(), in_memory_engine); let server_config = tikv.init_servers(); tikv.register_services(); tikv.init_metrics_flusher(fetcher, engines_info); @@ -225,33 +230,9 @@ pub fn run_tikv( dispatch_api_version!(config.storage.api_version(), { if !config.raft_engine.enable { - if cfg!(feature = "memory-engine") && config.range_cache_engine.enabled { - run_impl::, RocksEngine, API>( - config, - service_event_tx, - service_event_rx, - ) - } else { - run_impl::( - config, - service_event_tx, - service_event_rx, - ) - } + run_impl::(config, service_event_tx, service_event_rx) } else { - if cfg!(feature = "memory-engine") && config.range_cache_engine.enabled { - run_impl::, RaftLogEngine, API>( - config, - service_event_tx, - service_event_rx, - ) - } else { - run_impl::( - config, - service_event_tx, - service_event_rx, - ) - } + run_impl::(config, service_event_tx, service_event_rx) } }) } @@ -262,9 +243,8 @@ const DEFAULT_STORAGE_STATS_INTERVAL: Duration = Duration::from_secs(1); const DEFAULT_CGROUP_MONITOR_INTERVAL: Duration = Duration::from_secs(10); /// A complete TiKV server. -struct TikvServer +struct TikvServer where - EK: KvEngine, ER: RaftEngine, F: KvFormat, { @@ -272,17 +252,17 @@ where cfg_controller: Option, security_mgr: Arc, pd_client: Arc, - router: RaftRouter, - system: Option>, + router: RaftRouter, + system: Option>, resolver: Option, snap_mgr: Option, // Will be filled in `init_servers`. - engines: Option>, + engines: Option>, kv_statistics: Option>, range_cache_engine_statistics: Option>, raft_statistics: Option>, - servers: Option>, + servers: Option>, region_info_accessor: RegionInfoAccessor, - coprocessor_host: Option>, + coprocessor_host: Option>, concurrency_manager: ConcurrencyManager, env: Arc, check_leader_worker: Worker, @@ -297,34 +277,38 @@ where snap_br_rejector: Option>, } -struct TikvEngines { - engines: Engines, +struct TikvEngines { + engines: Engines, store_meta: Arc>, - engine: RaftKv>, + engine: RaftKv>, } -struct Servers { +struct Servers { lock_mgr: LockManager, - server: LocalServer, - raft_server: MultiRaftServer, - importer: Arc>, + server: LocalServer, + raft_server: MultiRaftServer, + importer: Arc>, cdc_scheduler: tikv_util::worker::Scheduler, cdc_memory_quota: Arc, rsmeter_pubsub_service: resource_metering::PubSubService, backup_stream_scheduler: Option>, - debugger: DebuggerImpl>, LockManager, F>, + debugger: DebuggerImpl< + ER, + RaftKv>, + LockManager, + F, + >, } type LocalServer = Server>; type LocalRaftKv = RaftKv>; -impl TikvServer +impl TikvServer where - EK: KvEngine, ER: RaftEngine, F: KvFormat, { - fn init(mut config: TikvConfig, tx: TikvMpsc::Sender) -> TikvServer { + fn init(mut config: TikvConfig, tx: TikvMpsc::Sender) -> TikvServer { tikv_util::thread_group::set_properties(Some(GroupProperties::default())); // It is okay use pd config and security config before `init_config`, // because these configs must be provided by command line, and only @@ -509,7 +493,11 @@ where } } - fn init_engines(&mut self, engines: Engines) { + fn init_engines( + &mut self, + engines: Engines, + in_memory_engine: Option>, + ) { let store_meta = Arc::new(Mutex::new(StoreMeta::new(PENDING_MSG_CAP))); let engine = RaftKv::new( ServerRaftStoreRouter::new( @@ -518,9 +506,11 @@ where engines.kv.clone(), StoreMetaDelegate::new(store_meta.clone(), engines.kv.clone()), self.router.clone(), + self.coprocessor_host.as_ref().unwrap().clone(), ), ), engines.kv.clone(), + in_memory_engine.clone(), self.region_info_accessor.region_leaders(), ); @@ -531,7 +521,9 @@ where }); } - fn init_gc_worker(&mut self) -> GcWorker>> { + fn init_gc_worker( + &mut self, + ) -> GcWorker>> { let engines = self.engines.as_ref().unwrap(); let gc_worker = GcWorker::new( engines.engine.clone(), @@ -597,7 +589,7 @@ where if let Some(sst_worker) = &mut self.sst_worker { let sst_runner = RecoveryRunner::new( - engines.engines.kv.get_disk_engine().clone(), + engines.engines.kv.clone(), engines.store_meta.clone(), self.core .config @@ -733,12 +725,6 @@ where ReplicaReadLockChecker::new(self.concurrency_manager.clone()) .register(self.coprocessor_host.as_mut().unwrap()); - // Hybrid engine observer. - if self.core.config.range_cache_engine.enabled { - let observer = HybridEngineObserver::new(Arc::new(engines.engines.kv.clone())); - observer.register_to(self.coprocessor_host.as_mut().unwrap()); - } - // Create snapshot manager, server. let snap_path = self .core @@ -1135,10 +1121,7 @@ where // Create Debugger. let mut debugger = DebuggerImpl::new( - Engines::new( - engines.engines.kv.get_disk_engine().clone(), - engines.engines.raft.clone(), - ), + Engines::new(engines.engines.kv.clone(), engines.engines.raft.clone()), self.cfg_controller.as_ref().unwrap().clone(), Some(storage), ); @@ -1384,7 +1367,7 @@ where ); } - fn init_storage_stats_task(&self, engines: Engines) { + fn init_storage_stats_task(&self, engines: Engines) { let config_disk_capacity: u64 = self.core.config.raft_store.capacity.0; let data_dir = self.core.config.storage.data_dir.clone(); let store_path = self.core.store_path.clone(); @@ -1604,16 +1587,20 @@ where } } -impl TikvServer +impl TikvServer where - EK: KvEngine + KvEngineBuilder, + RocksEngine: KvEngine, CER: ConfiguredRaftEngine, F: KvFormat, { fn init_raw_engines( &mut self, flow_listener: engine_rocks::FlowListener, - ) -> (Engines, Arc) { + ) -> ( + Engines, + Arc, + Option>, + ) { let block_cache = self.core.config.storage.block_cache.build_shared_cache(); let env = self .core @@ -1647,7 +1634,7 @@ where .sst_recovery_sender(self.init_sst_recovery_sender()) .flow_listener(flow_listener); let factory = Box::new(builder.build()); - let disk_engine = factory + let kv_engine = factory .create_shared_db(&self.core.store_path) .unwrap_or_else(|s| fatal!("failed to create kv engine: {}", s)); let mut range_cache_engine_config = self.core.config.range_cache_engine.clone(); @@ -1658,23 +1645,39 @@ where let range_cache_engine_context = RangeCacheEngineContext::new(range_cache_engine_config.clone(), self.pd_client.clone()); let range_cache_engine_statistics = range_cache_engine_context.statistics(); - let kv_engine: EK = KvEngineBuilder::build( - range_cache_engine_context, - disk_engine.clone(), - Some(self.pd_client.clone()), - Some(Arc::new(self.region_info_accessor.clone())), - ); + let in_memory_engine = if self.core.config.range_cache_engine.enabled { + let in_memory_engine = build_hybrid_engine( + range_cache_engine_context, + kv_engine.clone(), + Some(self.pd_client.clone()), + Some(Arc::new(self.region_info_accessor.clone())), + ); + + // Hybrid engine observer. + let eviction_observer = HybridEngineObserver::new(Arc::new(in_memory_engine.clone())); + eviction_observer.register_to(self.coprocessor_host.as_mut().unwrap()); + let write_batch_observer = + RegionCacheWriteBatchObserver::new(in_memory_engine.range_cache_engine().clone()); + write_batch_observer.register_to(self.coprocessor_host.as_mut().unwrap()); + let snapshot_observer = + HybridSnapshotObserver::new(in_memory_engine.range_cache_engine().clone()); + snapshot_observer.register_to(self.coprocessor_host.as_mut().unwrap()); + + Some(in_memory_engine) + } else { + None + }; let range_cache_config_manager = RangeCacheConfigManager(range_cache_engine_config); self.kv_statistics = Some(factory.rocks_statistics()); self.range_cache_engine_statistics = Some(range_cache_engine_statistics); - let engines = Engines::new(kv_engine, raft_engine); + let engines = Engines::new(kv_engine.clone(), raft_engine); let cfg_controller = self.cfg_controller.as_mut().unwrap(); cfg_controller.register( tikv::config::Module::Rocksdb, Box::new(DbConfigManger::new( cfg_controller.get_current().rocksdb, - disk_engine.clone(), + kv_engine.clone(), DbType::Kv, )), ); @@ -1683,7 +1686,7 @@ where Box::new(range_cache_config_manager), ); let reg = TabletRegistry::new( - Box::new(SingletonFactory::new(disk_engine)), + Box::new(SingletonFactory::new(kv_engine)), &self.core.store_path, ) .unwrap(); @@ -1700,7 +1703,7 @@ where 180, // max_samples_to_preserve )); - (engines, engines_info) + (engines, engines_info, in_memory_engine) } } diff --git a/components/test_backup/src/disk_snap.rs b/components/test_backup/src/disk_snap.rs index af7d7f2ebb3..9a505ed28fe 100644 --- a/components/test_backup/src/disk_snap.rs +++ b/components/test_backup/src/disk_snap.rs @@ -7,7 +7,6 @@ use std::{ }; use backup::disk_snap::Env as BEnv; -use engine_rocks::RocksEngine as KTE; use futures_executor::block_on; use futures_util::{ sink::SinkExt, @@ -40,7 +39,7 @@ pub struct Node { } pub struct Suite { - pub cluster: Cluster>, + pub cluster: Cluster, pub nodes: HashMap, grpc_env: Arc, } diff --git a/components/test_backup/src/lib.rs b/components/test_backup/src/lib.rs index 5ea853799b5..cf68db05833 100644 --- a/components/test_backup/src/lib.rs +++ b/components/test_backup/src/lib.rs @@ -13,7 +13,6 @@ use backup::Task; use collections::HashMap; // NOTE: Perhaps we'd better use test engine here. But it seems for now we cannot initialize a // mock cluster with `PanicEngine` and in our CI environment clippy will complain that. -use engine_rocks::RocksEngine as KTE; use engine_traits::{CfName, IterOptions, CF_DEFAULT, CF_WRITE, DATA_KEY_PREFIX_LEN}; use external_storage::make_local_backend; use futures::{channel::mpsc as future_mpsc, executor::block_on}; @@ -44,7 +43,7 @@ use txn_types::TimeStamp; pub mod disk_snap; pub struct TestSuite { - pub cluster: Cluster>, + pub cluster: Cluster, pub endpoints: HashMap>, pub tikv_cli: TikvClient, pub context: Context, diff --git a/components/test_coprocessor/Cargo.toml b/components/test_coprocessor/Cargo.toml index f3af09512eb..12abb38bfa2 100644 --- a/components/test_coprocessor/Cargo.toml +++ b/components/test_coprocessor/Cargo.toml @@ -22,11 +22,13 @@ test-engines-panic = [ [dependencies] api_version = { workspace = true } +codec = { workspace = true } collections = { workspace = true } concurrency_manager = { workspace = true } engine_rocks = { workspace = true } futures = "0.3" kvproto = { workspace = true } +pd_client = { workspace = true } protobuf = "2" resource_metering = { workspace = true } test_storage = { workspace = true } diff --git a/components/test_coprocessor/src/dag.rs b/components/test_coprocessor/src/dag.rs index 76e91cc6ef5..07f7155b2f9 100644 --- a/components/test_coprocessor/src/dag.rs +++ b/components/test_coprocessor/src/dag.rs @@ -12,6 +12,7 @@ use tipb::{ Aggregation, ByItem, Chunk, ColumnInfo, DagRequest, ExecType, Executor, Expr, ExprType, IndexScan, Limit, Selection, TableScan, TopN, }; +use txn_types::TimeStamp; use super::*; @@ -25,6 +26,7 @@ pub struct DagSelect { pub key_ranges: Vec, pub output_offsets: Option>, pub paging_size: Option, + pub start_ts: Option, } impl DagSelect { @@ -48,6 +50,7 @@ impl DagSelect { key_ranges: vec![table.get_record_range_all()], output_offsets: None, paging_size: None, + start_ts: None, } } @@ -75,6 +78,7 @@ impl DagSelect { key_ranges: vec![range], output_offsets: None, paging_size: None, + start_ts: None, } } @@ -213,6 +217,11 @@ impl DagSelect { self } + pub fn start_ts(mut self, start_ts: TimeStamp) -> DagSelect { + self.start_ts = Some(start_ts.into_inner()); + self + } + pub fn build(self) -> Request { self.build_with(Context::default(), &[0]) } @@ -267,7 +276,7 @@ impl DagSelect { dag.set_output_offsets(output_offsets); let mut req = Request::default(); - req.set_start_ts(next_id() as u64); + req.set_start_ts(self.start_ts.unwrap_or_else(|| next_id() as u64)); req.set_tp(REQ_TYPE_DAG); req.set_data(dag.write_to_bytes().unwrap()); req.set_ranges(self.key_ranges.into()); diff --git a/components/test_coprocessor/src/fixture.rs b/components/test_coprocessor/src/fixture.rs index 57446b8d4f9..08299db2803 100644 --- a/components/test_coprocessor/src/fixture.rs +++ b/components/test_coprocessor/src/fixture.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::Context; +use pd_client::PdClient; use resource_metering::ResourceTagFactory; use tidb_query_datatype::codec::{row::v2::CODEC_VERSION, Datum}; use tikv::{ @@ -45,6 +46,10 @@ impl ProductTable { .build(); ProductTable(table) } + + pub fn table_id(&self) -> i64 { + self.0.id + } } impl Default for ProductTable { @@ -71,7 +76,7 @@ pub fn init_data_with_engine_and_commit( init_data_with_details(ctx, engine, tbl, vals, commit, &Config::default()) } -pub fn init_data_with_engine_and_commit_v2_checksum( +fn init_data_with_engine_and_commit_v2_checksum( ctx: Context, engine: E, tbl: &ProductTable, @@ -100,10 +105,24 @@ pub fn init_data_with_details( commit: bool, cfg: &Config, ) -> (Store, Endpoint, Arc) { - init_data_with_details_impl(ctx, engine, tbl, vals, commit, cfg, 0, false, None) + init_data_with_details_impl(ctx, engine, tbl, vals, commit, cfg, 0, false, None, None) +} + +pub fn init_data_with_details_pd_client( + ctx: Context, + engine: E, + tbl: &ProductTable, + vals: &[(i64, Option<&str>, i64)], + commit: bool, + cfg: &Config, + pd_client: Option>, +) -> (Store, Endpoint, Arc) { + init_data_with_details_impl( + ctx, engine, tbl, vals, commit, cfg, 0, false, None, pd_client, + ) } -pub fn init_data_with_details_v2_checksum( +fn init_data_with_details_v2_checksum( ctx: Context, engine: E, tbl: &ProductTable, @@ -123,6 +142,7 @@ pub fn init_data_with_details_v2_checksum( CODEC_VERSION, with_checksum, extra_checksum, + None, ) } @@ -136,11 +156,12 @@ fn init_data_with_details_impl( codec_ver: u8, with_checksum: bool, extra_checksum: Option, + pd_client: Option>, ) -> (Store, Endpoint, Arc) { let storage = TestStorageBuilderApiV1::from_engine_and_lock_mgr(engine, MockLockManager::new()) .build() .unwrap(); - let mut store = Store::from_storage(storage); + let mut store = Store::from_storage_pd_client(storage, pd_client); store.begin(); for &(id, name, count) in vals { diff --git a/components/test_coprocessor/src/store.rs b/components/test_coprocessor/src/store.rs index e5589969911..72d4c3ce157 100644 --- a/components/test_coprocessor/src/store.rs +++ b/components/test_coprocessor/src/store.rs @@ -1,9 +1,10 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. -use std::collections::BTreeMap; +use std::{collections::BTreeMap, sync::Arc, time::Duration}; use collections::HashMap; use kvproto::kvrpcpb::{Context, IsolationLevel}; +use pd_client::PdClient; use test_storage::SyncTestStorageApiV1; use tidb_query_datatype::{ codec::{ @@ -23,6 +24,7 @@ use tikv::{ SnapshotStore, StorageApiV1, TestStorageBuilderApiV1, }, }; +use tikv_util::future::block_on_timeout; use txn_types::{Key, Mutation, TimeStamp}; use super::*; @@ -166,6 +168,7 @@ pub struct Store { current_ts: TimeStamp, last_committed_ts: TimeStamp, handles: Vec>, + pd_client: Option>, } impl Store { @@ -185,11 +188,29 @@ impl Default for Store { impl Store { pub fn from_storage(storage: StorageApiV1) -> Self { + Self::from_storage_pd_client(storage, None) + } + + pub fn from_storage_pd_client( + storage: StorageApiV1, + pd_client: Option>, + ) -> Self { Self { store: SyncTestStorageApiV1::from_storage(0, storage, GcConfig::default()).unwrap(), current_ts: 1.into(), last_committed_ts: TimeStamp::zero(), handles: vec![], + pd_client, + } + } + + fn get_ts(&self) -> TimeStamp { + if let Some(client) = self.pd_client.as_ref() { + block_on_timeout(client.get_tso(), Duration::from_secs(5)) + .unwrap() + .unwrap() + } else { + (next_id() as u64).into() } } @@ -198,7 +219,7 @@ impl Store { } pub fn begin(&mut self) { - self.current_ts = (next_id() as u64).into(); + self.current_ts = self.get_ts(); self.handles.clear(); } @@ -233,7 +254,7 @@ impl Store { } pub fn commit_with_ctx(&mut self, ctx: Context) { - let commit_ts = (next_id() as u64).into(); + let commit_ts = self.get_ts(); let handles: Vec<_> = self.handles.drain(..).map(|x| Key::from_raw(&x)).collect(); if !handles.is_empty() { self.store diff --git a/components/test_coprocessor/src/table.rs b/components/test_coprocessor/src/table.rs index af070f62759..3009dc78018 100644 --- a/components/test_coprocessor/src/table.rs +++ b/components/test_coprocessor/src/table.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; +use codec::{buffer::BufferWriter, number::NumberEncoder as _}; use kvproto::coprocessor::KeyRange; use tidb_query_datatype::codec::table; use tikv_util::codec::number::NumberEncoder; @@ -116,6 +117,13 @@ impl Table { range.set_end(table::encode_index_seek_key(self.id, idx, &buf)); range } + + pub fn get_table_prefix(&self) -> Vec { + let mut buf = vec![]; + buf.write_bytes(table::TABLE_PREFIX).unwrap(); + buf.write_i64(self.id).unwrap(); + buf + } } impl> std::ops::Index for Table { diff --git a/components/test_raftstore-v2/src/server.rs b/components/test_raftstore-v2/src/server.rs index fafe049e643..e73efd2c0a1 100644 --- a/components/test_raftstore-v2/src/server.rs +++ b/components/test_raftstore-v2/src/server.rs @@ -147,6 +147,12 @@ impl Engine for TestRaftKv2 { self.raftkv.async_snapshot(ctx) } + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } + type WriteRes = as Engine>::WriteRes; fn async_write( &self, diff --git a/components/test_raftstore/src/cluster.rs b/components/test_raftstore/src/cluster.rs index 0167c9b6629..9824f02adbe 100644 --- a/components/test_raftstore/src/cluster.rs +++ b/components/test_raftstore/src/cluster.rs @@ -12,15 +12,15 @@ use std::{ time::Duration, }; -use ::server::common::KvEngineBuilder; use collections::{HashMap, HashSet}; use crossbeam::channel::TrySendError; use encryption_export::DataKeyManager; -use engine_rocks::{RocksCompactedEvent, RocksEngine, RocksStatistics}; +use engine_rocks::{RocksEngine, RocksSnapshot, RocksStatistics}; use engine_test::raft::RaftTestEngine; use engine_traits::{ - CacheRegion, Engines, Iterable, KvEngine, ManualCompactionOptions, Mutable, Peekable, - RaftEngineReadOnly, SnapshotContext, SyncMutable, WriteBatch, CF_DEFAULT, CF_RAFT, + CacheRegion, CompactExt, Engines, Iterable, ManualCompactionOptions, MiscExt, Mutable, + Peekable, RaftEngineReadOnly, SnapshotContext, SyncMutable, WriteBatch, WriteBatchExt, + CF_DEFAULT, CF_RAFT, }; use file_system::IoRateLimiter; use futures::{self, channel::oneshot, executor::block_on, future::BoxFuture, StreamExt}; @@ -52,7 +52,6 @@ use raftstore::{ }, Error, Result, }; -use range_cache_memory_engine::RangeCacheMemoryEngine; use resource_control::ResourceGroupManager; use tempfile::TempDir; use test_pd_client::TestPdClient; @@ -68,17 +67,12 @@ use txn_types::WriteBatchFlags; use self::range_cache_engine::RangCacheEngineExt; use super::*; use crate::Config; - -pub trait KvEngineWithRocks = KvEngine - + KvEngineBuilder - + RangCacheEngineExt; - // We simulate 3 or 5 nodes, each has a store. // Sometimes, we use fixed id to test, which means the id // isn't allocated by pd, and node id, store id are same. // E,g, for node 1, the node id and store id are both 1. -pub trait Simulator { +pub trait Simulator { // Pass 0 to let pd allocate a node id if db is empty. // If node id > 0, the node must be created in db already, // and the node id must be the same as given argument. @@ -88,11 +82,11 @@ pub trait Simulator { &mut self, node_id: u64, cfg: Config, - engines: Engines, + engines: Engines, store_meta: Arc>, key_manager: Option>, - router: RaftRouter, - system: RaftBatchSystem, + router: RaftRouter, + system: RaftBatchSystem, resource_manager: &Option>, ) -> ServerResult; fn stop_node(&mut self, node_id: u64); @@ -101,7 +95,7 @@ pub trait Simulator { &self, node_id: u64, request: RaftCmdRequest, - cb: Callback, + cb: Callback, ) -> Result<()> { self.async_command_on_node_with_opts(node_id, request, cb, Default::default()) } @@ -109,13 +103,13 @@ pub trait Simulator { &self, node_id: u64, request: RaftCmdRequest, - cb: Callback, + cb: Callback, opts: RaftCmdExtraOpts, ) -> Result<()>; fn send_raft_msg(&mut self, msg: RaftMessage) -> Result<()>; fn get_snap_dir(&self, node_id: u64) -> String; fn get_snap_mgr(&self, node_id: u64) -> &SnapManager; - fn get_router(&self, node_id: u64) -> Option>; + fn get_router(&self, node_id: u64) -> Option>; fn add_send_filter(&mut self, node_id: u64, filter: Box); fn clear_send_filters(&mut self, node_id: u64); fn add_recv_filter(&mut self, node_id: u64, filter: Box); @@ -134,7 +128,7 @@ pub trait Simulator { timeout: Duration, ) -> Result { let node_id = request.get_header().get_peer().get_store_id(); - let (cb, mut rx) = make_cb::(&request); + let (cb, mut rx) = make_cb(&request); self.async_read(snap_ctx, node_id, batch_id, request, cb); rx.recv_timeout(timeout) .map_err(|_| Error::Timeout(format!("request timeout for {:?}", timeout))) @@ -146,7 +140,7 @@ pub trait Simulator { node_id: u64, batch_id: Option, request: RaftCmdRequest, - cb: Callback, + cb: Callback, ); fn call_command_on_node( @@ -155,7 +149,7 @@ pub trait Simulator { request: RaftCmdRequest, timeout: Duration, ) -> Result { - let (cb, mut rx) = make_cb::(&request); + let (cb, mut rx) = make_cb(&request); match self.async_command_on_node(node_id, request, cb) { Ok(()) => {} @@ -170,17 +164,17 @@ pub trait Simulator { } } -pub struct Cluster> { +pub struct Cluster { pub cfg: Config, leaders: HashMap, pub count: usize, pub paths: Vec, - pub dbs: Vec>, + pub dbs: Vec>, pub store_metas: HashMap>>, key_managers: Vec>>, pub io_rate_limiter: Option>, - pub engines: HashMap>, + pub engines: HashMap>, key_managers_map: HashMap>>, pub labels: HashMap>, group_props: HashMap, @@ -198,11 +192,7 @@ pub struct Cluster> { range_cache_engine_enabled_with_whole_range: bool, } -impl Cluster -where - EK: KvEngineWithRocks, - T: Simulator, -{ +impl Cluster { // Create the default Store cluster. pub fn new( id: u64, @@ -210,7 +200,7 @@ where sim: Arc>, pd_client: Arc, api_version: ApiVersion, - ) -> Cluster { + ) -> Cluster { // TODO: In the future, maybe it's better to test both case where // `use_delete_range` is true and false Cluster { @@ -273,14 +263,9 @@ where assert!(self.sst_workers_map.insert(node_id, offset).is_none()); } - fn create_engine(&mut self, router: Option>) { + fn create_engine(&mut self, router: Option>) { let (engines, key_manager, dir, sst_worker, kv_statistics, raft_statistics) = - create_test_engine( - router, - self.io_rate_limiter.clone(), - self.pd_client.clone(), - &self.cfg, - ); + create_test_engine(router, self.io_rate_limiter.clone(), &self.cfg); self.dbs.push(engines); self.key_managers.push(key_manager); self.paths.push(dir); @@ -449,7 +434,7 @@ where tikv_util::thread_group::set_properties(previous_prop); } - pub fn get_engine(&self, node_id: u64) -> EK { + pub fn get_engine(&self, node_id: u64) -> RocksEngine { self.engines[&node_id].kv.clone() } @@ -457,7 +442,7 @@ where self.engines[&node_id].raft.clone() } - pub fn get_all_engines(&self, node_id: u64) -> Engines { + pub fn get_all_engines(&self, node_id: u64) -> Engines { self.engines[&node_id].clone() } @@ -838,7 +823,7 @@ where self.leaders.remove(®ion_id); } - pub fn assert_quorum bool>(&self, mut condition: F) { + pub fn assert_quorum bool>(&self, mut condition: F) { if self.engines.is_empty() { return; } @@ -1144,7 +1129,7 @@ where let region_id = req.get_header().get_region_id(); let leader = self.leader_of_region(region_id).unwrap(); req.mut_header().set_peer(leader.clone()); - let (cb, mut rx) = make_cb::(&req); + let (cb, mut rx) = make_cb(&req); self.sim .rl() .async_command_on_node_with_opts(leader.get_store_id(), req, cb, opts)?; @@ -1516,7 +1501,7 @@ where } } - pub fn restore_kv_meta(&self, region_id: u64, store_id: u64, snap: &EK::Snapshot) { + pub fn restore_kv_meta(&self, region_id: u64, store_id: u64, snap: &RocksSnapshot) { let (meta_start, meta_end) = ( keys::region_meta_prefix(region_id), keys::region_meta_prefix(region_id + 1), @@ -1644,7 +1629,7 @@ where &mut self, region: &metapb::Region, split_key: &[u8], - cb: Callback, + cb: Callback, ) { let leader = self.leader_of_region(region.get_id()).unwrap(); let router = self.sim.rl().get_router(leader.get_store_id()).unwrap(); @@ -1884,7 +1869,7 @@ where ) } - pub fn merge_region(&mut self, source: u64, target: u64, cb: Callback) { + pub fn merge_region(&mut self, source: u64, target: u64, cb: Callback) { let mut req = self.new_prepare_merge(source, target); let leader = self.leader_of_region(source).unwrap(); req.mut_header().set_peer(leader.clone()); @@ -2055,7 +2040,7 @@ where ctx } - pub fn get_router(&self, node_id: u64) -> Option> { + pub fn get_router(&self, node_id: u64) -> Option> { self.sim.rl().get_router(node_id) } @@ -2161,7 +2146,7 @@ where } } -impl> Drop for Cluster { +impl Drop for Cluster { fn drop(&mut self) { test_util::clear_failpoints(); self.shutdown(); @@ -2223,14 +2208,3 @@ impl RawEngine for HybridEngineImpl { .get_msg_cf(CF_RAFT, &keys::raft_state_key(region_id)) } } - -impl> Cluster { - pub fn get_range_cache_engine(&self, node_id: u64) -> RangeCacheMemoryEngine { - self.engines - .get(&node_id) - .unwrap() - .kv - .range_cache_engine() - .clone() - } -} diff --git a/components/test_raftstore/src/node.rs b/components/test_raftstore/src/node.rs index 3e7dc1c8dfe..620d1420ef9 100644 --- a/components/test_raftstore/src/node.rs +++ b/components/test_raftstore/src/node.rs @@ -8,11 +8,10 @@ use std::{ use collections::{HashMap, HashSet}; use concurrency_manager::ConcurrencyManager; use encryption_export::DataKeyManager; -use engine_rocks::RocksEngine; +use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_test::raft::RaftTestEngine; -use engine_traits::{Engines, KvEngine, SnapshotContext}; +use engine_traits::{Engines, MiscExt, Peekable, SnapshotContext}; use health_controller::HealthController; -use hybrid_engine::observer::Observer as HybridEngineObserver; use kvproto::{ kvrpcpb::ApiVersion, metapb, @@ -32,7 +31,6 @@ use raftstore::{ }, Result, }; -use range_cache_memory_engine::RangeCacheEngineConfig; use resource_control::ResourceGroupManager; use resource_metering::CollectorRegHandle; use service::service_manager::GrpcServiceManager; @@ -52,18 +50,18 @@ use tikv_util::{ use super::*; use crate::Config; -pub struct ChannelTransportCore { +pub struct ChannelTransportCore { snap_paths: HashMap, - routers: HashMap, EK>>, + routers: HashMap>>, } #[derive(Clone)] -pub struct ChannelTransport { - core: Arc>>, +pub struct ChannelTransport { + core: Arc>, } -impl ChannelTransport { - pub fn new() -> ChannelTransport { +impl ChannelTransport { + pub fn new() -> ChannelTransport { ChannelTransport { core: Arc::new(Mutex::new(ChannelTransportCore { snap_paths: HashMap::default(), @@ -73,13 +71,13 @@ impl ChannelTransport { } } -impl Default for ChannelTransport { +impl Default for ChannelTransport { fn default() -> Self { Self::new() } } -impl Transport for ChannelTransport { +impl Transport for ChannelTransport { fn send(&mut self, msg: RaftMessage) -> Result<()> { let from_store = msg.get_from_peer().get_store_id(); let to_store = msg.get_to_peer().get_store_id(); @@ -152,23 +150,23 @@ impl Transport for ChannelTransport { fn flush(&mut self) {} } -type SimulateChannelTransport = SimulateTransport, EK>; +type SimulateChannelTransport = SimulateTransport; -pub struct NodeCluster { - trans: ChannelTransport, +pub struct NodeCluster { + trans: ChannelTransport, pd_client: Arc, - nodes: HashMap>, + nodes: HashMap>, snap_mgrs: HashMap, cfg_controller: HashMap, - simulate_trans: HashMap>, + simulate_trans: HashMap, concurrency_managers: HashMap, - importers: HashMap>>, + importers: HashMap>>, #[allow(clippy::type_complexity)] - post_create_coprocessor_host: Option)>>, + post_create_coprocessor_host: Option)>>, } -impl NodeCluster { - pub fn new(pd_client: Arc) -> NodeCluster { +impl NodeCluster { + pub fn new(pd_client: Arc) -> NodeCluster { NodeCluster { trans: ChannelTransport::new(), pd_client, @@ -183,12 +181,12 @@ impl NodeCluster { } } -impl NodeCluster { +impl NodeCluster { #[allow(dead_code)] pub fn get_node_router( &self, node_id: u64, - ) -> SimulateTransport, EK> { + ) -> SimulateTransport> { self.trans .core .lock() @@ -203,14 +201,17 @@ impl NodeCluster { // first argument of `op` is the node_id. // Set this before invoking `run_node`. #[allow(clippy::type_complexity)] - pub fn post_create_coprocessor_host(&mut self, op: Box)>) { + pub fn post_create_coprocessor_host( + &mut self, + op: Box)>, + ) { self.post_create_coprocessor_host = Some(op) } pub fn get_node( &mut self, node_id: u64, - ) -> Option<&mut MultiRaftServer> { + ) -> Option<&mut MultiRaftServer> { self.nodes.get_mut(&node_id) } @@ -222,21 +223,21 @@ impl NodeCluster { self.cfg_controller.get(&node_id) } - pub fn get_importer(&self, node_id: u64) -> Option>> { + pub fn get_importer(&self, node_id: u64) -> Option>> { self.importers.get(&node_id).cloned() } } -impl Simulator for NodeCluster { +impl Simulator for NodeCluster { fn run_node( &mut self, node_id: u64, cfg: Config, - engines: Engines, + engines: Engines, store_meta: Arc>, key_manager: Option>, - router: RaftRouter, - system: RaftBatchSystem, + router: RaftRouter, + system: RaftBatchSystem, _resource_manager: &Option>, ) -> ServerResult { assert!(node_id == 0 || !self.nodes.contains_key(&node_id)); @@ -302,12 +303,6 @@ impl Simulator for NodeCluster { f(node_id, &mut coprocessor_host); } - // Hybrid engine observer. - if cfg.tikv.range_cache_engine.enabled { - let observer = HybridEngineObserver::new(Arc::new(engines.kv.clone())); - observer.register_to(&mut coprocessor_host); - } - let cm = ConcurrencyManager::new(1.into()); self.concurrency_managers.insert(node_id, cm.clone()); ReplicaReadLockChecker::new(cm.clone()).register(&mut coprocessor_host); @@ -324,6 +319,7 @@ impl Simulator for NodeCluster { engines.kv.clone(), StoreMetaDelegate::new(store_meta.clone(), engines.kv.clone()), router.clone(), + coprocessor_host.clone(), ); let cfg_controller = ConfigController::new(cfg.tikv.clone()); @@ -435,7 +431,7 @@ impl Simulator for NodeCluster { &self, node_id: u64, request: RaftCmdRequest, - cb: Callback, + cb: Callback, opts: RaftCmdExtraOpts, ) -> Result<()> { if !self @@ -467,7 +463,7 @@ impl Simulator for NodeCluster { node_id: u64, batch_id: Option, request: RaftCmdRequest, - cb: Callback, + cb: Callback, ) { if !self .trans @@ -516,50 +512,22 @@ impl Simulator for NodeCluster { trans.routers.get_mut(&node_id).unwrap().clear_filters(); } - fn get_router(&self, node_id: u64) -> Option> { + fn get_router(&self, node_id: u64) -> Option> { self.nodes.get(&node_id).map(|node| node.get_router()) } } // Compare to server cluster, node cluster does not have server layer and // storage layer. -pub fn new_node_cluster(id: u64, count: usize) -> Cluster> { +pub fn new_node_cluster(id: u64, count: usize) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, false)); let sim = Arc::new(RwLock::new(NodeCluster::new(Arc::clone(&pd_client)))); Cluster::new(id, count, sim, pd_client, ApiVersion::V1) } -// the hybrid engine with disk engine "RocksEngine" and region cache engine -// "RangeCacheMemoryEngine" is used in the node cluster. -pub fn new_node_cluster_with_hybrid_engine( - id: u64, - count: usize, -) -> Cluster> { - let pd_client = Arc::new(TestPdClient::new(id, false)); - let sim = Arc::new(RwLock::new(NodeCluster::new(Arc::clone(&pd_client)))); - let mut cluster = Cluster::new(id, count, sim, pd_client, ApiVersion::V1); - cluster.range_cache_engine_enabled_with_whole_range(true); - cluster.cfg.tikv.range_cache_engine = RangeCacheEngineConfig::config_for_test(); - cluster -} - -pub fn new_node_cluster_with_hybrid_engine_with_no_range_cache( - id: u64, - count: usize, -) -> Cluster> { - let pd_client = Arc::new(TestPdClient::new(id, false)); - let sim = Arc::new(RwLock::new(NodeCluster::new(Arc::clone(&pd_client)))); - let mut cluster = Cluster::new(id, count, sim, pd_client, ApiVersion::V1); - cluster.cfg.tikv.range_cache_engine = RangeCacheEngineConfig::config_for_test(); - cluster -} - // This cluster does not support batch split, we expect it to transfer the // `BatchSplit` request to `split` request -pub fn new_incompatible_node_cluster( - id: u64, - count: usize, -) -> Cluster> { +pub fn new_incompatible_node_cluster(id: u64, count: usize) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, true)); let sim = Arc::new(RwLock::new(NodeCluster::new(Arc::clone(&pd_client)))); Cluster::new(id, count, sim, pd_client, ApiVersion::V1) diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index 0c12efefb20..343e5e13281 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -8,18 +8,21 @@ use std::{ usize, }; +use ::server::common::build_hybrid_engine; use api_version::{dispatch_api_version, KvFormat}; use causal_ts::CausalTsProviderImpl; use collections::{HashMap, HashSet}; use concurrency_manager::ConcurrencyManager; use encryption_export::DataKeyManager; -use engine_rocks::RocksEngine; +use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_test::raft::RaftTestEngine; -use engine_traits::{Engines, KvEngine, SnapshotContext}; +use engine_traits::{Engines, MiscExt, SnapshotContext}; use futures::executor::block_on; use grpcio::{ChannelBuilder, EnvBuilder, Environment, Error as GrpcError, Service}; use health_controller::HealthController; -use hybrid_engine::observer::Observer as HybridEngineObserver; +use hybrid_engine::observer::{ + EvictionObserver, HybridSnapshotObserver, RegionCacheWriteBatchObserver, +}; use kvproto::{ deadlock::create_deadlock, debugpb::{create_debug, DebugClient}, @@ -43,7 +46,9 @@ use raftstore::{ }, Result, }; -use range_cache_memory_engine::RangeCacheEngineConfig; +use range_cache_memory_engine::{ + RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, +}; use resource_control::ResourceGroupManager; use resource_metering::{CollectorRegHandle, ResourceTagFactory}; use security::SecurityManager; @@ -52,7 +57,8 @@ use tempfile::TempDir; use test_pd_client::TestPdClient; use tikv::{ config::ConfigController, - coprocessor, coprocessor_v2, + coprocessor::{self, Endpoint}, + coprocessor_v2, import::{ImportSstService, SstImporter}, read_pool::ReadPool, server::{ @@ -88,12 +94,12 @@ use txn_types::TxnExtraScheduler; use super::*; use crate::Config; -type SimulateStoreTransport = SimulateTransport, EK>; +type SimulateStoreTransport = SimulateTransport>; -pub type SimulateEngine = RaftKv>; -type SimulateRaftExtension = as Engine>::RaftExtension; -type SimulateServerTransport = - SimulateTransport, PdStoreAddrResolver>, EK>; +pub type SimulateEngine = RaftKv; +type SimulateRaftExtension = ::RaftExtension; +type SimulateServerTransport = + SimulateTransport>; #[derive(Default, Clone)] pub struct AddressMap { @@ -129,29 +135,30 @@ impl StoreAddrResolver for AddressMap { } } -struct ServerMeta { - node: MultiRaftServer, - server: Server>, - sim_router: SimulateStoreTransport, - sim_trans: SimulateServerTransport, - raw_router: RaftRouter, - raw_apply_router: ApplyRouter, - gc_worker: GcWorker>>, +struct ServerMeta { + node: MultiRaftServer, + server: Server, + sim_router: SimulateStoreTransport, + sim_trans: SimulateServerTransport, + raw_router: RaftRouter, + raw_apply_router: ApplyRouter, + gc_worker: GcWorker>, rts_worker: Option>, rsmeter_cleanup: Box, } type PendingServices = Vec Service>>; -type CopHooks = Vec)>>; +type CopHooks = Vec)>>; -pub struct ServerCluster { - metas: HashMap>, +pub struct ServerCluster { + metas: HashMap, addrs: AddressMap, - pub storages: HashMap>, + pub storages: HashMap, + pub copr_endpoints: HashMap>, pub region_info_accessors: HashMap, - pub importers: HashMap>>, + pub importers: HashMap>>, pub pending_services: HashMap, - pub coprocessor_hooks: HashMap>, + pub coprocessor_hooks: HashMap>, pub health_controllers: HashMap, pub security_mgr: Arc, pub txn_extra_schedulers: HashMap>, @@ -164,10 +171,11 @@ pub struct ServerCluster { env: Arc, pub causal_ts_providers: HashMap>, pub encryption: Option>, + pub in_memory_engines: HashMap>, } -impl ServerCluster { - pub fn new(pd_client: Arc) -> ServerCluster { +impl ServerCluster { + pub fn new(pd_client: Arc) -> ServerCluster { let env = Arc::new( EnvBuilder::new() .cq_count(2) @@ -194,6 +202,8 @@ impl ServerCluster { pd_client, security_mgr, storages: HashMap::default(), + copr_endpoints: HashMap::default(), + in_memory_engines: HashMap::default(), region_info_accessors: HashMap::default(), importers: HashMap::default(), snap_paths: HashMap::default(), @@ -215,16 +225,19 @@ impl ServerCluster { self.addrs.get(node_id).unwrap() } - pub fn get_apply_router(&self, node_id: u64) -> ApplyRouter { + pub fn get_apply_router(&self, node_id: u64) -> ApplyRouter { self.metas.get(&node_id).unwrap().raw_apply_router.clone() } - pub fn get_server_router(&self, node_id: u64) -> SimulateStoreTransport { + pub fn get_server_router(&self, node_id: u64) -> SimulateStoreTransport { self.metas.get(&node_id).unwrap().sim_router.clone() } /// To trigger GC manually. - pub fn get_gc_worker(&self, node_id: u64) -> &GcWorker>> { + pub fn get_gc_worker( + &self, + node_id: u64, + ) -> &GcWorker> { &self.metas.get(&node_id).unwrap().gc_worker } @@ -265,11 +278,11 @@ impl ServerCluster { &mut self, node_id: u64, mut cfg: Config, - engines: Engines, + engines: Engines, store_meta: Arc>, key_manager: Option>, - router: RaftRouter, - system: RaftBatchSystem, + router: RaftRouter, + system: RaftBatchSystem, resource_manager: &Option>, ) -> ServerResult { self.encryption = key_manager.clone(); @@ -294,12 +307,6 @@ impl ServerCluster { } } - let local_reader = LocalReader::new( - engines.kv.clone(), - StoreMetaDelegate::new(store_meta.clone(), engines.kv.clone()), - router.clone(), - ); - // Create coprocessor. let enable_region_stats_mgr_cb: Arc bool + Send + Sync> = if cfg.range_cache_engine.enabled { @@ -308,48 +315,76 @@ impl ServerCluster { Arc::new(|| false) }; let mut coprocessor_host = CoprocessorHost::new(router.clone(), cfg.coprocessor.clone()); + if let Some(hooks) = self.coprocessor_hooks.get(&node_id) { + for hook in hooks { + hook(&mut coprocessor_host); + } + } let region_info_accessor = RegionInfoAccessor::new( &mut coprocessor_host, enable_region_stats_mgr_cb, cfg.range_cache_engine.mvcc_amplification_threshold, ); + // In-memory engine + let mut range_cache_engine_config = cfg.range_cache_engine.clone(); + let _ = range_cache_engine_config + .expected_region_size + .get_or_insert(cfg.coprocessor.region_split_size()); + let range_cache_engine_config = Arc::new(VersionTrack::new(range_cache_engine_config)); + let range_cache_engine_context = + RangeCacheEngineContext::new(range_cache_engine_config.clone(), self.pd_client.clone()); + let in_memory_engine = if cfg.range_cache_engine.enabled { + let in_memory_engine = build_hybrid_engine( + range_cache_engine_context, + engines.kv.clone(), + None, + Some(Arc::new(region_info_accessor.clone())), + ); + // Eviction observer + let observer = EvictionObserver::new(Arc::new(in_memory_engine.clone())); + observer.register_to(&mut coprocessor_host); + // Write batch observer + let write_batch_observer = + RegionCacheWriteBatchObserver::new(in_memory_engine.range_cache_engine().clone()); + write_batch_observer.register_to(&mut coprocessor_host); + // Snapshot observer + let snapshot_observer = + HybridSnapshotObserver::new(in_memory_engine.range_cache_engine().clone()); + snapshot_observer.register_to(&mut coprocessor_host); + Some(in_memory_engine) + } else { + None + }; + self.in_memory_engines + .insert(node_id, in_memory_engine.clone()); + + let local_reader = LocalReader::new( + engines.kv.clone(), + StoreMetaDelegate::new(store_meta.clone(), engines.kv.clone()), + router.clone(), + coprocessor_host.clone(), + ); let raft_router = ServerRaftStoreRouter::new(router.clone(), local_reader); let sim_router = SimulateTransport::new(raft_router.clone()); - let raft_engine = RaftKv::new( + let mut raft_kv = RaftKv::new( sim_router.clone(), engines.kv.clone(), + in_memory_engine, region_info_accessor.region_leaders(), ); - if let Some(hooks) = self.coprocessor_hooks.get(&node_id) { - for hook in hooks { - hook(&mut coprocessor_host); - } - } - - // Hybrid engine observer. - if cfg.tikv.range_cache_engine.enabled { - let observer = HybridEngineObserver::new(Arc::new(engines.kv.clone())); - observer.register_to(&mut coprocessor_host); - } - // Create storage. let pd_worker = LazyWorker::new("test-pd-worker"); let pd_sender = pd_worker.scheduler(); let storage_read_pool = ReadPool::from(storage::build_read_pool( &tikv::config::StorageReadPoolConfig::default_for_test(), pd_sender.clone(), - raft_engine.clone(), + raft_kv.clone(), )); - let mut engine = RaftKv::new( - sim_router.clone(), - engines.kv.clone(), - region_info_accessor.region_leaders(), - ); if let Some(scheduler) = self.txn_extra_schedulers.remove(&node_id) { - engine.set_txn_extra_scheduler(scheduler); + raft_kv.set_txn_extra_scheduler(scheduler); } let latest_ts = @@ -358,7 +393,7 @@ impl ServerCluster { let (tx, _rx) = std::sync::mpsc::channel(); let mut gc_worker = GcWorker::new( - engine.clone(), + raft_kv.clone(), tx, cfg.gc.clone(), Default::default(), @@ -425,9 +460,9 @@ impl ServerCluster { cfg.quota.max_delay_duration, cfg.quota.enable_auto_tune, )); - let extension = engine.raft_extension(); + let extension = raft_kv.raft_extension(); let store = Storage::<_, _, F>::from_engine( - engine.clone(), + raft_kv.clone(), &cfg.storage, storage_read_pool.handle(), lock_mgr.clone(), @@ -444,7 +479,7 @@ impl ServerCluster { .map(|m| m.derive_controller("scheduler-worker-pool".to_owned(), true)), resource_manager.clone(), )?; - self.storages.insert(node_id, raft_engine); + self.storages.insert(node_id, raft_kv.clone()); ReplicaReadLockChecker::new(concurrency_manager.clone()).register(&mut coprocessor_host); @@ -465,7 +500,7 @@ impl ServerCluster { let import_service = ImportSstService::new( cfg.import.clone(), cfg.raft_store.raft_entry_max_size, - engine, + raft_kv, LocalTablets::Singleton(engines.kv.clone()), Arc::clone(&importer), None, @@ -604,6 +639,7 @@ impl ServerCluster { let simulate_trans = SimulateTransport::new(trans); let max_grpc_thread_count = cfg.server.grpc_concurrency; let server_cfg = Arc::new(VersionTrack::new(cfg.server.clone())); + self.copr_endpoints.insert(node_id, copr); // Register the role change observer of the lock manager. lock_mgr.register_detector_role_change_observer(&mut coprocessor_host); @@ -692,18 +728,28 @@ impl ServerCluster { let w = meta.rts_worker.as_ref()?; Some(w.scheduler()) } + + pub fn get_range_cache_engine(&self, node_id: u64) -> RangeCacheMemoryEngine { + self.in_memory_engines + .get(&node_id) + .unwrap() + .as_ref() + .unwrap() + .range_cache_engine() + .clone() + } } -impl Simulator for ServerCluster { +impl Simulator for ServerCluster { fn run_node( &mut self, node_id: u64, cfg: Config, - engines: Engines, + engines: Engines, store_meta: Arc>, key_manager: Option>, - router: RaftRouter, - system: RaftBatchSystem, + router: RaftRouter, + system: RaftBatchSystem, resource_manager: &Option>, ) -> ServerResult { dispatch_api_version!( @@ -754,7 +800,7 @@ impl Simulator for ServerCluster { &self, node_id: u64, request: RaftCmdRequest, - cb: Callback, + cb: Callback, opts: RaftCmdExtraOpts, ) -> Result<()> { let router = match self.metas.get(&node_id) { @@ -770,7 +816,7 @@ impl Simulator for ServerCluster { node_id: u64, batch_id: Option, request: RaftCmdRequest, - cb: Callback, + cb: Callback, ) { match self.metas.get_mut(&node_id) { None => { @@ -829,13 +875,13 @@ impl Simulator for ServerCluster { .clear_filters(); } - fn get_router(&self, node_id: u64) -> Option> { + fn get_router(&self, node_id: u64) -> Option> { self.metas.get(&node_id).map(|m| m.raw_router.clone()) } } -impl Cluster> { - pub fn must_get_snapshot_of_region(&mut self, region_id: u64) -> RegionSnapshot { +impl Cluster { + pub fn must_get_snapshot_of_region(&mut self, region_id: u64) -> RegionSnapshot { self.must_get_snapshot_of_region_with_ctx(region_id, Default::default()) } @@ -843,8 +889,8 @@ impl Cluster> { &mut self, region_id: u64, snap_ctx: SnapContext<'_>, - ) -> RegionSnapshot { - let mut try_snapshot = || -> Option> { + ) -> RegionSnapshot { + let mut try_snapshot = || -> Option> { let leader = self.leader_of_region(region_id)?; let store_id = leader.store_id; let epoch = self.get_region_epoch(region_id); @@ -869,7 +915,7 @@ impl Cluster> { panic!("failed to get snapshot of region {}", region_id); } - pub fn raft_extension(&self, node_id: u64) -> SimulateRaftExtension { + pub fn raft_extension(&self, node_id: u64) -> SimulateRaftExtension { self.sim.rl().storages[&node_id].raft_extension() } @@ -877,7 +923,11 @@ impl Cluster> { self.sim.rl().get_addr(node_id) } - pub fn register_hook(&self, node_id: u64, register: Box)>) { + pub fn register_hook( + &self, + node_id: u64, + register: Box)>, + ) { self.sim .wl() .coprocessor_hooks @@ -887,25 +937,19 @@ impl Cluster> { } } -pub fn new_server_cluster( - id: u64, - count: usize, -) -> Cluster> { +pub fn new_server_cluster(id: u64, count: usize) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, false)); let sim = Arc::new(RwLock::new(ServerCluster::new(Arc::clone(&pd_client)))); Cluster::new(id, count, sim, pd_client, ApiVersion::V1) } -// the hybrid engine with disk engine "RocksEngine" and region cache engine -// "RangeCacheMemoryEngine" is used in the server cluster. -pub fn new_server_cluster_with_hybrid_engine( +pub fn new_server_cluster_with_hybrid_engine_with_no_range_cache( id: u64, count: usize, -) -> Cluster> { +) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, false)); let sim = Arc::new(RwLock::new(ServerCluster::new(Arc::clone(&pd_client)))); let mut cluster = Cluster::new(id, count, sim, pd_client, ApiVersion::V1); - cluster.range_cache_engine_enabled_with_whole_range(true); cluster.cfg.tikv.range_cache_engine = RangeCacheEngineConfig::config_for_test(); cluster } @@ -914,49 +958,32 @@ pub fn new_server_cluster_with_api_ver( id: u64, count: usize, api_ver: ApiVersion, -) -> Cluster> { +) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, false)); let sim = Arc::new(RwLock::new(ServerCluster::new(Arc::clone(&pd_client)))); Cluster::new(id, count, sim, pd_client, api_ver) } -pub fn new_incompatible_server_cluster( - id: u64, - count: usize, -) -> Cluster> { +pub fn new_incompatible_server_cluster(id: u64, count: usize) -> Cluster { let pd_client = Arc::new(TestPdClient::new(id, true)); let sim = Arc::new(RwLock::new(ServerCluster::new(Arc::clone(&pd_client)))); Cluster::new(id, count, sim, pd_client, ApiVersion::V1) } -pub fn must_new_cluster_mul( - count: usize, -) -> ( - Cluster>, - metapb::Peer, - Context, -) { +pub fn must_new_cluster_mul(count: usize) -> (Cluster, metapb::Peer, Context) { must_new_and_configure_cluster_mul(count, |_| ()) } pub fn must_new_and_configure_cluster( - configure: impl FnMut(&mut Cluster>), -) -> ( - Cluster>, - metapb::Peer, - Context, -) { + configure: impl FnMut(&mut Cluster), +) -> (Cluster, metapb::Peer, Context) { must_new_and_configure_cluster_mul(1, configure) } fn must_new_and_configure_cluster_mul( count: usize, - mut configure: impl FnMut(&mut Cluster>), -) -> ( - Cluster>, - metapb::Peer, - Context, -) { + mut configure: impl FnMut(&mut Cluster), +) -> (Cluster, metapb::Peer, Context) { let mut cluster = new_server_cluster(0, count); configure(&mut cluster); cluster.run(); @@ -971,32 +998,20 @@ fn must_new_and_configure_cluster_mul( (cluster, leader, ctx) } -pub fn must_new_cluster_and_kv_client() -> ( - Cluster>, - TikvClient, - Context, -) { +pub fn must_new_cluster_and_kv_client() -> (Cluster, TikvClient, Context) { must_new_cluster_and_kv_client_mul(1) } pub fn must_new_cluster_and_kv_client_mul( count: usize, -) -> ( - Cluster>, - TikvClient, - Context, -) { +) -> (Cluster, TikvClient, Context) { must_new_cluster_with_cfg_and_kv_client_mul(count, |_| {}) } pub fn must_new_cluster_with_cfg_and_kv_client_mul( count: usize, - configure: impl FnMut(&mut Cluster>), -) -> ( - Cluster>, - TikvClient, - Context, -) { + configure: impl FnMut(&mut Cluster), +) -> (Cluster, TikvClient, Context) { let (cluster, leader, ctx) = must_new_and_configure_cluster_mul(count, configure); let env = Arc::new(Environment::new(1)); let channel = @@ -1006,11 +1021,7 @@ pub fn must_new_cluster_with_cfg_and_kv_client_mul( (cluster, client, ctx) } -pub fn must_new_cluster_and_debug_client() -> ( - Cluster>, - DebugClient, - u64, -) { +pub fn must_new_cluster_and_debug_client() -> (Cluster, DebugClient, u64) { let (cluster, leader, _) = must_new_cluster_mul(1); let env = Arc::new(Environment::new(1)); @@ -1021,12 +1032,8 @@ pub fn must_new_cluster_and_debug_client() -> ( (cluster, client, leader.get_store_id()) } -pub fn must_new_cluster_kv_client_and_debug_client() -> ( - Cluster>, - TikvClient, - DebugClient, - Context, -) { +pub fn must_new_cluster_kv_client_and_debug_client() +-> (Cluster, TikvClient, DebugClient, Context) { let (cluster, leader, ctx) = must_new_cluster_mul(1); let env = Arc::new(Environment::new(1)); @@ -1040,12 +1047,8 @@ pub fn must_new_cluster_kv_client_and_debug_client() -> ( } pub fn must_new_and_configure_cluster_and_kv_client( - configure: impl FnMut(&mut Cluster>), -) -> ( - Cluster>, - TikvClient, - Context, -) { + configure: impl FnMut(&mut Cluster), +) -> (Cluster, TikvClient, Context) { let (cluster, leader, ctx) = must_new_and_configure_cluster(configure); let env = Arc::new(Environment::new(1)); @@ -1056,12 +1059,7 @@ pub fn must_new_and_configure_cluster_and_kv_client( (cluster, client, ctx) } -pub fn setup_cluster() -> ( - Cluster>, - TikvClient, - String, - Context, -) { +pub fn setup_cluster() -> (Cluster, TikvClient, String, Context) { let mut cluster = new_server_cluster(0, 3); cluster.run(); diff --git a/components/test_raftstore/src/transport_simulate.rs b/components/test_raftstore/src/transport_simulate.rs index 5ce376b6873..420826f0f60 100644 --- a/components/test_raftstore/src/transport_simulate.rs +++ b/components/test_raftstore/src/transport_simulate.rs @@ -11,7 +11,8 @@ use std::{ use collections::{HashMap, HashSet}; use crossbeam::channel::TrySendError; -use engine_traits::{KvEngine, SnapshotContext}; +use engine_rocks::{RocksEngine, RocksSnapshot}; +use engine_traits::SnapshotContext; use kvproto::{ raft_cmdpb::RaftCmdRequest, raft_serverpb::{ExtraMessageType, RaftMessage}, @@ -143,19 +144,16 @@ impl Filter for DelayFilter { } #[derive(Clone)] -pub struct SimulateTransport { +pub struct SimulateTransport { filters: Arc>>>, ch: C, - - _p: PhantomData, } -impl SimulateTransport { - pub fn new(ch: C) -> SimulateTransport { +impl SimulateTransport { + pub fn new(ch: C) -> SimulateTransport { SimulateTransport { filters: Arc::new(RwLock::new(vec![])), ch, - _p: PhantomData, } } @@ -201,7 +199,7 @@ where res } -impl Transport for SimulateTransport { +impl Transport for SimulateTransport { fn send(&mut self, m: RaftMessage) -> Result<()> { let ch = &mut self.ch; filter_send(&self.filters, m, |m| ch.send(m)) @@ -220,50 +218,48 @@ impl Transport for SimulateTransport { } } -impl> StoreRouter for SimulateTransport { - fn send(&self, msg: StoreMsg) -> Result<()> { +impl> StoreRouter for SimulateTransport { + fn send(&self, msg: StoreMsg) -> Result<()> { StoreRouter::send(&self.ch, msg) } } -impl> ProposalRouter<::Snapshot> - for SimulateTransport -{ +impl> ProposalRouter for SimulateTransport { fn send( &self, - cmd: RaftCommand<::Snapshot>, - ) -> std::result::Result<(), TrySendError::Snapshot>>> { - ProposalRouter::<::Snapshot>::send(&self.ch, cmd) + cmd: RaftCommand, + ) -> std::result::Result<(), TrySendError>> { + ProposalRouter::::send(&self.ch, cmd) } } -impl> CasualRouter for SimulateTransport { - fn send(&self, region_id: u64, msg: CasualMessage) -> Result<()> { - CasualRouter::::send(&self.ch, region_id, msg) +impl> CasualRouter for SimulateTransport { + fn send(&self, region_id: u64, msg: CasualMessage) -> Result<()> { + CasualRouter::::send(&self.ch, region_id, msg) } } -impl> SignificantRouter for SimulateTransport { - fn significant_send(&self, region_id: u64, msg: SignificantMsg) -> Result<()> { +impl> SignificantRouter for SimulateTransport { + fn significant_send(&self, region_id: u64, msg: SignificantMsg) -> Result<()> { self.ch.significant_send(region_id, msg) } } -impl> RaftStoreRouter for SimulateTransport { +impl> RaftStoreRouter for SimulateTransport { fn send_raft_msg(&self, msg: RaftMessage) -> Result<()> { filter_send(&self.filters, msg, |m| self.ch.send_raft_msg(m)) } - fn broadcast_normal(&self, _: impl FnMut() -> PeerMsg) {} + fn broadcast_normal(&self, _: impl FnMut() -> PeerMsg) {} } -impl> LocalReadRouter for SimulateTransport { +impl> LocalReadRouter for SimulateTransport { fn read( &mut self, snap_ctx: Option, read_id: Option, req: RaftCmdRequest, - cb: Callback, + cb: Callback, ) -> RaftStoreResult<()> { self.ch.read(snap_ctx, read_id, req, cb) } diff --git a/components/test_raftstore/src/util.rs b/components/test_raftstore/src/util.rs index 82e774c7915..82312adb32f 100644 --- a/components/test_raftstore/src/util.rs +++ b/components/test_raftstore/src/util.rs @@ -16,9 +16,7 @@ use collections::HashMap; use encryption_export::{ data_key_manager_from_config, DataKeyManager, FileConfig, MasterKeyConfig, }; -use engine_rocks::{ - config::BlobRunMode, RocksCompactedEvent, RocksEngine, RocksSnapshot, RocksStatistics, -}; +use engine_rocks::{config::BlobRunMode, RocksEngine, RocksSnapshot, RocksStatistics}; use engine_test::raft::RaftTestEngine; use engine_traits::{ CfName, CfNamesExt, Engines, Iterable, KvEngine, Peekable, RaftEngineDebug, RaftEngineReadOnly, @@ -50,8 +48,8 @@ use raftstore::{ RaftRouterCompactedEventSender, Result, }; use rand::{seq::SliceRandom, RngCore}; -use range_cache_memory_engine::{RangeCacheEngineContext, RangeCacheMemoryEngine}; -use server::common::{ConfiguredRaftEngine, KvEngineBuilder}; +use range_cache_memory_engine::RangeCacheMemoryEngine; +use server::common::ConfiguredRaftEngine; use tempfile::TempDir; use test_pd_client::TestPdClient; use test_util::eventually; @@ -74,7 +72,7 @@ use tikv_util::{ }; use txn_types::Key; -use crate::{Cluster, Config, KvEngineWithRocks, RawEngine, ServerCluster, Simulator}; +use crate::{Cluster, Config, RawEngine, ServerCluster, Simulator}; pub type HybridEngineImpl = HybridEngine; @@ -431,17 +429,17 @@ pub fn check_raft_cmd_request(cmd: &RaftCmdRequest) -> bool { pub fn make_cb_rocks( cmd: &RaftCmdRequest, ) -> (Callback, future::Receiver) { - make_cb::(cmd) + make_cb(cmd) } -pub fn make_cb( +pub fn make_cb( cmd: &RaftCmdRequest, -) -> (Callback, future::Receiver) { +) -> (Callback, future::Receiver) { let is_read = check_raft_cmd_request(cmd); let (tx, rx) = future::bounded(1, future::WakePolicy::Immediately); let mut detector = CallbackLeakDetector::default(); let cb = if is_read { - Callback::read(Box::new(move |resp: ReadResponse| { + Callback::read(Box::new(move |resp: ReadResponse| { detector.called = true; // we don't care error actually. let _ = tx.send(resp.response); @@ -460,8 +458,8 @@ pub fn make_cb_ext( cmd: &RaftCmdRequest, proposed: Option, committed: Option, -) -> (Callback, future::Receiver) { - let (cb, receiver) = make_cb::(cmd); +) -> (Callback, future::Receiver) { + let (cb, receiver) = make_cb(cmd); if let Callback::Write { cb, .. } = cb { (Callback::write_ext(cb, proposed, committed), receiver) } else { @@ -470,8 +468,8 @@ pub fn make_cb_ext( } // Issue a read request on the specified peer. -pub fn read_on_peer>( - cluster: &mut Cluster, +pub fn read_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, key: &[u8], @@ -488,8 +486,8 @@ pub fn read_on_peer>( cluster.read(None, None, request, timeout) } -pub fn async_read_on_peer>( - cluster: &mut Cluster, +pub fn async_read_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, key: &[u8], @@ -517,10 +515,10 @@ pub fn async_read_on_peer>( }) } -pub fn batch_read_on_peer>( - cluster: &mut Cluster, +pub fn batch_read_on_peer( + cluster: &mut Cluster, requests: &[(metapb::Peer, metapb::Region)], -) -> Vec> { +) -> Vec> { let batch_id = Some(ThreadReadId::new()); let (tx, rx) = mpsc::sync_channel(3); let mut results = vec![]; @@ -551,8 +549,8 @@ pub fn batch_read_on_peer>( results.into_iter().map(|resp| resp.1).collect() } -pub fn read_index_on_peer>( - cluster: &mut Cluster, +pub fn read_index_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, read_quorum: bool, @@ -568,8 +566,8 @@ pub fn read_index_on_peer>( cluster.read(None, None, request, timeout) } -pub fn async_read_index_on_peer>( - cluster: &mut Cluster, +pub fn async_read_index_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, key: &[u8], @@ -600,12 +598,12 @@ pub fn async_read_index_on_peer>( }) } -pub fn async_command_on_node>( - cluster: &mut Cluster, +pub fn async_command_on_node( + cluster: &mut Cluster, node_id: u64, request: RaftCmdRequest, ) -> BoxFuture<'static, RaftCmdResponse> { - let (cb, mut rx) = make_cb::(&request); + let (cb, mut rx) = make_cb(&request); cluster .sim .rl() @@ -627,8 +625,8 @@ pub fn must_get_value(resp: &RaftCmdResponse) -> Vec { resp.get_responses()[0].get_get().get_value().to_vec() } -pub fn must_read_on_peer>( - cluster: &mut Cluster, +pub fn must_read_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, key: &[u8], @@ -646,8 +644,8 @@ pub fn must_read_on_peer>( } } -pub fn must_error_read_on_peer>( - cluster: &mut Cluster, +pub fn must_error_read_on_peer( + cluster: &mut Cluster, peer: metapb::Peer, region: metapb::Region, key: &[u8], @@ -673,23 +671,19 @@ pub fn must_contains_error(resp: &RaftCmdResponse, msg: &str) { assert!(err_msg.contains(msg), "{:?}", resp); } -pub fn create_test_engine( +pub fn create_test_engine( // TODO: pass it in for all cases. - router: Option>, + router: Option>, limiter: Option>, - pd_client: Arc, cfg: &Config, ) -> ( - Engines, + Engines, Option>, TempDir, LazyWorker, Arc, Option>, -) -where - EK: KvEngine + KvEngineBuilder, -{ +) { let dir = test_util::temp_dir("test_cluster", cfg.prefer_mem); let mut cfg = cfg.clone(); cfg.storage.data_dir = dir.path().to_str().unwrap().to_string(); @@ -717,15 +711,8 @@ where })); } let factory = builder.build(); - let disk_engine = factory.create_shared_db(dir.path()).unwrap(); - let config = Arc::new(VersionTrack::new(cfg.tikv.range_cache_engine.clone())); - let kv_engine: EK = KvEngineBuilder::build( - RangeCacheEngineContext::new(config, pd_client), - disk_engine, - None, - None, - ); - let engines = Engines::new(kv_engine, raft_engine); + let engine = factory.create_shared_db(dir.path()).unwrap(); + let engines = Engines::new(engine, raft_engine); ( engines, key_manager, @@ -802,8 +789,8 @@ pub fn configure_for_lease_read( election_timeout } -pub fn configure_for_enable_titan>( - cluster: &mut Cluster, +pub fn configure_for_enable_titan( + cluster: &mut Cluster, min_blob_size: ReadableSize, ) { cluster.cfg.rocksdb.titan.enabled = Some(true); @@ -814,15 +801,11 @@ pub fn configure_for_enable_titan>( cluster.cfg.rocksdb.defaultcf.titan.min_gc_batch_size = ReadableSize::kb(0); } -pub fn configure_for_disable_titan>( - cluster: &mut Cluster, -) { +pub fn configure_for_disable_titan(cluster: &mut Cluster) { cluster.cfg.rocksdb.titan.enabled = Some(false); } -pub fn configure_for_encryption>( - cluster: &mut Cluster, -) { +pub fn configure_for_encryption(cluster: &mut Cluster) { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let master_key_file = manifest_dir.join("src/master-key.data"); @@ -836,8 +819,8 @@ pub fn configure_for_encryption>( } } -pub fn configure_for_causal_ts>( - cluster: &mut Cluster, +pub fn configure_for_causal_ts( + cluster: &mut Cluster, renew_interval: &str, renew_batch_min_size: u32, ) { @@ -847,24 +830,24 @@ pub fn configure_for_causal_ts>( } /// Keep putting random kvs until specified size limit is reached. -pub fn put_till_size>( - cluster: &mut Cluster, +pub fn put_till_size( + cluster: &mut Cluster, limit: u64, range: &mut dyn Iterator, ) -> Vec { put_cf_till_size(cluster, CF_DEFAULT, limit, range) } -pub fn put_till_count>( - cluster: &mut Cluster, +pub fn put_till_count( + cluster: &mut Cluster, limit: u64, range: &mut dyn Iterator, ) -> Vec { put_cf_till_count(cluster, CF_WRITE, limit, range) } -pub fn put_cf_till_size>( - cluster: &mut Cluster, +pub fn put_cf_till_size( + cluster: &mut Cluster, cf: &'static str, limit: u64, range: &mut dyn Iterator, @@ -895,8 +878,8 @@ pub fn put_cf_till_size>( key.into_bytes() } -pub fn put_cf_till_count>( - cluster: &mut Cluster, +pub fn put_cf_till_count( + cluster: &mut Cluster, cf: &'static str, limit: u64, range: &mut dyn Iterator, @@ -1641,11 +1624,7 @@ pub struct PeerClient { } impl PeerClient { - pub fn new( - cluster: &Cluster>, - region_id: u64, - peer: metapb::Peer, - ) -> PeerClient { + pub fn new(cluster: &Cluster, region_id: u64, peer: metapb::Peer) -> PeerClient { let cli = { let env = Arc::new(Environment::new(1)); let channel = @@ -1752,11 +1731,7 @@ pub fn peer_on_store(region: &metapb::Region, store_id: u64) -> metapb::Peer { .clone() } -pub fn wait_for_synced( - cluster: &mut Cluster>, - node_id: u64, - region_id: u64, -) { +pub fn wait_for_synced(cluster: &mut Cluster, node_id: u64, region_id: u64) { let mut storage = cluster .sim .read() @@ -1786,10 +1761,7 @@ pub fn wait_for_synced( assert!(snapshot.ext().is_max_ts_synced()); } -pub fn test_delete_range>( - cluster: &mut Cluster, - cf: CfName, -) { +pub fn test_delete_range(cluster: &mut Cluster, cf: CfName) { let data_set: Vec<_> = (1..500) .map(|i| { ( @@ -1822,8 +1794,8 @@ pub fn test_delete_range>( } } -pub fn put_with_timeout>( - cluster: &mut Cluster, +pub fn put_with_timeout( + cluster: &mut Cluster, node_id: u64, key: &[u8], value: &[u8], @@ -1840,11 +1812,7 @@ pub fn put_with_timeout>( cluster.call_command_on_node(node_id, req, timeout) } -pub fn wait_down_peers>( - cluster: &Cluster, - count: u64, - peer: Option, -) { +pub fn wait_down_peers(cluster: &Cluster, count: u64, peer: Option) { let mut peers = cluster.get_down_peers(); for _ in 1..1000 { if peers.len() == count as usize && peer.as_ref().map_or(true, |p| peers.contains_key(p)) { diff --git a/components/test_storage/src/assert_storage.rs b/components/test_storage/src/assert_storage.rs index d4cdbdb2698..3a641a322a2 100644 --- a/components/test_storage/src/assert_storage.rs +++ b/components/test_storage/src/assert_storage.rs @@ -1,7 +1,6 @@ // Copyright 2017 TiKV Project Authors. Licensed under Apache-2.0. use api_version::{ApiV1, KvFormat}; -use engine_rocks::RocksEngine as RocksDb; use kvproto::{ kvrpcpb::{Context, KeyRange, LockInfo}, metapb, @@ -45,11 +44,11 @@ impl AssertionStorage { } } -impl AssertionStorage, F> { +impl AssertionStorage { pub fn new_raft_storage_with_store_count( count: usize, key: &str, - ) -> (Cluster>, Self) { + ) -> (Cluster, Self) { let (cluster, store, ctx) = new_raft_storage_with_store_count::(count, key); let storage = Self { store, ctx }; (cluster, storage) @@ -57,7 +56,7 @@ impl AssertionStorage, F> { pub fn update_with_key_byte( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], ) -> metapb::Region { // ensure the leader of range which contains current key has been elected @@ -80,7 +79,7 @@ impl AssertionStorage, F> { pub fn delete_ok_for_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], start_ts: impl Into, commit_ts: impl Into, @@ -99,7 +98,7 @@ impl AssertionStorage, F> { fn get_from_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], ts: impl Into, ) -> Option { @@ -117,7 +116,7 @@ impl AssertionStorage, F> { pub fn get_none_from_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], ts: impl Into, ) { @@ -126,7 +125,7 @@ impl AssertionStorage, F> { pub fn put_ok_for_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], value: &[u8], start_ts: impl Into, @@ -139,7 +138,7 @@ impl AssertionStorage, F> { pub fn batch_put_ok_for_cluster<'a>( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, keys: &[impl AsRef<[u8]>], vals: impl Iterator, start_ts: impl Into, @@ -163,7 +162,7 @@ impl AssertionStorage, F> { fn two_pc_ok_for_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, prewrite_mutations: Vec, key: &[u8], commit_keys: Vec, @@ -207,7 +206,7 @@ impl AssertionStorage, F> { pub fn gc_ok_for_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, region_key: &[u8], mut region: metapb::Region, safe_point: impl Into, @@ -226,7 +225,7 @@ impl AssertionStorage, F> { pub fn test_txn_store_gc3_for_cluster( &mut self, - cluster: &mut Cluster>, + cluster: &mut Cluster, key_prefix: u8, ) { let key_len = 10_000; diff --git a/components/test_storage/src/util.rs b/components/test_storage/src/util.rs index 54f82375afe..e91125ba001 100644 --- a/components/test_storage/src/util.rs +++ b/components/test_storage/src/util.rs @@ -1,7 +1,6 @@ // Copyright 2017 TiKV Project Authors. Licensed under Apache-2.0. use api_version::KvFormat; -use engine_rocks::RocksEngine; use kvproto::kvrpcpb::Context; use test_raftstore::{new_server_cluster, Cluster, ServerCluster, SimulateEngine}; use tikv_util::HandyRwLock; @@ -56,11 +55,7 @@ macro_rules! follower_raft_engine { pub fn new_raft_engine( count: usize, key: &str, -) -> ( - Cluster>, - SimulateEngine, - Context, -) { +) -> (Cluster, SimulateEngine, Context) { let mut cluster = new_server_cluster(0, count); let (engine, ctx) = prepare_raft_engine!(cluster, key); (cluster, engine, ctx) @@ -70,8 +65,8 @@ pub fn new_raft_storage_with_store_count( count: usize, key: &str, ) -> ( - Cluster>, - SyncTestStorage, F>, + Cluster, + SyncTestStorage, Context, ) { let (cluster, engine, ctx) = new_raft_engine(count, key); diff --git a/components/tikv_kv/src/btree_engine.rs b/components/tikv_kv/src/btree_engine.rs index 12c0903c15b..04a14059eb1 100644 --- a/components/tikv_kv/src/btree_engine.rs +++ b/components/tikv_kv/src/btree_engine.rs @@ -113,6 +113,12 @@ impl Engine for BTreeEngine { fn async_snapshot(&mut self, _ctx: SnapContext<'_>) -> Self::SnapshotRes { futures::future::ready(Ok(BTreeEngineSnapshot::new(self))) } + + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } } impl Display for BTreeEngine { diff --git a/components/tikv_kv/src/lib.rs b/components/tikv_kv/src/lib.rs index 1590eee2e53..9b1ea42b54f 100644 --- a/components/tikv_kv/src/lib.rs +++ b/components/tikv_kv/src/lib.rs @@ -367,6 +367,14 @@ pub trait Engine: Send + Clone + 'static { /// future is polled or not. fn async_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::SnapshotRes; + type IMSnap: Snapshot; + type IMSnapshotRes: Future> + Send + 'static; + /// Get a snapshot asynchronously. + /// + /// Note the snapshot is queried immediately no matter whether the returned + /// future is polled or not. + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes; + /// Precheck request which has write with it's context. fn precheck_write_with_ctx(&self, _ctx: &Context) -> Result<()> { Ok(()) @@ -723,6 +731,24 @@ pub fn snapshot( } } +/// Get an in memory snapshot of `engine`. +pub fn in_memory_snapshot( + engine: &mut E, + ctx: SnapContext<'_>, +) -> impl std::future::Future> { + let begin = Instant::now(); + let val = engine.async_in_memory_snapshot(ctx); + // make engine not cross yield point + async move { + let result = val.await; + with_tls_tracker(|tracker| { + tracker.metrics.get_snapshot_nanos += begin.elapsed().as_nanos() as u64; + }); + fail_point!("after-snapshot"); + result + } +} + pub fn write( engine: &E, ctx: &Context, diff --git a/components/tikv_kv/src/mock_engine.rs b/components/tikv_kv/src/mock_engine.rs index 69a61d58963..dec1ac0b9a2 100644 --- a/components/tikv_kv/src/mock_engine.rs +++ b/components/tikv_kv/src/mock_engine.rs @@ -167,6 +167,12 @@ impl Engine for MockEngine { self.base.async_snapshot(ctx) } + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } + type WriteRes = ::WriteRes; fn async_write( &self, diff --git a/components/tikv_kv/src/rocksdb_engine.rs b/components/tikv_kv/src/rocksdb_engine.rs index 551b933faeb..404fee8ee58 100644 --- a/components/tikv_kv/src/rocksdb_engine.rs +++ b/components/tikv_kv/src/rocksdb_engine.rs @@ -311,6 +311,12 @@ impl Engine for RocksEngine { async move { Ok(res?.await.unwrap()) } } + + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } } impl Snapshot for Arc { diff --git a/src/coprocessor/endpoint.rs b/src/coprocessor/endpoint.rs index 14a6d3cda8e..a8cd4b16a80 100644 --- a/src/coprocessor/endpoint.rs +++ b/src/coprocessor/endpoint.rs @@ -177,7 +177,7 @@ impl Endpoint { req: coppb::Request, peer: Option, is_streaming: bool, - ) -> Result<(RequestHandlerBuilder, ReqContext)> { + ) -> Result<(RequestHandlerBuilder, ReqContext)> { dispatch_api_version!(req.get_context().get_api_version(), { self.parse_request_and_check_memory_locks_impl::(req, peer, is_streaming) }) @@ -192,7 +192,7 @@ impl Endpoint { mut req: coppb::Request, peer: Option, is_streaming: bool, - ) -> Result<(RequestHandlerBuilder, ReqContext)> { + ) -> Result<(RequestHandlerBuilder, ReqContext)> { fail_point!("coprocessor_parse_request", |_| Err(box_err!( "unsupported tp (failpoint)" ))); @@ -213,7 +213,7 @@ impl Endpoint { input.set_recursion_limit(self.recursion_limit); let mut req_ctx: ReqContext; - let builder: RequestHandlerBuilder; + let builder: RequestHandlerBuilder; match req.get_tp() { REQ_TYPE_DAG => { let mut dag = DagRequest::default(); @@ -394,10 +394,10 @@ impl Endpoint { } #[inline] - fn async_snapshot( + fn async_in_memory_snapshot( engine: &mut E, ctx: &ReqContext, - ) -> impl std::future::Future> { + ) -> impl std::future::Future> { let mut snap_ctx = SnapContext { pb_ctx: &ctx.context, start_ts: Some(ctx.txn_start_ts), @@ -415,7 +415,7 @@ impl Endpoint { snap_ctx.key_ranges.push(key_range); } } - kv::snapshot(engine, snap_ctx).map_err(Error::from) + kv::in_memory_snapshot(engine, snap_ctx).map_err(Error::from) } /// The real implementation of handling a unary request. @@ -427,7 +427,7 @@ impl Endpoint { async fn handle_unary_request_impl( semaphore: Option>, mut tracker: Box>, - handler_builder: RequestHandlerBuilder, + handler_builder: RequestHandlerBuilder, ) -> Result> { // When this function is being executed, it may be queued for a long time, so // that deadline may exceed. @@ -436,9 +436,10 @@ impl Endpoint { // Safety: spawning this function using a `FuturePool` ensures that a TLS engine // exists. - let snapshot = - unsafe { with_tls_engine(|engine| Self::async_snapshot(engine, &tracker.req_ctx)) } - .await?; + let snapshot = unsafe { + with_tls_engine(|engine| Self::async_in_memory_snapshot(engine, &tracker.req_ctx)) + } + .await?; let latest_buckets = snapshot.ext().get_buckets(); let range_cache_snap = snapshot.ext().range_cache_engine_hit(); @@ -516,7 +517,7 @@ impl Endpoint { fn handle_unary_request( &self, req_ctx: ReqContext, - handler_builder: RequestHandlerBuilder, + handler_builder: RequestHandlerBuilder, ) -> impl Future>> { let priority = req_ctx.context.get_priority(); let task_id = req_ctx.build_task_id(); @@ -716,7 +717,7 @@ impl Endpoint { fn handle_stream_request_impl( semaphore: Option>, mut tracker: Box>, - handler_builder: RequestHandlerBuilder, + handler_builder: RequestHandlerBuilder, ) -> impl futures::stream::Stream> { try_stream! { let _permit = if let Some(semaphore) = semaphore.as_ref() { @@ -733,7 +734,7 @@ impl Endpoint { // Safety: spawning this function using a `FuturePool` ensures that a TLS engine // exists. let snapshot = unsafe { - with_tls_engine(|engine| Self::async_snapshot(engine, &tracker.req_ctx)) + with_tls_engine(|engine| Self::async_in_memory_snapshot(engine, &tracker.req_ctx)) } .await?; // When snapshot is retrieved, deadline may exceed. @@ -790,7 +791,7 @@ impl Endpoint { fn handle_stream_request( &self, req_ctx: ReqContext, - handler_builder: RequestHandlerBuilder, + handler_builder: RequestHandlerBuilder, ) -> Result>> { let (tx, rx) = mpsc::channel::>(self.stream_channel_size); let priority = req_ctx.context.get_priority(); diff --git a/src/server/gc_worker/gc_worker.rs b/src/server/gc_worker/gc_worker.rs index 05096a16db1..8f2e04f100b 100644 --- a/src/server/gc_worker/gc_worker.rs +++ b/src/server/gc_worker/gc_worker.rs @@ -1470,6 +1470,12 @@ pub mod test_gc_worker { Ok(RegionSnapshot::from_snapshot(snap, Arc::new(region))) } } + + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } } pub struct MockSafePointProvider(pub u64); @@ -1529,6 +1535,12 @@ pub mod test_gc_worker { .unwrap() .async_snapshot(ctx) } + + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } } } diff --git a/src/server/raftkv/mod.rs b/src/server/raftkv/mod.rs index 5c7f5228c5f..549ebcbad93 100644 --- a/src/server/raftkv/mod.rs +++ b/src/server/raftkv/mod.rs @@ -24,6 +24,7 @@ use collections::{HashMap, HashSet}; use concurrency_manager::ConcurrencyManager; use engine_traits::{CfName, KvEngine, MvccProperties, Snapshot, SnapshotContext}; use futures::{future::BoxFuture, task::AtomicWaker, Future, Stream, StreamExt, TryFutureExt}; +use hybrid_engine::{HybridEngine, HybridEngineSnapshot}; use kvproto::{ errorpb, kvrpcpb::{Context, IsolationLevel}, @@ -48,6 +49,7 @@ use raftstore::{ ReadCallback, ReadIndexContext, ReadResponse, RegionSnapshot, StoreMsg, WriteResponse, }, }; +use range_cache_memory_engine::RangeCacheMemoryEngine; use thiserror::Error; use tikv_kv::{write_modifies, OnAppliedCb, WriteEvent}; use tikv_util::{ @@ -353,6 +355,7 @@ where { router: RaftRouterWrap, engine: E, + in_memory_engine: Option>, txn_extra_scheduler: Option>, region_leaders: Arc>>, } @@ -363,10 +366,16 @@ where S: RaftStoreRouter + LocalReadRouter + 'static, { /// Create a RaftKv using specified configuration. - pub fn new(router: S, engine: E, region_leaders: Arc>>) -> RaftKv { + pub fn new( + router: S, + engine: E, + in_memory_engine: Option>, + region_leaders: Arc>>, + ) -> RaftKv { RaftKv { router: RaftRouterWrap::new(router), engine, + in_memory_engine, txn_extra_scheduler: None, region_leaders, } @@ -600,53 +609,18 @@ where } type SnapshotRes = impl Future> + Send; - fn async_snapshot(&mut self, mut ctx: SnapContext<'_>) -> Self::SnapshotRes { - let mut res: kv::Result<()> = (|| { - fail_point!("raftkv_async_snapshot_err", |_| { - Err(box_err!("injected error for async_snapshot")) - }); - Ok(()) - })(); - - let mut req = Request::default(); - req.set_cmd_type(CmdType::Snap); - if !ctx.key_ranges.is_empty() && ctx.start_ts.map_or(false, |ts| !ts.is_zero()) { - req.mut_read_index() - .set_start_ts(ctx.start_ts.as_ref().unwrap().into_inner()); - req.mut_read_index() - .set_key_ranges(mem::take(&mut ctx.key_ranges).into()); - } - ASYNC_REQUESTS_COUNTER_VEC.snapshot.all.inc(); - let begin_instant = Instant::now(); - let (cb, f) = paired_must_called_future_callback(drop_snapshot_callback); - - let mut header = new_request_header(ctx.pb_ctx); - let mut flags = 0; - let need_encoded_start_ts = ctx.start_ts.map_or(true, |ts| !ts.is_zero()); - if ctx.pb_ctx.get_stale_read() && need_encoded_start_ts { - flags |= WriteBatchFlags::STALE_READ.bits(); - } - if ctx.allowed_in_flashback { - flags |= WriteBatchFlags::FLASHBACK.bits(); - } - header.set_flags(flags); - // Encode `start_ts` in `flag_data` for the check of stale read and flashback. - if need_encoded_start_ts { - encode_start_ts_into_flag_data( - &mut header, - ctx.start_ts.unwrap_or_default().into_inner(), - ); - } + fn async_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::SnapshotRes { + async_snapshot(&mut self.router, ctx, None) + } - let mut cmd = RaftCmdRequest::default(); - cmd.set_header(header); - cmd.set_requests(vec![req].into()); - let store_cb = StoreCallback::read(Box::new(move |resp| { - cb(on_read_result(resp).map_err(Error::into)); - })); - let tracker = store_cb.read_tracker().unwrap(); + fn release_snapshot(&mut self) { + self.router.release_snapshot_cache(); + } - let snap_ctx = if self.engine.range_cache_engine_enabled() { + type IMSnap = RegionSnapshot>; + type IMSnapshotRes = impl Future> + Send; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + let snap_ctx = if self.in_memory_engine.is_some() { // When range cache engine is enabled, we need snapshot context to determine // whether we should use range cache engine snapshot for this request. ctx.start_ts.map(|ts| SnapshotContext { @@ -656,76 +630,16 @@ where } else { None }; - - if res.is_ok() { - res = self - .router - .read(snap_ctx, ctx.read_id, cmd, store_cb) - .map_err(kv::Error::from); - } - async move { - let res = match res { - Ok(()) => match f.await { - Ok(r) => r, - // Canceled may be returned during shutdown. - Err(e) => Err(kv::Error::from(kv::ErrorInner::Other(box_err!(e)))), - }, - Err(e) => Err(e), - }; - match res { - Ok(CmdRes::Resp(mut r)) => { - let e = if r - .first() - .map(|resp| resp.get_read_index().has_locked()) - .unwrap_or(false) - { - let locked = r[0].take_read_index().take_locked(); - KvError::from(KvErrorInner::KeyIsLocked(locked)) - } else { - invalid_resp_type(CmdType::Snap, r[0].get_cmd_type()).into() - }; - Err(e) - } - Ok(CmdRes::Snap(s)) => { - let elapse = begin_instant.saturating_elapsed_secs(); - GLOBAL_TRACKERS.with_tracker(tracker, |tracker| { - if tracker.metrics.read_index_propose_wait_nanos > 0 { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_read_index_propose_wait - .observe( - tracker.metrics.read_index_propose_wait_nanos as f64 - / 1_000_000_000.0, - ); - // snapshot may be handled by lease read in raftstore - if tracker.metrics.read_index_confirm_wait_nanos > 0 { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_read_index_confirm - .observe( - tracker.metrics.read_index_confirm_wait_nanos as f64 - / 1_000_000_000.0, - ); - } - } else if tracker.metrics.local_read { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_local_read - .observe(elapse); - } - }); - ASYNC_REQUESTS_DURATIONS_VEC.snapshot.observe(elapse); - ASYNC_REQUESTS_COUNTER_VEC.snapshot.success.inc(); - Ok(s) - } - Err(e) => { - let status_kind = get_status_kind_from_engine_error(&e); - ASYNC_REQUESTS_COUNTER_VEC.snapshot.get(status_kind).inc(); - Err(e) - } - } - } - } - - fn release_snapshot(&mut self) { - self.router.release_snapshot_cache(); + async_snapshot(&mut self.router, ctx, snap_ctx.clone()).map_ok(|region_snap| { + // TODO: Remove replace_snapshot. Taking a snapshot and replacing it + // with a new one is a bit confusing. + // A better way to build an in-memory snapshot is to return + // `HybridEngineSnapshot, RangeCacheMemoryEngine>>;` + // so the `replace_snapshot` can be removed. + region_snap.replace_snapshot(move |disk_snap, pinned| { + HybridEngineSnapshot::from_observed_snapshot(disk_snap, pinned) + }) + }) } fn get_mvcc_properties_cf( @@ -780,6 +694,123 @@ where } } +fn async_snapshot( + router: &mut RaftRouterWrap, + mut ctx: SnapContext<'_>, + snap_ctx: Option, +) -> impl Future>> + Send +where + E: KvEngine, + S: RaftStoreRouter + LocalReadRouter + 'static, +{ + let mut res: kv::Result<()> = (|| { + fail_point!("raftkv_async_snapshot_err", |_| { + Err(box_err!("injected error for async_snapshot")) + }); + Ok(()) + })(); + + let mut req = Request::default(); + req.set_cmd_type(CmdType::Snap); + if !ctx.key_ranges.is_empty() && ctx.start_ts.map_or(false, |ts| !ts.is_zero()) { + req.mut_read_index() + .set_start_ts(ctx.start_ts.as_ref().unwrap().into_inner()); + req.mut_read_index() + .set_key_ranges(mem::take(&mut ctx.key_ranges).into()); + } + ASYNC_REQUESTS_COUNTER_VEC.snapshot.all.inc(); + let begin_instant = Instant::now(); + let (cb, f) = paired_must_called_future_callback(drop_snapshot_callback); + + let mut header = new_request_header(ctx.pb_ctx); + let mut flags = 0; + let need_encoded_start_ts = ctx.start_ts.map_or(true, |ts| !ts.is_zero()); + if ctx.pb_ctx.get_stale_read() && need_encoded_start_ts { + flags |= WriteBatchFlags::STALE_READ.bits(); + } + if ctx.allowed_in_flashback { + flags |= WriteBatchFlags::FLASHBACK.bits(); + } + header.set_flags(flags); + // Encode `start_ts` in `flag_data` for the check of stale read and flashback. + if need_encoded_start_ts { + encode_start_ts_into_flag_data(&mut header, ctx.start_ts.unwrap_or_default().into_inner()); + } + + let mut cmd = RaftCmdRequest::default(); + cmd.set_header(header); + cmd.set_requests(vec![req].into()); + let store_cb = StoreCallback::read(Box::new(move |resp| { + cb(on_read_result(resp).map_err(Error::into)); + })); + let tracker = store_cb.read_tracker().unwrap(); + + if res.is_ok() { + res = router + .read(snap_ctx, ctx.read_id, cmd, store_cb) + .map_err(kv::Error::from); + } + async move { + let res = match res { + Ok(()) => match f.await { + Ok(r) => r, + // Canceled may be returned during shutdown. + Err(e) => Err(kv::Error::from(kv::ErrorInner::Other(box_err!(e)))), + }, + Err(e) => Err(e), + }; + match res { + Ok(CmdRes::Resp(mut r)) => { + let e = if r + .first() + .map(|resp| resp.get_read_index().has_locked()) + .unwrap_or(false) + { + let locked = r[0].take_read_index().take_locked(); + KvError::from(KvErrorInner::KeyIsLocked(locked)) + } else { + invalid_resp_type(CmdType::Snap, r[0].get_cmd_type()).into() + }; + Err(e) + } + Ok(CmdRes::Snap(s)) => { + let elapse = begin_instant.saturating_elapsed_secs(); + GLOBAL_TRACKERS.with_tracker(tracker, |tracker| { + if tracker.metrics.read_index_propose_wait_nanos > 0 { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_read_index_propose_wait + .observe( + tracker.metrics.read_index_propose_wait_nanos as f64 + / 1_000_000_000.0, + ); + // snapshot may be handled by lease read in raftstore + if tracker.metrics.read_index_confirm_wait_nanos > 0 { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_read_index_confirm + .observe( + tracker.metrics.read_index_confirm_wait_nanos as f64 + / 1_000_000_000.0, + ); + } + } else if tracker.metrics.local_read { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_local_read + .observe(elapse); + } + }); + ASYNC_REQUESTS_DURATIONS_VEC.snapshot.observe(elapse); + ASYNC_REQUESTS_COUNTER_VEC.snapshot.success.inc(); + Ok(s) + } + Err(e) => { + let status_kind = get_status_kind_from_engine_error(&e); + ASYNC_REQUESTS_COUNTER_VEC.snapshot.get(status_kind).inc(); + Err(e) + } + } + } +} + #[derive(Clone)] pub struct ReplicaReadLockChecker { concurrency_manager: ConcurrencyManager, diff --git a/src/server/raftkv2/mod.rs b/src/server/raftkv2/mod.rs index c9d53ef7c99..2f8bfb3d53a 100644 --- a/src/server/raftkv2/mod.rs +++ b/src/server/raftkv2/mod.rs @@ -271,6 +271,12 @@ impl tikv_kv::Engine for RaftKv2 { } } + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: tikv_kv::SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } + type WriteRes = impl Stream + Send + Unpin; fn async_write( &self, diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 858e56efa57..aeaac73ef30 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -3439,6 +3439,12 @@ impl Engine for TxnTestEngine { } } + type IMSnap = Self::Snap; + type IMSnapshotRes = Self::SnapshotRes; + fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { + self.async_snapshot(ctx) + } + type WriteRes = E::WriteRes; fn async_write( &self, diff --git a/tests/benches/misc/raftkv/mod.rs b/tests/benches/misc/raftkv/mod.rs index 2650434c80f..551042f764b 100644 --- a/tests/benches/misc/raftkv/mod.rs +++ b/tests/benches/misc/raftkv/mod.rs @@ -185,6 +185,7 @@ fn bench_async_snapshot(b: &mut test::Bencher) { let mut kv = RaftKv::new( SyncBenchRouter::new(region.clone(), db.clone()), db, + None, Arc::new(RwLock::new(HashSet::default())), ); @@ -219,6 +220,7 @@ fn bench_async_write(b: &mut test::Bencher) { let kv = RaftKv::new( SyncBenchRouter::new(region.clone(), db.clone()), db, + None, Arc::new(RwLock::new(HashSet::default())), ); diff --git a/tests/benches/raftstore/mod.rs b/tests/benches/raftstore/mod.rs index f32c9e49626..e164d59f82a 100644 --- a/tests/benches/raftstore/mod.rs +++ b/tests/benches/raftstore/mod.rs @@ -18,10 +18,7 @@ fn enc_write_kvs(db: &RocksEngine, kvs: &[(Vec, Vec)]) { wb.write().unwrap(); } -fn prepare_cluster>( - cluster: &mut Cluster, - initial_kvs: &[(Vec, Vec)], -) { +fn prepare_cluster(cluster: &mut Cluster, initial_kvs: &[(Vec, Vec)]) { cluster.run(); for engines in cluster.engines.values() { enc_write_kvs(&engines.kv, initial_kvs); @@ -38,7 +35,7 @@ struct SetConfig { fn bench_set(b: &mut Bencher<'_>, input: &SetConfig) where - T: Simulator, + T: Simulator, F: ClusterFactory, { let mut cluster = input.factory.build(input.nodes); @@ -60,7 +57,7 @@ struct GetConfig { fn bench_get(b: &mut Bencher<'_>, input: &GetConfig) where - T: Simulator, + T: Simulator, F: ClusterFactory, { let mut cluster = input.factory.build(input.nodes); @@ -87,7 +84,7 @@ struct DeleteConfig { fn bench_delete(b: &mut Bencher<'_>, input: &DeleteConfig) where - T: Simulator, + T: Simulator, F: ClusterFactory, { let mut cluster = input.factory.build(input.nodes); @@ -108,7 +105,7 @@ where fn bench_raft_cluster(c: &mut Criterion, factory: F, label: &str) where - T: Simulator + 'static, + T: Simulator + 'static, F: ClusterFactory, { let nodes_coll = vec![1, 3, 5]; @@ -139,15 +136,15 @@ where group.finish(); } -trait ClusterFactory>: Clone + fmt::Debug + 'static { - fn build(&self, nodes: usize) -> Cluster; +trait ClusterFactory: Clone + fmt::Debug + 'static { + fn build(&self, nodes: usize) -> Cluster; } #[derive(Clone)] struct NodeClusterFactory; -impl ClusterFactory> for NodeClusterFactory { - fn build(&self, nodes: usize) -> Cluster> { +impl ClusterFactory for NodeClusterFactory { + fn build(&self, nodes: usize) -> Cluster { new_node_cluster(1, nodes) } } @@ -161,8 +158,8 @@ impl fmt::Debug for NodeClusterFactory { #[derive(Clone)] struct ServerClusterFactory; -impl ClusterFactory> for ServerClusterFactory { - fn build(&self, nodes: usize) -> Cluster> { +impl ClusterFactory for ServerClusterFactory { + fn build(&self, nodes: usize) -> Cluster { new_server_cluster(1, nodes) } } diff --git a/tests/failpoints/cases/test_bootstrap.rs b/tests/failpoints/cases/test_bootstrap.rs index 9b4663616ed..8dc2eb8b371 100644 --- a/tests/failpoints/cases/test_bootstrap.rs +++ b/tests/failpoints/cases/test_bootstrap.rs @@ -2,7 +2,6 @@ use std::sync::{Arc, RwLock}; -use engine_rocks::RocksEngine; use engine_traits::Peekable; use kvproto::{kvrpcpb::ApiVersion, metapb, raft_serverpb}; use test_pd_client::TestPdClient; @@ -10,9 +9,7 @@ use test_raftstore::*; fn test_bootstrap_half_way_failure(fp: &str) { let pd_client = Arc::new(TestPdClient::new(0, false)); - let sim = Arc::new(RwLock::new(NodeCluster::::new( - pd_client.clone(), - ))); + let sim = Arc::new(RwLock::new(NodeCluster::new(pd_client.clone()))); let mut cluster = Cluster::new(0, 5, sim, pd_client, ApiVersion::V1); // Try to start this node, return after persisted some keys. diff --git a/tests/failpoints/cases/test_cmd_epoch_checker.rs b/tests/failpoints/cases/test_cmd_epoch_checker.rs index 7c39dd2589b..3b76ac78d35 100644 --- a/tests/failpoints/cases/test_cmd_epoch_checker.rs +++ b/tests/failpoints/cases/test_cmd_epoch_checker.rs @@ -76,10 +76,7 @@ fn make_cb(cmd: &RaftCmdRequest) -> (Callback, CbReceivers) { ) } -fn make_write_req( - cluster: &mut Cluster>, - k: &[u8], -) -> RaftCmdRequest { +fn make_write_req(cluster: &mut Cluster, k: &[u8]) -> RaftCmdRequest { let r = cluster.get_region(k); let mut req = new_request( r.get_id(), diff --git a/tests/failpoints/cases/test_merge.rs b/tests/failpoints/cases/test_merge.rs index b56490435c9..b07e497bd43 100644 --- a/tests/failpoints/cases/test_merge.rs +++ b/tests/failpoints/cases/test_merge.rs @@ -10,7 +10,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use engine_traits::{Peekable, CF_RAFT}; use grpcio::{ChannelBuilder, Environment}; use kvproto::{ @@ -1307,7 +1306,7 @@ fn test_prewrite_before_max_ts_is_synced() { let channel = ChannelBuilder::new(env).connect(&addr); let client = TikvClient::new(channel); - let do_prewrite = |cluster: &mut Cluster>| { + let do_prewrite = |cluster: &mut Cluster| { let region_id = right.get_id(); let leader = cluster.leader_of_region(region_id).unwrap(); let epoch = cluster.get_region_epoch(region_id); diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index e14ed2c6f82..c6b335a6e63 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -7,8 +7,7 @@ use std::{ use engine_rocks::RocksSstWriterBuilder; use engine_traits::{ - CacheRegion, EvictReason, RangeCacheEngine, SnapshotContext, SstWriter, SstWriterBuilder, - CF_DEFAULT, CF_WRITE, + CacheRegion, EvictReason, RangeCacheEngine, SstWriter, SstWriterBuilder, CF_DEFAULT, }; use file_system::calc_crc32_bytes; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; @@ -16,22 +15,58 @@ use kvproto::{ import_sstpb::SstMeta, raft_cmdpb::{CmdType, RaftCmdRequest, RaftRequestHeader, Request}, }; +use protobuf::Message; use range_cache_memory_engine::test_util::new_region; use tempfile::tempdir; +use test_coprocessor::{handle_request, init_data_with_details_pd_client, DagSelect, ProductTable}; use test_raftstore::{ - make_cb, new_node_cluster_with_hybrid_engine_with_no_range_cache, new_peer, new_put_cmd, - new_request, Cluster, HybridEngineImpl, NodeCluster, Simulator, + get_tso, new_peer, new_server_cluster_with_hybrid_engine_with_no_range_cache, Cluster, + ServerCluster, }; -use tikv_util::HandyRwLock; +use tikv_util::{mpsc::unbounded, HandyRwLock}; +use tipb::SelectResponse; use txn_types::Key; +fn must_copr_point_get(cluster: &mut Cluster, table: &ProductTable, row_id: i64) { + let key = table.get_table_prefix(); + let table_key = Key::from_raw(&key).into_encoded(); + let ctx = cluster.get_ctx(&table_key); + let endpoint = cluster.sim.rl().copr_endpoints[&1].clone(); + let key_range = table.get_record_range_one(row_id); + let req = DagSelect::from(table) + .key_ranges(vec![key_range]) + .build_with(ctx, &[0]); + let cop_resp = handle_request(&endpoint, req); + let mut resp = SelectResponse::default(); + resp.merge_from_bytes(cop_resp.get_data()).unwrap(); + assert!(!cop_resp.has_region_error(), "{:?}", cop_resp); + assert!(cop_resp.get_other_error().is_empty(), "{:?}", cop_resp); +} + +fn must_copr_load_data(cluster: &mut Cluster, table: &ProductTable, row_id: i64) { + let key = table.get_table_prefix(); + let table_key = Key::from_raw(&key).into_encoded(); + let ctx = cluster.get_ctx(&table_key); + let engine = cluster.sim.rl().storages[&1].clone(); + let _ = init_data_with_details_pd_client( + ctx.clone(), + engine, + table, + &[(row_id, Some(&format!("name:{}", row_id)), row_id)], + true, + &cluster.cfg.tikv.server, + Some(cluster.pd_client.clone()), + ); +} + #[test] -fn test_basic_put_get() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); +fn test_put_copr_get() { + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.cfg.raft_store.apply_batch_system.pool_size = 1; cluster.run(); - let range_cache_engine = cluster.get_range_cache_engine(1); + let current_ts = get_tso(&cluster.pd_client); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); // FIXME: load is not implemented, so we have to insert range manually { let region = cluster.get_region(b"k"); @@ -39,49 +74,46 @@ fn test_basic_put_get() { let mut core = range_cache_engine.core().write(); core.mut_range_manager() .new_region(CacheRegion::from_region(®ion)); - core.mut_range_manager().set_safe_point(rid, 1000); + core.mut_range_manager().set_safe_point(rid, current_ts); } - cluster.put(b"k05", b"val").unwrap(); - let snap_ctx = SnapshotContext { - read_ts: 1001, - region: None, - }; - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { + let product = ProductTable::new(); + must_copr_load_data(&mut cluster, &product, 1); + let (tx, rx) = unbounded(); + fail::cfg_callback("on_range_cache_iterator_seek", move || { tx.send(true).unwrap(); }) .unwrap(); - let val = cluster.get_with_snap_ctx(b"k05", false, snap_ctx).unwrap(); - assert_eq!(&val, b"val"); + must_copr_point_get(&mut cluster, &product, 1); // verify it's read from range cache engine - assert!(rx.try_recv().unwrap()); + rx.try_recv().unwrap(); } #[test] fn test_load() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.cfg.raft_store.apply_batch_system.pool_size = 2; cluster.run(); - for i in (0..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); + let mut tables = vec![]; + for _ in 0..3 { + let product = ProductTable::new(); + tables.push(product.clone()); + must_copr_load_data(&mut cluster, &product, 1); } - let r = cluster.get_region(b""); - let split_key1 = format!("key-{:04}", 10).into_bytes(); - cluster.must_split(&r, &split_key1); - let r = cluster.get_region(&split_key1); - let split_key2 = format!("key-{:04}", 20).into_bytes(); - cluster.must_split(&r, &split_key2); - let (tx, rx) = sync_channel(1); + let mut split_keys = vec![]; + for table in &tables[1..] { + let key = table.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let r = cluster.get_region(&split_key); + cluster.must_split(&r, &split_key); + split_keys.push(split_key); + } + + let (tx, rx) = unbounded(); fail::cfg_callback("on_snapshot_load_finished", move || { tx.send(true).unwrap(); }) @@ -90,9 +122,9 @@ fn test_load() { // load range { let r = cluster.get_region(b""); - let r1 = cluster.get_region(&split_key1); - let r2 = cluster.get_region(&split_key2); - let range_cache_engine = cluster.get_range_cache_engine(1); + let r1 = cluster.get_region(&split_keys[0]); + let r2 = cluster.get_region(&split_keys[1]); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); core.mut_range_manager() .load_region(CacheRegion::from_region(&r)) @@ -106,13 +138,8 @@ fn test_load() { } // put key to trigger load task - for i in &[0, 10, 20] { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); + for table in &tables { + must_copr_load_data(&mut cluster, table, 1); } // ensure the snapshot is loaded @@ -120,62 +147,33 @@ fn test_load() { rx.recv_timeout(Duration::from_secs(5)).unwrap(); rx.recv_timeout(Duration::from_secs(5)).unwrap(); - for i in (1..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); - } - - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { + let (tx, rx) = unbounded(); + fail::cfg_callback("on_range_cache_iterator_seek", move || { tx.send(true).unwrap(); }) .unwrap(); - let snap_ctx = SnapshotContext { - read_ts: 20, - region: None, - }; + for table in &tables { + must_copr_point_get(&mut cluster, table, 1); - for i in 0..30 { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - let val = cluster - .get_cf_with_snap_ctx(CF_WRITE, &encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-write"); - // verify it's read from range cache engine - assert!(rx.try_recv().unwrap()); - - let val = cluster - .get_with_snap_ctx(&encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-default"); // verify it's read from range cache engine assert!(rx.try_recv().unwrap()); } } -#[test] // It tests that after we schedule the pending range to load snapshot, the range // splits. +#[test] fn test_load_with_split() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.cfg.raft_store.apply_batch_system.pool_size = 2; cluster.run(); - for i in (0..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); + let mut tables = vec![]; + for _ in 0..3 { + let product = ProductTable::new(); + tables.push(product.clone()); + must_copr_load_data(&mut cluster, &product, 1); } let (tx, rx) = sync_channel(0); @@ -190,7 +188,7 @@ fn test_load_with_split() { // load range { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. @@ -204,92 +202,100 @@ fn test_load_with_split() { // Now, the snapshot load is finished, and blocked before consuming cached // write batches. Let split the range. - let r = cluster.get_region(b""); - let split_key1 = format!("key-{:04}", 10).into_bytes(); - cluster.must_split(&r, &split_key1); - let r = cluster.get_region(&split_key1); - let split_key2 = format!("key-{:04}", 20).into_bytes(); - cluster.must_split(&r, &split_key2); - // Now, we have 3 regions: [min, 10), [10, 20), [20, max) - - for i in (1..30).step_by(2) { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - cluster.must_put(&encoded_key, b"val-default"); - cluster.must_put_cf(CF_WRITE, &encoded_key, b"val-write"); + for table in &tables[1..] { + let key = table.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let r = cluster.get_region(&split_key); + cluster.must_split(&r, &split_key); + } + // Now, we have 3 regions: [min, table1), [table1, table2), [table2, max) + + for table in &tables { + must_copr_load_data(&mut cluster, table, 1); } // unblock loading task tx2.send(true).unwrap(); - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { + let (tx, rx) = unbounded(); + fail::cfg_callback("on_range_cache_iterator_seek", move || { tx.send(true).unwrap(); }) .unwrap(); - let snap_ctx = SnapshotContext { - read_ts: 20, - region: None, - }; - - for i in 0..30 { - let key = format!("key-{:04}", i); - let encoded_key = Key::from_raw(key.as_bytes()) - .append_ts(20.into()) - .into_encoded(); - let val = cluster - .get_cf_with_snap_ctx(CF_WRITE, &encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-write"); - // verify it's read from range cache engine - assert!(rx.try_recv().unwrap()); + for table in &tables { + must_copr_point_get(&mut cluster, table, 1); - let val = cluster - .get_with_snap_ctx(&encoded_key, false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"val-default"); // verify it's read from range cache engine assert!(rx.try_recv().unwrap()); } } // It tests race between split and load. -// Takes k1-k10 as an example: -// We want to load k1-k10 where k1-k10 is already split into k1-k5, and k5-k10. -// And before we `load_region` k1-k10, k1-k5 has cached some writes, say k1, in -// write_batch which means k1 cannot be loaded from snapshot. Now, `load_region` -// k1-k10 is called, and k5-k10 calls prepare_for_apply and the snapshot is -// acquired and load task of k1-k10 is scheduled. We will loss data of k1 before -// this PR. +// Takes table1-table2 as an example: +// We want to load table1-table2 where table1-table2 is already split into +// ["", table2), and [table2, ""). +// And before we `load_region` table1-table2, ["", table2) has cached some +// writes, say table1_1, in write_batch which means table1_1 cannot be loaded +// from snapshot. Now, `load_region` table1-table2 is called, and [table2, "") +// calls prepare_for_apply and the snapshot is acquired and load task of +// table1-table2 is scheduled. #[test] fn test_load_with_split2() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.cfg.raft_store.apply_batch_system.pool_size = 4; cluster.run(); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - cluster.must_put(b"k01", b"val"); - cluster.must_put(b"k10", b"val"); - - let r = cluster.get_region(b""); - cluster.must_split(&r, b"k05"); + let product1 = ProductTable::new(); + let product2 = ProductTable::new(); - let r_split = cluster.get_region(b"k05"); + for table in [&product1, &product2] { + must_copr_load_data(&mut cluster, table, 1); + } - fail::cfg("on_handle_put", "pause").unwrap(); - let write_req = make_write_req(&mut cluster, b"k02"); - let (cb, _) = make_cb::(&write_req); - cluster - .sim - .rl() - .async_command_on_node(1, write_req, cb) - .unwrap(); + let key = product2.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let r = cluster.get_region(&split_key); + cluster.must_split(&r, &split_key); + let r_split = cluster.get_region(&split_key); + + let (handle_put_tx, handle_put_rx) = unbounded(); + let (handle_put_pause_tx, handle_put_pause_rx) = unbounded::<()>(); + fail::cfg_callback("on_handle_put", move || { + handle_put_tx.send(()).unwrap(); + let _ = handle_put_pause_rx.recv(); + }) + .unwrap(); + let mut async_put = |table: &ProductTable, row_id| { + let engine = cluster.sim.rl().storages[&1].clone(); + let cfg = cluster.cfg.tikv.server.clone(); + let pd_client = cluster.pd_client.clone(); + let key = table.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let ctx = cluster.get_ctx(&split_key); + let table_ = table.clone(); + let (tx, rx) = unbounded(); + let handle = std::thread::spawn(move || { + tx.send(()).unwrap(); + let _ = init_data_with_details_pd_client( + ctx, + engine, + &table_, + &[(row_id, Some(&format!("name:{}", row_id)), row_id)], + true, + &cfg, + Some(pd_client), + ); + }); + rx.recv_timeout(Duration::from_secs(5)).unwrap(); + handle + }; + let handle1 = async_put(&product1, 2); + handle_put_rx.recv_timeout(Duration::from_secs(5)).unwrap(); std::thread::sleep(Duration::from_secs(1)); { - let range_cache_engine = cluster.get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); // try to load a region with old epoch and bigger range, // it should be updated to the real region range. @@ -304,17 +310,13 @@ fn test_load_with_split2() { }) .unwrap(); - let write_req = make_write_req(&mut cluster, b"k09"); - let (cb2, _) = make_cb::(&write_req); - cluster - .sim - .rl() - .async_command_on_node(1, write_req, cb2) - .unwrap(); + let handle2 = async_put(&product2, 9); let _ = rx.recv_timeout(Duration::from_secs(5)).unwrap(); + drop(handle_put_pause_tx); + { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let core = range_cache_engine.core().read(); let meta = core.range_manager().region_meta(r_split.id).unwrap(); let split_range = CacheRegion::from_region(&r_split); @@ -323,56 +325,40 @@ fn test_load_with_split2() { fail::remove("on_handle_put"); std::thread::sleep(Duration::from_secs(1)); + handle1.join().unwrap(); + handle2.join().unwrap(); - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { + let (tx, rx) = unbounded(); + fail::cfg_callback("on_range_cache_iterator_seek", move || { tx.send(true).unwrap(); }) .unwrap(); - let snap_ctx = SnapshotContext { - read_ts: 20, - region: None, - }; - - let _ = cluster - .get_with_snap_ctx(b"k09", false, snap_ctx.clone()) - .unwrap(); + must_copr_point_get(&mut cluster, &product2, 9); assert!(rx.try_recv().unwrap()); - // k1-k5 should not cached. - let _ = cluster - .get_with_snap_ctx(b"k02", false, snap_ctx.clone()) - .unwrap(); + // ["", table2) should not cached. + must_copr_load_data(&mut cluster, &product1, 3); + let (tx, rx) = unbounded(); + fail::remove("on_range_cache_iterator_seek"); + fail::cfg_callback("on_range_cache_iterator_seek", move || { + tx.send(true).unwrap(); + }) + .unwrap(); + must_copr_point_get(&mut cluster, &product1, 2); rx.try_recv().unwrap_err(); } -fn make_write_req( - cluster: &mut Cluster>, - k: &[u8], -) -> RaftCmdRequest { - let r = cluster.get_region(k); - let mut req = new_request( - r.get_id(), - r.get_region_epoch().clone(), - vec![new_put_cmd(k, b"v")], - false, - ); - let leader = cluster.leader_of_region(r.get_id()).unwrap(); - req.mut_header().set_peer(leader); - req -} - +// It tests that for a apply delegate, at the time it prepares to apply +// something, the range of it is in pending range. When it begins to write the +// write batch to engine, the range has finished the loading, became a normal +// range, and even been evicted. #[test] -// It tests that for a apply delete, at the time it prepares to apply something, -// the range of it is in pending range. When it begins to write the write batch -// to engine, the range has finished the loading, became a normal range, and -// even been evicted. fn test_load_with_eviction() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.run(); // load range { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. @@ -380,28 +366,40 @@ fn test_load_with_eviction() { core.mut_range_manager().load_region(cache_range).unwrap(); } - let r = cluster.get_region(b""); - cluster.must_split(&r, b"k10"); - - fail::cfg("on_write_impl", "pause").unwrap(); - let write_req = make_write_req(&mut cluster, b"k01"); - let (cb, mut cb_rx) = make_cb::(&write_req); - cluster - .sim - .rl() - .async_command_on_node(1, write_req, cb) - .unwrap(); - - let write_req = make_write_req(&mut cluster, b"k15"); - let (cb, mut cb_rx2) = make_cb::(&write_req); - cluster - .sim - .rl() - .async_command_on_node(1, write_req, cb) - .unwrap(); + let product1 = ProductTable::new(); + let product2 = ProductTable::new(); + + let key = product2.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let r = cluster.get_region(&split_key); + cluster.must_split(&r, &split_key); + + fail::cfg("on_range_cache_write_batch_write_impl", "pause").unwrap(); + let mut async_put = |table: &ProductTable, row_id| { + let engine = cluster.sim.rl().storages[&1].clone(); + let cfg = cluster.cfg.tikv.server.clone(); + let pd_client = cluster.pd_client.clone(); + let key = table.get_table_prefix(); + let split_key = Key::from_raw(&key).into_encoded(); + let ctx = cluster.get_ctx(&split_key); + let table_ = table.clone(); + std::thread::spawn(move || { + let _ = init_data_with_details_pd_client( + ctx, + engine, + &table_, + &[(row_id, Some(&format!("name:{}", row_id)), row_id)], + true, + &cfg, + Some(pd_client), + ); + }) + }; + let handle1 = async_put(&product1, 1); + let handle2 = async_put(&product2, 15); { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut tried_count = 0; while range_cache_engine .snapshot(CacheRegion::from_region(&r), u64::MAX, u64::MAX) @@ -412,40 +410,44 @@ fn test_load_with_eviction() { tried_count += 1; } // Now, the range ["", "") should be cached - let region = new_region(1, b"k10", ""); + let region = new_region(1, split_key, ""); range_cache_engine.evict_region(&CacheRegion::from_region(®ion), EvictReason::AutoEvict); } - fail::remove("on_write_impl"); - let _ = cb_rx.recv_timeout(Duration::from_secs(5)); - let _ = cb_rx2.recv_timeout(Duration::from_secs(5)); + fail::remove("on_range_cache_write_batch_write_impl"); + handle1.join().unwrap(); + handle2.join().unwrap(); - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { - tx.send(true).unwrap(); - }) - .unwrap(); - - let snap_ctx = SnapshotContext { - read_ts: u64::MAX, - region: None, - }; - let val = cluster - .get_cf_with_snap_ctx(CF_DEFAULT, b"k01", false, snap_ctx.clone()) + for (table, is_cached) in &[(product1, true), (product2, false)] { + fail::remove("on_range_cache_iterator_seek"); + let (tx, rx) = unbounded(); + fail::cfg_callback("on_range_cache_iterator_seek", move || { + tx.send(true).unwrap(); + }) .unwrap(); - assert_eq!(&val, b"v"); - assert!(rx.try_recv().unwrap()); - let val = cluster - .get_cf_with_snap_ctx(CF_DEFAULT, b"k15", false, snap_ctx.clone()) - .unwrap(); - assert_eq!(&val, b"v"); - rx.try_recv().unwrap_err(); + let key = table.get_table_prefix(); + let table_key = Key::from_raw(&key).into_encoded(); + let ctx = cluster.get_ctx(&table_key); + let endpoint = cluster.sim.rl().copr_endpoints[&1].clone(); + let req = DagSelect::from(table).build_with(ctx, &[0]); + let cop_resp = handle_request(&endpoint, req); + let mut resp = SelectResponse::default(); + resp.merge_from_bytes(cop_resp.get_data()).unwrap(); + assert!(!cop_resp.has_region_error(), "{:?}", cop_resp); + assert!(cop_resp.get_other_error().is_empty(), "{:?}", cop_resp); + + if *is_cached { + rx.try_recv().unwrap(); + } else { + rx.try_recv().unwrap_err(); + } + } } #[test] fn test_evictions_after_transfer_leader() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 2); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 2); cluster.run(); let r = cluster.get_region(b""); @@ -453,7 +455,7 @@ fn test_evictions_after_transfer_leader() { let cache_region = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); let range_cache_engine = { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); core.mut_range_manager().new_region(cache_region.clone()); drop(core); @@ -472,7 +474,7 @@ fn test_evictions_after_transfer_leader() { #[test] fn test_eviction_after_merge() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.run(); let r = cluster.get_region(b""); cluster.must_split(&r, b"key1"); @@ -483,7 +485,7 @@ fn test_eviction_after_merge() { let range2 = CacheRegion::from_region(&r2); let range_cache_engine = { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); core.mut_range_manager().new_region(range1.clone()); core.mut_range_manager().new_region(range2.clone()); @@ -507,7 +509,7 @@ fn test_eviction_after_merge() { #[test] fn test_eviction_after_ingest_sst() { - let mut cluster = new_node_cluster_with_hybrid_engine_with_no_range_cache(0, 1); + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.run(); // Generate a sst file. @@ -523,7 +525,7 @@ fn test_eviction_after_ingest_sst() { let region = cluster.get_region(b""); let cache_region = CacheRegion::from_region(®ion); let range_cache_engine = { - let range_cache_engine = cluster.get_range_cache_engine(1); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); let mut core = range_cache_engine.core().write(); core.mut_range_manager().new_region(cache_region.clone()); drop(core); @@ -549,7 +551,7 @@ fn test_eviction_after_ingest_sst() { sst_meta.cf_name = CF_DEFAULT.to_owned(); // Prepare ingest. - let importer = cluster.sim.rl().get_importer(1).unwrap(); + let importer = cluster.sim.rl().importers.get(&1).unwrap().clone(); let mut f = importer.create(&sst_meta).unwrap(); f.append(&content).unwrap(); f.finish().unwrap(); diff --git a/tests/failpoints/cases/test_rawkv.rs b/tests/failpoints/cases/test_rawkv.rs index 38fea57874c..12ec2d4d4ee 100644 --- a/tests/failpoints/cases/test_rawkv.rs +++ b/tests/failpoints/cases/test_rawkv.rs @@ -3,7 +3,6 @@ use std::{sync::Arc, thread, time::Duration}; use causal_ts::{CausalTsProvider, CausalTsProviderImpl}; -use engine_rocks::RocksEngine; use futures::executor::block_on; use grpcio::{ChannelBuilder, Environment}; use kvproto::{ @@ -15,7 +14,7 @@ use test_raftstore::*; use tikv_util::{time::Instant, HandyRwLock}; struct TestSuite { - pub cluster: Cluster>, + pub cluster: Cluster, api_version: ApiVersion, } diff --git a/tests/failpoints/cases/test_replica_stale_read.rs b/tests/failpoints/cases/test_replica_stale_read.rs index 30ccda4fe21..cb986250d82 100644 --- a/tests/failpoints/cases/test_replica_stale_read.rs +++ b/tests/failpoints/cases/test_replica_stale_read.rs @@ -2,31 +2,20 @@ use std::{sync::Arc, time::Duration}; -use engine_rocks::RocksEngine; use kvproto::{kvrpcpb::Op, metapb::Peer}; use pd_client::PdClient; use raft::eraftpb::MessageType; use test_pd_client::TestPdClient; use test_raftstore::*; -fn prepare_for_stale_read( - leader: Peer, -) -> ( - Cluster>, - Arc, - PeerClient, -) { +fn prepare_for_stale_read(leader: Peer) -> (Cluster, Arc, PeerClient) { prepare_for_stale_read_before_run(leader, None) } fn prepare_for_stale_read_before_run( leader: Peer, before_run: Option>, -) -> ( - Cluster>, - Arc, - PeerClient, -) { +) -> (Cluster, Arc, PeerClient) { let mut cluster = new_server_cluster(0, 3); let pd_client = Arc::clone(&cluster.pd_client); pd_client.disable_default_operator(); diff --git a/tests/failpoints/cases/test_sst_recovery.rs b/tests/failpoints/cases/test_sst_recovery.rs index 05b0badd662..da5a3da1a32 100644 --- a/tests/failpoints/cases/test_sst_recovery.rs +++ b/tests/failpoints/cases/test_sst_recovery.rs @@ -179,11 +179,8 @@ fn compact_files_to_target_level( engine.compact_files_cf(CF_DEFAULT, file_names, Some(level), 1, false) } -fn create_tikv_cluster_with_one_node_damaged() -> ( - Cluster>, - Arc, - RocksEngine, -) { +fn create_tikv_cluster_with_one_node_damaged() +-> (Cluster, Arc, RocksEngine) { let mut cluster = new_server_cluster(0, 3); let pd_client = cluster.pd_client.clone(); pd_client.disable_default_operator(); diff --git a/tests/failpoints/cases/test_stale_read.rs b/tests/failpoints/cases/test_stale_read.rs index 26da3746d7b..cd12a80de80 100644 --- a/tests/failpoints/cases/test_stale_read.rs +++ b/tests/failpoints/cases/test_stale_read.rs @@ -6,7 +6,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use kvproto::metapb::{Peer, Region}; use pd_client::PdClient; use raft::eraftpb::MessageType; @@ -84,7 +83,7 @@ fn stale_read_during_splitting(right_derive: bool) { } fn must_not_stale_read( - cluster: &mut Cluster>, + cluster: &mut Cluster, stale_key: &[u8], old_region: &Region, old_leader: &Peer, @@ -167,7 +166,7 @@ fn must_not_stale_read( } fn must_not_eq_on_key( - cluster: &mut Cluster>, + cluster: &mut Cluster, key: &[u8], value: &[u8], read_quorum: bool, diff --git a/tests/failpoints/cases/test_unsafe_recovery.rs b/tests/failpoints/cases/test_unsafe_recovery.rs index da2aa28ab6a..1ff77023b74 100644 --- a/tests/failpoints/cases/test_unsafe_recovery.rs +++ b/tests/failpoints/cases/test_unsafe_recovery.rs @@ -2,7 +2,7 @@ use std::{iter::FromIterator, sync::Arc, time::Duration}; -use engine_traits::{RaftEngineReadOnly, CF_RAFT}; +use engine_traits::{Peekable, RaftEngineReadOnly, CF_RAFT}; use futures::executor::block_on; use kvproto::{ metapb, pdpb, @@ -583,10 +583,7 @@ fn test_unsafe_recovery_apply_before_persist() { cluster.must_put(format!("k{}", i).as_bytes(), b"v2"); } - fn get_applied_index>( - cluster: &Cluster, - store_id: u64, - ) -> u64 { + fn get_applied_index(cluster: &Cluster, store_id: u64) -> u64 { let state: RaftApplyState = cluster.engines[&store_id] .kv .get_msg_cf(CF_RAFT, &keys::apply_state_key(1)) diff --git a/tests/failpoints/cases/test_witness.rs b/tests/failpoints/cases/test_witness.rs index f6fec8b35de..32a62c32219 100644 --- a/tests/failpoints/cases/test_witness.rs +++ b/tests/failpoints/cases/test_witness.rs @@ -3,7 +3,6 @@ use std::{iter::FromIterator, sync::Arc, time::Duration}; use collections::HashMap; -use engine_rocks::RocksEngine; use futures::executor::block_on; use kvproto::{metapb, raft_serverpb::RaftApplyState}; use pd_client::PdClient; @@ -522,8 +521,8 @@ fn test_non_witness_replica_read() { assert_eq!(resp.get_header().has_error(), false); } -fn must_get_error_is_witness>( - cluster: &mut Cluster, +fn must_get_error_is_witness( + cluster: &mut Cluster, region: &metapb::Region, cmd: kvproto::raft_cmdpb::Request, ) { diff --git a/tests/integrations/coprocessor/test_select.rs b/tests/integrations/coprocessor/test_select.rs index 1677d007e67..d03e2e3b1ca 100644 --- a/tests/integrations/coprocessor/test_select.rs +++ b/tests/integrations/coprocessor/test_select.rs @@ -2,7 +2,6 @@ use std::{cmp, thread, time::Duration}; -use engine_rocks::RocksEngine; use engine_traits::CF_LOCK; use kvproto::{ coprocessor::{Request, Response, StoreBatchTask, StoreBatchTaskResponse}, @@ -2214,44 +2213,43 @@ fn test_batch_request() { true, ), ]; - let prepare_req = |cluster: &mut Cluster>, - ranges: &Vec| - -> Request { - let original_range = ranges.first().unwrap(); - let key_range = product.get_record_range(original_range.start, original_range.end); - let region_key = Key::from_raw(&key_range.start); - let mut req = DagSelect::from(&product) - .key_ranges(vec![key_range]) - .build_with(ctx.clone(), &[0]); - let mut new_ctx = Context::default(); - let new_region = cluster.get_region(region_key.as_encoded()); - let leader = cluster.leader_of_region(new_region.get_id()).unwrap(); - new_ctx.set_region_id(new_region.get_id()); - new_ctx.set_region_epoch(new_region.get_region_epoch().clone()); - new_ctx.set_peer(leader); - req.set_context(new_ctx); - req.set_start_ts(100); - - let batch_handle_ranges = &ranges.as_slice()[1..]; - for handle_range in batch_handle_ranges.iter() { - let range_start_key = Key::from_raw( - &product - .get_record_range(handle_range.start, handle_range.end) - .start, - ); - let batch_region = cluster.get_region(range_start_key.as_encoded()); - let batch_leader = cluster.leader_of_region(batch_region.get_id()).unwrap(); - let batch_key_ranges = - vec![product.get_record_range(handle_range.start, handle_range.end)]; - let mut store_batch_task = StoreBatchTask::new(); - store_batch_task.set_region_id(batch_region.get_id()); - store_batch_task.set_region_epoch(batch_region.get_region_epoch().clone()); - store_batch_task.set_peer(batch_leader); - store_batch_task.set_ranges(batch_key_ranges.into()); - req.tasks.push(store_batch_task); - } - req - }; + let prepare_req = + |cluster: &mut Cluster, ranges: &Vec| -> Request { + let original_range = ranges.first().unwrap(); + let key_range = product.get_record_range(original_range.start, original_range.end); + let region_key = Key::from_raw(&key_range.start); + let mut req = DagSelect::from(&product) + .key_ranges(vec![key_range]) + .build_with(ctx.clone(), &[0]); + let mut new_ctx = Context::default(); + let new_region = cluster.get_region(region_key.as_encoded()); + let leader = cluster.leader_of_region(new_region.get_id()).unwrap(); + new_ctx.set_region_id(new_region.get_id()); + new_ctx.set_region_epoch(new_region.get_region_epoch().clone()); + new_ctx.set_peer(leader); + req.set_context(new_ctx); + req.set_start_ts(100); + + let batch_handle_ranges = &ranges.as_slice()[1..]; + for handle_range in batch_handle_ranges.iter() { + let range_start_key = Key::from_raw( + &product + .get_record_range(handle_range.start, handle_range.end) + .start, + ); + let batch_region = cluster.get_region(range_start_key.as_encoded()); + let batch_leader = cluster.leader_of_region(batch_region.get_id()).unwrap(); + let batch_key_ranges = + vec![product.get_record_range(handle_range.start, handle_range.end)]; + let mut store_batch_task = StoreBatchTask::new(); + store_batch_task.set_region_id(batch_region.get_id()); + store_batch_task.set_region_epoch(batch_region.get_region_epoch().clone()); + store_batch_task.set_peer(batch_leader); + store_batch_task.set_ranges(batch_key_ranges.into()); + req.tasks.push(store_batch_task); + } + req + }; let verify_response = |result: &QueryResult, resp: &Response| { let (data, details, region_err, locked, other_err) = ( resp.get_data(), diff --git a/tests/integrations/import/util.rs b/tests/integrations/import/util.rs index 0e3701fe223..75c23f1f51f 100644 --- a/tests/integrations/import/util.rs +++ b/tests/integrations/import/util.rs @@ -13,7 +13,7 @@ use tikv_util::HandyRwLock; const CLEANUP_SST_MILLIS: u64 = 10; -pub fn new_cluster(cfg: TikvConfig) -> (Cluster>, Context) { +pub fn new_cluster(cfg: TikvConfig) -> (Cluster, Context) { let count = 1; let mut cluster = new_server_cluster(0, count); cluster.set_cfg(cfg); @@ -54,12 +54,7 @@ pub fn new_cluster_v2( pub fn open_cluster_and_tikv_import_client( cfg: Option, -) -> ( - Cluster>, - Context, - TikvClient, - ImportSstClient, -) { +) -> (Cluster, Context, TikvClient, ImportSstClient) { let cfg = cfg.unwrap_or_else(|| { let mut config = TikvConfig::default(); config.server.addr = "127.0.0.1:0".to_owned(); @@ -132,18 +127,14 @@ pub fn open_cluster_and_tikv_import_client_v2( (cluster, ctx, tikv, import) } -pub fn new_cluster_and_tikv_import_client() -> ( - Cluster>, - Context, - TikvClient, - ImportSstClient, -) { +pub fn new_cluster_and_tikv_import_client() +-> (Cluster, Context, TikvClient, ImportSstClient) { open_cluster_and_tikv_import_client(None) } pub fn new_cluster_and_tikv_import_client_tde() -> ( tempfile::TempDir, - Cluster>, + Cluster, Context, TikvClient, ImportSstClient, diff --git a/tests/integrations/raftstore/test_bootstrap.rs b/tests/integrations/raftstore/test_bootstrap.rs index ab00016722d..99ad19c21c1 100644 --- a/tests/integrations/raftstore/test_bootstrap.rs +++ b/tests/integrations/raftstore/test_bootstrap.rs @@ -6,7 +6,6 @@ use std::{ }; use concurrency_manager::ConcurrencyManager; -use engine_rocks::RocksEngine; use engine_traits::{ DbOptionsExt, Engines, MiscExt, Peekable, RaftEngine, RaftEngineReadOnly, ALL_CFS, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, @@ -29,7 +28,7 @@ use tikv_util::{ worker::{dummy_scheduler, Builder as WorkerBuilder, LazyWorker}, }; -fn test_bootstrap_idempotent>(cluster: &mut Cluster) { +fn test_bootstrap_idempotent(cluster: &mut Cluster) { // assume that there is a node bootstrap the cluster and add region in pd // successfully cluster.add_first_region().unwrap(); @@ -51,8 +50,7 @@ fn test_node_bootstrap_with_prepared_data() { let cfg = new_tikv_config(0); let (_, system) = fsm::create_raft_batch_system(&cfg.raft_store, &None); - let simulate_trans = - SimulateTransport::<_, RocksEngine>::new(ChannelTransport::::new()); + let simulate_trans = SimulateTransport::new(ChannelTransport::new()); let tmp_path = Builder::new().prefix("test_cluster").tempdir().unwrap(); let engine = engine_rocks::util::new_engine(tmp_path.path().to_str().unwrap(), ALL_CFS).unwrap(); diff --git a/tests/integrations/raftstore/test_clear_stale_data.rs b/tests/integrations/raftstore/test_clear_stale_data.rs index 69696a191d4..8010d4c956c 100644 --- a/tests/integrations/raftstore/test_clear_stale_data.rs +++ b/tests/integrations/raftstore/test_clear_stale_data.rs @@ -47,7 +47,7 @@ fn check_kv_in_all_cfs(db: &RocksEngine, i: u8, found: bool) { } } -fn test_clear_stale_data>(cluster: &mut Cluster) { +fn test_clear_stale_data(cluster: &mut Cluster) { // Disable compaction at level 0. cluster .cfg diff --git a/tests/integrations/raftstore/test_compact_after_delete.rs b/tests/integrations/raftstore/test_compact_after_delete.rs index 564676aa82d..47d10b906c7 100644 --- a/tests/integrations/raftstore/test_compact_after_delete.rs +++ b/tests/integrations/raftstore/test_compact_after_delete.rs @@ -6,7 +6,7 @@ use std::{ }; use collections::HashMap; -use engine_rocks::{raw::Range, util::get_cf_handle, RocksEngine}; +use engine_rocks::{raw::Range, util::get_cf_handle}; use engine_traits::{CachedTablet, MiscExt, CF_WRITE}; use keys::{data_key, DATA_MAX_KEY}; use test_raftstore::*; @@ -32,7 +32,7 @@ fn gen_delete_k(k: &[u8], commit_ts: TimeStamp) -> Vec { k.as_encoded().clone() } -fn test_compact_after_delete>(cluster: &mut Cluster) { +fn test_compact_after_delete(cluster: &mut Cluster) { cluster.cfg.raft_store.region_compact_check_interval = ReadableDuration::millis(100); cluster.cfg.raft_store.region_compact_min_tombstones = 500; cluster.cfg.raft_store.region_compact_tombstones_percent = 50; diff --git a/tests/integrations/raftstore/test_compact_lock_cf.rs b/tests/integrations/raftstore/test_compact_lock_cf.rs index 2f3f882927e..fbc7629c73f 100644 --- a/tests/integrations/raftstore/test_compact_lock_cf.rs +++ b/tests/integrations/raftstore/test_compact_lock_cf.rs @@ -1,21 +1,17 @@ // Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0. -use engine_rocks::{raw::DBStatisticsTickerType, RocksEngine}; +use engine_rocks::raw::DBStatisticsTickerType; use engine_traits::{MiscExt, CF_LOCK}; use test_raftstore::*; use tikv_util::config::*; -fn flush>(cluster: &mut Cluster) { +fn flush(cluster: &mut Cluster) { for engines in cluster.engines.values() { engines.kv.flush_cf(CF_LOCK, true).unwrap(); } } -fn flush_then_check>( - cluster: &mut Cluster, - interval: u64, - written: bool, -) { +fn flush_then_check(cluster: &mut Cluster, interval: u64, written: bool) { flush(cluster); // Wait for compaction. sleep_ms(interval * 2); @@ -30,7 +26,7 @@ fn flush_then_check>( } } -fn test_compact_lock_cf>(cluster: &mut Cluster) { +fn test_compact_lock_cf(cluster: &mut Cluster) { let interval = 500; // Set lock_cf_compact_interval. cluster.cfg.raft_store.lock_cf_compact_interval = ReadableDuration::millis(interval); diff --git a/tests/integrations/raftstore/test_compact_log.rs b/tests/integrations/raftstore/test_compact_log.rs index fcafec4a82e..bc097dd27e9 100644 --- a/tests/integrations/raftstore/test_compact_log.rs +++ b/tests/integrations/raftstore/test_compact_log.rs @@ -1,13 +1,12 @@ // Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0. use collections::HashMap; -use engine_rocks::RocksEngine; use kvproto::raft_serverpb::RaftApplyState; use raftstore::store::*; use test_raftstore::*; use tikv_util::config::*; -fn test_compact_log>(cluster: &mut Cluster) { +fn test_compact_log(cluster: &mut Cluster) { cluster.run(); let mut before_states = HashMap::default(); @@ -43,7 +42,7 @@ fn test_compact_log>(cluster: &mut Cluster>(cluster: &mut Cluster) { +fn test_compact_count_limit(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_log_gc_count_limit = Some(100); cluster.cfg.raft_store.raft_log_gc_threshold = 500; cluster.cfg.raft_store.raft_log_gc_size_limit = Some(ReadableSize::mb(20)); @@ -108,7 +107,7 @@ fn test_compact_count_limit>(cluster: &mut Cluster>(cluster: &mut Cluster) { +fn test_compact_many_times(cluster: &mut Cluster) { let gc_limit: u64 = 100; cluster.cfg.raft_store.raft_log_gc_count_limit = Some(gc_limit); cluster.cfg.raft_store.raft_log_gc_threshold = 500; @@ -177,7 +176,7 @@ fn test_node_compact_many_times() { test_compact_many_times(&mut cluster); } -fn test_compact_size_limit>(cluster: &mut Cluster) { +fn test_compact_size_limit(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_log_gc_count_limit = Some(100000); cluster.cfg.raft_store.raft_log_gc_size_limit = Some(ReadableSize::mb(1)); cluster.run(); @@ -252,9 +251,7 @@ fn test_node_compact_size_limit() { test_compact_size_limit(&mut cluster); } -fn test_compact_reserve_max_ticks>( - cluster: &mut Cluster, -) { +fn test_compact_reserve_max_ticks(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_log_gc_count_limit = Some(100); cluster.cfg.raft_store.raft_log_gc_threshold = 500; cluster.cfg.raft_store.raft_log_gc_size_limit = Some(ReadableSize::mb(20)); diff --git a/tests/integrations/raftstore/test_early_apply.rs b/tests/integrations/raftstore/test_early_apply.rs index ec42ceda52d..c6b9f3910fe 100644 --- a/tests/integrations/raftstore/test_early_apply.rs +++ b/tests/integrations/raftstore/test_early_apply.rs @@ -2,7 +2,6 @@ use std::time::Duration; -use engine_rocks::RocksEngine; use engine_traits::{RaftEngine, RaftEngineDebug}; use kvproto::raft_serverpb::RaftLocalState; use raft::eraftpb::MessageType; @@ -44,14 +43,10 @@ enum DataLost { AllLost, } -fn test( - cluster: &mut Cluster>, - action: A, - check: C, - mode: DataLost, -) where - A: FnOnce(&mut Cluster>), - C: FnOnce(&mut Cluster>), +fn test(cluster: &mut Cluster, action: A, check: C, mode: DataLost) +where + A: FnOnce(&mut Cluster), + C: FnOnce(&mut Cluster), { let filter = match mode { DataLost::AllLost | DataLost::LeaderCommit => RegionPacketFilter::new(1, 1) diff --git a/tests/integrations/raftstore/test_flashback.rs b/tests/integrations/raftstore/test_flashback.rs index d6ba8c62629..ee19a99bcdd 100644 --- a/tests/integrations/raftstore/test_flashback.rs +++ b/tests/integrations/raftstore/test_flashback.rs @@ -555,11 +555,9 @@ trait ClusterI { ) -> raftstore::Result; } -impl ClusterI for Cluster> { +impl ClusterI for Cluster { fn region_local_state(&self, region_id: u64, store_id: u64) -> RegionLocalState { - Cluster::>::region_local_state( - self, region_id, store_id, - ) + Cluster::::region_local_state(self, region_id, store_id) } fn query_leader( &self, @@ -567,16 +565,14 @@ impl ClusterI for Cluster> { region_id: u64, timeout: Duration, ) -> Option { - Cluster::>::query_leader( - self, store_id, region_id, timeout, - ) + Cluster::::query_leader(self, store_id, region_id, timeout) } fn call_command( &self, request: RaftCmdRequest, timeout: Duration, ) -> raftstore::Result { - Cluster::>::call_command(self, request, timeout) + Cluster::::call_command(self, request, timeout) } } diff --git a/tests/integrations/raftstore/test_joint_consensus.rs b/tests/integrations/raftstore/test_joint_consensus.rs index e682aa9a656..55def7a099b 100644 --- a/tests/integrations/raftstore/test_joint_consensus.rs +++ b/tests/integrations/raftstore/test_joint_consensus.rs @@ -2,7 +2,6 @@ use std::{sync::Arc, time::*}; -use engine_rocks::RocksEngine; use kvproto::{ metapb::{self, PeerRole, Region}, raft_cmdpb::{ChangePeerRequest, RaftCmdRequest, RaftCmdResponse}, @@ -474,12 +473,12 @@ fn test_leader_down_in_joint_state() { } fn call_conf_change_v2( - cluster: &mut Cluster, + cluster: &mut Cluster, region_id: u64, changes: Vec, ) -> Result where - T: Simulator, + T: Simulator, { let conf_change = new_change_peer_v2_request(changes); let epoch = cluster.pd_client.get_region_epoch(region_id); @@ -488,13 +487,13 @@ where } fn call_conf_change( - cluster: &mut Cluster, + cluster: &mut Cluster, region_id: u64, conf_change_type: ConfChangeType, peer: metapb::Peer, ) -> Result where - T: Simulator, + T: Simulator, { let conf_change = new_change_peer_request(conf_change_type, peer); let epoch = cluster.pd_client.get_region_epoch(region_id); @@ -502,9 +501,9 @@ where cluster.call_command_on_leader(admin_req, Duration::from_secs(3)) } -fn leave_joint(cluster: &mut Cluster, region_id: u64) -> Result +fn leave_joint(cluster: &mut Cluster, region_id: u64) -> Result where - T: Simulator, + T: Simulator, { call_conf_change_v2(cluster, region_id, vec![]) } diff --git a/tests/integrations/raftstore/test_lease_read.rs b/tests/integrations/raftstore/test_lease_read.rs index de2f0196d48..42ebc07c6f5 100644 --- a/tests/integrations/raftstore/test_lease_read.rs +++ b/tests/integrations/raftstore/test_lease_read.rs @@ -113,7 +113,6 @@ macro_rules! test_renew_lease { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_one_node_renew_lease() { let count = 1; let mut cluster = new_cluster(0, count); @@ -122,7 +121,6 @@ fn test_one_node_renew_lease() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_renew_lease() { let count = 3; let mut cluster = new_cluster(0, count); @@ -134,7 +132,6 @@ fn test_node_renew_lease() { // the old leader will fail to renew its lease. #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_lease_expired() { let count = 3; let mut cluster = new_cluster(0, count); @@ -175,7 +172,6 @@ fn test_node_lease_expired() { // the lease as usual. #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_lease_unsafe_during_leader_transfers() { let count = 3; let mut cluster = new_cluster(0, count); @@ -586,7 +582,6 @@ fn test_read_index_stale_in_suspect_lease() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_local_read_cache() { let mut cluster = new_cluster(0, 3); configure_for_lease_read(&mut cluster.cfg, Some(50), None); @@ -740,7 +735,6 @@ fn test_read_index_after_write() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_infinite_lease() { let mut cluster = new_cluster(0, 3); // Avoid triggering the log compaction in this test case. @@ -799,7 +793,6 @@ fn test_infinite_lease() { // continuous reads should not go to hibernate. #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_local_read_renew_lease() { let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_store_max_leader_lease = ReadableDuration::millis(500); @@ -843,7 +836,6 @@ fn test_node_local_read_renew_lease() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_lease_restart_during_isolation() { let mut cluster = new_cluster(0, 3); let election_timeout = configure_for_lease_read(&mut cluster.cfg, Some(500), Some(3)); diff --git a/tests/integrations/raftstore/test_multi.rs b/tests/integrations/raftstore/test_multi.rs index b56d864e7ce..3e18d7317d6 100644 --- a/tests/integrations/raftstore/test_multi.rs +++ b/tests/integrations/raftstore/test_multi.rs @@ -6,7 +6,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use engine_traits::Peekable; use kvproto::raft_cmdpb::RaftCmdResponse; use raft::eraftpb::MessageType; @@ -17,15 +16,13 @@ use tikv::storage::{kv::SnapshotExt, Snapshot}; use tikv_util::{config::*, HandyRwLock}; use txn_types::{Key, LastChange, PessimisticLock}; -fn test_multi_base>(cluster: &mut Cluster) { +fn test_multi_base(cluster: &mut Cluster) { cluster.run(); test_multi_base_after_bootstrap(cluster); } -fn test_multi_base_after_bootstrap>( - cluster: &mut Cluster, -) { +fn test_multi_base_after_bootstrap(cluster: &mut Cluster) { let (key, value) = (b"k1", b"v1"); cluster.must_put(key, value); @@ -52,7 +49,7 @@ fn test_multi_base_after_bootstrap>( // TODO add epoch not match test cases. } -fn test_multi_leader_crash>(cluster: &mut Cluster) { +fn test_multi_leader_crash(cluster: &mut Cluster) { cluster.run(); let (key1, value1) = (b"k1", b"v1"); @@ -93,7 +90,7 @@ fn test_multi_leader_crash>(cluster: &mut Cluster>(cluster: &mut Cluster) { +fn test_multi_cluster_restart(cluster: &mut Cluster) { cluster.run(); let (key, value) = (b"k1", b"v1"); @@ -113,10 +110,7 @@ fn test_multi_cluster_restart>(cluster: &mut Cluster>( - cluster: &mut Cluster, - count: usize, -) { +fn test_multi_lost_majority(cluster: &mut Cluster, count: usize) { cluster.run(); let leader = cluster.leader_of_region(1); @@ -135,8 +129,8 @@ fn test_multi_lost_majority>( assert!(cluster.leader_of_region(1).is_none()); } -fn test_multi_random_restart>( - cluster: &mut Cluster, +fn test_multi_random_restart( + cluster: &mut Cluster, node_count: usize, restart_count: u32, ) { @@ -179,7 +173,7 @@ fn test_multi_server_base() { test_multi_base(&mut cluster) } -fn test_multi_latency>(cluster: &mut Cluster) { +fn test_multi_latency(cluster: &mut Cluster) { cluster.run(); cluster.add_send_filter(CloneFilterFactory(DelayFilter::new(Duration::from_millis( 30, @@ -201,7 +195,7 @@ fn test_multi_server_latency() { test_multi_latency(&mut cluster); } -fn test_multi_random_latency>(cluster: &mut Cluster) { +fn test_multi_random_latency(cluster: &mut Cluster) { cluster.run(); cluster.add_send_filter(CloneFilterFactory(RandomLatencyFilter::new(50))); test_multi_base_after_bootstrap(cluster); @@ -221,7 +215,7 @@ fn test_multi_server_random_latency() { test_multi_random_latency(&mut cluster); } -fn test_multi_drop_packet>(cluster: &mut Cluster) { +fn test_multi_drop_packet(cluster: &mut Cluster) { cluster.run(); cluster.add_send_filter(CloneFilterFactory(DropPacketFilter::new(30))); test_multi_base_after_bootstrap(cluster); @@ -301,9 +295,7 @@ fn test_multi_server_random_restart() { test_multi_random_restart(&mut cluster, count, 10); } -fn test_leader_change_with_uncommitted_log>( - cluster: &mut Cluster, -) { +fn test_leader_change_with_uncommitted_log(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_election_timeout_ticks = 50; // disable compact log to make test more stable. cluster.cfg.raft_store.raft_log_gc_threshold = 1000; @@ -493,9 +485,7 @@ fn test_node_leader_change_with_log_overlap() { panic!("callback has not been called after 5s."); } -fn test_read_leader_with_unapplied_log>( - cluster: &mut Cluster, -) { +fn test_read_leader_with_unapplied_log(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_election_timeout_ticks = 50; // disable compact log to make test more stable. cluster.cfg.raft_store.raft_log_gc_threshold = 1000; @@ -584,8 +574,8 @@ fn test_server_read_leader_with_unapplied_log() { test_read_leader_with_unapplied_log(&mut cluster); } -fn get_with_timeout>( - cluster: &mut Cluster, +fn get_with_timeout( + cluster: &mut Cluster, key: &[u8], read_quorum: bool, timeout: Duration, @@ -601,9 +591,7 @@ fn get_with_timeout>( cluster.call_command_on_leader(req, timeout) } -fn test_remove_leader_with_uncommitted_log>( - cluster: &mut Cluster, -) { +fn test_remove_leader_with_uncommitted_log(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_election_timeout_ticks = 50; // disable compact log to make test more stable. cluster.cfg.raft_store.raft_log_gc_threshold = 1000; @@ -729,7 +717,7 @@ fn test_node_dropped_proposal() { .expect("callback should have been called with in 5s."); } -fn test_consistency_check>(cluster: &mut Cluster) { +fn test_consistency_check(cluster: &mut Cluster) { cluster.cfg.raft_store.raft_election_timeout_ticks = 50; // disable compact log to make test more stable. cluster.cfg.raft_store.raft_log_gc_threshold = 1000; @@ -752,7 +740,7 @@ fn test_node_consistency_check() { test_consistency_check(&mut cluster); } -fn test_batch_write>(cluster: &mut Cluster) { +fn test_batch_write(cluster: &mut Cluster) { cluster.run(); let r = cluster.get_region(b""); cluster.must_split(&r, b"k3"); diff --git a/tests/integrations/raftstore/test_prevote.rs b/tests/integrations/raftstore/test_prevote.rs index c843154b121..c81b34f0435 100644 --- a/tests/integrations/raftstore/test_prevote.rs +++ b/tests/integrations/raftstore/test_prevote.rs @@ -6,7 +6,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use raft::eraftpb::MessageType; use test_raftstore::*; use tikv_util::HandyRwLock; @@ -16,10 +15,7 @@ enum FailureType<'a> { Reboot(&'a [u64]), } -fn attach_prevote_notifiers>( - cluster: &Cluster, - peer: u64, -) -> mpsc::Receiver<()> { +fn attach_prevote_notifiers(cluster: &Cluster, peer: u64) -> mpsc::Receiver<()> { // Setup a notifier let (tx, rx) = mpsc::channel(); let response_notifier = Box::new(MessageTypeNotifier::new( @@ -41,8 +37,8 @@ fn attach_prevote_notifiers>( // Validate that prevote is used in elections after partition or reboot of some // nodes. -fn test_prevote>( - cluster: &mut Cluster, +fn test_prevote( + cluster: &mut Cluster, failure_type: FailureType<'_>, leader_after_failure_id: impl Into>, detect_during_failure: impl Into>, @@ -223,7 +219,7 @@ fn test_prevote_reboot_minority_followers() { // Test isolating a minority of the cluster and make sure that the remove // themselves. -fn test_pair_isolated>(cluster: &mut Cluster) { +fn test_pair_isolated(cluster: &mut Cluster) { let region = 1; let pd_client = Arc::clone(&cluster.pd_client); @@ -250,9 +246,7 @@ fn test_server_pair_isolated() { test_pair_isolated(&mut cluster); } -fn test_isolated_follower_leader_does_not_change>( - cluster: &mut Cluster, -) { +fn test_isolated_follower_leader_does_not_change(cluster: &mut Cluster) { cluster.run(); cluster.must_transfer_leader(1, new_peer(1, 1)); cluster.must_put(b"k1", b"v1"); @@ -288,9 +282,7 @@ fn test_server_isolated_follower_leader_does_not_change() { test_isolated_follower_leader_does_not_change(&mut cluster); } -fn test_create_peer_from_pre_vote>( - cluster: &mut Cluster, -) { +fn test_create_peer_from_pre_vote(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); pd_client.disable_default_operator(); diff --git a/tests/integrations/raftstore/test_region_change_observer.rs b/tests/integrations/raftstore/test_region_change_observer.rs index 4b37e8aa962..72bbfdc9b8f 100644 --- a/tests/integrations/raftstore/test_region_change_observer.rs +++ b/tests/integrations/raftstore/test_region_change_observer.rs @@ -9,7 +9,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use kvproto::metapb::Region; use raft::StateRole; use raftstore::coprocessor::{ @@ -40,7 +39,7 @@ impl RegionChangeObserver for TestObserver { } } -fn test_region_change_observer_impl(mut cluster: Cluster>) { +fn test_region_change_observer_impl(mut cluster: Cluster) { let pd_client = Arc::clone(&cluster.pd_client); pd_client.disable_default_operator(); diff --git a/tests/integrations/raftstore/test_region_heartbeat.rs b/tests/integrations/raftstore/test_region_heartbeat.rs index 1f9b7cb1eb8..29f7e8b10dd 100644 --- a/tests/integrations/raftstore/test_region_heartbeat.rs +++ b/tests/integrations/raftstore/test_region_heartbeat.rs @@ -6,7 +6,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use test_raftstore::*; use test_raftstore_macro::test_case; use tikv_util::{ @@ -92,7 +91,7 @@ fn test_server_down_peers_without_hibernate_regions() { test_down_peers!(&mut cluster); } -fn test_pending_peers>(cluster: &mut Cluster) { +fn test_pending_peers(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); // Disable default max peer count check. pd_client.disable_default_operator(); diff --git a/tests/integrations/raftstore/test_region_info_accessor.rs b/tests/integrations/raftstore/test_region_info_accessor.rs index c02a655d649..391f57e4815 100644 --- a/tests/integrations/raftstore/test_region_info_accessor.rs +++ b/tests/integrations/raftstore/test_region_info_accessor.rs @@ -6,7 +6,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use kvproto::metapb::Region; use raft::StateRole; use raftstore::coprocessor::{RangeKey, RegionInfo, RegionInfoAccessor}; @@ -48,10 +47,7 @@ fn check_region_ranges(regions: &[(Region, StateRole)], ranges: &[(&[u8], &[u8]) }) } -fn test_region_info_accessor_impl( - cluster: &mut Cluster>, - c: &RegionInfoAccessor, -) { +fn test_region_info_accessor_impl(cluster: &mut Cluster, c: &RegionInfoAccessor) { for i in 0..9 { let k = format!("k{}", i).into_bytes(); let v = format!("v{}", i).into_bytes(); diff --git a/tests/integrations/raftstore/test_replication_mode.rs b/tests/integrations/raftstore/test_replication_mode.rs index db373106402..05e38c41935 100644 --- a/tests/integrations/raftstore/test_replication_mode.rs +++ b/tests/integrations/raftstore/test_replication_mode.rs @@ -2,14 +2,13 @@ use std::{iter::FromIterator, sync::Arc, thread, time::Duration}; -use engine_rocks::RocksEngine; use kvproto::replication_modepb::*; use pd_client::PdClient; use raft::eraftpb::ConfChangeType; use test_raftstore::*; use tikv_util::{config::*, mpsc::future, HandyRwLock}; -fn prepare_cluster() -> Cluster> { +fn prepare_cluster() -> Cluster { let mut cluster = new_server_cluster(0, 3); cluster.pd_client.disable_default_operator(); cluster.pd_client.configure_dr_auto_sync("zone"); @@ -21,7 +20,7 @@ fn prepare_cluster() -> Cluster> { cluster } -fn configure_for_snapshot(cluster: &mut Cluster>) { +fn configure_for_snapshot(cluster: &mut Cluster) { // Truncate the log quickly so that we can force sending snapshot. cluster.cfg.raft_store.raft_log_gc_tick_interval = ReadableDuration::millis(20); cluster.cfg.raft_store.raft_log_gc_count_limit = Some(2); @@ -29,13 +28,13 @@ fn configure_for_snapshot(cluster: &mut Cluster>) { +fn run_cluster(cluster: &mut Cluster) { cluster.run(); cluster.must_transfer_leader(1, new_peer(1, 1)); cluster.must_put(b"k1", b"v0"); } -fn prepare_labels(cluster: &mut Cluster>) { +fn prepare_labels(cluster: &mut Cluster) { cluster.add_label(1, "dc", "dc1"); cluster.add_label(2, "dc", "dc1"); cluster.add_label(3, "dc", "dc2"); diff --git a/tests/integrations/raftstore/test_single.rs b/tests/integrations/raftstore/test_single.rs index 4abb5ba4304..d6fef53f2cc 100644 --- a/tests/integrations/raftstore/test_single.rs +++ b/tests/integrations/raftstore/test_single.rs @@ -15,8 +15,6 @@ use tikv_util::{config::*, time::Instant}; #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_put() { let mut cluster = new_cluster(0, 1); cluster.run(); @@ -65,8 +63,6 @@ fn test_put() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_delete() { let mut cluster = new_cluster(0, 1); cluster.run(); @@ -121,8 +117,6 @@ fn test_node_not_use_delete_range() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_wrong_store_id() { let mut cluster = new_cluster(0, 1); cluster.run(); @@ -152,8 +146,6 @@ fn test_wrong_store_id() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_put_large_entry() { let mut cluster = new_cluster(0, 1); let max_size: usize = 1024; diff --git a/tests/integrations/raftstore/test_snap.rs b/tests/integrations/raftstore/test_snap.rs index 1b8e2835c88..ca1b028da18 100644 --- a/tests/integrations/raftstore/test_snap.rs +++ b/tests/integrations/raftstore/test_snap.rs @@ -12,7 +12,6 @@ use std::{ }; use collections::HashMap; -use engine_rocks::RocksEngine; use engine_traits::{Checkpointer, KvEngine, RaftEngineDebug}; use file_system::{IoOp, IoType}; use futures::executor::block_on; @@ -40,10 +39,7 @@ use tikv_util::{ HandyRwLock, }; -fn test_huge_snapshot>( - cluster: &mut Cluster, - max_snapshot_file_size: u64, -) { +fn test_huge_snapshot(cluster: &mut Cluster, max_snapshot_file_size: u64) { cluster.cfg.rocksdb.titan.enabled = Some(true); cluster.cfg.raft_store.raft_log_gc_count_limit = Some(1000); cluster.cfg.raft_store.raft_log_gc_tick_interval = ReadableDuration::millis(10); diff --git a/tests/integrations/raftstore/test_split_region.rs b/tests/integrations/raftstore/test_split_region.rs index 4b47aff6b48..28400c0ac3c 100644 --- a/tests/integrations/raftstore/test_split_region.rs +++ b/tests/integrations/raftstore/test_split_region.rs @@ -7,7 +7,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use engine_traits::{Peekable, CF_DEFAULT, CF_WRITE}; use keys::data_key; use kvproto::{ @@ -35,7 +34,6 @@ pub const REGION_SPLIT_SIZE: u64 = 30000; #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_server_base_split_region() { let test_base_split_region = |right_derive| { let count = 5; @@ -108,7 +106,6 @@ fn test_server_base_split_region() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_server_split_region_twice() { let count = 5; let mut cluster = new_cluster(0, count); @@ -160,8 +157,6 @@ fn test_server_split_region_twice() { #[test_case(test_raftstore::new_incompatible_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_auto_split_region() { let count = 5; let mut cluster = new_cluster(0, count); @@ -297,7 +292,6 @@ macro_rules! check_cluster { /// sure broadcast commit is disabled when split. #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_delay_split_region() { let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_log_gc_count_limit = Some(500); @@ -354,8 +348,6 @@ fn test_delay_split_region() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_node_split_overlap_snapshot() { let mut cluster = new_cluster(0, 3); // We use three nodes([1, 2, 3]) for this test. @@ -412,8 +404,6 @@ fn test_node_split_overlap_snapshot() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_apply_new_version_snapshot() { let mut cluster = new_cluster(0, 3); // truncate the log quickly so that we can force sending snapshot. @@ -470,7 +460,6 @@ fn test_apply_new_version_snapshot() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_server_split_with_stale_peer() { let mut cluster = new_cluster(0, 3); // disable raft log gc. @@ -544,8 +533,6 @@ fn test_server_split_with_stale_peer() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_split_region_diff_check() { let count = 1; let mut cluster = new_cluster(0, count); @@ -599,7 +586,6 @@ fn test_split_region_diff_check() { // verify the region is splitted. #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_node_split_region_after_reboot_with_config_change() { let count = 1; let mut cluster = new_cluster(0, count); @@ -643,10 +629,7 @@ fn test_node_split_region_after_reboot_with_config_change() { } } -fn test_split_epoch_not_match>( - cluster: &mut Cluster, - right_derive: bool, -) { +fn test_split_epoch_not_match(cluster: &mut Cluster, right_derive: bool) { cluster.cfg.raft_store.right_derive_when_split = right_derive; cluster.run(); let pd_client = Arc::clone(&cluster.pd_client); @@ -744,8 +727,6 @@ fn test_node_split_epoch_not_match_right_derive() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_node_quick_election_after_split() { let mut cluster = new_cluster(0, 3); @@ -784,8 +765,6 @@ fn test_node_quick_election_after_split() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_node_split_region() { let count = 5; let mut cluster = new_cluster(0, count); @@ -826,7 +805,6 @@ fn test_node_split_region() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_split_update_region_right_derive() { let mut cluster = new_cluster(0, 3); // Election timeout and max leader lease is 1s. @@ -882,7 +860,6 @@ fn test_node_split_update_region_right_derive() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_split_with_epoch_not_match() { let mut cluster = new_cluster(0, 3); let pd_client = Arc::clone(&cluster.pd_client); @@ -918,7 +895,6 @@ fn test_split_with_epoch_not_match() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_split_with_in_memory_pessimistic_locks() { let mut cluster = new_cluster(0, 3); let pd_client = Arc::clone(&cluster.pd_client); @@ -1260,7 +1236,6 @@ fn test_gen_split_check_bucket_ranges() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] -#[test_case(test_raftstore::new_server_cluster_with_hybrid_engine)] fn test_catch_up_peers_after_split() { let mut cluster = new_cluster(0, 3); let pd_client = Arc::clone(&cluster.pd_client); @@ -1331,7 +1306,6 @@ fn test_split_region_keep_records() { #[test_case(test_raftstore::new_node_cluster)] #[test_case(test_raftstore_v2::new_node_cluster)] -#[test_case(test_raftstore::new_node_cluster_with_hybrid_engine)] fn test_node_slow_split_does_not_cause_snapshot() { // We use three nodes([1, 2, 3]) for this test. let mut cluster = new_cluster(0, 3); diff --git a/tests/integrations/raftstore/test_stale_peer.rs b/tests/integrations/raftstore/test_stale_peer.rs index 5ef90e30e94..c3a765ecf3d 100644 --- a/tests/integrations/raftstore/test_stale_peer.rs +++ b/tests/integrations/raftstore/test_stale_peer.rs @@ -4,7 +4,6 @@ use std::{sync::Arc, thread, time::*}; -use engine_rocks::RocksEngine; use engine_traits::{Peekable, CF_RAFT}; use kvproto::raft_serverpb::{PeerState, RegionLocalState}; use pd_client::PdClient; @@ -31,7 +30,7 @@ use tikv_util::{config::ReadableDuration, HandyRwLock}; /// time, and it would check with pd to confirm whether it's still a member of /// the cluster. If not, it should destroy itself as a stale peer which is /// removed out already. -fn test_stale_peer_out_of_region>(cluster: &mut Cluster) { +fn test_stale_peer_out_of_region(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); // Disable default max peer number check. pd_client.disable_default_operator(); @@ -114,10 +113,7 @@ fn test_server_stale_peer_out_of_region() { /// time, and it's an initialized peer without any data. It would destroy itself /// as stale peer directly and should not impact other region data on the /// same store. -fn test_stale_peer_without_data>( - cluster: &mut Cluster, - right_derive: bool, -) { +fn test_stale_peer_without_data(cluster: &mut Cluster, right_derive: bool) { cluster.cfg.raft_store.right_derive_when_split = right_derive; let pd_client = Arc::clone(&cluster.pd_client); diff --git a/tests/integrations/raftstore/test_stats.rs b/tests/integrations/raftstore/test_stats.rs index 3b6d9434e11..34b894ed08b 100644 --- a/tests/integrations/raftstore/test_stats.rs +++ b/tests/integrations/raftstore/test_stats.rs @@ -7,7 +7,6 @@ use std::{ }; use api_version::{test_kv_format_impl, KvFormat}; -use engine_rocks::RocksEngine; use engine_traits::MiscExt; use futures::{executor::block_on, SinkExt, StreamExt}; use grpcio::*; @@ -18,7 +17,7 @@ use test_raftstore::*; use tikv_util::{config::*, store::QueryStats}; use txn_types::Key; -fn check_available>(cluster: &mut Cluster) { +fn check_available(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); let engine = cluster.get_engine(1); @@ -44,7 +43,7 @@ fn check_available>(cluster: &mut Cluster>(cluster: &mut Cluster) { +fn test_simple_store_stats(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); cluster.cfg.raft_store.pd_store_heartbeat_tick_interval = ReadableDuration::millis(20); @@ -143,14 +142,7 @@ fn test_store_heartbeat_report_hotspots() { fail::remove("mock_hotspot_threshold"); } -type Query = dyn Fn( - Context, - &Cluster>, - TikvClient, - u64, - u64, - Vec, -); +type Query = dyn Fn(Context, &Cluster, TikvClient, u64, u64, Vec); #[test] fn test_query_stats() { @@ -443,7 +435,7 @@ fn test_txn_query_stats_tmpl() { } fn raw_put( - _cluster: &Cluster>, + _cluster: &Cluster, client: &TikvClient, ctx: &Context, _store_id: u64, @@ -461,7 +453,7 @@ fn raw_put( } fn put( - cluster: &Cluster>, + cluster: &Cluster, client: &TikvClient, ctx: &Context, store_id: u64, @@ -682,7 +674,7 @@ fn test_txn_delete_query() { } fn check_query_num_read( - cluster: &Cluster>, + cluster: &Cluster, store_id: u64, region_id: u64, kind: QueryKind, @@ -708,7 +700,7 @@ fn check_query_num_read( } fn check_query_num_write( - cluster: &Cluster>, + cluster: &Cluster, store_id: u64, kind: QueryKind, expect: u64, @@ -728,7 +720,7 @@ fn check_query_num_write( } fn check_split_key( - cluster: &Cluster>, + cluster: &Cluster, start_key: Vec, end_key: Option>, ) -> bool { diff --git a/tests/integrations/raftstore/test_tombstone.rs b/tests/integrations/raftstore/test_tombstone.rs index f5c419ac65b..c1cd0befcf1 100644 --- a/tests/integrations/raftstore/test_tombstone.rs +++ b/tests/integrations/raftstore/test_tombstone.rs @@ -3,7 +3,6 @@ use std::{sync::Arc, thread, time::Duration}; use crossbeam::channel; -use engine_rocks::RocksEngine; use engine_traits::{CfNamesExt, Iterable, Peekable, RaftEngineDebug, SyncMutable, CF_RAFT}; use kvproto::raft_serverpb::{PeerState, RaftMessage, RegionLocalState, StoreIdent}; use protobuf::Message; @@ -11,7 +10,7 @@ use raft::eraftpb::MessageType; use test_raftstore::*; use tikv_util::{config::*, time::Instant}; -fn test_tombstone>(cluster: &mut Cluster) { +fn test_tombstone(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); // Disable default max peer number check. pd_client.disable_default_operator(); @@ -114,7 +113,7 @@ fn test_server_tombstone() { test_tombstone(&mut cluster); } -fn test_fast_destroy>(cluster: &mut Cluster) { +fn test_fast_destroy(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); // Disable default max peer number check. @@ -159,7 +158,7 @@ fn test_server_fast_destroy() { test_fast_destroy(&mut cluster); } -fn test_readd_peer>(cluster: &mut Cluster) { +fn test_readd_peer(cluster: &mut Cluster) { let pd_client = Arc::clone(&cluster.pd_client); // Disable default max peer number check. pd_client.disable_default_operator(); diff --git a/tests/integrations/raftstore/test_transport.rs b/tests/integrations/raftstore/test_transport.rs index cb1bcefbcad..4ed3d8da160 100644 --- a/tests/integrations/raftstore/test_transport.rs +++ b/tests/integrations/raftstore/test_transport.rs @@ -1,9 +1,8 @@ // Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0. -use engine_rocks::RocksEngine; use test_raftstore::*; -fn test_partition_write>(cluster: &mut Cluster) { +fn test_partition_write(cluster: &mut Cluster) { cluster.run(); let (key, value) = (b"k1", b"v1"); diff --git a/tests/integrations/raftstore/test_update_region_size.rs b/tests/integrations/raftstore/test_update_region_size.rs index 22a5e1f4534..f2ff0d4f217 100644 --- a/tests/integrations/raftstore/test_update_region_size.rs +++ b/tests/integrations/raftstore/test_update_region_size.rs @@ -2,19 +2,18 @@ use std::{sync::Arc, thread, time}; -use engine_rocks::RocksEngine; use engine_traits::MiscExt; use pd_client::PdClient; use test_raftstore::*; use tikv_util::config::*; -fn flush>(cluster: &mut Cluster) { +fn flush(cluster: &mut Cluster) { for engines in cluster.engines.values() { engines.kv.flush_cfs(&[], true).unwrap(); } } -fn test_update_region_size>(cluster: &mut Cluster) { +fn test_update_region_size(cluster: &mut Cluster) { cluster.cfg.raft_store.pd_heartbeat_tick_interval = ReadableDuration::millis(50); cluster.cfg.raft_store.split_region_check_tick_interval = ReadableDuration::millis(50); cluster.cfg.raft_store.region_split_check_diff = Some(ReadableSize::kb(1)); @@ -25,7 +24,7 @@ fn test_update_region_size>(cluster: &mut Cluster, mut start, end| { + let batch_put = |cluster: &mut Cluster, mut start, end| { while start < end { let next = std::cmp::min(end, start + 50); let requests = (start..next) diff --git a/tests/integrations/raftstore/test_witness.rs b/tests/integrations/raftstore/test_witness.rs index e42ac75598e..d99f8692bcc 100644 --- a/tests/integrations/raftstore/test_witness.rs +++ b/tests/integrations/raftstore/test_witness.rs @@ -7,7 +7,6 @@ use std::{ }; use collections::HashMap; -use engine_rocks::RocksEngine; use futures::executor::block_on; use kvproto::{ metapb, @@ -485,8 +484,8 @@ fn test_witness_replica_read() { ); } -fn must_get_error_is_witness>( - cluster: &mut Cluster, +fn must_get_error_is_witness( + cluster: &mut Cluster, region: &metapb::Region, cmd: kvproto::raft_cmdpb::Request, ) { diff --git a/tests/integrations/resource_metering/test_read_keys.rs b/tests/integrations/resource_metering/test_read_keys.rs index 64c291049d9..f7a4ef86906 100644 --- a/tests/integrations/resource_metering/test_read_keys.rs +++ b/tests/integrations/resource_metering/test_read_keys.rs @@ -4,7 +4,6 @@ use std::{sync::Arc, time::Duration}; use concurrency_manager::ConcurrencyManager; use crossbeam::channel::{unbounded, Receiver, RecvTimeoutError, Sender}; -use engine_rocks::RocksEngine as RocksDb; use grpcio::{ChannelBuilder, Environment}; use kvproto::{coprocessor, kvrpcpb::*, resource_usage_agent::ResourceUsageRecord, tikvpb::*}; use protobuf::Message; @@ -109,14 +108,7 @@ pub fn test_read_keys() { }); } -fn new_cluster( - port: u16, - env: Arc, -) -> ( - Cluster>, - TikvClient, - Context, -) { +fn new_cluster(port: u16, env: Arc) -> (Cluster, TikvClient, Context) { let (cluster, leader, ctx) = must_new_and_configure_cluster(|cluster| { cluster.cfg.resource_metering.receiver_address = format!("127.0.0.1:{}", port); cluster.cfg.resource_metering.precision = ReadableDuration::millis(100); diff --git a/tests/integrations/server/kv_service.rs b/tests/integrations/server/kv_service.rs index c352b5c0371..3fc08306688 100644 --- a/tests/integrations/server/kv_service.rs +++ b/tests/integrations/server/kv_service.rs @@ -11,7 +11,6 @@ use std::{ use api_version::{ApiV1, ApiV1Ttl, ApiV2, KvFormat}; use concurrency_manager::ConcurrencyManager; -use engine_rocks::RocksEngine; use engine_traits::{ MiscExt, Peekable, RaftEngine, RaftEngineReadOnly, RaftLogBatch, SyncMutable, CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE, @@ -1385,8 +1384,7 @@ fn test_double_run_node() { let mut sim = cluster.sim.wl(); let node = sim.get_node(id).unwrap(); let pd_worker = LazyWorker::new("test-pd-worker"); - let simulate_trans = - SimulateTransport::<_, RocksEngine>::new(ChannelTransport::::new()); + let simulate_trans = SimulateTransport::new(ChannelTransport::new()); let tmp = Builder::new().prefix("test_cluster").tempdir().unwrap(); let snap_mgr = SnapManager::new(tmp.path().to_str().unwrap()); let coprocessor_host = CoprocessorHost::new(router, raftstore::coprocessor::Config::default()); diff --git a/tests/integrations/server/lock_manager.rs b/tests/integrations/server/lock_manager.rs index 2d8b8d326e3..289b10303a8 100644 --- a/tests/integrations/server/lock_manager.rs +++ b/tests/integrations/server/lock_manager.rs @@ -10,7 +10,6 @@ use std::{ time::Duration, }; -use engine_rocks::RocksEngine; use grpcio::{ChannelBuilder, Environment}; use kvproto::{ kvrpcpb::*, @@ -70,10 +69,7 @@ fn deadlock(client: &TikvClient, ctx: Context, key1: &[u8], ts: u64) -> bool { resp.errors[0].has_deadlock() } -fn build_leader_client( - cluster: &mut Cluster>, - key: &[u8], -) -> (TikvClient, Context) { +fn build_leader_client(cluster: &mut Cluster, key: &[u8]) -> (TikvClient, Context) { let region_id = cluster.get_region_id(key); let leader = cluster.leader_of_region(region_id).unwrap(); let epoch = cluster.get_region_epoch(region_id); @@ -92,11 +88,7 @@ fn build_leader_client( } /// Creates a deadlock on the store containing key. -fn must_detect_deadlock( - cluster: &mut Cluster>, - key: &[u8], - ts: u64, -) { +fn must_detect_deadlock(cluster: &mut Cluster, key: &[u8], ts: u64) { // Sometimes, deadlocks can't be detected at once due to leader change, but it // will be detected. for _ in 0..5 { @@ -108,10 +100,7 @@ fn must_detect_deadlock( panic!("failed to detect deadlock"); } -fn deadlock_detector_leader_must_be( - cluster: &mut Cluster>, - store_id: u64, -) { +fn deadlock_detector_leader_must_be(cluster: &mut Cluster, store_id: u64) { let leader_region = cluster.get_region(b""); assert_eq!( cluster @@ -126,11 +115,7 @@ fn deadlock_detector_leader_must_be( .region_leader_must_be(leader_region.get_id(), leader_peer); } -fn must_transfer_leader( - cluster: &mut Cluster>, - region_key: &[u8], - store_id: u64, -) { +fn must_transfer_leader(cluster: &mut Cluster, region_key: &[u8], store_id: u64) { let region = cluster.get_region(region_key); let target_peer = find_peer_of_store(®ion, store_id); cluster.must_transfer_leader(region.get_id(), target_peer.clone()); @@ -145,7 +130,7 @@ fn must_transfer_leader( /// REQUIRE: The source store must be the leader the region and the target store /// must not have this region. fn must_transfer_region( - cluster: &mut Cluster>, + cluster: &mut Cluster, region_key: &[u8], source_store_id: u64, target_store_id: u64, @@ -164,18 +149,14 @@ fn must_transfer_region( cluster.must_put(region_key, b"v"); } -fn must_split_region( - cluster: &mut Cluster>, - region_key: &[u8], - split_key: &[u8], -) { +fn must_split_region(cluster: &mut Cluster, region_key: &[u8], split_key: &[u8]) { let region = cluster.get_region(region_key); cluster.must_split(®ion, split_key); cluster.must_put(split_key, b"v"); } fn must_merge_region( - cluster: &mut Cluster>, + cluster: &mut Cluster, source_region_key: &[u8], target_region_key: &[u8], ) { @@ -198,7 +179,7 @@ fn find_peer_of_store(region: &Region, store_id: u64) -> Peer { /// Creates a cluster with only one region and store(1) is the leader of the /// region. -fn new_cluster_for_deadlock_test(count: usize) -> Cluster> { +fn new_cluster_for_deadlock_test(count: usize) -> Cluster { let mut cluster = new_server_cluster(0, count); cluster.cfg.pessimistic_txn.wait_for_lock_timeout = ReadableDuration::millis(500); cluster.cfg.pessimistic_txn.pipelined = false; diff --git a/tests/integrations/server_encryption.rs b/tests/integrations/server_encryption.rs index 041b15fd953..7c88afde76a 100644 --- a/tests/integrations/server_encryption.rs +++ b/tests/integrations/server_encryption.rs @@ -1,9 +1,8 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. -use engine_rocks::RocksEngine; use test_raftstore::*; -fn test_snapshot_encryption>(cluster: &mut Cluster) { +fn test_snapshot_encryption(cluster: &mut Cluster) { configure_for_encryption(cluster); cluster.pd_client.disable_default_operator(); let r1 = cluster.run_conf_change(); diff --git a/tests/integrations/storage/test_raft_storage.rs b/tests/integrations/storage/test_raft_storage.rs index 1b3ba6dc43b..684b7a261fb 100644 --- a/tests/integrations/storage/test_raft_storage.rs +++ b/tests/integrations/storage/test_raft_storage.rs @@ -8,7 +8,6 @@ use std::{ use api_version::{ApiV1, KvFormat}; use collections::HashMap; -use engine_rocks::RocksEngine; use error_code::{raftstore::STALE_COMMAND, ErrorCodeExt}; use kvproto::kvrpcpb::Context; use test_raftstore::*; @@ -26,8 +25,8 @@ use tikv_util::HandyRwLock; use txn_types::{Key, Mutation, TimeStamp}; fn new_raft_storage() -> ( - Cluster>, - SyncTestStorageApiV1>, + Cluster, + SyncTestStorageApiV1, Context, ) { new_raft_storage_with_store_count::(1, "") @@ -235,7 +234,7 @@ fn write_test_data( } fn check_data( - cluster: &mut Cluster>, + cluster: &mut Cluster, storages: &HashMap>, test_data: &[(Vec, Vec)], ts: impl Into, diff --git a/tests/integrations/storage/test_raftkv.rs b/tests/integrations/storage/test_raftkv.rs index 4129d5bc721..1fb8075e10f 100644 --- a/tests/integrations/storage/test_raftkv.rs +++ b/tests/integrations/storage/test_raftkv.rs @@ -4,7 +4,6 @@ use std::{ thread, time, }; -use engine_rocks::RocksEngine as RocksDb; use engine_traits::{CfName, IterOptions, CF_DEFAULT}; use futures::executor::block_on; use kvproto::kvrpcpb::{Context, KeyRange}; @@ -324,7 +323,7 @@ fn test_invalid_read_index_when_no_leader() { true, ); request.mut_header().set_peer(follower.clone()); - let (cb, mut rx) = make_cb::(&request); + let (cb, mut rx) = make_cb(&request); cluster .sim .rl() diff --git a/tests/integrations/storage/test_region_info_accessor.rs b/tests/integrations/storage/test_region_info_accessor.rs index 1bac3d7c42e..d2d558791af 100644 --- a/tests/integrations/storage/test_region_info_accessor.rs +++ b/tests/integrations/storage/test_region_info_accessor.rs @@ -9,7 +9,6 @@ use std::{ }; use collections::HashMap; -use engine_rocks::RocksEngine; use kvproto::metapb::Region; use more_asserts::{assert_gt, assert_le}; use pd_client::{RegionStat, RegionWriteCfCopDetail}; @@ -20,9 +19,7 @@ use raftstore::coprocessor::{ use test_raftstore::*; use tikv_util::HandyRwLock; -fn prepare_cluster>( - cluster: &mut Cluster, -) -> Vec { +fn prepare_cluster(cluster: &mut Cluster) -> Vec { for i in 0..15 { let i = i + b'0'; let key = vec![b'k', i]; From a862e2729d5ff019eb0b7da13093ae4a351370f7 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 9 Sep 2024 14:12:02 +0800 Subject: [PATCH 053/144] OWNERS: Auto Sync OWNERS files from community membership (#17496) Signed-off-by: Ti Chi Robot --- OWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OWNERS b/OWNERS index 3bc3e5e32e7..f7d1f4d67bb 100644 --- a/OWNERS +++ b/OWNERS @@ -10,6 +10,7 @@ approvers: - cfzjywxk - Connor1996 - coocood + - crazycs520 - disksing - ekexium - gengliqi @@ -47,10 +48,10 @@ approvers: - zhangjinpeng87 - zhongzc - zhouqiang-cl + - zyguan reviewers: - 3pointer - CalvinNeo - - crazycs520 - ethercflow - fredchenbj - Fullstop000 @@ -74,4 +75,3 @@ reviewers: - wjhuang2016 - wshwsh12 - Xuanwo - - zyguan From a982d31c9a49b4eb8e31ffbdb978461ef9c91513 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:02:35 +0800 Subject: [PATCH 054/144] In-memory engine: provide a callback API for eviction (#17499) ref tikv/tikv#16141, close tikv/tikv#17498 provide a callback API for eviction Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 22 +++-- .../range_cache_memory_engine/src/engine.rs | 74 ++++++++++++++--- .../src/range_manager.rs | 82 ++++++++++++------- .../range_cache_memory_engine/src/read.rs | 6 +- .../src/write_batch.rs | 3 +- .../tests/failpoints/test_memory_engine.rs | 51 ++++++++++-- .../cases/test_range_cache_engine.rs | 6 +- 7 files changed, 186 insertions(+), 58 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 13b93bf8a7f..9f2b7271dfe 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -516,7 +516,7 @@ impl BackgroundRunnerCore { meta.set_safe_point(safe_point); } else { assert_eq!(meta.get_state(), RegionState::LoadingCanceled); - meta.mark_evict(RegionState::Evicting, EvictReason::LoadFailed); + meta.mark_evict(RegionState::Evicting, EvictReason::LoadFailed, None); remove_regions.push(meta.get_region().clone()); } }; @@ -573,7 +573,7 @@ impl BackgroundRunnerCore { } else { EvictReason::LoadFailedWithoutStart }; - meta.mark_evict(RegionState::Evicting, reason); + meta.mark_evict(RegionState::Evicting, reason, None); remove_regions.push(meta.get_region().clone()); }; @@ -639,9 +639,11 @@ impl BackgroundRunnerCore { } let cache_region = CacheRegion::from_region(®ion); let mut engine_wr = self.engine.write(); - let deleteable_regions = engine_wr - .mut_range_manager() - .evict_region(&cache_region, EvictReason::MemoryLimitReached); + let deleteable_regions = engine_wr.mut_range_manager().evict_region( + &cache_region, + EvictReason::MemoryLimitReached, + None, + ); if !deleteable_regions.is_empty() { info!( "ime evict on soft limit reached"; @@ -700,9 +702,11 @@ impl BackgroundRunnerCore { if self.memory_controller.reached_soft_limit() { let cache_region = CacheRegion::from_region(&evict_region); let mut core = self.engine.write(); - let deleteable_regions = core - .mut_range_manager() - .evict_region(&cache_region, EvictReason::AutoEvict); + let deleteable_regions = core.mut_range_manager().evict_region( + &cache_region, + EvictReason::AutoEvict, + None, + ); info!( "ime load_evict: soft limit reached"; "region_to_evict" => ?&cache_region, @@ -2440,7 +2444,7 @@ pub mod tests { }); assert_eq!(engine.core.read().range_manager().regions().len(), 3); - engine.evict_region(®ion2, EvictReason::AutoEvict); + engine.evict_region(®ion2, EvictReason::AutoEvict, None); assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 84ebaf031c4..e9ddff3101c 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -313,12 +313,17 @@ impl RangeCacheMemoryEngine { /// Evict a region from the in-memory engine. After this call, the region /// will not be readable, but the data of the region may not be deleted /// immediately due to some ongoing snapshots. - pub fn evict_region(&self, region: &CacheRegion, evict_reason: EvictReason) { - let deleteable_regions = self - .core - .write() - .range_manager - .evict_region(region, evict_reason); + pub fn evict_region( + &self, + region: &CacheRegion, + evict_reason: EvictReason, + cb: Option>, + ) { + let deleteable_regions = + self.core + .write() + .range_manager + .evict_region(region, evict_reason, cb); if !deleteable_regions.is_empty() { // The range can be deleted directly. if let Err(e) = self @@ -463,7 +468,7 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { fn on_region_event(&self, event: RegionEvent) { match event { RegionEvent::Eviction { region, reason } => { - self.evict_region(®ion, reason); + self.evict_region(®ion, reason, None); } RegionEvent::Split { source, @@ -485,7 +490,7 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { true }); for r in regions { - self.evict_region(&r, reason); + self.evict_region(&r, reason, None); } } } @@ -503,11 +508,17 @@ impl Iterable for RangeCacheMemoryEngine { #[cfg(test)] pub mod tests { - use std::sync::Arc; + use std::{ + sync::{mpsc::sync_channel, Arc}, + time::Duration, + }; use crossbeam::epoch; - use engine_traits::{CacheRegion, CF_DEFAULT, CF_LOCK, CF_WRITE}; - use tikv_util::config::{ReadableSize, VersionTrack}; + use engine_traits::{ + CacheRegion, EvictReason, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, + CF_LOCK, CF_WRITE, + }; + use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; use super::SkiplistEngine; use crate::{ @@ -660,4 +671,45 @@ pub mod tests { iter.next(guard); assert!(!iter.valid()); } + + #[test] + fn test_cb_on_eviction_with_on_going_snapshot() { + let mut config = RangeCacheEngineConfig::config_for_test(); + config.gc_interval = ReadableDuration(Duration::from_secs(1)); + let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(config), + ))); + + let region = new_region(1, b"", b"z"); + let cache_region = CacheRegion::from_region(®ion); + engine.new_region(region.clone()); + + let mut wb = engine.write_batch(); + wb.prepare_for_region(cache_region.clone()); + wb.set_sequence_number(10).unwrap(); + wb.put(b"a", b"val1").unwrap(); + wb.put(b"b", b"val2").unwrap(); + wb.put(b"c", b"val3").unwrap(); + wb.write().unwrap(); + + let snap = engine.snapshot(cache_region.clone(), 100, 100).unwrap(); + + let (tx, rx) = sync_channel(0); + engine.evict_region( + &cache_region, + EvictReason::BecomeFollower, + Some(Box::new(move || { + let _ = tx.send(true); + })), + ); + + rx.recv_timeout(Duration::from_secs(1)).unwrap_err(); + drop(snap); + let _ = rx.recv(); + + { + let core = engine.core().read(); + assert!(core.range_manager().region_meta(1).is_none()); + } + } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index b6a7d02266d..f820d9fe77d 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -6,6 +6,7 @@ use std::{ BTreeMap, Bound::{self, Excluded, Unbounded}, }, + fmt::Debug, result, sync::atomic::{AtomicBool, Ordering}, }; @@ -95,14 +96,23 @@ pub struct CacheRegionMeta { state: RegionState, // whether a gc task is running with this region. in_gc: bool, - // region eviction triggers info, used for logging. + // region eviction triggers info and callback when eviction finishes. evict_info: Option, } -#[derive(Debug, Clone, Copy)] struct EvictInfo { start: Instant, reason: EvictReason, + // called when eviction finishes + cb: Option>, +} + +impl Debug for EvictInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EvictInfo") + .field("reason", &self.reason) + .finish() + } } impl CacheRegionMeta { @@ -174,7 +184,12 @@ impl CacheRegionMeta { self.state = new_state; } - pub(crate) fn mark_evict(&mut self, state: RegionState, reason: EvictReason) { + pub(crate) fn mark_evict( + &mut self, + state: RegionState, + reason: EvictReason, + cb: Option>, + ) { use RegionState::*; assert_matches!(self.state, Loading | Active | LoadingCanceled); assert_matches!(state, PendingEvict | Evicting); @@ -182,6 +197,7 @@ impl CacheRegionMeta { self.evict_info = Some(EvictInfo { start: Instant::now_coarse(), reason, + cb, }); } @@ -205,7 +221,7 @@ impl CacheRegionMeta { safe_point: source_meta.safe_point, state: source_meta.state, in_gc: source_meta.in_gc, - evict_info: source_meta.evict_info, + evict_info: None, } } @@ -599,23 +615,16 @@ impl RegionManager { } /// Return ranges that can be deleted now (no ongoing snapshot). - // There are two cases based on the relationship between `evict_range` and - // cached ranges: - // 1. `evict_range` is contained(including equals) by a cached range (at most - // one due to non-overlapping in cached ranges) - // 2. `evict_range` is overlapped with (including contains but not be contained) - // one or more cached ranges - // - // For 1, if the `evict_range` is a proper subset of the cached_range, we will - // split the cached_range so that only the `evict_range` part will be evicted - // and deleted. - // - // For 2, this is caused by some special operations such as merge and delete - // range. So, conservatively, we evict all ranges overlap with it. + // If the region epoch has changed which means the region range may have + // changed, evict the regions overlapped with the range of `evict_region`. + // `cb` is called when the eviction of the region with id equaling to the id of + // `evict_region` has done. + // Note: `cb` should not do anything heavy. pub(crate) fn evict_region( &mut self, evict_region: &CacheRegion, evict_reason: EvictReason, + mut cb: Option>, ) -> Vec { info!( "ime try to evict region"; @@ -627,9 +636,11 @@ impl RegionManager { // if epoch not changed, no need to do range scan. if meta.region.epoch_version == evict_region.epoch_version { if let Some(region) = - self.do_evict_region(evict_region.id, evict_region, evict_reason) + self.do_evict_region(evict_region.id, evict_region, evict_reason, cb) { return vec![region]; + } else { + return vec![]; } } } @@ -649,7 +660,16 @@ impl RegionManager { "region" => ?evict_region); } for rid in evict_ids { - if let Some(region) = self.do_evict_region(rid, evict_region, evict_reason) { + if let Some(region) = self.do_evict_region( + rid, + evict_region, + evict_reason, + if rid == evict_region.id { + cb.take() + } else { + None + }, + ) { deleteable_regions.push(region); } } @@ -662,6 +682,7 @@ impl RegionManager { id: u64, evict_region: &CacheRegion, evict_reason: EvictReason, + cb: Option>, ) -> Option { let meta = self.regions.get_mut(&id).unwrap(); let prev_state = meta.state; @@ -688,7 +709,7 @@ impl RegionManager { } if prev_state == RegionState::Active { - meta.mark_evict(RegionState::PendingEvict, evict_reason); + meta.mark_evict(RegionState::PendingEvict, evict_reason, cb); } else { meta.set_state(RegionState::LoadingCanceled) }; @@ -718,6 +739,7 @@ impl RegionManager { } pub fn on_delete_regions(&mut self, regions: &[CacheRegion]) { + fail::fail_point!("in_memory_engine_on_delete_regions"); for r in regions { let meta = self.remove_region(r.id); assert_eq!(meta.region.epoch_version, r.epoch_version); @@ -727,6 +749,10 @@ impl RegionManager { evict_info.start.saturating_elapsed_secs(), evict_info.reason, ); + if let Some(cb) = evict_info.cb { + cb(); + } + info!( "ime range eviction done"; "region" => ?r, @@ -898,7 +924,7 @@ mod tests { let r_left = CacheRegion::new(1, 2, b"k00", b"k03"); let r_right = CacheRegion::new(3, 2, b"k06", b"k10"); range_mgr.split_region(&r1, vec![r_left.clone(), r_evict.clone(), r_right.clone()]); - range_mgr.evict_region(&r_evict, EvictReason::AutoEvict); + range_mgr.evict_region(&r_evict, EvictReason::AutoEvict, None); let meta1 = range_mgr .historical_regions .get(&KeyAndVersion(r1.end.clone(), 0)) @@ -918,7 +944,7 @@ mod tests { // evict a range with accurate match range_mgr.region_snapshot(r_left.id, 2, 10).unwrap(); let snapshot3 = RangeCacheSnapshotMeta::new(r_left.clone(), 10, 3); - range_mgr.evict_region(&r_left, EvictReason::AutoEvict); + range_mgr.evict_region(&r_left, EvictReason::AutoEvict, None); assert_eq!( range_mgr.regions.get(&r_left.id).unwrap().state, RegionState::PendingEvict, @@ -951,7 +977,7 @@ mod tests { range_mgr.new_region(r1.clone()); range_mgr.load_region(r2.clone()).unwrap(); range_mgr.new_region(r3.clone()); - range_mgr.evict_region(&r1, EvictReason::AutoEvict); + range_mgr.evict_region(&r1, EvictReason::AutoEvict, None); assert_eq!( range_mgr.load_region(r1).unwrap_err(), @@ -977,7 +1003,7 @@ mod tests { let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); - range_mgr.evict_region(&r1, EvictReason::AutoEvict); + range_mgr.evict_region(&r1, EvictReason::AutoEvict, None); range_mgr.load_region(r3).unwrap(); @@ -1020,7 +1046,7 @@ mod tests { let r4 = CacheRegion::new(4, 2, b"k00", b"k05"); assert_eq!( - range_mgr.evict_region(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict, None), vec![r1] ); } @@ -1039,7 +1065,7 @@ mod tests { let r4 = CacheRegion::new(4, 0, b"k", b"k51"); assert_eq!( - range_mgr.evict_region(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict, None), vec![r1, r2, r3] ); assert!( @@ -1061,7 +1087,7 @@ mod tests { let r4 = CacheRegion::new(4, 0, b"k25", b"k55"); assert_eq!( - range_mgr.evict_region(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict, None), vec![r2, r3] ); assert_eq!( @@ -1085,7 +1111,7 @@ mod tests { let r4 = CacheRegion::new(4, 0, b"k25", b"k75"); assert_eq!( - range_mgr.evict_region(&r4, EvictReason::AutoEvict), + range_mgr.evict_region(&r4, EvictReason::AutoEvict, None), vec![r2, r3] ); assert_eq!( diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index bb50ed110a3..b42b07a5b5e 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -1809,7 +1809,7 @@ mod tests { }); let evict_region = new_regions[1].clone(); - engine.evict_region(&evict_region, EvictReason::AutoEvict); + engine.evict_region(&evict_region, EvictReason::AutoEvict, None); assert_eq!( engine.snapshot(range.clone(), 10, 200).unwrap_err(), FailedReason::EpochNotMatch @@ -1886,7 +1886,7 @@ mod tests { }); let evict_region = new_regions[1].clone(); - engine.evict_region(&evict_region, EvictReason::AutoEvict); + engine.evict_region(&evict_region, EvictReason::AutoEvict, None); let r_left = new_regions[0].clone(); let s3 = engine.snapshot(r_left.clone(), 20, 20).unwrap(); @@ -1894,7 +1894,7 @@ mod tests { let s4 = engine.snapshot(r_right, 20, 20).unwrap(); drop(s3); - engine.evict_region(&r_left, EvictReason::AutoEvict); + engine.evict_region(&r_left, EvictReason::AutoEvict, None); // todo(SpadeA): memory limiter { diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index e3b97bd4fa1..96ba517b14b 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -222,7 +222,7 @@ impl RangeCacheWriteBatch { return; } self.engine - .evict_region(self.current_region.as_ref().unwrap(), reason); + .evict_region(self.current_region.as_ref().unwrap(), reason, None); // cleanup cached entries belong to this region as there is no need // to write them. assert!(self.save_points.is_empty()); @@ -879,6 +879,7 @@ mod tests { engine.evict_region( &CacheRegion::from_region(®ions[0]), EvictReason::AutoEvict, + None, ); wait_evict_done(&engine); flush_epoch(); diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 814f92fdbe0..73f3de4969f 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -256,7 +256,7 @@ fn test_evict_with_loading_range() { let engine_clone = engine.clone(); fail::cfg_callback("on_snapshot_load_finished", move || { let _ = snapshot_load_tx.send(true); - engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict); + engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict, None); }) .unwrap(); @@ -443,8 +443,8 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { // Now, three ranges are in write status, delete range will not be performed // until they leave the write status - engine.evict_region(&cache_region1, EvictReason::AutoEvict); - engine.evict_region(&cache_region2, EvictReason::AutoEvict); + engine.evict_region(&cache_region1, EvictReason::AutoEvict, None); + engine.evict_region(&cache_region2, EvictReason::AutoEvict, None); let verify_data = |r: &Region, expected_num: u64| { let handle = engine.core().read().engine().cf_handle(CF_LOCK); @@ -491,7 +491,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { snapshot_load_rx .recv_timeout(Duration::from_secs(5)) .unwrap(); - engine.evict_region(&CacheRegion::from_region(&r3), EvictReason::AutoEvict); + engine.evict_region(&CacheRegion::from_region(&r3), EvictReason::AutoEvict, None); fail::cfg("before_clear_ranges_in_being_written", "pause").unwrap(); write_batch_consume_rx @@ -532,7 +532,7 @@ fn test_double_delete_range_schedule() { let _ = snapshot_load_tx.send(true); // evict all ranges. So the loading ranges will also be evicted and a delete // range task will be scheduled. - engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict); + engine_clone.evict_region(&CacheRegion::from_region(&r), EvictReason::AutoEvict, None); }) .unwrap(); @@ -747,3 +747,44 @@ fn test_region_split_before_batch_loading_start() { }, ); } + +#[test] +fn test_cb_on_eviction() { + let mut config = RangeCacheEngineConfig::config_for_test(); + config.gc_interval = ReadableDuration(Duration::from_secs(1)); + let engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(Arc::new( + VersionTrack::new(config), + ))); + + let region = new_region(1, b"", b"z"); + let cache_region = CacheRegion::from_region(®ion); + engine.new_region(region.clone()); + + let mut wb = engine.write_batch(); + wb.prepare_for_region(cache_region.clone()); + wb.set_sequence_number(10).unwrap(); + wb.put(b"a", b"val1").unwrap(); + wb.put(b"b", b"val2").unwrap(); + wb.put(b"c", b"val3").unwrap(); + wb.write().unwrap(); + + fail::cfg("in_memory_engine_on_delete_regions", "pause").unwrap(); + + let (tx, rx) = sync_channel(0); + engine.evict_region( + &cache_region, + EvictReason::BecomeFollower, + Some(Box::new(move || { + let _ = tx.send(true); + })), + ); + + rx.recv_timeout(Duration::from_secs(1)).unwrap_err(); + fail::remove("in_memory_engine_on_delete_regions"); + let _ = rx.recv(); + + { + let core = engine.core().read(); + assert!(core.range_manager().region_meta(1).is_none()); + } +} diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index c6b335a6e63..422891ef2a6 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -411,7 +411,11 @@ fn test_load_with_eviction() { } // Now, the range ["", "") should be cached let region = new_region(1, split_key, ""); - range_cache_engine.evict_region(&CacheRegion::from_region(®ion), EvictReason::AutoEvict); + range_cache_engine.evict_region( + &CacheRegion::from_region(®ion), + EvictReason::AutoEvict, + None, + ); } fail::remove("on_range_cache_write_batch_write_impl"); From 6e4f1f45dc334120d6eece71c2f3c94401139ac4 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 9 Sep 2024 20:30:11 +0800 Subject: [PATCH 055/144] OWNERS: Auto Sync OWNERS files from community membership (#17509) Signed-off-by: Ti Chi Robot --- OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS b/OWNERS index f7d1f4d67bb..9361aa6c138 100644 --- a/OWNERS +++ b/OWNERS @@ -50,6 +50,7 @@ approvers: - zhouqiang-cl - zyguan reviewers: + - 3AceShowHand - 3pointer - CalvinNeo - ethercflow From 74fea6c1605959e5b9d68d8aed470ce3d7930c87 Mon Sep 17 00:00:00 2001 From: wuhuizuo Date: Tue, 10 Sep 2024 10:44:48 +0800 Subject: [PATCH 056/144] ci: update owners aliases (#17490) close tikv/tikv#17004 Signed-off-by: wuhuizuo Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- OWNERS_ALIASES | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index aa71e7f7ac8..49fdc25e4ee 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -1,11 +1,13 @@ # Sort the member alphabetically. aliases: sig-critical-approvers-config-components: - - easonn7 + - BenMeadowcroft + - yudongusa - zhangjinpeng87 sig-critical-approvers-config-src: - - easonn7 + - BenMeadowcroft - cfzjywxk + - yudongusa - zhangjinpeng87 sig-critical-approvers-config-cdc: - BenMeadowcroft From d0c738abd5e2cbbb16c64d8eac0c422415e82876 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:22:54 +0800 Subject: [PATCH 057/144] In-memory engine: optimize auto evict (#17450) ref tikv/tikv#16141 This PR optimizes the auto eviction by: 1. periodically, check regions with pretty low read flow or mvcc amplification and evict them regardless of the memory usage. 2. maintain the moving average of the mvcc amplification reduction (reduced multiples before and after cache). When new top regions comes in and the memory usage reaches stop-load-limit-threshold, use the moving average of the mvcc amplification reduction to estimate the mvcc amplification of the top regions after cache and use it to judge whether some regions should be evicted. Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/pd_client/src/lib.rs | 12 + .../src/coprocessor/region_info_accessor.rs | 118 ++++- .../src/background.rs | 53 +- .../range_cache_memory_engine/src/engine.rs | 1 + .../range_cache_memory_engine/src/lib.rs | 2 +- .../src/memory_controller.rs | 5 - .../src/range_manager.rs | 13 + .../src/range_stats.rs | 492 +++++++++++++----- components/tikv_util/src/lib.rs | 1 + components/tikv_util/src/smoother.rs | 332 ++++++++++++ .../singleton_flow_controller.rs | 315 +---------- 11 files changed, 844 insertions(+), 500 deletions(-) create mode 100644 components/tikv_util/src/smoother.rs diff --git a/components/pd_client/src/lib.rs b/components/pd_client/src/lib.rs index 1b19a6322bd..4cde27de7ce 100644 --- a/components/pd_client/src/lib.rs +++ b/components/pd_client/src/lib.rs @@ -601,4 +601,16 @@ impl RegionWriteCfCopDetail { self.processed_keys - other.processed_keys, ) } + + pub fn iterated_count(&self) -> usize { + self.next + self.prev + } + + pub fn mvcc_amplification(&self) -> f64 { + if self.processed_keys == 0 { + 0f64 + } else { + (self.next + self.prev) as f64 / self.processed_keys as f64 + } + } } diff --git a/components/raftstore/src/coprocessor/region_info_accessor.rs b/components/raftstore/src/coprocessor/region_info_accessor.rs index 3cc60c04d1a..26e14c2cd1c 100644 --- a/components/raftstore/src/coprocessor/region_info_accessor.rs +++ b/components/raftstore/src/coprocessor/region_info_accessor.rs @@ -29,6 +29,9 @@ use super::{ RegionHeartbeatObserver, Result, RoleChange, RoleObserver, }; +// TODO(SpadeA): this 100 may be adjusted by observing more workloads. +const ITERATED_COUNT_FILTER_FACTOR: usize = 100; + /// `RegionInfoAccessor` is used to collect all regions' information on this /// TiKV into a collection so that other parts of TiKV can get region /// information from it. It registers a observer to raftstore, which is named @@ -167,6 +170,10 @@ pub enum RegionInfoQuery { count: usize, callback: Callback, }, + GetRegionsStat { + region_ids: Vec, + callback: Callback>, + }, /// Gets all contents from the collection. Only used for testing. DebugDump(mpsc::Sender<(RegionsMap, RegionRangesMap)>), } @@ -192,6 +199,9 @@ impl Display for RegionInfoQuery { RegionInfoQuery::GetTopRegions { count, .. } => { write!(f, "GetTopRegions(count: {})", count) } + RegionInfoQuery::GetRegionsStat { region_ids, .. } => { + write!(f, "GetRegionsActivity(region_ids: {:?})", region_ids) + } RegionInfoQuery::DebugDump(_) => write!(f, "DebugDump"), } } @@ -582,16 +592,15 @@ impl RegionCollector { /// region_activity. This is acceptable, as region_activity is populated /// by heartbeats for this node's region, so N cannot be greater than /// approximately `300_000``. - pub fn handle_get_top_regions(&mut self, count: usize, callback: Callback) { + pub fn handle_get_top_regions(&self, count: usize, callback: Callback) { let compare_fn = |a: &RegionActivity, b: &RegionActivity| { - let a = a.region_stat.cop_detail.next + a.region_stat.cop_detail.prev; - let b = b.region_stat.cop_detail.next + b.region_stat.cop_detail.prev; + let a = a.region_stat.cop_detail.iterated_count(); + let b = b.region_stat.cop_detail.iterated_count(); b.cmp(&a) }; // Only used to log. let mut max_qps = 0; - let mut max_next_prev = 0; let mut top_regions = if count == 0 { self.regions .values() @@ -612,10 +621,6 @@ impl RegionCollector { r, ra.map(|ra| { max_qps = u64::max(ra.region_stat.query_stats.coprocessor, max_qps); - max_next_prev = usize::max( - ra.region_stat.cop_detail.prev + ra.region_stat.cop_detail.next, - max_next_prev, - ); ra.region_stat.clone() }) .unwrap_or_default(), @@ -628,13 +633,12 @@ impl RegionCollector { .iter() .filter_map(|(id, ac)| { max_qps = u64::max(ac.region_stat.query_stats.coprocessor, max_qps); - max_next_prev = usize::max( - ac.region_stat.cop_detail.prev + ac.region_stat.cop_detail.next, - max_next_prev, - ); self.regions .get(id) - .filter(|ri| ri.role == StateRole::Leader) + .filter(|ri| { + ri.role == StateRole::Leader + && ac.region_stat.cop_detail.iterated_count() != 0 + }) .map(|ri| (ri, ac)) }) .sorted_by(|(_, activity_0), (_, activity_1)| compare_fn(activity_0, activity_1)) @@ -649,11 +653,12 @@ impl RegionCollector { .iter() .map(|(r, s)| { format!( - "region_id={}, read_keys={}, cop={}, cop_detail={:?}", + "region_id={}, read_keys={}, cop={}, cop_detail={:?}, mvcc_amplification={}", r.get_id(), s.read_keys, s.query_stats.coprocessor, s.cop_detail, + s.cop_detail.mvcc_amplification(), ) }) .collect_vec(); @@ -666,10 +671,25 @@ impl RegionCollector { ); } + // Get the average iterated count of the first top 10 regions and use the + // 1/ITERATED_COUNT_FILTER_FACTOR of it to filter regions with less read + // flows + let top_regions_iterated_count: Vec<_> = top_regions + .iter() + .map(|(_, r)| r.cop_detail.iterated_count()) + .take(10) + .collect(); + let iterated_count_to_filter: usize = if !top_regions_iterated_count.is_empty() { + top_regions_iterated_count.iter().sum::() + / top_regions_iterated_count.len() + / ITERATED_COUNT_FILTER_FACTOR + } else { + 0 + }; top_regions.retain(|(_, s)| { - s.cop_detail.next + s.cop_detail.prev >= max_next_prev / 10 - && s.cop_detail.processed_keys != 0 - && (s.cop_detail.next + s.cop_detail.prev) / s.cop_detail.processed_keys + s.cop_detail.iterated_count() >= iterated_count_to_filter + // plus processed_keys by 1 to make it not 0 + && (s.cop_detail.iterated_count()) / (s.cop_detail.processed_keys + 1) >= self.mvcc_amplification_threshold }); @@ -679,11 +699,12 @@ impl RegionCollector { .iter() .map(|(r, s)| { format!( - "region_id={}, read_keys={}, cop={}, cop_detail={:?}", + "region_id={}, read_keys={}, cop={}, cop_detail={:?}, mvcc_amplification={}", r.get_id(), s.read_keys, s.query_stats.coprocessor, s.cop_detail, + s.cop_detail.mvcc_amplification(), ) }) .collect_vec(); @@ -700,7 +721,27 @@ impl RegionCollector { callback( top_regions .into_iter() - .map(|(r, stat)| (r, stat.approximate_size)) + .map(|(r, stat)| (r, stat.clone())) + .collect_vec(), + ) + } + + fn handle_get_regions_stat( + &self, + region_ids: Vec, + callback: Callback>, + ) { + callback( + region_ids + .into_iter() + .filter_map(|id| { + self.region_activity.get(&id).map(|r| { + ( + self.regions.get(&id).unwrap().region.clone(), + r.region_stat.clone(), + ) + }) + }) .collect_vec(), ) } @@ -785,6 +826,12 @@ impl Runnable for RegionCollector { RegionInfoQuery::GetTopRegions { count, callback } => { self.handle_get_top_regions(count, callback); } + RegionInfoQuery::GetRegionsStat { + region_ids, + callback, + } => { + self.handle_get_regions_stat(region_ids, callback); + } RegionInfoQuery::DebugDump(tx) => { tx.send((self.regions.clone(), self.region_ranges.clone())) .unwrap(); @@ -894,7 +941,7 @@ impl RegionInfoAccessor { } /// Top regions result: region and its approximate size. -pub type TopRegions = Vec<(Region, u64)>; +pub type TopRegions = Vec<(Region, RegionStat)>; pub trait RegionInfoProvider: Send + Sync { /// Get a iterator of regions that contains `from` or have keys larger than @@ -918,9 +965,14 @@ pub trait RegionInfoProvider: Send + Sync { fn get_regions_in_range(&self, _start_key: &[u8], _end_key: &[u8]) -> Result> { unimplemented!() } + fn get_top_regions(&self, _count: Option) -> Result { unimplemented!() } + + fn get_regions_stat(&self, _: Vec) -> Result> { + unimplemented!() + } } impl RegionInfoProvider for RegionInfoAccessor { @@ -1015,6 +1067,29 @@ impl RegionInfoProvider for RegionInfoAccessor { }) }) } + + fn get_regions_stat(&self, region_ids: Vec) -> Result> { + let (tx, rx) = mpsc::channel(); + let msg = RegionInfoQuery::GetRegionsStat { + region_ids, + callback: Box::new(move |regions_activity| { + if let Err(e) = tx.send(regions_activity) { + warn!("failed to send get_regions_activity result: {:?}", e); + } + }), + }; + self.scheduler + .schedule(msg) + .map_err(|e| box_err!("failed to send request to region collector: {:?}", e)) + .and_then(|_| { + rx.recv().map_err(|e| { + box_err!( + "failed to receive get_regions_activity result from region_collector: {:?}", + e + ) + }) + }) + } } // Use in tests only. @@ -1102,7 +1177,8 @@ impl RegionInfoProvider for MockRegionInfoProvider { b"", Box::new(move |iter| { for region_info in iter { - tx.send((region_info.region.clone(), 0)).unwrap(); + tx.send((region_info.region.clone(), RegionStat::default())) + .unwrap(); } }), )?; diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 9f2b7271dfe..92428df4a27 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -221,6 +221,7 @@ impl BgWorkManager { gc_interval: Duration, load_evict_interval: Duration, expected_region_size: usize, + mvcc_amplification_threshold: usize, memory_controller: Arc, region_info_provider: Option>, ) -> Self { @@ -230,6 +231,7 @@ impl BgWorkManager { memory_controller, region_info_provider.clone(), expected_region_size, + mvcc_amplification_threshold, gc_interval, pd_client.clone(), ); @@ -693,27 +695,24 @@ impl BackgroundRunnerCore { let threshold = self.memory_controller.stop_load_limit_threshold(); range_stats_manager.adjust_max_num_regions(curr_memory_usage, threshold); - let mut regions_to_add = Vec::with_capacity(256); - let mut regions_to_remove = Vec::with_capacity(256); - range_stats_manager.collect_changed_ranges(&mut regions_to_add, &mut regions_to_remove); - let mut regions_to_delete = Vec::with_capacity(regions_to_remove.len()); - info!("ime load_evict"; "ranges_to_add" => ?®ions_to_add, "may_evict" => ?®ions_to_remove); - for evict_region in regions_to_remove { - if self.memory_controller.reached_soft_limit() { - let cache_region = CacheRegion::from_region(&evict_region); - let mut core = self.engine.write(); - let deleteable_regions = core.mut_range_manager().evict_region( - &cache_region, - EvictReason::AutoEvict, - None, - ); - info!( - "ime load_evict: soft limit reached"; - "region_to_evict" => ?&cache_region, - "evicted_regions" => ?&deleteable_regions, - ); - regions_to_delete.extend(deleteable_regions); - } + let cached_regions = self.engine.read().range_manager().cached_regions(); + let (regions_to_load, regions_to_evict) = range_stats_manager + .collect_regions_to_load_and_evict(cached_regions, &self.memory_controller); + + let mut regions_to_delete = Vec::with_capacity(regions_to_evict.len()); + info!("ime load_evict"; "regions_to_load" => ?®ions_to_load, "regions_to_evict" => ?®ions_to_evict); + for evict_region in regions_to_evict { + let cache_region = CacheRegion::from_region(&evict_region); + let mut core = self.engine.write(); + let deleteable_regions = + core.mut_range_manager() + .evict_region(&cache_region, EvictReason::AutoEvict, None); + info!( + "ime load_evict: auto evict"; + "region_to_evict" => ?&cache_region, + "evicted_regions" => ?&deleteable_regions, + ); + regions_to_delete.extend(deleteable_regions); } if !regions_to_delete.is_empty() { @@ -727,7 +726,7 @@ impl BackgroundRunnerCore { assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } } - for region in regions_to_add { + for region in regions_to_load { let cache_region = CacheRegion::from_region(®ion); let mut core = self.engine.write(); if let Err(e) = core.mut_range_manager().load_region(cache_region) { @@ -801,6 +800,7 @@ impl BackgroundRunner { memory_controller: Arc, region_info_provider: Option>, expected_region_size: usize, + mvcc_amplification_threshold: usize, gc_interval: Duration, pd_client: Arc, ) -> (Self, Scheduler) { @@ -834,6 +834,7 @@ impl BackgroundRunner { num_regions_to_cache, DEFAULT_EVICT_MIN_DURATION, expected_region_size, + mvcc_amplification_threshold, region_info_provider, ) }); @@ -1902,6 +1903,7 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -1979,6 +1981,7 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2141,6 +2144,7 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2158,6 +2162,7 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2208,6 +2213,7 @@ pub mod tests { memory_controller.clone(), None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2310,6 +2316,7 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2453,6 +2460,7 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); @@ -2604,6 +2612,7 @@ pub mod tests { memory_controller, None, engine.expected_region_size(), + 0, Duration::from_secs(100), Arc::new(MockPdClient {}), ); diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index e9ddff3101c..746be71089f 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -277,6 +277,7 @@ impl RangeCacheMemoryEngine { config.value().gc_interval.0, config.value().load_evict_interval.0, config.value().expected_region_size(), + config.value().mvcc_amplification_threshold, memory_controller.clone(), region_info_provider, )); diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index 0fffad89317..7407febd3ea 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -80,7 +80,7 @@ impl Default for RangeCacheEngineConfig { soft_limit_threshold: None, hard_limit_threshold: None, expected_region_size: None, - mvcc_amplification_threshold: 10, + mvcc_amplification_threshold: 100, } } } diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index 6ceba104c14..924e2460743 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -90,11 +90,6 @@ impl MemoryController { self.mem_usage() >= self.config.value().stop_load_limit_threshold() } - #[inline] - pub(crate) fn reached_soft_limit(&self) -> bool { - self.mem_usage() >= self.config.value().soft_limit_threshold() - } - #[inline] pub(crate) fn stop_load_limit_threshold(&self) -> usize { self.config.value().stop_load_limit_threshold() diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index f820d9fe77d..8ef6f10daa5 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -327,6 +327,19 @@ impl RegionManager { self.regions.get_mut(&id) } + pub fn cached_regions(&self) -> Vec { + self.regions + .iter() + .filter_map(|(id, meta)| { + if meta.state == RegionState::Active { + Some(*id) + } else { + None + } + }) + .collect::>() + } + pub fn iter_overlapped_regions( &self, region: &CacheRegion, diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 2de4bc5d2a0..30fcf345065 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -1,7 +1,7 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. use std::{ cmp, - collections::BTreeMap, + collections::{BTreeMap, HashSet}, num::NonZeroUsize, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -10,25 +10,39 @@ use std::{ time::{Duration, Instant}, }; +use collections::HashMap; use crossbeam::sync::ShardedLock; use kvproto::metapb::Region; use parking_lot::Mutex; use raftstore::coprocessor::RegionInfoProvider; -use tikv_util::info; +use tikv_util::{info, smoother::Smoother}; + +use crate::memory_controller::MemoryController; + +/// Do not evict a region if has been cached for less than this duration. +pub const DEFAULT_EVICT_MIN_DURATION: Duration = Duration::from_secs(60 * 5); +const MIN_REGION_COUNT_TO_EVICT: usize = 5; +// TODO(SpadeA): this 10 and 20 may be adjusted by observing more workloads. +const MVCC_AMPLIFICATION_FILTER_FACTOR: f64 = 10.0; +const ITERATED_COUNT_FILTER_FACTOR: usize = 20; #[derive(Clone)] pub(crate) struct RangeStatsManager { num_regions: Arc, info_provider: Arc, - prev_top_regions: Arc>>, checking_top_regions: Arc, region_loaded_at: Arc>>, evict_min_duration: Duration, expected_region_size: usize, -} + // Moving average of amplification reduction. Amplification reduction is the reduced + // multiple before and after the cache. When a new top region (of course, not cached) comes in, + // this moving average number is used to estimate the mvcc amplification after cache so we can + // use it to determine whether to evict some regions if memory usage is relative high. + ma_mvcc_amplification_reduction: Arc>>, + mvcc_amplification_threshold: usize, -/// Do not evict a region if has been cached for less than this duration. -pub const DEFAULT_EVICT_MIN_DURATION: Duration = Duration::from_secs(60 * 3); + mvcc_amplification_record: Arc>>, +} impl RangeStatsManager { /// Creates a new RangeStatsManager that retrieves state from @@ -42,16 +56,19 @@ impl RangeStatsManager { num_regions: usize, evict_min_duration: Duration, expected_region_size: usize, + mvcc_amplification_threshold: usize, info_provider: Arc, ) -> Self { RangeStatsManager { num_regions: Arc::new(AtomicUsize::new(num_regions)), info_provider, - prev_top_regions: Arc::new(Mutex::new(BTreeMap::new())), checking_top_regions: Arc::new(AtomicBool::new(false)), region_loaded_at: Arc::new(ShardedLock::new(BTreeMap::new())), + ma_mvcc_amplification_reduction: Arc::new(Mutex::new(Smoother::default())), + mvcc_amplification_record: Arc::default(), evict_min_duration, expected_region_size, + mvcc_amplification_threshold, } } @@ -109,7 +126,7 @@ impl RangeStatsManager { Some(_) | None => // None indicates range loaded from a hint, not by this manager. { - Some((region.clone(), *approx_size)) + Some((region.clone(), approx_size.approximate_size)) } } }) @@ -129,7 +146,6 @@ impl RangeStatsManager { /// TODO (afeinberg): This is inefficient, either make this method bulk, or /// find another way to avoid calling `find_region_by_key` in a loop. pub fn handle_region_evicted(&self, region: &Region) { - self.prev_top_regions.lock().remove(®ion.id); self.region_loaded_at.write().unwrap().remove(®ion.id); } @@ -175,37 +191,66 @@ impl RangeStatsManager { }; } - /// Collects changes to top regions since the previous time this method was - /// called. This method should be called by background tasks responsing - /// for algorithmic loading and eviction. + /// Collects regions to load and evict based on region stat, mvcc + /// amplification, and memory constraints. New top regions will be + /// collected in `regions_added_out` to be loaded. /// - /// 1. Calls [raftstore::coprocessor::RegionCollector::handle_get_top_regions] to - /// request the top `self.max_num_regions()` regions. + /// If memory usage is below the stop load limit, regions with low read flow + /// or low mvcc amplification are considered for eviction. /// - /// 2. If this is the first time this method has been called on this - /// instance, stores the results of previous step in `ranges_added_out` - /// and returns. + /// If memory usage reaches stop load limit, whether to evict region is + /// determined by comparison between the new top regions' activity and the + /// current cached regions. /// - /// 3. If this method has been called before, compare results of step 1 with - /// previous results: - /// - Newly added ranges (regions missing from previous results) are - /// stored in `ranges_added_out`. This can happen when - /// `max_num_regions()` increases, or when `max_num_regions()` is - /// unchanged but the activity order changed. - /// - Removed regions - regions included in previous results - but not the - /// current ones are stored in `ranges_removed_out`. - pub fn collect_changed_ranges( + /// # Returns + /// (Regions to load, Regions to evict) + pub fn collect_regions_to_load_and_evict( &self, - regions_added_out: &mut Vec, - regions_removed_out: &mut Vec, - ) { + cached_region_ids: Vec, + memory_controller: &MemoryController, + ) -> (Vec, Vec) { + // Get regions' stat of the cached region and sort them by next + prev in + // descending order. + let mut regions_stat = self + .info_provider + .get_regions_stat(cached_region_ids.clone()) + .unwrap(); + regions_stat.sort_by(|a, b| { + let next_prev_a = a.1.cop_detail.iterated_count(); + let next_prev_b = b.1.cop_detail.iterated_count(); + next_prev_b.cmp(&next_prev_a) + }); + + let ma_mvcc_amplification_reduction = { + let mut ma_mvcc_amplification_reduction = self.ma_mvcc_amplification_reduction.lock(); + let mut record = self.mvcc_amplification_record.lock(); + // update the moving average of the mvcc amplification reduction(the reduced + // multiple before and after the cache). + regions_stat.iter().for_each(|(r, a)| { + if let Some(&lification) = record.get(&r.id) { + let amp_after_cache = a.cop_detail.mvcc_amplification(); + if amp_after_cache != 0.0 && amp_after_cache != amplification { + ma_mvcc_amplification_reduction + .observe(amplification / a.cop_detail.mvcc_amplification()); + } + } + }); + record.clear(); + // this reduction should not be less than 1 + ma_mvcc_amplification_reduction.get_avg() + }; + info!( + "IME moving average mvcc amplification reduction update"; + "ma_mvcc_amplification_reduction" => ma_mvcc_amplification_reduction, + ); + info!("ime collect_changed_ranges"; "num_regions" => self.max_num_regions()); let curr_top_regions = self .info_provider .get_top_regions(Some(NonZeroUsize::try_from(self.max_num_regions()).unwrap())) .unwrap() // TODO (afeinberg): Potentially custom error handling here. .iter() - .map(|(r, _)| (r.id, r.clone())) + .map(|(r, region_stats)| (r.id, (r.clone(), region_stats.clone()))) .collect::>(); { let mut region_loaded_map = self.region_loaded_at.write().unwrap(); @@ -213,60 +258,161 @@ impl RangeStatsManager { let _ = region_loaded_map.insert(region_id, Instant::now()); } } - let prev_top_regions = { - let mut mut_prev_top_regions = self.prev_top_regions.lock(); - let ret = mut_prev_top_regions.clone(); - *mut_prev_top_regions = curr_top_regions.clone(); - ret - }; - if prev_top_regions.is_empty() { - regions_added_out.extend(curr_top_regions.values().cloned()); - return; - } - let added_ranges = curr_top_regions - .iter() - .filter(|(id, _)| !prev_top_regions.contains_key(id)) - .map(|(_, region)| region.clone()); - let regions_loaded = self.region_loaded_at.read().unwrap(); - let removed_ranges = prev_top_regions.iter().filter_map(|(&id, region)| { - if !curr_top_regions.contains_key(&id) { - match regions_loaded.get(&id) { - // Do not evict ranges that were loaded less than `EVICT_MIN_DURATION` ago. - Some(&time_loaded) - if Instant::now() - time_loaded < self.evict_min_duration => - { - let mut mut_prev_top_regions = self.prev_top_regions.lock(); - let _ = mut_prev_top_regions.insert(id, region.clone()); + + let cached_region_ids = cached_region_ids.into_iter().collect::>(); + let (mvcc_amplification_to_filter, regions_to_load) = { + let mut max_mvcc_amplification: f64 = 0.0; + let mut record = self.mvcc_amplification_record.lock(); + let regions_to_load = curr_top_regions + .iter() + .filter_map(|(id, (r, region_stats))| { + if !cached_region_ids.contains(id) { + max_mvcc_amplification = max_mvcc_amplification + .max(region_stats.cop_detail.mvcc_amplification()); + record.insert(*id, region_stats.cop_detail.mvcc_amplification()); + Some(r.clone()) + } else { None } - _ => Some(region.clone()), - } + }) + .collect(); + // `max_mvcc_amplification / ma_mvcc_amplification_reduction` is the + // expected mvcc amplification factor after cache. Make the half of it to filter + // the cached regions. + ( + max_mvcc_amplification / f64::max(1.0, ma_mvcc_amplification_reduction / 2.0), + regions_to_load, + ) + }; + + info!( + "IME mvcc amplification reduction filter"; + "mvcc_amplification_to_filter" => mvcc_amplification_to_filter, + ); + + { + // TODO(SpadeA): remove it after it's stable + let debug: Vec<_> = regions_stat + .iter() + .map(|(r, s)| { + format!( + "region_id={}, cop={}, cop_detail={:?}, mvcc_amplification={}", + r.id, + s.query_stats.coprocessor, + s.cop_detail, + s.cop_detail.mvcc_amplification(), + ) + }) + .collect(); + info!( + "ime collect regions activities"; + "regions" => ?debug, + ); + } + + let reach_stop_load = memory_controller.reached_stop_load_limit(); + let mut regions_loaded = self.region_loaded_at.write().unwrap(); + // Evict at most 1/10 of the regions. + let max_count_to_evict = usize::max(1, regions_stat.len() / 10); + // Use top MIN_REGION_COUNT_TO_EVICT regions next and prev to filter regions + // with very few next and prev. If there's less than or equal to + // MIN_REGION_COUNT_TO_EVICT regions, do not evict any one. + let regions_to_evict = if regions_stat.len() > MIN_REGION_COUNT_TO_EVICT { + let avg_top_next_prev = if reach_stop_load { + regions_stat + .iter() + .map(|r| r.1.cop_detail.iterated_count()) + .take(MIN_REGION_COUNT_TO_EVICT) + .sum::() + / MIN_REGION_COUNT_TO_EVICT } else { - None - } - }); - regions_added_out.extend(added_ranges); - regions_removed_out.extend(removed_ranges); + 0 + }; + let region_to_evict: Vec<_> = regions_stat + .into_iter() + .filter(|(_, r)| { + if reach_stop_load { + r.cop_detail.mvcc_amplification() + < mvcc_amplification_to_filter + } else { + // In this case, memory usage is relarively low, we only evict those that should not be cached apparently. + r.cop_detail.mvcc_amplification() + <= self.mvcc_amplification_threshold as f64 / MVCC_AMPLIFICATION_FILTER_FACTOR + || r.cop_detail.iterated_count() < avg_top_next_prev / ITERATED_COUNT_FILTER_FACTOR + } + }) + .filter_map(|(r, s)| { + // Do not evict regions that were loaded less than `EVICT_MIN_DURATION` ago. + // If it has no time recorded, it should be loaded + // be pre-load or something, record the time and + // does not evict it this time. + let time_loaded = regions_loaded.entry(r.id).or_insert(Instant::now()); + if Instant::now() - *time_loaded < self.evict_min_duration { + None + } else { + Some((r, s)) + } + }) + .rev() // evict the regions with least next + prev after the filter + .take(max_count_to_evict) + .collect(); + + // TODO(SpadeA): remove it after it's stable + let debug: Vec<_> = region_to_evict + .iter() + .map(|(r, s)| { + format!( + "region_id={}, cop={}, cop_detail={:?}, mvcc_amplification={}", + r.id, + s.query_stats.coprocessor, + s.cop_detail, + s.cop_detail.mvcc_amplification(), + ) + }) + .collect(); + info!( + "ime collect regions to evict"; + "reached_stop_limit" => reach_stop_load, + "regions" => ?debug, + ); + region_to_evict.into_iter().map(|(r, _)| r).collect() + } else { + vec![] + }; + (regions_to_load, regions_to_evict) } } #[cfg(test)] pub mod tests { + use pd_client::{RegionStat, RegionWriteCfCopDetail}; use raftstore::coprocessor::{self, region_info_accessor::TopRegions, RegionInfoProvider}; - use tikv_util::box_err; + use tikv_util::{ + box_err, + config::{ReadableSize, VersionTrack}, + }; use super::*; - use crate::{test_util::new_region, RangeCacheEngineConfig}; + use crate::{engine::SkiplistEngine, test_util::new_region, RangeCacheEngineConfig}; struct RegionInfoSimulator { regions: Mutex, + region_stats: Mutex>, } impl RegionInfoSimulator { fn set_top_regions(&self, top_regions: &TopRegions) { *self.regions.lock() = top_regions.clone() } + + fn set_region_stats(&self, region_stats: &[(Region, RegionStat)]) { + *self.region_stats.lock() = region_stats + .iter() + .map(|(r, s)| (r.id, (r.clone(), s.clone()))) + .collect::>(); + } } + impl RegionInfoProvider for RegionInfoSimulator { fn find_region_by_key(&self, key: &[u8]) -> coprocessor::Result { self.regions @@ -293,110 +439,182 @@ pub mod tests { }, )) } + + fn get_regions_stat( + &self, + ids: Vec, + ) -> coprocessor::Result> { + let g = self.region_stats.lock().clone(); + Ok(ids + .into_iter() + .filter_map(|id| g.get(&id).cloned()) + .collect()) + } + } + + fn new_region_stat(next: usize, processed_keys: usize) -> RegionStat { + let mut stat = RegionStat::default(); + stat.cop_detail = RegionWriteCfCopDetail::new(next, 0, processed_keys); + stat } #[test] fn test_collect_changed_regions() { - let region_1 = new_region(1, b"k1", b"k2"); + let skiplist_engine = SkiplistEngine::new(); + let mut config = RangeCacheEngineConfig::config_for_test(); + config.stop_load_limit_threshold = Some(ReadableSize::kb(1)); + let config = Arc::new(VersionTrack::new(config)); + let mc = MemoryController::new(config, skiplist_engine); + let region_1 = new_region(1, b"k01", b"k02"); - let region_2 = new_region(2, b"k3", b"k4"); + let region_2 = new_region(2, b"k03", b"k04"); let sim = Arc::new(RegionInfoSimulator { - regions: Mutex::new(vec![(region_1.clone(), 42)]), + regions: Mutex::new(vec![(region_1.clone(), new_region_stat(1000, 10))]), + region_stats: Mutex::default(), }); // 10 ms min duration eviction for testing purposes. let rsm = RangeStatsManager::new( - 5, + 10, Duration::from_millis(10), RangeCacheEngineConfig::config_for_test().expected_region_size(), + 10, sim.clone(), ); - let mut added = Vec::new(); - let mut removed = Vec::new(); - rsm.collect_changed_ranges(&mut added, &mut removed); + let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![], &mc); assert_eq!(&added, &[region_1.clone()]); assert!(removed.is_empty()); - let top_regions = vec![(region_1.clone(), 42), (region_2.clone(), 7)]; + let top_regions = vec![(region_2.clone(), new_region_stat(1000, 8))]; + let region_stats = vec![(region_1.clone(), new_region_stat(20, 10))]; sim.set_top_regions(&top_regions); - added.clear(); - removed.clear(); - rsm.collect_changed_ranges(&mut added, &mut removed); + sim.set_region_stats(®ion_stats); + let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![1], &mc); assert_eq!(&added, &[region_2.clone()]); assert!(removed.is_empty()); - let region_3 = new_region(3, b"k5", b"k6"); - let region_4 = new_region(4, b"k7", b"k8"); - let region_5 = new_region(5, b"k9", b"k10"); + let region_3 = new_region(3, b"k05", b"k06"); + let region_4 = new_region(4, b"k07", b"k08"); + let region_5 = new_region(5, b"k09", b"k10"); let region_6 = new_region(6, b"k11", b"k12"); + let region_7 = new_region(7, b"k13", b"k14"); + let region_8 = new_region(8, b"k15", b"k16"); let top_regions = vec![ - (region_6.clone(), 42), - (region_2.clone(), 7), - (region_3.clone(), 8), - (region_4.clone(), 9), - (region_5.clone(), 2), + (region_6.clone(), new_region_stat(1000, 10)), + (region_3.clone(), new_region_stat(1000, 10)), + (region_4.clone(), new_region_stat(1000, 10)), + (region_5.clone(), new_region_stat(1000, 10)), + (region_7.clone(), new_region_stat(2000, 10)), + ]; + let region_stats = vec![ + (region_1.clone(), new_region_stat(20, 10)), + (region_2.clone(), new_region_stat(20, 8)), ]; sim.set_top_regions(&top_regions); - added.clear(); - removed.clear(); - rsm.collect_changed_ranges(&mut added, &mut removed); - assert_eq!(&added, &[region_3, region_4, region_5, region_6]); - // `region_1` is no longer in the top regions list, but since it was loaded less + sim.set_region_stats(®ion_stats); + let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2], &mc); + assert!(removed.is_empty()); + assert_eq!( + &added, + &[ + region_3.clone(), + region_4.clone(), + region_5.clone(), + region_6.clone(), + region_7.clone() + ] + ); + + let region_stats = vec![ + (region_1.clone(), new_region_stat(2, 10)), + (region_6.clone(), new_region_stat(30, 10)), + (region_2.clone(), new_region_stat(20, 8)), + (region_3.clone(), new_region_stat(15, 10)), + (region_4.clone(), new_region_stat(20, 10)), + (region_5.clone(), new_region_stat(25, 10)), + (region_7.clone(), new_region_stat(40, 10)), + ]; + sim.set_top_regions(&vec![]); + sim.set_region_stats(®ion_stats); + let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2, 3, 4, 5, 6, 7], &mc); + // `region_1` is no longer needed to cached, but since it was loaded less // than 10 ms ago, it should not be included in the removed ranges. assert!(removed.is_empty()); std::thread::sleep(Duration::from_millis(100)); // After 100 ms passed, check again, and verify `region_1` is evictable. - rsm.collect_changed_ranges(&mut added, &mut removed); + + sim.set_top_regions(&vec![]); + sim.set_region_stats(®ion_stats); + let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2, 3, 4, 5, 6, 7], &mc); assert_eq!(&removed, &[region_1.clone()]); + + let top_regions = vec![(region_8.clone(), new_region_stat(4000, 10))]; + sim.set_top_regions(&top_regions); + sim.set_region_stats(®ion_stats); + mc.acquire(2000); + let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![2, 3, 4, 5, 6, 7], &mc); + assert_eq!(&removed, &[region_3.clone()]); } - #[test] - fn test_collect_candidates_for_eviction() { - fn make_region_vec(rs: &[&Region]) -> TopRegions { - rs.iter().map(|&r| (r.clone(), 42)).collect::>() - } + // todo(SpadeA): fix this in the next PR (optimize eviction when soft + // limit reached) + // #[test] + // fn test_collect_candidates_for_eviction() { + // let skiplist_engine = SkiplistEngine::new(); + // let mut config = RangeCacheEngineConfig::config_for_test(); + // config.stop_load_limit_threshold = Some(ReadableSize::kb(1)); + // let config = Arc::new(VersionTrack::new(config)); + // let mc = MemoryController::new(config, skiplist_engine); - let region_1 = new_region(1, b"k1", b"k2"); - let region_2 = new_region(2, b"k3", b"k4"); - let region_3 = new_region(3, b"k5", b"k6"); - let region_4 = new_region(4, b"k7", b"k8"); - let region_5 = new_region(5, b"k9", b"k10"); - let region_6 = new_region(6, b"k11", b"k12"); + // fn make_region_vec(rs: &[&Region]) -> TopRegions { + // let mut stat = RegionStat::default(); + // stat.approximate_size = 42; + // rs.iter().map(|&r| (r.clone(), stat)).collect::>() + // } - let all_regions = make_region_vec(&[ - ®ion_1, ®ion_2, ®ion_3, ®ion_4, ®ion_5, ®ion_6, - ]); + // let region_1 = new_region(1, b"k1", b"k2"); + // let region_2 = new_region(2, b"k3", b"k4"); + // let region_3 = new_region(3, b"k5", b"k6"); + // let region_4 = new_region(4, b"k7", b"k8"); + // let region_5 = new_region(5, b"k9", b"k10"); + // let region_6 = new_region(6, b"k11", b"k12"); - let sim = Arc::new(RegionInfoSimulator { - regions: Mutex::new(all_regions.clone()), - }); - // 10 ms min duration eviction for testing purposes. - let rsm = RangeStatsManager::new( - 5, - Duration::from_millis(10), - RangeCacheEngineConfig::config_for_test().expected_region_size(), - sim.clone(), - ); - let r_i_p: Arc = sim.clone(); - let check_is_cached = move |r: &Region| -> bool { - r_i_p.find_region_by_key(&r.start_key).unwrap().get_id() <= 5 - }; - let mut _added = Vec::new(); - let mut _removed = Vec::new(); - rsm.collect_changed_ranges(&mut _added, &mut _removed); - let mut candidates_for_eviction = Vec::new(); - rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, &check_is_cached); - assert!(candidates_for_eviction.is_empty()); - std::thread::sleep(Duration::from_millis(100)); - rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, &check_is_cached); - let expected_candidates_for_eviction = all_regions - .iter() - .rev() - .filter_map(|(r, s)| { - if r.get_id() <= 5 { - Some((r.clone(), *s)) - } else { - None - } - }) - .collect::>(); - assert_eq!(expected_candidates_for_eviction, candidates_for_eviction); - } + // let all_regions = make_region_vec(&[ + // ®ion_1, ®ion_2, ®ion_3, ®ion_4, ®ion_5, ®ion_6, + // ]); + + // let sim = Arc::new(RegionInfoSimulator { + // regions: Mutex::new(all_regions.clone()), + // region_stats: Mutex::default(), + // }); + // // 10 ms min duration eviction for testing purposes. + // let rsm = RangeStatsManager::new( + // 5, + // Duration::from_millis(10), + // RangeCacheEngineConfig::config_for_test().expected_region_size(), + // 10, + // sim.clone(), + // ); + // let r_i_p: Arc = sim.clone(); + // let check_is_cached = move |r: &Region| -> bool { + // r_i_p.find_region_by_key(&r.start_key).unwrap().get_id() <= 5 + // }; + // let mut _added = Vec::new(); + // let mut _removed = Vec::new(); + // rsm.collect_regions_to_load_and_evict(&mut _added, vec![], &mc); + // let mut candidates_for_eviction = Vec::new(); + // rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, + // &check_is_cached); assert!(candidates_for_eviction.is_empty()); + // std::thread::sleep(Duration::from_millis(100)); + // rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, + // &check_is_cached); let expected_candidates_for_eviction = + // all_regions .iter() + // .rev() + // .filter_map(|(r, s)| { + // if r.get_id() <= 5 { + // Some((r.clone(), *s)) + // } else { + // None + // } + // }) + // .collect::>(); + // assert_eq!(expected_candidates_for_eviction, + // candidates_for_eviction); } } diff --git a/components/tikv_util/src/lib.rs b/components/tikv_util/src/lib.rs index 96fe826a10e..1171e5f4286 100644 --- a/components/tikv_util/src/lib.rs +++ b/components/tikv_util/src/lib.rs @@ -55,6 +55,7 @@ pub mod metrics; pub mod mpsc; pub mod quota_limiter; pub mod resource_control; +pub mod smoother; pub mod store; pub mod stream; pub mod sys; diff --git a/components/tikv_util/src/smoother.rs b/components/tikv_util/src/smoother.rs new file mode 100644 index 00000000000..e7384b0d381 --- /dev/null +++ b/components/tikv_util/src/smoother.rs @@ -0,0 +1,332 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::{ + collections::VecDeque, + ops::{Add, AddAssign, Sub, SubAssign}, +}; + +use num_traits::{AsPrimitive, FromPrimitive}; + +use crate::time::Instant; + +#[derive(PartialEq, Debug)] +pub enum Trend { + Increasing, + Decreasing, + NoTrend, +} + +pub const SMOOTHER_STALE_RECORD_THRESHOLD: u64 = 300; // 5min +pub const SMOOTHER_TIME_RANGE_THRESHOLD: u64 = 60; // 1min + +// Smoother is a sliding window used to provide steadier flow statistics. +pub struct Smoother +where + T: Default + + Add + + Sub + + AddAssign + + SubAssign + + PartialOrd + + AsPrimitive + + FromPrimitive, +{ + records: VecDeque<(T, Instant)>, + total: T, +} + +impl Default + for Smoother +where + T: Default + + Add + + Sub + + AddAssign + + SubAssign + + PartialOrd + + AsPrimitive + + FromPrimitive, +{ + fn default() -> Self { + Self { + records: VecDeque::with_capacity(CAP), + total: Default::default(), + } + } +} + +impl + Smoother +where + T: Default + + Add + + Sub + + AddAssign + + SubAssign + + PartialOrd + + AsPrimitive + + FromPrimitive, +{ + pub fn observe(&mut self, record: T) { + self.observe_with_time(record, Instant::now_coarse()); + } + + pub fn observe_with_time(&mut self, record: T, time: Instant) { + if self.records.len() == CAP { + let v = self.records.pop_front().unwrap().0; + self.total -= v; + } + + self.total += record; + + self.records.push_back((record, time)); + self.remove_stale_records(); + } + + fn remove_stale_records(&mut self) { + // make sure there are two records left at least + while self.records.len() > 2 { + if self.records.front().unwrap().1.saturating_elapsed_secs() > STALE_DUR as f64 { + let v = self.records.pop_front().unwrap().0; + self.total -= v; + } else { + break; + } + } + } + + pub fn get_recent(&self) -> T { + if self.records.is_empty() { + return T::default(); + } + self.records.back().unwrap().0 + } + + pub fn get_avg(&self) -> f64 { + if self.records.is_empty() { + return 0.0; + } + self.total.as_() / self.records.len() as f64 + } + + pub fn get_max(&self) -> T { + if self.records.is_empty() { + return T::default(); + } + self.records + .iter() + .max_by(|a, b| a.0.partial_cmp(&b.0).unwrap()) + .unwrap() + .0 + } + + pub fn get_percentile_90(&mut self) -> T { + if self.records.is_empty() { + return FromPrimitive::from_u64(0).unwrap(); + } + let mut v: Vec<_> = self.records.iter().collect(); + v.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); + v[((self.records.len() - 1) as f64 * 0.90) as usize].0 + } + + pub fn trend(&self) -> Trend { + if self.records.len() <= 1 { + return Trend::NoTrend; + } + + // If the lastest record is too old, no trend + if self.records.back().unwrap().1.saturating_elapsed_secs() > STALE_DUR as f64 { + return Trend::NoTrend; + } + + let (mut left, mut left_cnt) = (T::default(), 0); + let (mut right, mut right_cnt) = (T::default(), 0); + + // The time span matters + if MIN_TIME_SPAN > 0 { + // If the records doesn't cover a enough time span, no trend + let time_span = self.records.front().unwrap().1.saturating_elapsed_secs() + - self.records.back().unwrap().1.saturating_elapsed_secs(); + if time_span < MIN_TIME_SPAN as f64 { + return Trend::NoTrend; + } + + // Split the record into left and right by the middle of time range + for r in self.records.iter() { + let elapsed_secs = r.1.saturating_elapsed_secs(); + if elapsed_secs > time_span / 2.0 { + left += r.0; + left_cnt += 1; + } else { + right += r.0; + right_cnt += 1; + } + } + } else { + let half = self.records.len() / 2; + for (i, r) in self.records.iter().enumerate() { + if i < half { + left += r.0; + left_cnt += 1; + } else { + right += r.0; + right_cnt += 1; + } + } + } + + // Decide if there is a trend by the two averages. + // Adding 2 here is to give a tolerance + let (l_avg, r_avg) = (left.as_() / left_cnt as f64, right.as_() / right_cnt as f64); + if r_avg > l_avg + 2.0 { + return Trend::Increasing; + } + if l_avg > r_avg + 2.0 { + return Trend::Decreasing; + } + + Trend::NoTrend + } +} + +#[cfg(test)] +pub(super) mod tests { + use std::{ops::Sub, time::Duration}; + + use crate::{ + smoother::{ + Smoother, Trend, SMOOTHER_STALE_RECORD_THRESHOLD, SMOOTHER_TIME_RANGE_THRESHOLD, + }, + time::Instant, + }; + + #[test] + fn test_smoother() { + let mut smoother = Smoother::::default(); + smoother.observe(1); + smoother.observe(6); + smoother.observe(2); + smoother.observe(3); + smoother.observe(4); + smoother.observe(5); + smoother.observe(0); + + assert!((smoother.get_avg() - 2.8).abs() < f64::EPSILON); + assert_eq!(smoother.get_recent(), 0); + assert_eq!(smoother.get_max(), 5); + assert_eq!(smoother.get_percentile_90(), 4); + assert_eq!(smoother.trend(), Trend::NoTrend); + + let mut smoother = Smoother::::default(); + smoother.observe(1.0); + smoother.observe(6.0); + smoother.observe(2.0); + smoother.observe(3.0); + smoother.observe(4.0); + smoother.observe(5.0); + smoother.observe(9.0); + assert!((smoother.get_avg() - 4.6).abs() < f64::EPSILON); + assert!((smoother.get_recent() - 9.0).abs() < f64::EPSILON); + assert!((smoother.get_max() - 9.0).abs() < f64::EPSILON); + assert!((smoother.get_percentile_90() - 5.0).abs() < f64::EPSILON); + assert_eq!(smoother.trend(), Trend::Increasing); + } + + #[test] + fn test_smoother_trend() { + // The time range is not enough + let mut smoother = Smoother::< + u64, + 6, + SMOOTHER_STALE_RECORD_THRESHOLD, + SMOOTHER_TIME_RANGE_THRESHOLD, + >::default(); + let now = Instant::now_coarse(); + smoother.observe_with_time( + 1, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 1)), + ); + smoother.observe_with_time( + 1, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 2)), + ); + smoother.observe_with_time( + 1, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 3)), + ); + smoother.observe_with_time(4, now.sub(Duration::from_secs(2))); + smoother.observe_with_time(4, now.sub(Duration::from_secs(1))); + smoother.observe_with_time(4, now); + assert_eq!(smoother.trend(), Trend::NoTrend); + + // Increasing trend, the left range contains 3 records, the right range contains + // 1 records. + let mut smoother = Smoother::< + f64, + 6, + SMOOTHER_STALE_RECORD_THRESHOLD, + SMOOTHER_TIME_RANGE_THRESHOLD, + >::default(); + smoother.observe_with_time( + 1.0, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), + ); + smoother.observe_with_time( + 1.0, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD)), + ); + smoother.observe_with_time( + 1.0, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 1)), + ); + smoother.observe_with_time(4.0, now); + assert_eq!(smoother.trend(), Trend::Increasing); + + // Decreasing trend, the left range contains 1 records, the right range contains + // 3 records. + let mut smoother = Smoother::< + f32, + 6, + SMOOTHER_STALE_RECORD_THRESHOLD, + SMOOTHER_TIME_RANGE_THRESHOLD, + >::default(); + smoother.observe_with_time( + 4.0, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), + ); + smoother.observe_with_time(1.0, now.sub(Duration::from_secs(2))); + smoother.observe_with_time(2.0, now.sub(Duration::from_secs(1))); + smoother.observe_with_time(1.0, now); + assert_eq!(smoother.trend(), Trend::Decreasing); + + // No trend, the left range contains 1 records, the right range contains 3 + // records. + let mut smoother = Smoother::< + f32, + 6, + SMOOTHER_STALE_RECORD_THRESHOLD, + SMOOTHER_TIME_RANGE_THRESHOLD, + >::default(); + smoother.observe_with_time( + 1.0, + now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), + ); + smoother.observe_with_time(1.0, now.sub(Duration::from_secs(2))); + smoother.observe_with_time(3.0, now.sub(Duration::from_secs(1))); + smoother.observe_with_time(2.0, now); + assert_eq!(smoother.trend(), Trend::NoTrend); + + // No trend, because the latest record is too old + let mut smoother = Smoother::< + u32, + 6, + SMOOTHER_STALE_RECORD_THRESHOLD, + SMOOTHER_TIME_RANGE_THRESHOLD, + >::default(); + smoother.observe_with_time( + 1, + now.sub(Duration::from_secs(SMOOTHER_STALE_RECORD_THRESHOLD + 1)), + ); + assert_eq!(smoother.trend(), Trend::NoTrend); + } +} diff --git a/src/storage/txn/flow_controller/singleton_flow_controller.rs b/src/storage/txn/flow_controller/singleton_flow_controller.rs index 2d36b9d15b0..54f568cf444 100644 --- a/src/storage/txn/flow_controller/singleton_flow_controller.rs +++ b/src/storage/txn/flow_controller/singleton_flow_controller.rs @@ -2,9 +2,6 @@ // #[PerformanceCriticalPath] use std::{ - cmp::PartialOrd, - collections::VecDeque, - ops::{Add, AddAssign, Sub, SubAssign}, sync::{ atomic::{AtomicU32, Ordering}, mpsc::{self, Receiver, RecvTimeoutError, SyncSender}, @@ -19,11 +16,11 @@ use collections::HashMap; use engine_rocks::FlowInfo; use engine_traits::{CfNamesExt, FlowControlFactorsExt}; use getset::{CopyGetters, Setters}; -use num_traits::cast::{AsPrimitive, FromPrimitive}; use online_config::{ConfigChange, OnlineConfig}; use rand::Rng; use tikv_util::{ config::VersionTrack, + smoother::{Smoother, Trend, SMOOTHER_STALE_RECORD_THRESHOLD, SMOOTHER_TIME_RANGE_THRESHOLD}, sys::thread::StdThreadBuildWrapper, time::{Instant, Limiter}, }; @@ -40,13 +37,6 @@ const MAX_THROTTLE_SPEED: f64 = 200.0 * 1024.0 * 1024.0; // 200MB const EMA_FACTOR: f64 = 0.6; // EMA stands for Exponential Moving Average -#[derive(PartialEq, Debug)] -enum Trend { - Increasing, - Decreasing, - NoTrend, -} - /// Flow controller is used to throttle the write rate at scheduler level, /// aiming to substitute the write stall mechanism of RocksDB. It features in /// two points: @@ -200,179 +190,6 @@ impl EngineFlowController { } } -const SMOOTHER_STALE_RECORD_THRESHOLD: u64 = 300; // 5min -const SMOOTHER_TIME_RANGE_THRESHOLD: u64 = 60; // 1min - -// Smoother is a sliding window used to provide steadier flow statistics. -struct Smoother -where - T: Default - + Add - + Sub - + AddAssign - + SubAssign - + PartialOrd - + AsPrimitive - + FromPrimitive, -{ - records: VecDeque<(T, Instant)>, - total: T, -} - -impl Default - for Smoother -where - T: Default - + Add - + Sub - + AddAssign - + SubAssign - + PartialOrd - + AsPrimitive - + FromPrimitive, -{ - fn default() -> Self { - Self { - records: VecDeque::with_capacity(CAP), - total: Default::default(), - } - } -} - -impl - Smoother -where - T: Default - + Add - + Sub - + AddAssign - + SubAssign - + PartialOrd - + AsPrimitive - + FromPrimitive, -{ - pub fn observe(&mut self, record: T) { - self.observe_with_time(record, Instant::now_coarse()); - } - - pub fn observe_with_time(&mut self, record: T, time: Instant) { - if self.records.len() == CAP { - let v = self.records.pop_front().unwrap().0; - self.total -= v; - } - - self.total += record; - - self.records.push_back((record, time)); - self.remove_stale_records(); - } - - fn remove_stale_records(&mut self) { - // make sure there are two records left at least - while self.records.len() > 2 { - if self.records.front().unwrap().1.saturating_elapsed_secs() > STALE_DUR as f64 { - let v = self.records.pop_front().unwrap().0; - self.total -= v; - } else { - break; - } - } - } - - pub fn get_recent(&self) -> T { - if self.records.is_empty() { - return T::default(); - } - self.records.back().unwrap().0 - } - - pub fn get_avg(&self) -> f64 { - if self.records.is_empty() { - return 0.0; - } - self.total.as_() / self.records.len() as f64 - } - - pub fn get_max(&self) -> T { - if self.records.is_empty() { - return T::default(); - } - self.records - .iter() - .max_by(|a, b| a.0.partial_cmp(&b.0).unwrap()) - .unwrap() - .0 - } - - pub fn get_percentile_90(&mut self) -> T { - if self.records.is_empty() { - return FromPrimitive::from_u64(0).unwrap(); - } - let mut v: Vec<_> = self.records.iter().collect(); - v.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); - v[((self.records.len() - 1) as f64 * 0.90) as usize].0 - } - - pub fn trend(&self) -> Trend { - if self.records.len() <= 1 { - return Trend::NoTrend; - } - - // If the lastest record is too old, no trend - if self.records.back().unwrap().1.saturating_elapsed_secs() > STALE_DUR as f64 { - return Trend::NoTrend; - } - - let (mut left, mut left_cnt) = (T::default(), 0); - let (mut right, mut right_cnt) = (T::default(), 0); - - // The time span matters - if MIN_TIME_SPAN > 0 { - // If the records doesn't cover a enough time span, no trend - let time_span = self.records.front().unwrap().1.saturating_elapsed_secs() - - self.records.back().unwrap().1.saturating_elapsed_secs(); - if time_span < MIN_TIME_SPAN as f64 { - return Trend::NoTrend; - } - - // Split the record into left and right by the middle of time range - for r in self.records.iter() { - let elapsed_secs = r.1.saturating_elapsed_secs(); - if elapsed_secs > time_span / 2.0 { - left += r.0; - left_cnt += 1; - } else { - right += r.0; - right_cnt += 1; - } - } - } else { - let half = self.records.len() / 2; - for (i, r) in self.records.iter().enumerate() { - if i < half { - left += r.0; - left_cnt += 1; - } else { - right += r.0; - right_cnt += 1; - } - } - } - - // Decide if there is a trend by the two averages. - // Adding 2 here is to give a tolerance - let (l_avg, r_avg) = (left.as_() / left_cnt as f64, right.as_() / right_cnt as f64); - if r_avg > l_avg + 2.0 { - return Trend::Increasing; - } - if l_avg > r_avg + 2.0 { - return Trend::Decreasing; - } - - Trend::NoTrend - } -} - // CfFlowChecker records some statistics and states related to one CF. // These statistics fall into five categories: // * memtable @@ -1447,134 +1264,4 @@ pub(super) mod tests { send_flow_info(&tx, region_id); assert!(flow_controller.discard_ratio(region_id) > f64::EPSILON); } - - #[test] - fn test_smoother() { - let mut smoother = Smoother::::default(); - smoother.observe(1); - smoother.observe(6); - smoother.observe(2); - smoother.observe(3); - smoother.observe(4); - smoother.observe(5); - smoother.observe(0); - - assert!((smoother.get_avg() - 2.8).abs() < f64::EPSILON); - assert_eq!(smoother.get_recent(), 0); - assert_eq!(smoother.get_max(), 5); - assert_eq!(smoother.get_percentile_90(), 4); - assert_eq!(smoother.trend(), Trend::NoTrend); - - let mut smoother = Smoother::::default(); - smoother.observe(1.0); - smoother.observe(6.0); - smoother.observe(2.0); - smoother.observe(3.0); - smoother.observe(4.0); - smoother.observe(5.0); - smoother.observe(9.0); - assert!((smoother.get_avg() - 4.6).abs() < f64::EPSILON); - assert!((smoother.get_recent() - 9.0).abs() < f64::EPSILON); - assert!((smoother.get_max() - 9.0).abs() < f64::EPSILON); - assert!((smoother.get_percentile_90() - 5.0).abs() < f64::EPSILON); - assert_eq!(smoother.trend(), Trend::Increasing); - } - - #[test] - fn test_smoother_trend() { - // The time range is not enough - let mut smoother = Smoother::< - u64, - 6, - SMOOTHER_STALE_RECORD_THRESHOLD, - SMOOTHER_TIME_RANGE_THRESHOLD, - >::default(); - let now = Instant::now_coarse(); - smoother.observe_with_time( - 1, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 1)), - ); - smoother.observe_with_time( - 1, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 2)), - ); - smoother.observe_with_time( - 1, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 3)), - ); - smoother.observe_with_time(4, now.sub(Duration::from_secs(2))); - smoother.observe_with_time(4, now.sub(Duration::from_secs(1))); - smoother.observe_with_time(4, now); - assert_eq!(smoother.trend(), Trend::NoTrend); - - // Increasing trend, the left range contains 3 records, the right range contains - // 1 records. - let mut smoother = Smoother::< - f64, - 6, - SMOOTHER_STALE_RECORD_THRESHOLD, - SMOOTHER_TIME_RANGE_THRESHOLD, - >::default(); - smoother.observe_with_time( - 1.0, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), - ); - smoother.observe_with_time( - 1.0, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD)), - ); - smoother.observe_with_time( - 1.0, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD - 1)), - ); - smoother.observe_with_time(4.0, now); - assert_eq!(smoother.trend(), Trend::Increasing); - - // Decreasing trend, the left range contains 1 records, the right range contains - // 3 records. - let mut smoother = Smoother::< - f32, - 6, - SMOOTHER_STALE_RECORD_THRESHOLD, - SMOOTHER_TIME_RANGE_THRESHOLD, - >::default(); - smoother.observe_with_time( - 4.0, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), - ); - smoother.observe_with_time(1.0, now.sub(Duration::from_secs(2))); - smoother.observe_with_time(2.0, now.sub(Duration::from_secs(1))); - smoother.observe_with_time(1.0, now); - assert_eq!(smoother.trend(), Trend::Decreasing); - - // No trend, the left range contains 1 records, the right range contains 3 - // records. - let mut smoother = Smoother::< - f32, - 6, - SMOOTHER_STALE_RECORD_THRESHOLD, - SMOOTHER_TIME_RANGE_THRESHOLD, - >::default(); - smoother.observe_with_time( - 1.0, - now.sub(Duration::from_secs(SMOOTHER_TIME_RANGE_THRESHOLD + 1)), - ); - smoother.observe_with_time(1.0, now.sub(Duration::from_secs(2))); - smoother.observe_with_time(3.0, now.sub(Duration::from_secs(1))); - smoother.observe_with_time(2.0, now); - assert_eq!(smoother.trend(), Trend::NoTrend); - - // No trend, because the latest record is too old - let mut smoother = Smoother::< - u32, - 6, - SMOOTHER_STALE_RECORD_THRESHOLD, - SMOOTHER_TIME_RANGE_THRESHOLD, - >::default(); - smoother.observe_with_time( - 1, - now.sub(Duration::from_secs(SMOOTHER_STALE_RECORD_THRESHOLD + 1)), - ); - assert_eq!(smoother.trend(), Trend::NoTrend); - } } From 7f154c0086580019fc01c7b41199acfb0eff5554 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 10 Sep 2024 11:45:56 +0800 Subject: [PATCH 058/144] In-memory Engine: unify thread names (#17506) ref tikv/tikv#16141 Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 46 +++++++++++-------- .../src/region_label.rs | 2 +- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 92428df4a27..76415a945bc 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::HashMap, fmt::Display, sync::Arc, thread::JoinHandle, time::Duration}; +use std::{collections::HashMap, fmt::Display, sync::Arc, time::Duration}; use bytes::Bytes; use crossbeam::{ @@ -124,16 +124,16 @@ pub struct BgWorkManager { worker: Worker, scheduler: Scheduler, delete_region_scheduler: Scheduler, - tick_stopper: Option<(JoinHandle<()>, Sender)>, + tick_stopper: Option<(Worker, Sender)>, core: Arc>, region_info_provider: Option>, } impl Drop for BgWorkManager { fn drop(&mut self) { - let (h, tx) = self.tick_stopper.take().unwrap(); + let (ticker, tx) = self.tick_stopper.take().unwrap(); let _ = tx.send(true); - let _ = h.join(); + ticker.stop(); self.worker.stop(); } } @@ -225,7 +225,7 @@ impl BgWorkManager { memory_controller: Arc, region_info_provider: Option>, ) -> Self { - let worker = Worker::new("range-cache-background-worker"); + let worker = Worker::new("ime-bg"); let (runner, delete_range_scheduler) = BackgroundRunner::new( core.clone(), memory_controller, @@ -235,9 +235,9 @@ impl BgWorkManager { gc_interval, pd_client.clone(), ); - let scheduler = worker.start_with_timer("range-cache-engine-background", runner); + let scheduler = worker.start_with_timer("ime-bg-runner", runner); - let (h, tx) = BgWorkManager::start_tick( + let (ticker, tx) = BgWorkManager::start_tick( scheduler.clone(), pd_client, gc_interval, @@ -248,7 +248,7 @@ impl BgWorkManager { worker, scheduler, delete_region_scheduler: delete_range_scheduler, - tick_stopper: Some((h, tx)), + tick_stopper: Some((ticker, tx)), core, region_info_provider, } @@ -307,11 +307,17 @@ impl BgWorkManager { pd_client: Arc, gc_interval: Duration, load_evict_interval: Duration, - ) -> (JoinHandle<()>, Sender) { + ) -> (Worker, Sender) { let (tx, rx) = bounded(0); // TODO: Instead of spawning a new thread, we should run this task // in a shared background thread. - let h = std::thread::spawn(move || { + let ticker = Builder::new("ime-ticker").thread_count(1).create(); + // The interval here is somewhat arbitrary, as long as it is less than + // intervals in the loop, it should be fine, because it spawns a + // blocking task. + // TODO: Spawn non-blocking tasks and make full use of the ticker. + let interval = Duration::from_millis(100); + ticker.spawn_interval_task(interval, move || { let gc_ticker = tick(gc_interval); let load_evict_ticker = tick(load_evict_interval); // TODO (afeinberg): Use a real value. let tso_timeout = std::cmp::min(gc_interval, TIMTOUT_FOR_TSO); @@ -349,7 +355,7 @@ impl BgWorkManager { recv(rx) -> r => { if let Err(e) = r { error!( - "ime receive error in range cache engien gc ticker"; + "ime receive error in range cache engine gc ticker"; "err" => ?e, ); } @@ -358,7 +364,7 @@ impl BgWorkManager { } } }); - (h, tx) + (ticker, tx) } } @@ -804,28 +810,28 @@ impl BackgroundRunner { gc_interval: Duration, pd_client: Arc, ) -> (Self, Scheduler) { - let range_load_worker = Builder::new("background-range-load-worker") + let range_load_worker = Builder::new("ime-load") // Range load now is implemented sequentially, so we must use exactly one thread to handle it. // todo(SpadeA): if the load speed is a bottleneck, we may consider to use multiple threads to load ranges. .thread_count(1) .create(); let range_load_remote = range_load_worker.remote(); - let delete_range_worker = Worker::new("background-delete-range-worker"); + let delete_range_worker = Worker::new("ime-delete"); let delete_range_runner = DeleteRangeRunner::new(engine.clone()); let delete_range_scheduler = - delete_range_worker.start_with_timer("delete-range-runner", delete_range_runner); + delete_range_worker.start_with_timer("ime-delete-runner", delete_range_runner); - let lock_cleanup_worker = Worker::new("lock-cleanup-worker"); + let lock_cleanup_worker = Worker::new("ime-lock-cleanup"); let lock_cleanup_remote = lock_cleanup_worker.remote(); - let gc_range_worker = Builder::new("background-range-load-worker") + let gc_range_worker = Builder::new("ime-gc") // Gc must also use exactly one thread to handle it. .thread_count(1) .create(); let gc_range_remote = gc_range_worker.remote(); - let load_evict_worker = Worker::new("background-region-load-evict-worker"); + let load_evict_worker = Worker::new("ime-evict"); let load_evict_remote = load_evict_worker.remote(); let num_regions_to_cache = memory_controller.soft_limit_threshold() / expected_region_size; @@ -3048,7 +3054,7 @@ pub mod tests { let gc_interval = Duration::from_millis(100); let load_evict_interval = Duration::from_millis(200); let (scheduler, mut rx) = dummy_scheduler(); - let (handle, stop) = + let (ticker, stop) = BgWorkManager::start_tick(scheduler, pd_client, gc_interval, load_evict_interval); let Some(BackgroundTask::Gc(GcTask { safe_point })) = @@ -3065,6 +3071,6 @@ pub mod tests { pd_client_rx.try_recv().unwrap(); stop.send(true).unwrap(); - handle.join().unwrap(); + ticker.stop(); } } diff --git a/components/range_cache_memory_engine/src/region_label.rs b/components/range_cache_memory_engine/src/region_label.rs index 9e0d5cc8d66..3f842440629 100644 --- a/components/range_cache_memory_engine/src/region_label.rs +++ b/components/range_cache_memory_engine/src/region_label.rs @@ -424,7 +424,7 @@ pub mod tests { ); }; - let background_worker = Builder::new("background").thread_count(1).create(); + let background_worker = Builder::new("ime-test").thread_count(1).create(); let mut s_clone = s.clone(); background_worker.spawn_async_task(async move { s_clone.watch_region_labels().await; From a2870bd4c8dedd118ddc8398b9abd800df0fdc1e Mon Sep 17 00:00:00 2001 From: okJiang Date: Tue, 10 Sep 2024 15:38:26 +0800 Subject: [PATCH 059/144] util: bump kvproto version (#17514) close tikv/tikv#17513 Signed-off-by: okJiang <819421878@qq.com> --- Cargo.lock | 2 +- components/pd_client/src/util.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 36ca62879e5..19c95ce2607 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2845,7 +2845,7 @@ dependencies = [ [[package]] name = "kvproto" version = "0.0.2" -source = "git+https://github.com/pingcap/kvproto.git#0ad602a429126e39bd4a87c687be64f9ae173c02" +source = "git+https://github.com/pingcap/kvproto.git#0b10bdf8ba4b5f71b8cb74daee97e302f7e146e2" dependencies = [ "futures 0.3.15", "grpcio", diff --git a/components/pd_client/src/util.rs b/components/pd_client/src/util.rs index 058590dceff..e0de84b3b01 100644 --- a/components/pd_client/src/util.rs +++ b/components/pd_client/src/util.rs @@ -952,6 +952,8 @@ pub fn check_resp_header(header: &ResponseHeader) -> Result<()> { ErrorType::Unknown => Err(box_err!(err.get_message())), ErrorType::InvalidValue => Err(box_err!(err.get_message())), ErrorType::GlobalConfigNotFound => panic!("unexpected error {:?}", err), + // It will not happen, because we don't call `batch_scan_regions` in TiKV. + ErrorType::RegionsNotContainAllKeyRange => Err(box_err!(err.get_message())), } } From d99bd9b0dc835972846039242b79838df76f045b Mon Sep 17 00:00:00 2001 From: qupeng Date: Tue, 10 Sep 2024 18:15:29 +0800 Subject: [PATCH 060/144] cdc: handles unordered prewrites on one same key (#16864) close tikv/tikv#17502 add generation field into TiCDC Prewrite events Signed-off-by: qupeng Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/cdc/src/delegate.rs | 24 +++++-- components/cdc/src/initializer.rs | 3 +- .../cdc/tests/failpoints/test_endpoint.rs | 66 +++++++++++++++++++ components/cdc/tests/mod.rs | 45 +++++++++++++ 4 files changed, 131 insertions(+), 7 deletions(-) diff --git a/components/cdc/src/delegate.rs b/components/cdc/src/delegate.rs index 5b979ade2ec..cbc8ad3118f 100644 --- a/components/cdc/src/delegate.rs +++ b/components/cdc/src/delegate.rs @@ -290,16 +290,18 @@ impl fmt::Debug for LockTracker { pub struct MiniLock { pub ts: TimeStamp, pub txn_source: u64, + pub generation: u64, } impl MiniLock { - pub fn new(ts: T, txn_source: u64) -> Self + pub fn new(ts: T, txn_source: u64, generation: u64) -> Self where TimeStamp: From, { MiniLock { ts: TimeStamp::from(ts), txn_source, + generation, } } @@ -311,6 +313,7 @@ impl MiniLock { MiniLock { ts: TimeStamp::from(ts), txn_source: 0, + generation: 0, } } } @@ -368,13 +371,19 @@ impl Delegate { CDC_PENDING_BYTES_GAUGE.add(bytes as _); locks.push(PendingLock::Track { key, start_ts }); } - LockTracker::Prepared { locks, .. } => { - if locks.insert(key, start_ts).is_none() { + LockTracker::Prepared { locks, .. } => match locks.entry(key) { + BTreeMapEntry::Occupied(mut x) => { + assert_eq!(x.get().ts, start_ts.ts); + assert!(x.get().generation <= start_ts.generation); + x.get_mut().generation = start_ts.generation; + } + BTreeMapEntry::Vacant(x) => { + x.insert(start_ts); self.memory_quota.alloc(bytes)?; CDC_PENDING_BYTES_GAUGE.add(bytes as _); lock_count_modify = 1; } - } + }, } Ok(lock_count_modify) } @@ -428,7 +437,8 @@ impl Delegate { x.insert(start_ts); } BTreeMapEntry::Occupied(x) => { - assert_eq!(*x.get(), start_ts); + assert_eq!(x.get().ts, start_ts.ts); + assert!(x.get().generation <= start_ts.generation); } }, PendingLock::Untrack { key } => match locks.entry(key.clone()) { @@ -1027,6 +1037,7 @@ impl Delegate { let lock = Lock::parse(put.get_value()).unwrap(); let for_update_ts = lock.for_update_ts; let txn_source = lock.txn_source; + let generation = lock.generation; let key = Key::from_encoded_slice(&put.key); let row = rows.txns_by_key.entry(key.clone()).or_default(); @@ -1035,7 +1046,7 @@ impl Delegate { } assert_eq!(row.lock_count_modify, 0); - let mini_lock = MiniLock::new(row.v.start_ts, txn_source); + let mini_lock = MiniLock::new(row.v.start_ts, txn_source, generation); row.lock_count_modify = self.push_lock(key, mini_lock)?; let read_old_ts = std::cmp::max(for_update_ts, row.v.start_ts.into()); @@ -1265,6 +1276,7 @@ fn decode_lock(key: Vec, mut lock: Lock, row: &mut EventRow, has_value: &mut }; row.start_ts = lock.ts.into_inner(); + row.generation = lock.generation; row.key = key.into_raw().unwrap(); row.op_type = op_type as _; row.txn_source = lock.txn_source; diff --git a/components/cdc/src/initializer.rs b/components/cdc/src/initializer.rs index 488a8e432f7..a3460272918 100644 --- a/components/cdc/src/initializer.rs +++ b/components/cdc/src/initializer.rs @@ -277,7 +277,8 @@ impl Initializer { for (key, lock) in key_locks { // When `decode_lock`, only consider `Put` and `Delete` if matches!(lock.lock_type, LockType::Put | LockType::Delete) { - locks.insert(key, MiniLock::new(lock.ts, lock.txn_source)); + let mini_lock = MiniLock::new(lock.ts, lock.txn_source, lock.generation); + locks.insert(key, mini_lock); } } self.finish_scan_locks(region, locks); diff --git a/components/cdc/tests/failpoints/test_endpoint.rs b/components/cdc/tests/failpoints/test_endpoint.rs index 2e9103727e4..2e11018ba8d 100644 --- a/components/cdc/tests/failpoints/test_endpoint.rs +++ b/components/cdc/tests/failpoints/test_endpoint.rs @@ -656,3 +656,69 @@ fn test_delegate_fail_during_incremental_scan() { recv_timeout(&mut recver, Duration::from_secs(1)).unwrap_err(); recv.replace(Some(recver)); } + +// The case shows it's possible that unordered Prewrite events on one same key +// can be sent to TiCDC clients. Generally it only happens when a region changes +// during a Pipelined-DML transaction. +// +// To ensure TiCDC can handle the situation, `generation` should be carried in +// Prewrite events. +#[test] +fn test_cdc_pipeline_dml() { + let mut cluster = new_server_cluster(0, 1); + configure_for_lease_read(&mut cluster.cfg, Some(100), Some(10)); + cluster.pd_client.disable_default_operator(); + let mut suite = TestSuiteBuilder::new().cluster(cluster).build(); + let region = suite.cluster.get_region(&[]); + let rid = region.id; + + let prewrite_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + let (k, v) = (b"key".to_vec(), vec![b'x'; 16]); + let mut mutation = Mutation::default(); + mutation.set_op(Op::Put); + mutation.key = k.clone(); + mutation.value = v; + suite.must_kv_flush(rid, vec![mutation], k.clone(), prewrite_tso, 1); + + fail::cfg("cdc_incremental_scan_start", "pause").unwrap(); + + let cf_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + let (mut req_tx, _, receive_event) = new_event_feed_v2(suite.get_region_cdc_client(rid)); + let mut req = suite.new_changedata_request(rid); + req.request_id = 1; + req.checkpoint_ts = cf_tso.into_inner(); + block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + + let (k, v) = (b"key".to_vec(), vec![b'y'; 16]); + let mut mutation = Mutation::default(); + mutation.set_op(Op::Put); + mutation.key = k.clone(); + mutation.value = v; + suite.must_kv_flush(rid, vec![mutation], k.clone(), prewrite_tso, 2); + + let events = receive_event(false).take_events().into_vec(); + for entry in events[0].get_entries().get_entries() { + assert_eq!(entry.r_type, EventLogType::Prewrite); + assert_eq!(entry.generation, 2); + assert_eq!(entry.value, vec![b'y'; 16]); + } + + let commit_tso = block_on(suite.cluster.pd_client.get_tso()).unwrap(); + suite.must_kv_commit(rid, vec![b"key".to_vec()], prewrite_tso, commit_tso); + + let events = receive_event(false).take_events().into_vec(); + for entry in events[0].get_entries().get_entries() { + assert_eq!(entry.r_type, EventLogType::Commit); + assert_eq!(entry.start_ts, prewrite_tso.into_inner()); + assert_eq!(entry.commit_ts, commit_tso.into_inner()); + } + + fail::remove("cdc_incremental_scan_start"); + + let events = receive_event(false).take_events().into_vec(); + let entries = events[0].get_entries().get_entries(); + assert_eq!(entries[0].r_type, EventLogType::Prewrite); + assert_eq!(entries[0].generation, 1); + assert_eq!(entries[0].value, vec![b'x'; 16]); + assert_eq!(entries[1].r_type, EventLogType::Initialized); +} diff --git a/components/cdc/tests/mod.rs b/components/cdc/tests/mod.rs index 31b1db087a4..efe6bca2492 100644 --- a/components/cdc/tests/mod.rs +++ b/components/cdc/tests/mod.rs @@ -343,6 +343,51 @@ impl TestSuite { ); } + pub fn must_kv_flush( + &mut self, + region_id: u64, + muts: Vec, + pk: Vec, + ts: TimeStamp, + generation: u64, + ) { + self.must_kv_flush_with_source(region_id, muts, pk, ts, generation, 0); + } + + pub fn must_kv_flush_with_source( + &mut self, + region_id: u64, + muts: Vec, + pk: Vec, + ts: TimeStamp, + generation: u64, + txn_source: u64, + ) { + let mut flush_req = FlushRequest::default(); + let mut context = self.get_context(region_id); + context.set_txn_source(txn_source); + flush_req.set_context(context); + flush_req.set_mutations(muts.into_iter().collect()); + flush_req.primary_key = pk; + flush_req.start_ts = ts.into_inner(); + flush_req.generation = generation; + flush_req.lock_ttl = flush_req.start_ts + 1; + let flush_resp = self + .get_tikv_client(region_id) + .kv_flush(&flush_req) + .unwrap(); + assert!( + !flush_resp.has_region_error(), + "{:?}", + flush_resp.get_region_error() + ); + assert!( + flush_resp.errors.is_empty(), + "{:?}", + flush_resp.get_errors() + ); + } + pub fn must_kv_put(&mut self, region_id: u64, key: Vec, value: Vec) { let mut rawkv_req = RawPutRequest::default(); rawkv_req.set_context(self.get_context(region_id)); From 4f47cb0670129dad6ee6a1a667ee23c95a58561b Mon Sep 17 00:00:00 2001 From: glorv Date: Wed, 11 Sep 2024 16:35:26 +0800 Subject: [PATCH 061/144] In-memory-engine: refactor region manager to avoiding acquire global write lock in hot path (#17477) ref tikv/tikv#16141 refactor region manager to avoiding acquire global write lock in hot path Signed-off-by: glorv Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/hybrid_engine/src/engine.rs | 8 +- components/hybrid_engine/src/misc.rs | 2 +- components/hybrid_engine/src/snapshot.rs | 5 +- components/hybrid_engine/src/write_batch.rs | 23 +- .../tests/failpoints/test_write_batch.rs | 7 +- components/raftstore/src/store/worker/read.rs | 16 +- .../src/background.rs | 305 ++++---- .../range_cache_memory_engine/src/engine.rs | 242 ++++-- .../src/range_manager.rs | 699 ++++++++++-------- .../range_cache_memory_engine/src/read.rs | 239 +++--- .../src/write_batch.rs | 160 ++-- .../tests/failpoints/test_memory_engine.rs | 43 +- .../cases/test_range_cache_engine.rs | 109 +-- 13 files changed, 957 insertions(+), 901 deletions(-) diff --git a/components/hybrid_engine/src/engine.rs b/components/hybrid_engine/src/engine.rs index cddb3a15d37..870b122a695 100644 --- a/components/hybrid_engine/src/engine.rs +++ b/components/hybrid_engine/src/engine.rs @@ -242,10 +242,10 @@ mod tests { let region = new_region(1, b"k00", b"k10"); let range = CacheRegion::from_region(®ion); memory_engine.new_region(region.clone()); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(region.id, 10); - } + memory_engine + .core() + .region_manager() + .set_safe_point(region.id, 10); let hybrid_engine = HybridEngine::new(disk_engine, memory_engine.clone()); let s = hybrid_engine.snapshot(None); diff --git a/components/hybrid_engine/src/misc.rs b/components/hybrid_engine/src/misc.rs index ef08e56c10a..e9fd5936346 100644 --- a/components/hybrid_engine/src/misc.rs +++ b/components/hybrid_engine/src/misc.rs @@ -194,7 +194,7 @@ pub mod tests { write_batch.put(b"zk23", b"val").unwrap(); write_batch.prepare_for_region(cache_r3.clone()); write_batch.put(b"zk42", b"val").unwrap(); - write_batch.put(b"zk42", b"val").unwrap(); + write_batch.put(b"zk43", b"val").unwrap(); write_batch.write().unwrap(); hybrid_engine diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index 7a07e95dbf9..b3cc5c33781 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -184,10 +184,7 @@ mod tests { RangeCacheEngineConfig::config_for_test(), move |memory_engine| { memory_engine.new_region(region_clone); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(1, 5); - } + memory_engine.core().region_manager().set_safe_point(1, 5); }, ) .unwrap(); diff --git a/components/hybrid_engine/src/write_batch.rs b/components/hybrid_engine/src/write_batch.rs index 2c718c3bd6d..f79101dda6e 100644 --- a/components/hybrid_engine/src/write_batch.rs +++ b/components/hybrid_engine/src/write_batch.rs @@ -171,11 +171,7 @@ mod tests { move |memory_engine| { let id = region_clone.id; memory_engine.new_region(region_clone); - memory_engine - .core() - .write() - .mut_range_manager() - .set_safe_point(id, 5); + memory_engine.core().region_manager().set_safe_point(id, 5); }, ) .unwrap(); @@ -216,10 +212,7 @@ mod tests { |memory_engine| { let region = new_region(1, b"k00", b"k10"); memory_engine.new_region(region); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(1, 10); - } + memory_engine.core().region_manager().set_safe_point(1, 10); }, ) .unwrap(); @@ -260,7 +253,7 @@ mod tests { wb.prepare_for_region(cache_region1.clone()); wb.put(b"zk05", b"val").unwrap(); wb.put(b"zk08", b"val2").unwrap(); - wb.prepare_for_region(cache_region1.clone()); + wb.prepare_for_region(cache_region2.clone()); wb.put(b"zk25", b"val3").unwrap(); wb.put(b"zk27", b"val4").unwrap(); wb.write().unwrap(); @@ -278,7 +271,6 @@ mod tests { hybrid_engine .range_cache_engine() .core() - .read() .engine() .cf_handle("default") .len() @@ -305,14 +297,7 @@ mod tests { test_util::eventually( Duration::from_millis(100), Duration::from_millis(2000), - || { - m_engine - .core() - .read() - .engine() - .cf_handle("default") - .is_empty() - }, + || m_engine.core().engine().cf_handle("default").is_empty(), ); } } diff --git a/components/hybrid_engine/tests/failpoints/test_write_batch.rs b/components/hybrid_engine/tests/failpoints/test_write_batch.rs index 1185bfb8e58..2db925ba248 100644 --- a/components/hybrid_engine/tests/failpoints/test_write_batch.rs +++ b/components/hybrid_engine/tests/failpoints/test_write_batch.rs @@ -63,12 +63,7 @@ fn test_sequence_number_unique() { rx.recv().unwrap(); wb.write().unwrap(); - let mut iter = engine - .core() - .read() - .engine() - .cf_handle("default") - .iterator(); + let mut iter = engine.core().engine().cf_handle("default").iterator(); let guard = &epoch::pin(); let mut first = true; diff --git a/components/raftstore/src/store/worker/read.rs b/components/raftstore/src/store/worker/read.rs index b3d8044e8bf..cf6d492b51c 100644 --- a/components/raftstore/src/store/worker/read.rs +++ b/components/raftstore/src/store/worker/read.rs @@ -2581,10 +2581,10 @@ mod tests { let leader2 = prs[0].clone(); region1.set_region_epoch(epoch13.clone()); memory_engine.new_region(region1.clone()); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(region1.id, 1); - } + memory_engine + .core() + .region_manager() + .set_safe_point(region1.id, 1); let kv = (&[DATA_PREFIX, b'a'], b"b"); reader.kv_engine.put(kv.0, kv.1).unwrap(); let term6 = 6; @@ -2628,10 +2628,10 @@ mod tests { let s = get_snapshot(None, &mut reader, cmd.clone(), &rx); assert!(!s.range_cache_snapshot_available()); - { - let mut core = memory_engine.core().write(); - core.mut_range_manager().set_safe_point(region1.id, 10); - } + memory_engine + .core() + .region_manager() + .set_safe_point(region1.id, 10); let snap_ctx = SnapshotContext { read_ts: 15, diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 76415a945bc..71da8480b27 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -13,7 +13,6 @@ use engine_traits::{ SnapshotMiscExt, CF_DEFAULT, CF_WRITE, DATA_CFS, }; use hex::FromHexError; -use parking_lot::RwLock; use pd_client::{PdClient, RpcClient}; use raftstore::coprocessor::RegionInfoProvider; use slog_global::{error, info, warn}; @@ -125,7 +124,7 @@ pub struct BgWorkManager { scheduler: Scheduler, delete_region_scheduler: Scheduler, tick_stopper: Option<(Worker, Sender)>, - core: Arc>, + core: Arc, region_info_provider: Option>, } @@ -216,7 +215,7 @@ impl PdRangeHintService { impl BgWorkManager { pub fn new( - core: Arc>, + core: Arc, pd_client: Arc, gc_interval: Duration, load_evict_interval: Duration, @@ -288,10 +287,9 @@ impl BgWorkManager { return; } - let mut engine = core.write(); for r in regions { let cache_region = CacheRegion::from_region(&r); - if let Err(e) = engine.mut_range_manager().load_region(cache_region) { + if let Err(e) = core.region_manager().load_region(cache_region) { warn!("ime load region by label failed"; "err" => ?e, "region" => ?r); } } @@ -370,7 +368,7 @@ impl BgWorkManager { #[derive(Clone)] struct BackgroundRunnerCore { - engine: Arc>, + engine: Arc, memory_controller: Arc, range_stats_manager: Option, } @@ -381,13 +379,13 @@ impl BackgroundRunnerCore { /// Returns empty vector if there are no ranges cached or the previous gc is /// not finished. fn regions_for_gc(&self) -> Vec { - let core = self.engine.read(); // another gc task is running, skipped. - if !core.range_manager().try_set_regions_in_gc(true) { + if !self.engine.region_manager().try_set_regions_in_gc(true) { return vec![]; } - core.range_manager() + let regions_map = self.engine.region_manager().regions_map.read(); + regions_map .regions() .values() .filter_map(|m| { @@ -406,16 +404,16 @@ impl BackgroundRunnerCore { safe_point: u64, oldest_seqno: u64, ) -> FilterMetrics { - let (skiplist_engine, safe_point) = { - let mut core = self.engine.write(); + let safe_point = { + let region_manager = self.engine.region_manager(); // We should also consider the ongoing snapshot of the historical ranges (ranges // that have been evicted). - let historical_safe_point = core - .range_manager() + let historical_safe_point = region_manager .get_history_regions_min_ts(region) .unwrap_or(u64::MAX); - let Some(region_meta) = core.mut_range_manager().mut_region_meta(region.id) else { + let mut regions_map = region_manager.regions_map.write(); + let Some(region_meta) = regions_map.mut_region_meta(region.id) else { return FilterMetrics::default(); }; @@ -427,6 +425,8 @@ impl BackgroundRunnerCore { let min_snapshot = region_meta .region_snapshot_list() + .lock() + .unwrap() .min_snapshot_ts() .unwrap_or(u64::MAX); let safe_point = safe_point.min(min_snapshot).min(historical_safe_point); @@ -448,10 +448,11 @@ impl BackgroundRunnerCore { ); region_meta.set_safe_point(safe_point); region_meta.set_in_gc(true); - (core.engine(), safe_point) + safe_point }; let start = Instant::now(); + let skiplist_engine = self.engine.engine(); let mut filter = Filter::new( safe_point, oldest_seqno, @@ -459,11 +460,7 @@ impl BackgroundRunnerCore { skiplist_engine.cf_handle(CF_WRITE), ); filter.filter_keys_in_range(region); - - { - let mut engine = self.engine.write(); - engine.mut_range_manager().on_gc_region_finished(region); - } + self.engine.region_manager().on_gc_region_finished(region); let duration = start.saturating_elapsed(); RANGE_GC_TIME_HISTOGRAM.observe(duration.as_secs_f64()); @@ -490,11 +487,7 @@ impl BackgroundRunnerCore { } fn on_gc_finished(&self) { - let success = self - .engine - .read() - .range_manager() - .try_set_regions_in_gc(false); + let success = self.engine.region_manager().try_set_regions_in_gc(false); assert!(success); } @@ -507,10 +500,9 @@ impl BackgroundRunnerCore { ) -> bool { fail::fail_point!("on_snapshot_load_finished"); fail::fail_point!("on_snapshot_load_finished2"); - // Consume the cached write batch after the snapshot is acquired. - let mut core = self.engine.write(); // We still need to check whether the snapshot is canceled during the load - let region_meta = core.mut_range_manager().mut_region_meta(region.id).unwrap(); + let mut regions_map = self.engine.region_manager().regions_map.write(); + let region_meta = regions_map.mut_region_meta(region.id).unwrap(); let mut remove_regions = vec![]; let mut on_region_meta = |meta: &mut CacheRegionMeta| { assert!( @@ -533,13 +525,12 @@ impl BackgroundRunnerCore { on_region_meta(region_meta); } else { // epoch version changed, should use scan to find all overlapped regions - core.range_manager - .iter_overlapped_regions_mut(region, |meta| { - assert!(region.contains_range(meta.get_region())); - on_region_meta(meta); - }); + regions_map.iter_overlapped_regions_mut(region, |meta| { + assert!(region.contains_range(meta.get_region())); + on_region_meta(meta); + }); } - drop(core); + drop(regions_map); if !remove_regions.is_empty() { fail::fail_point!("in_memory_engine_snapshot_load_canceled"); @@ -567,10 +558,9 @@ impl BackgroundRunnerCore { delete_range_scheduler: &Scheduler, started: bool, ) { - let mut core = self.engine.write(); - let region_meta = core.range_manager.mut_region_meta(region.id).unwrap(); + let mut regions_map = self.engine.region_manager().regions_map.write(); + let region_meta = regions_map.mut_region_meta(region.id).unwrap(); let mut remove_regions = vec![]; - let mut mark_region_evicted = |meta: &mut CacheRegionMeta| { assert!( meta.get_state() == RegionState::Loading @@ -589,11 +579,10 @@ impl BackgroundRunnerCore { mark_region_evicted(region_meta); } else { // epoch version changed, should use scan to find all overlap regions - core.range_manager - .iter_overlapped_regions_mut(region, |meta| { - assert!(region.contains_range(meta.get_region())); - mark_region_evicted(meta); - }); + regions_map.iter_overlapped_regions_mut(region, |meta| { + assert!(region.contains_range(meta.get_region())); + mark_region_evicted(meta); + }); } if let Err(e) = @@ -632,10 +621,7 @@ impl BackgroundRunnerCore { // TODO (afeinberg, low): consider returning just an iterator and using scan // below for cleaner code. range_stats_manager.collect_candidates_for_eviction(&mut regions_to_evict, |region| { - self.engine - .read() - .range_manager() - .contains_region(region.id) + self.engine.region_manager().contains_region(region.id) }); let mut regions_to_delete = vec![]; @@ -646,8 +632,7 @@ impl BackgroundRunnerCore { break; } let cache_region = CacheRegion::from_region(®ion); - let mut engine_wr = self.engine.write(); - let deleteable_regions = engine_wr.mut_range_manager().evict_region( + let deleteable_regions = self.engine.region_manager().evict_region( &cache_region, EvictReason::MemoryLimitReached, None, @@ -701,7 +686,12 @@ impl BackgroundRunnerCore { let threshold = self.memory_controller.stop_load_limit_threshold(); range_stats_manager.adjust_max_num_regions(curr_memory_usage, threshold); - let cached_regions = self.engine.read().range_manager().cached_regions(); + let cached_regions = self + .engine + .region_manager() + .regions_map() + .read() + .cached_regions(); let (regions_to_load, regions_to_evict) = range_stats_manager .collect_regions_to_load_and_evict(cached_regions, &self.memory_controller); @@ -709,10 +699,11 @@ impl BackgroundRunnerCore { info!("ime load_evict"; "regions_to_load" => ?®ions_to_load, "regions_to_evict" => ?®ions_to_evict); for evict_region in regions_to_evict { let cache_region = CacheRegion::from_region(&evict_region); - let mut core = self.engine.write(); - let deleteable_regions = - core.mut_range_manager() - .evict_region(&cache_region, EvictReason::AutoEvict, None); + let deleteable_regions = self.engine.region_manager().evict_region( + &cache_region, + EvictReason::AutoEvict, + None, + ); info!( "ime load_evict: auto evict"; "region_to_evict" => ?&cache_region, @@ -732,10 +723,10 @@ impl BackgroundRunnerCore { assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } } + let mut regions_map = self.engine.region_manager().regions_map.write(); for region in regions_to_load { let cache_region = CacheRegion::from_region(®ion); - let mut core = self.engine.write(); - if let Err(e) = core.mut_range_manager().load_region(cache_region) { + if let Err(e) = regions_map.load_region(cache_region) { error!("ime error loading range"; "cache_range" => ?region, "err" => ?e); } } @@ -802,7 +793,7 @@ impl Drop for BackgroundRunner { impl BackgroundRunner { pub fn new( - engine: Arc>, + engine: Arc, memory_controller: Arc, region_info_provider: Option>, expected_region_size: usize, @@ -933,9 +924,9 @@ impl Runnable for BackgroundRunner { fail::fail_point!("before_start_loading_region"); fail::fail_point!("on_start_loading_region"); let mut is_canceled = false; - let skiplist_engine = { - let engine = core.engine.read(); - let region_meta = engine.range_manager().region_meta(region.id).unwrap(); + { + let regions_map = core.engine.region_manager().regions_map.read(); + let region_meta = regions_map.region_meta(region.id).unwrap(); // if loading is canceled, we skip the batch load. // NOTE: here we don't check the region epoch version change, // We will handle possible region split and partial cancelation @@ -944,9 +935,8 @@ impl Runnable for BackgroundRunner { assert_eq!(region_meta.get_state(), RegionState::LoadingCanceled); is_canceled = true; } - - engine.engine.clone() - }; + } + let skiplist_engine = core.engine.engine.clone(); if core.memory_controller.reached_stop_load_limit() { // We are running out of memory, so cancel the load. @@ -1128,7 +1118,7 @@ impl Runnable for BackgroundRunner { let mut removed = 0; let mut total = 0; let now = Instant::now(); - let lock_handle = core.engine.read().engine().cf_handle("lock"); + let lock_handle = core.engine.engine().cf_handle("lock"); let guard = &epoch::pin(); let mut iter = lock_handle.iterator(); iter.seek_to_first(guard); @@ -1195,12 +1185,12 @@ impl RunnableWithTimer for BackgroundRunner { let mem_usage = self.core.memory_controller.mem_usage(); RANGE_CACHE_MEMORY_USAGE.set(mem_usage as i64); - let core = self.core.engine.read(); + let regions_map = self.core.engine.region_manager().regions_map.read(); let mut count_by_state = HashMap::new(); - for m in core.range_manager.regions().values() { + for m in regions_map.regions().values() { *count_by_state.entry(m.get_state()).or_default() += 1; } - drop(core); + drop(regions_map); for (state, count) in count_by_state { RANGE_CACHE_COUNT .with_label_values(&[state.as_str()]) @@ -1214,7 +1204,7 @@ impl RunnableWithTimer for BackgroundRunner { } pub struct DeleteRangeRunner { - engine: Arc>, + engine: Arc, // It is possible that when `DeleteRangeRunner` begins to delete a range, the range is being // written by apply threads. In that case, we have to delay the delete range task to avoid race // condition between them. Periodically, these delayed ranges will be checked to see if it is @@ -1223,7 +1213,7 @@ pub struct DeleteRangeRunner { } impl DeleteRangeRunner { - fn new(engine: Arc>) -> Self { + fn new(engine: Arc) -> Self { Self { engine, delay_regions: vec![], @@ -1231,14 +1221,11 @@ impl DeleteRangeRunner { } fn delete_regions(&mut self, regions: &[CacheRegion]) { - let skiplist_engine = self.engine.read().engine(); + let skiplist_engine = self.engine.engine(); for r in regions { skiplist_engine.delete_range(r); } - self.engine - .write() - .mut_range_manager() - .on_delete_regions(regions); + self.engine.region_manager().on_delete_regions(regions); fail::fail_point!("in_memory_engine_delete_range_done"); @@ -1254,20 +1241,17 @@ impl Runnable for DeleteRangeRunner { BackgroundTask::DeleteRegions(regions) => { fail::fail_point!("on_in_memory_engine_delete_range"); let (mut regions_to_delay, regions_to_delete) = { - let core = self.engine.write(); + let region_manager = self.engine.region_manager(); + let regions_map = region_manager.regions_map.read(); let mut regions_to_delay = vec![]; let mut regions_to_delete = vec![]; for r in regions { - let region_meta = core.range_manager.region_meta(r.id).unwrap(); + let region_meta = regions_map.region_meta(r.id).unwrap(); assert_eq!(region_meta.get_region().epoch_version, r.epoch_version); assert_eq!(region_meta.get_state(), RegionState::Evicting); - // If the range is overlapped with ranges in `ranges_being_written`, the - // range has to be delayed to delete. See comment on `delay_ranges`. - if region_meta.is_in_gc() - || core - .range_manager - .is_overlapped_with_regions_being_written(region_meta.get_region()) - { + // If the region is currently written into, the region has to be delayed + // to delete. See comment on `delay_ranges`. + if region_meta.is_in_gc() || region_meta.is_written() { regions_to_delay.push(r); } else { regions_to_delete.push(r); @@ -1831,13 +1815,9 @@ pub mod tests { let cache_region = CacheRegion::from_region(®ion); engine.new_region(region.clone()); - let (write, default) = { - let skiplist_engine = engine.core().write().engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); put_data( b"key1", @@ -1932,13 +1912,10 @@ pub mod tests { let memory_controller = engine.memory_controller(); let region = new_region(1, b"", b"z"); engine.new_region(region.clone()); - let (write, default) = { - let skiplist_engine = engine.core().write().engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); let encode_key = |key, ts| { let data_key = data_key(key); @@ -2035,15 +2012,13 @@ pub mod tests { ))); let memory_controller = engine.memory_controller(); let (write, default, region1, region2) = { - let mut core = engine.core().write(); - let region1 = CacheRegion::new(1, 0, b"zk00", b"zk10"); - core.mut_range_manager().new_region(region1.clone()); + engine.core.region_manager().new_region(region1.clone()); let region2 = CacheRegion::new(2, 0, b"zk30", b"zk40"); - core.mut_range_manager().new_region(region2.clone()); + engine.core.region_manager().new_region(region2.clone()); - let engine = core.engine(); + let engine = engine.core.engine(); ( engine.cf_handle(CF_WRITE), engine.cf_handle(CF_DEFAULT), @@ -2190,13 +2165,9 @@ pub mod tests { let memory_controller = engine.memory_controller(); let region = new_region(1, b"", b"z"); engine.new_region(region.clone()); - let (write, default) = { - let skiplist_engine = engine.core().write().engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); put_data_with_overwrite( b"key1", @@ -2240,13 +2211,9 @@ pub mod tests { let memory_controller = engine.memory_controller(); let region = new_region(1, b"", b"z"); engine.new_region(region.clone()); - let (write, default) = { - let skiplist_engine = engine.core().write().engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); put_data( b"key1", @@ -2364,13 +2331,9 @@ pub mod tests { let memory_controller = engine.memory_controller(); let region = new_region(1, b"", b"z"); engine.new_region(region.clone()); - let (write, default) = { - let skiplist_engine = engine.core().write().engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); put_data( b"key1", @@ -2455,7 +2418,16 @@ pub mod tests { source: cache_region.clone(), new_regions, }); - assert_eq!(engine.core.read().range_manager().regions().len(), 3); + assert_eq!( + engine + .core + .region_manager() + .regions_map + .read() + .regions() + .len(), + 3 + ); engine.evict_region(®ion2, EvictReason::AutoEvict, None); assert_eq!(6, element_count(&default)); @@ -2473,8 +2445,9 @@ pub mod tests { let regions: Vec<_> = engine .core + .region_manager() + .regions_map .read() - .range_manager() .regions() .values() .filter_map(|m| { @@ -2538,17 +2511,18 @@ pub mod tests { let k = format!("zk{:08}", 15).into_bytes(); let region1 = CacheRegion::new(1, 0, DATA_MIN_KEY, k.clone()); let region2 = CacheRegion::new(2, 0, k, DATA_MAX_KEY); - { - let mut core = engine.core.write(); - core.mut_range_manager() - .load_region(region1.clone()) - .unwrap(); - core.mut_range_manager() - .load_region(region2.clone()) - .unwrap(); - } - engine.prepare_for_apply(1, ®ion1); - engine.prepare_for_apply(1, ®ion2); + engine + .core + .region_manager() + .load_region(region1.clone()) + .unwrap(); + engine + .core + .region_manager() + .load_region(region2.clone()) + .unwrap(); + engine.prepare_for_apply(®ion1); + engine.prepare_for_apply(®ion2); // concurrent write to rocksdb, but the key will not be loaded in the memory // engine @@ -2562,14 +2536,9 @@ pub mod tests { .put_cf(CF_WRITE, &key20, value.as_bytes()) .unwrap(); - let (write, default) = { - let core = engine.core().write(); - let skiplist_engine = core.engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); // wait for background load std::thread::sleep(Duration::from_secs(1)); @@ -2718,30 +2687,33 @@ pub mod tests { test_util::eventually( Duration::from_millis(10), Duration::from_millis(200), - || !engine.core.read().range_manager().regions().is_empty(), + || { + !engine + .core + .region_manager() + .regions_map + .read() + .regions() + .is_empty() + }, ); let cache_region = CacheRegion::from_region(®ion); - engine.prepare_for_apply(1, &cache_region); + engine.prepare_for_apply(&cache_region); // Wait for the range to be loaded. test_util::eventually( Duration::from_millis(50), Duration::from_millis(1000), || { - let core = engine.core.read(); - core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active + let regions_map = engine.core.region_manager().regions_map.read(); + regions_map.region_meta(1).unwrap().get_state() == RegionState::Active }, ); let _ = engine.snapshot(cache_region, u64::MAX, u64::MAX).unwrap(); - let (write, default) = { - let core = engine.core().write(); - let skiplist_engine = core.engine(); - ( - skiplist_engine.cf_handle(CF_WRITE), - skiplist_engine.cf_handle(CF_DEFAULT), - ) - }; + let skiplist_engine = engine.core.engine(); + let write = skiplist_engine.cf_handle(CF_WRITE); + let default = skiplist_engine.cf_handle(CF_DEFAULT); let guard = &epoch::pin(); for i in 10..15 { @@ -2840,15 +2812,16 @@ pub mod tests { for r in [®ion1, ®ion2] { engine.load_region(r.clone()).unwrap(); - engine.prepare_for_apply(1, &CacheRegion::from_region(r)); + engine.prepare_for_apply(&CacheRegion::from_region(r)); } // ensure all ranges are finshed test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { !engine .core + .region_manager() + .regions_map() .read() - .range_manager() .regions() .values() .any(|m| matches!(m.get_state(), Pending | Loading)) @@ -2916,15 +2889,13 @@ pub mod tests { for r in [®ion1, ®ion2, ®ion3] { engine.load_region(r.clone()).unwrap(); - engine.prepare_for_apply(1, &CacheRegion::from_region(r)); + engine.prepare_for_apply(&CacheRegion::from_region(r)); } // ensure all ranges are finshed test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { - !engine - .core - .read() - .range_manager() + let regions_map = engine.core.region_manager().regions_map.read(); + !regions_map .regions() .values() .any(|m| matches!(m.get_state(), Pending | Loading)) @@ -2967,7 +2938,7 @@ pub mod tests { rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); // After loading range1, the memory usage should be 140*6=840 engine.load_region(region1.clone()).unwrap(); - engine.prepare_for_apply(1, &CacheRegion::from_region(®ion1)); + engine.prepare_for_apply(&CacheRegion::from_region(®ion1)); let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); let key = construct_key(3, 10); @@ -2992,14 +2963,12 @@ pub mod tests { assert_eq!(config.value().hard_limit_threshold(), 2000); engine.load_region(region2.clone()).unwrap(); - engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); + engine.prepare_for_apply(&CacheRegion::from_region(®ion2)); // ensure all ranges are finshed test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { - !engine - .core - .read() - .range_manager() + let regions_map = engine.core.region_manager().regions_map.read(); + !regions_map .regions() .values() .any(|m| matches!(m.get_state(), Pending | Loading)) diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 746be71089f..b33a0e79f9f 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -4,10 +4,7 @@ use std::{ fmt::{self, Debug}, ops::Bound, result, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, - }, + sync::{atomic::AtomicU64, Arc}, }; use crossbeam::epoch::{self, default_collector, Guard}; @@ -21,7 +18,6 @@ use engine_traits::{ RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use kvproto::metapb::Region; -use parking_lot::RwLock; use raftstore::coprocessor::RegionInfoProvider; use slog_global::error; use tikv_util::{config::VersionTrack, info}; @@ -185,7 +181,7 @@ impl Debug for SkiplistEngine { pub struct RangeCacheMemoryEngineCore { pub(crate) engine: SkiplistEngine, - pub(crate) range_manager: RegionManager, + pub(crate) region_manager: RegionManager, } impl Default for RangeCacheMemoryEngineCore { @@ -198,7 +194,7 @@ impl RangeCacheMemoryEngineCore { pub fn new() -> RangeCacheMemoryEngineCore { RangeCacheMemoryEngineCore { engine: SkiplistEngine::new(), - range_manager: RegionManager::default(), + region_manager: RegionManager::default(), } } @@ -206,12 +202,8 @@ impl RangeCacheMemoryEngineCore { self.engine.clone() } - pub fn range_manager(&self) -> &RegionManager { - &self.range_manager - } - - pub fn mut_range_manager(&mut self) -> &mut RegionManager { - &mut self.range_manager + pub fn region_manager(&self) -> &RegionManager { + &self.region_manager } } @@ -235,7 +227,7 @@ impl RangeCacheMemoryEngineCore { #[derive(Clone)] pub struct RangeCacheMemoryEngine { bg_work_manager: Arc, - pub(crate) core: Arc>, + pub(crate) core: Arc, pub(crate) rocks_engine: Option, memory_controller: Arc, statistics: Arc, @@ -245,9 +237,6 @@ pub struct RangeCacheMemoryEngine { // When reaching to the threshold, a CleanLockTombstone task will be scheduled to clean lock cf // tombstones. pub(crate) lock_modification_bytes: Arc, - - // `write_batch_id_allocator` is used to allocate id for each write batch - write_batch_id_allocator: Arc, } impl RangeCacheMemoryEngine { @@ -260,8 +249,8 @@ impl RangeCacheMemoryEngine { region_info_provider: Option>, ) -> Self { info!("ime init range cache memory engine"); - let core = Arc::new(RwLock::new(RangeCacheMemoryEngineCore::new())); - let skiplist_engine = { core.read().engine().clone() }; + let core = Arc::new(RangeCacheMemoryEngineCore::new()); + let skiplist_engine = core.engine().clone(); let RangeCacheEngineContext { config, @@ -290,7 +279,6 @@ impl RangeCacheMemoryEngine { statistics, config, lock_modification_bytes: Arc::default(), - write_batch_id_allocator: Arc::default(), } } @@ -300,15 +288,12 @@ impl RangeCacheMemoryEngine { pub fn new_region(&self, region: Region) { let cache_region = CacheRegion::from_region(®ion); - self.core.write().range_manager.new_region(cache_region); + self.core.region_manager.new_region(cache_region); } pub fn load_region(&self, region: Region) -> result::Result<(), LoadFailedReason> { let cache_region = CacheRegion::from_region(®ion); - self.core - .write() - .mut_range_manager() - .load_region(cache_region) + self.core.region_manager().load_region(cache_region) } /// Evict a region from the in-memory engine. After this call, the region @@ -320,11 +305,10 @@ impl RangeCacheMemoryEngine { evict_reason: EvictReason, cb: Option>, ) { - let deleteable_regions = - self.core - .write() - .range_manager - .evict_region(region, evict_reason, cb); + let deleteable_regions = self + .core + .region_manager + .evict_region(region, evict_reason, cb); if !deleteable_regions.is_empty() { // The range can be deleted directly. if let Err(e) = self @@ -342,38 +326,79 @@ impl RangeCacheMemoryEngine { // It handles the pending range and check whether to buffer write for this // range. - pub(crate) fn prepare_for_apply( - &self, - write_batch_id: u64, - region: &CacheRegion, - ) -> RangeCacheStatus { - let mut core = self.core.write(); - let range_manager = core.mut_range_manager(); - let Some(mut region_state) = range_manager.check_region_state(region) else { + pub(crate) fn prepare_for_apply(&self, region: &CacheRegion) -> RangeCacheStatus { + let manager = self.core.region_manager(); + if !manager.is_active() { + return RangeCacheStatus::NotInCache; + } + + // fast path, only need to hold the read lock. + { + let regions_map = manager.regions_map.read(); + let Some(region_meta) = regions_map.region_meta(region.id) else { + return RangeCacheStatus::NotInCache; + }; + let state = region_meta.get_state(); + if state == RegionState::Active { + region_meta.set_being_written(); + return RangeCacheStatus::Cached; + } else if state.is_evict() { + return RangeCacheStatus::NotInCache; + } else if state == RegionState::Loading { + region_meta.set_being_written(); + return RangeCacheStatus::Loading; + } + } + + // slow path, handle pending region + let mut regions_map = manager.regions_map.write(); + let cached_count = regions_map.regions().len(); + let Some(mut region_meta) = regions_map.mut_region_meta(region.id) else { return RangeCacheStatus::NotInCache; }; + if region_meta.get_region().epoch_version < region.epoch_version { + let meta = regions_map.remove_region(region.id); + assert_eq!(meta.get_state(), RegionState::Pending); + // try update outdated region. + if meta.can_be_updated_to(region) { + info!("ime update outdated pending region"; + "current_meta" => ?meta, + "new_region" => ?region); + // the new region's range is smaller than removed region, so it is impossible to + // be overlapped with other existing regions. + regions_map.load_region(region.clone()).unwrap(); + region_meta = regions_map.mut_region_meta(region.id).unwrap(); + } else { + info!("ime remove outdated pending region"; + "pending_region" => ?meta.get_region(), + "new_region" => ?region); + return RangeCacheStatus::NotInCache; + } + } + + let mut region_state = region_meta.get_state(); let schedule_load = region_state == RegionState::Pending; if schedule_load { - range_manager.update_region_state(region.id, RegionState::Loading); + region_meta.set_state(RegionState::Loading); info!( "ime region to load"; "region" => ?region, - "cached" => range_manager.regions().len(), + "cached" => cached_count, ); region_state = RegionState::Loading; } let mut result = RangeCacheStatus::NotInCache; if region_state == RegionState::Loading || region_state == RegionState::Active { - range_manager.record_in_region_being_written(write_batch_id, region.clone()); + region_meta.set_being_written(); if region_state == RegionState::Active { result = RangeCacheStatus::Cached; } else { result = RangeCacheStatus::Loading; } } - drop(core); + drop(regions_map); // get snapshot and schedule loading task at last to avoid locking IME for too // long. @@ -406,15 +431,10 @@ impl RangeCacheMemoryEngine { pub fn statistics(&self) -> Arc { self.statistics.clone() } - - pub fn alloc_write_batch_id(&self) -> u64 { - self.write_batch_id_allocator - .fetch_add(1, Ordering::Relaxed) - } } impl RangeCacheMemoryEngine { - pub fn core(&self) -> &Arc> { + pub fn core(&self) -> &Arc { &self.core } } @@ -459,7 +479,7 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { } fn get_region_for_key(&self, key: &[u8]) -> Option { - self.core.read().range_manager().get_region_for_key(key) + self.core.region_manager().get_region_for_key(key) } fn enabled(&self) -> bool { @@ -475,21 +495,19 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { source, new_regions, } => { - self.core - .write() - .range_manager - .split_region(&source, new_regions); + self.core.region_manager.split_region(&source, new_regions); } RegionEvent::EvictByRange { range, reason } => { let mut regions = vec![]; - self.core() - .read() - .range_manager() - .iter_overlapped_regions(&range, |meta| { + { + let regions_map = self.core.region_manager.regions_map.read(); + regions_map.iter_overlapped_regions(&range, |meta| { assert!(meta.get_region().overlaps(&range)); regions.push(meta.get_region().clone()); true }); + } + for r in regions { self.evict_region(&r, reason, None); } @@ -515,9 +533,10 @@ pub mod tests { }; use crossbeam::epoch; + use engine_rocks::util::new_engine; use engine_traits::{ - CacheRegion, EvictReason, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, - CF_LOCK, CF_WRITE, + CacheRegion, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, + WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; @@ -532,7 +551,8 @@ pub mod tests { }; fn count_region(mgr: &RegionManager, mut f: impl FnMut(&CacheRegionMeta) -> bool) -> usize { - mgr.regions().values().filter(|m| f(m)).count() + let regions_map = mgr.regions_map.read(); + regions_map.regions().values().filter(|m| f(m)).count() } #[test] fn test_region_overlap_with_outdated_epoch() { @@ -544,9 +564,9 @@ pub mod tests { let mut region2 = new_region(1, b"k1", b"k5"); region2.mut_region_epoch().version = 2; - engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); + engine.prepare_for_apply(&CacheRegion::from_region(®ion2)); assert_eq!( - count_region(engine.core.read().range_manager(), |m| { + count_region(engine.core.region_manager(), |m| { matches!(m.get_state(), Pending | Loading) }), 0 @@ -557,9 +577,9 @@ pub mod tests { let mut region2 = new_region(1, b"k2", b"k5"); region2.mut_region_epoch().version = 2; - engine.prepare_for_apply(1, &CacheRegion::from_region(®ion2)); + engine.prepare_for_apply(&CacheRegion::from_region(®ion2)); assert_eq!( - count_region(engine.core.read().range_manager(), |m| { + count_region(engine.core.region_manager(), |m| { matches!(m.get_state(), Pending | Loading) }), 0 @@ -673,6 +693,96 @@ pub mod tests { assert!(!iter.valid()); } + #[test] + fn test_is_active() { + let mut engine = RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests( + Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())), + )); + let path = tempfile::Builder::new() + .prefix("test_is_active") + .tempdir() + .unwrap(); + let path_str = path.path().to_str().unwrap(); + let rocks_engine = new_engine(path_str, DATA_CFS).unwrap(); + engine.set_disk_engine(rocks_engine.clone()); + + let region = new_region(1, b"k00", b"k30"); + let cache_region = CacheRegion::from_region(®ion); + engine.load_region(region).unwrap(); + assert!(engine.core.region_manager.is_active()); + + let mut wb = engine.write_batch(); + wb.prepare_for_region(cache_region.clone()); + wb.put(b"zk00", b"v1").unwrap(); + wb.put(b"zk10", b"v1").unwrap(); + wb.put(b"zk20", b"v1").unwrap(); + wb.set_sequence_number(1).unwrap(); + wb.write().unwrap(); + + test_util::eventually( + Duration::from_millis(10), + Duration::from_millis(1000), + || { + let regions_map = engine.core.region_manager().regions_map().read(); + regions_map.region_meta(1).unwrap().get_state() == Active + }, + ); + + let mut wb = engine.write_batch(); + wb.prepare_for_region(cache_region.clone()); + wb.put(b"zk10", b"v2").unwrap(); + wb.set_sequence_number(10).unwrap(); + + // trigger split and eviction during write. + let new_regions = vec![ + CacheRegion::new(1, 1, "zk00", "zk10"), + CacheRegion::new(2, 1, "zk10", "zk20"), + CacheRegion::new(3, 1, "zk20", "zk30"), + ]; + engine.on_region_event(RegionEvent::Split { + source: cache_region.clone(), + new_regions: new_regions.clone(), + }); + + engine.on_region_event(RegionEvent::Eviction { + region: new_regions[0].clone(), + reason: EvictReason::AutoEvict, + }); + + // trigger split again + let split_regions = vec![ + CacheRegion::new(2, 2, "zk10", "zk13"), + CacheRegion::new(4, 2, "zk13", "zk16"), + CacheRegion::new(5, 2, "zk16", "zk20"), + ]; + engine.on_region_event(RegionEvent::Split { + source: new_regions[1].clone(), + new_regions: split_regions.clone(), + }); + + { + let regions_map = engine.core.region_manager.regions_map.read(); + assert!(regions_map.regions().values().all(|m| m.is_written())); + } + wb.write().unwrap(); + { + let regions_map = engine.core.region_manager.regions_map.read(); + assert!(regions_map.regions().values().all(|m| !m.is_written())); + } + + engine.on_region_event(RegionEvent::Eviction { + region: cache_region, + reason: EvictReason::AutoEvict, + }); + + // engine should become inactive after all regions are evicted. + test_util::eventually( + Duration::from_millis(10), + Duration::from_millis(1000), + || !engine.core.region_manager.is_active(), + ); + } + #[test] fn test_cb_on_eviction_with_on_going_snapshot() { let mut config = RangeCacheEngineConfig::config_for_test(); @@ -709,8 +819,8 @@ pub mod tests { let _ = rx.recv(); { - let core = engine.core().read(); - assert!(core.range_manager().region_meta(1).is_none()); + let regions_map = engine.core().region_manager().regions_map().read(); + assert!(regions_map.region_meta(1).is_none()); } } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 8ef6f10daa5..8f1afc23c3b 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -8,11 +8,15 @@ use std::{ }, fmt::Debug, result, - sync::atomic::{AtomicBool, Ordering}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, }; use collections::HashMap; use engine_traits::{CacheRegion, EvictReason, FailedReason}; +use parking_lot::RwLock; use tikv_util::{info, time::Instant, warn}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; @@ -90,13 +94,15 @@ pub struct CacheRegionMeta { // the cached region meta. region: CacheRegion, // active region snapshots. - region_snapshot_list: SnapshotList, + region_snapshot_list: Mutex, // the gc safe point. safe_point: u64, state: RegionState, // whether a gc task is running with this region. - in_gc: bool, - // region eviction triggers info and callback when eviction finishes. + in_gc: AtomicBool, + // whether the raft apply thread is written new KVs in this region. + is_written: AtomicBool, + // region eviction triggers info, and callback when eviction finishes. evict_info: Option, } @@ -119,10 +125,11 @@ impl CacheRegionMeta { fn new(region: CacheRegion) -> Self { Self { region, - region_snapshot_list: SnapshotList::default(), + region_snapshot_list: Mutex::new(SnapshotList::default()), safe_point: 0, state: RegionState::Pending, - in_gc: false, + in_gc: AtomicBool::new(false), + is_written: AtomicBool::new(false), evict_info: None, } } @@ -134,7 +141,7 @@ impl CacheRegionMeta { // check whether we can replace the current outdated pending region with the new // one. - fn can_be_updated_to(&self, region: &CacheRegion) -> bool { + pub(crate) fn can_be_updated_to(&self, region: &CacheRegion) -> bool { assert!( self.region.id == region.id && self.region.epoch_version < region.epoch_version, "current: {:?}, new: {:?}", @@ -201,13 +208,24 @@ impl CacheRegionMeta { }); } - pub(crate) fn set_in_gc(&mut self, in_gc: bool) { - assert!(self.in_gc != in_gc); - self.in_gc = in_gc; + pub(crate) fn set_in_gc(&self, in_gc: bool) { + assert!(self.in_gc.load(Ordering::Acquire) != in_gc); + self.in_gc.store(in_gc, Ordering::Release); } pub(crate) fn is_in_gc(&self) -> bool { - self.in_gc + self.in_gc.load(Ordering::Acquire) + } + + #[inline] + pub(crate) fn set_being_written(&self) { + debug_assert!(!self.is_written.load(Ordering::Relaxed)); + self.is_written.store(true, Ordering::Relaxed); + } + + #[inline] + pub(crate) fn is_written(&self) -> bool { + self.is_written.load(Ordering::Relaxed) } // Build a new RangeMeta from a existing meta, the new meta should inherit @@ -217,15 +235,16 @@ impl CacheRegionMeta { assert!(source_meta.region.contains_range(®ion)); Self { region, - region_snapshot_list: SnapshotList::default(), + region_snapshot_list: Mutex::new(SnapshotList::default()), safe_point: source_meta.safe_point, state: source_meta.state, - in_gc: source_meta.in_gc, + in_gc: AtomicBool::new(source_meta.in_gc.load(Ordering::Relaxed)), + is_written: AtomicBool::new(source_meta.is_written.load(Ordering::Relaxed)), evict_info: None, } } - pub(crate) fn region_snapshot_list(&self) -> &SnapshotList { + pub(crate) fn region_snapshot_list(&self) -> &Mutex { &self.region_snapshot_list } } @@ -235,65 +254,55 @@ impl CacheRegionMeta { #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] struct KeyAndVersion(Vec, u64); -// RegionManger manges the regions for RangeCacheMemoryEngine. Every new region -// (whether created by new_region/load_region or by split)'s range is unique and -// is not overlap with any other regions. -// -// Each region is first added with `pending` state. Because `pending` can be -// added by the background workers, it is possible the pending region is added -// with an outdated epoch. We handle this outdated epoch in the raft apply -// thread, before handling a region, the apply worker will check the region in -// RegionManager, if its epoch is outdated(only possible in `pending` state), if -// the old region's range contains new region's range, then we update it to the -// new version, else we just drop the outdated region. -// -// In RegionCacheEngine, we only keep region's epoch version updated with -// raftstore, but not the conf version for simplicity because conf version -// change doesn't affect the correctness of data. In order to always keep the -// region epoch version updated, we handle region epoch we use a ApplyObserver -// to watch following event: -// - PrepareMerge/CommitMerge. We evict target region currently for simplicity. -// - Leader Resign. evict the region. -// - SST Ingestion. evict the region. -// - Split/BatchSplit. For split event, we just replace the source region with -// the split new regions. The new regions should inherit the state of the -// source region including(state, safe_point, in_gc). If there are ongoing -// snapshot in the source region, the source region meta should be put in -// `historical_regions`. -#[derive(Default)] -pub struct RegionManager { +pub struct RegionMetaMap { // ranges that are cached now // data_end_key --> region_id regions_by_range: BTreeMap, u64>, // region_id --> region_meta regions: HashMap, - // we use this flag to ensure there is only 1 running gc task. - is_gc_task_running: AtomicBool, - // Outdated regions that are split but still hold some on going snapshots. - // These on going snapshot should block regions fell in this range from gc or eviction. - // It's possible that multi region with the same end key are in `historical_regions`, - // so we add epoch version into the key to ensure the uniqueness. - // (data_end_key, epoch_version) --> region_id - historical_regions: BTreeMap, - // Record the region ranges that are being written. - // - // It is used to avoid the conccurency issue between delete range and write to memory: after - // the range is evicted or failed to load, the range is marked as `PendingEvict` - // which means no further write of it is allowed, and a DeleteRegion task of the range will be - // scheduled to cleanup the KVs of this region. However, it is possible that the apply thread - // is writing data for this range. Therefore, we have to delay the DeleteRange task until - // the range leaves the `ranges_being_written`. - // - // The key in this map is the id of the write batch, and the value is a collection - // the ranges of this batch. So, when the write batch is consumed by the in-memory engine, - // all ranges of it are cleared from `ranges_being_written`. - // write_batch_id --> Vec - regions_being_written: HashMap>, + // active flag, cloned from RegionManager, + is_active: Arc, } -impl RegionManager { - pub(crate) fn regions(&self) -> &HashMap { - &self.regions +impl RegionMetaMap { + fn new_region_meta(&mut self, meta: CacheRegionMeta) { + assert!(!self.overlaps_with(&meta.region)); + let id = meta.region.id; + let data_end_key = meta.region.end.clone(); + self.regions.insert(id, meta); + self.regions_by_range.insert(data_end_key, id); + if self.regions.len() == 1 { + assert!(!self.is_active.load(Ordering::Relaxed)); + self.is_active.store(true, Ordering::Relaxed); + } + } + + pub(crate) fn load_region( + &mut self, + cache_region: CacheRegion, + ) -> Result<(), LoadFailedReason> { + use RegionState::*; + if let Some(state) = self.check_overlap_with_region(&cache_region) { + let reason = match state { + Pending | Loading => LoadFailedReason::PendingRange, + Active => LoadFailedReason::Overlapped, + LoadingCanceled | PendingEvict | Evicting => LoadFailedReason::Evicting, + }; + return Err(reason); + } + let meta = CacheRegionMeta::new(cache_region); + self.new_region_meta(meta); + Ok(()) + } + + pub(crate) fn remove_region(&mut self, id: u64) -> CacheRegionMeta { + let meta = self.regions.remove(&id).unwrap(); + self.regions_by_range.remove(&meta.region.end); + if self.regions.is_empty() { + assert!(self.is_active.load(Ordering::Relaxed)); + self.is_active.store(false, Ordering::Relaxed); + } + meta } #[cfg(test)] @@ -303,28 +312,64 @@ impl RegionManager { .and_then(|id| self.regions.get(id)) } - // load a new region directly in the active state. - // This fucntion is used for unit/integration tests only. - pub fn new_region(&mut self, region: CacheRegion) { - let mut range_meta = CacheRegionMeta::new(region); - range_meta.state = RegionState::Active; - self.new_region_meta(range_meta); - } - - fn new_region_meta(&mut self, meta: CacheRegionMeta) { - assert!(!self.overlaps_with(&meta.region)); - let id = meta.region.id; - let data_end_key = meta.region.end.clone(); - self.regions.insert(id, meta); - self.regions_by_range.insert(data_end_key, id); + fn overlaps_with(&self, region: &CacheRegion) -> bool { + let entry = self + .regions_by_range + .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(®ion.start), Unbounded)) + .next(); + if let Some((_key, id)) = entry { + let meta = &self.regions[id]; + if meta.region.start < region.end { + return true; + } + } + false } - pub fn region_meta(&self, id: u64) -> Option<&CacheRegionMeta> { - self.regions.get(&id) + /// `check_overlap_with_region` check whether there are regions overlap with + /// target region. If there are regions with `pending` state and whose + /// epoch version is smaller than target region, the pending regions will + /// be removed first. + fn check_overlap_with_region(&mut self, region: &CacheRegion) -> Option { + let mut removed_regions = vec![]; + let mut overlapped_region_state = None; + self.iter_overlapped_regions(region, |region_meta| { + // pending region with out-dated epoch, should be removed. + if region_meta.state == RegionState::Pending + && region_meta.region.epoch_version < region.epoch_version + { + removed_regions.push(region_meta.region.id); + return true; + } + warn!("ime load region overlaps with existing region"; + "region" => ?region, + "exist_meta" => ?region_meta); + overlapped_region_state = Some(region_meta.state); + false + }); + if !removed_regions.is_empty() { + info!("ime load region meet pending region with stale epoch, removed"; + "region" => ?region, "stale_regions" => ?removed_regions); + } + for id in removed_regions { + self.remove_region(id); + } + overlapped_region_state } - pub fn mut_region_meta(&mut self, id: u64) -> Option<&mut CacheRegionMeta> { - self.regions.get_mut(&id) + fn on_all_overlapped_regions(&self, region: &CacheRegion, mut f: impl FnMut(&CacheRegionMeta)) { + // fast path: region epoch match + if let Some(region_meta) = self.region_meta(region.id) + && region_meta.region.epoch_version == region.epoch_version + { + f(region_meta); + return; + } + // epoch not match, need to iter all overlapped regions. + self.iter_overlapped_regions(region, |meta| { + f(meta); + true + }); } pub fn cached_regions(&self) -> Vec { @@ -376,8 +421,107 @@ impl RegionManager { } } - pub fn set_safe_point(&mut self, region_id: u64, safe_ts: u64) -> bool { - if let Some(meta) = self.regions.get_mut(®ion_id) { + #[inline] + pub fn region_meta(&self, id: u64) -> Option<&CacheRegionMeta> { + self.regions.get(&id) + } + + #[inline] + pub(crate) fn mut_region_meta(&mut self, id: u64) -> Option<&mut CacheRegionMeta> { + self.regions.get_mut(&id) + } + + pub(crate) fn regions(&self) -> &HashMap { + &self.regions + } +} + +#[cfg(test)] +impl Drop for RegionMetaMap { + fn drop(&mut self) { + assert_eq!(self.regions.len(), self.regions_by_range.len()); + // check regions and regions by range matches with each other. + for (key, id) in &self.regions_by_range { + let meta = self.regions.get(id).unwrap(); + assert_eq!(key, &meta.region.end); + } + } +} + +// RegionManger manges the regions for RangeCacheMemoryEngine. Every new region +// (whether created by new_region/load_region or by split)'s range is unique and +// is not overlap with any other regions. +// +// Each region is first added with `pending` state. Because `pending` can be +// added by the background workers, it is possible the pending region is added +// with an outdated epoch. We handle this outdated epoch in the raft apply +// thread, before handling a region, the apply worker will check the region in +// RegionManager, if its epoch is outdated(only possible in `pending` state), if +// the old region's range contains new region's range, then we update it to the +// new version, else we just drop the outdated region. +// +// In RegionCacheEngine, we only keep region's epoch version updated with +// raftstore, but not the conf version for simplicity because conf version +// change doesn't affect the correctness of data. In order to always keep the +// region epoch version updated, we handle region epoch we use a ApplyObserver +// to watch following event: +// - PrepareMerge/CommitMerge. We evict target region currently for simplicity. +// - Leader Resign. evict the region. +// - SST Ingestion. evict the region. +// - Split/BatchSplit. For split event, we just replace the source region with +// the split new regions. The new regions should inherit the state of the +// source region including(state, safe_point, in_gc). If there are ongoing +// snapshot in the source region, the source region meta should be put in +// `historical_regions`. +pub struct RegionManager { + // regions hold the metadata of all cached regions. + pub(crate) regions_map: RwLock, + // we use this flag to ensure there is only 1 running gc task. + is_gc_task_running: AtomicBool, + // Outdated regions that are split but still hold some on going snapshots. + // These on going snapshot should block regions fell in this range from gc or eviction. + // It's possible that multi region with the same end key are in `historical_regions`, + // so we add epoch version into the key to ensure the uniqueness. + // (data_end_key, epoch_version) --> region_id + historical_regions: Mutex>, + // whether there are any cached regions. We use this flag to minimize the overhead of + // `prepare_for_apply` when no region is cached. + is_active: Arc, +} + +impl Default for RegionManager { + fn default() -> Self { + let is_active = Arc::new(AtomicBool::new(false)); + let regions_map = RwLock::new(RegionMetaMap { + regions_by_range: BTreeMap::default(), + regions: HashMap::default(), + is_active: is_active.clone(), + }); + Self { + regions_map, + is_gc_task_running: AtomicBool::default(), + historical_regions: Mutex::new(BTreeMap::default()), + is_active, + } + } +} + +impl RegionManager { + // load a new region directly in the active state. + // This fucntion is used for unit/integration tests only. + pub fn new_region(&self, region: CacheRegion) { + let mut range_meta = CacheRegionMeta::new(region); + range_meta.state = RegionState::Active; + self.regions_map.write().new_region_meta(range_meta); + } + + pub fn is_active(&self) -> bool { + self.is_active.load(Ordering::Acquire) + } + + pub fn set_safe_point(&self, region_id: u64, safe_ts: u64) -> bool { + let mut regions_map = self.regions_map.write(); + if let Some(meta) = regions_map.mut_region_meta(region_id) { if meta.safe_point > safe_ts { return false; } @@ -389,12 +533,13 @@ impl RegionManager { } pub fn get_region_for_key(&self, key: &[u8]) -> Option { - if let Some((key, id)) = self + let regions_map = self.regions_map.read(); + if let Some((key, id)) = regions_map .regions_by_range .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(key), Unbounded)) .next() { - let meta = &self.regions[id]; + let meta = ®ions_map.regions[id]; if &meta.region.start <= key { return Some(meta.region.clone()); } @@ -403,94 +548,23 @@ impl RegionManager { } pub fn contains_region(&self, region_id: u64) -> bool { - self.regions.contains_key(®ion_id) + self.regions_map.read().regions.contains_key(®ion_id) } - pub fn check_region_state(&mut self, region: &CacheRegion) -> Option { - use RegionState::*; - let Some(cached_meta) = self.regions.get_mut(®ion.id) else { - return None; - }; - if cached_meta.state == Pending && cached_meta.region.epoch_version != region.epoch_version - { - let meta = self.remove_region(region.id); - if meta.can_be_updated_to(region) { - info!("ime update outdated pending region"; - "current_meta" => ?meta, - "new_region" => ?region); - // the new region's range is smaller than removed region, so it is impossible to - // be overlapped with other existing regions. - self.load_region(region.clone()).unwrap(); - - return Some(RegionState::Pending); - } - - info!("ime remove outdated pending region"; - "pending_region" => ?meta.region, - "new_region" => ?region); - return None; - } - Some(cached_meta.state) - } - - pub fn update_region_state(&mut self, id: u64, state: RegionState) { - self.regions.get_mut(&id).unwrap().state = state; - } - - fn overlaps_with(&self, region: &CacheRegion) -> bool { - let entry = self - .regions_by_range - .range::<[u8], (Bound<&[u8]>, Bound<&[u8]>)>((Excluded(®ion.start), Unbounded)) - .next(); - if let Some((_key, id)) = entry { - let meta = &self.regions[id]; - if meta.region.start < region.end { - return true; - } - } - false - } - - /// `check_overlap_with_region` check whether there are regions overlap with - /// target region. If there are regions with `pending` state and whose - /// epoch version is smaller than target region, the pending regions will - /// be removed first. - fn check_overlap_with_region(&mut self, region: &CacheRegion) -> Option { - let mut removed_regions = vec![]; - let mut overlapped_region_state = None; - self.iter_overlapped_regions(region, |region_meta| { - // pending region with out-dated epoch, should be removed. - if region_meta.state == RegionState::Pending - && region_meta.region.epoch_version < region.epoch_version - { - removed_regions.push(region_meta.region.id); - return true; - } - warn!("ime load region overlaps with existing region"; - "region" => ?region, - "exist_meta" => ?region_meta); - overlapped_region_state = Some(region_meta.state); - false - }); - if !removed_regions.is_empty() { - info!("ime load region meet pending region with stale epoch, removed"; - "region" => ?region, "stale_regions" => ?removed_regions); - } - for id in removed_regions { - self.remove_region(id); - } - overlapped_region_state + pub fn regions_map(&self) -> &RwLock { + &self.regions_map } // Acquire a snapshot of the `range` with `read_ts`. If the range is not // accessable, None will be returned. Otherwise, the range id will be returned. pub(crate) fn region_snapshot( - &mut self, + &self, region_id: u64, region_epoch: u64, read_ts: u64, ) -> result::Result<(), FailedReason> { - let Some(meta) = self.regions.get_mut(®ion_id) else { + let regions_map = self.regions_map.read(); + let Some(meta) = regions_map.region_meta(region_id) else { return Err(FailedReason::NotCached); }; @@ -506,7 +580,10 @@ impl RegionManager { return Err(FailedReason::TooOldRead); } - meta.region_snapshot_list.new_snapshot(read_ts); + meta.region_snapshot_list + .lock() + .unwrap() + .new_snapshot(read_ts); Ok(()) } @@ -516,18 +593,28 @@ impl RegionManager { // So, we return a vector of ranges to denote the ranges that are ready to be // removed. pub(crate) fn remove_region_snapshot( - &mut self, + &self, snapshot_meta: &RangeCacheSnapshotMeta, ) -> Vec { + let regions_map = self.regions_map.read(); // fast path: in most case, region is not changed. - if let Some(region_meta) = self.regions.get_mut(&snapshot_meta.region.id) + if let Some(region_meta) = regions_map.region_meta(snapshot_meta.region.id) && region_meta.region.epoch_version == snapshot_meta.region.epoch_version { // epoch not changed - region_meta - .region_snapshot_list - .remove_snapshot(snapshot_meta.snapshot_ts); - if Self::region_ready_to_evict(region_meta, &self.historical_regions) { + let mut snapshot_list = region_meta.region_snapshot_list.lock().unwrap(); + snapshot_list.remove_snapshot(snapshot_meta.snapshot_ts); + if Self::region_ready_to_evict( + region_meta, + &snapshot_list, + &self.historical_regions.lock().unwrap(), + ) { + drop(snapshot_list); + drop(regions_map); + let mut regions_map = self.regions_map.write(); + let region_meta = regions_map + .mut_region_meta(snapshot_meta.region.id) + .unwrap(); region_meta.set_state(RegionState::Evicting); return vec![region_meta.region.clone()]; } @@ -540,28 +627,36 @@ impl RegionManager { snapshot_meta.region.end.clone(), snapshot_meta.region.epoch_version, ); - let meta = self.historical_regions.get_mut(&hist_key).unwrap(); - meta.region_snapshot_list - .remove_snapshot(snapshot_meta.snapshot_ts); + let mut historical_regions = self.historical_regions.lock().unwrap(); + let meta = historical_regions.get_mut(&hist_key).unwrap(); + + let mut snapshot_list = meta.region_snapshot_list.lock().unwrap(); + snapshot_list.remove_snapshot(snapshot_meta.snapshot_ts); let mut deletable_regions = vec![]; - if meta.region_snapshot_list.is_empty() { - self.historical_regions.remove(&hist_key).unwrap(); - self.iter_overlapped_regions(&snapshot_meta.region, |meta| { + if snapshot_list.is_empty() { + drop(snapshot_list); + historical_regions.remove(&hist_key).unwrap(); + regions_map.iter_overlapped_regions(&snapshot_meta.region, |meta| { if matches!( meta.get_state(), RegionState::PendingEvict | RegionState::Evicting ) { assert_eq!(meta.get_state(), RegionState::PendingEvict); - if Self::region_ready_to_evict(meta, &self.historical_regions) { + let snap_list = meta.region_snapshot_list.lock().unwrap(); + if Self::region_ready_to_evict(meta, &snap_list, &historical_regions) { deletable_regions.push(meta.region.clone()); } } true }); - for r in &deletable_regions { - let meta = self.regions.get_mut(&r.id).unwrap(); - meta.set_state(RegionState::Evicting); + if !deletable_regions.is_empty() { + drop(regions_map); + let mut regions_map = self.regions_map.write(); + for r in &deletable_regions { + let meta = regions_map.mut_region_meta(r.id).unwrap(); + meta.set_state(RegionState::Evicting); + } } } deletable_regions @@ -574,12 +669,13 @@ impl RegionManager { #[inline] fn region_ready_to_evict( meta: &CacheRegionMeta, + snapshot_list: &SnapshotList, historical_regions: &BTreeMap, ) -> bool { if meta.state != RegionState::PendingEvict { return false; } - meta.region_snapshot_list.is_empty() + snapshot_list.is_empty() && !Self::overlaps_with_historical_regions(&meta.region, historical_regions) } @@ -600,13 +696,15 @@ impl RegionManager { pub(crate) fn get_history_regions_min_ts(&self, region: &CacheRegion) -> Option { self.historical_regions + .lock() + .unwrap() .range(( Excluded(KeyAndVersion(region.start.clone(), u64::MAX)), Unbounded, )) .filter_map(|(_, meta)| { if meta.region.start < region.end { - meta.region_snapshot_list.min_snapshot_ts() + meta.region_snapshot_list.lock().unwrap().min_snapshot_ts() } else { None } @@ -614,17 +712,12 @@ impl RegionManager { .min() } - pub(crate) fn on_gc_region_finished(&mut self, region: &CacheRegion) { - let region_meta = self.regions.get_mut(®ion.id).unwrap(); - if region_meta.region.epoch_version == region.epoch_version { - region_meta.set_in_gc(false); - } else { - let cache_region = region_meta.region.clone(); - self.iter_overlapped_regions_mut(&cache_region, |meta| { - assert!(cache_region.contains_range(&meta.region)); - meta.set_in_gc(false); - }); - } + pub(crate) fn on_gc_region_finished(&self, region: &CacheRegion) { + let regions_map = self.regions_map.read(); + regions_map.on_all_overlapped_regions(region, |meta| { + assert!(region.contains_range(&meta.region)); + meta.set_in_gc(false); + }); } /// Return ranges that can be deleted now (no ongoing snapshot). @@ -634,7 +727,7 @@ impl RegionManager { // `evict_region` has done. // Note: `cb` should not do anything heavy. pub(crate) fn evict_region( - &mut self, + &self, evict_region: &CacheRegion, evict_reason: EvictReason, mut cb: Option>, @@ -645,38 +738,25 @@ impl RegionManager { "reason" => ?evict_reason, ); - if let Some(meta) = self.regions.get(&evict_region.id) { - // if epoch not changed, no need to do range scan. - if meta.region.epoch_version == evict_region.epoch_version { - if let Some(region) = - self.do_evict_region(evict_region.id, evict_region, evict_reason, cb) - { - return vec![region]; - } else { - return vec![]; - } - } - } - - let mut deleteable_regions = vec![]; + let mut regions_map = self.regions_map.write(); let mut evict_ids = vec![]; - self.iter_overlapped_regions(evict_region, |meta| { - if evict_region.start >= meta.region.end { - return false; - } + regions_map.on_all_overlapped_regions(evict_region, |meta| { evict_ids.push(meta.region.id); - true }); if evict_ids.is_empty() { info!("ime evict a region that is not cached"; "reason" => ?evict_reason, "region" => ?evict_region); + return vec![]; } + + let mut deleteable_regions = vec![]; for rid in evict_ids { if let Some(region) = self.do_evict_region( rid, evict_region, evict_reason, + &mut regions_map, if rid == evict_region.id { cb.take() } else { @@ -691,13 +771,14 @@ impl RegionManager { // return the region if it can be directly deleted. fn do_evict_region( - &mut self, + &self, id: u64, evict_region: &CacheRegion, evict_reason: EvictReason, + regions_map: &mut RegionMetaMap, cb: Option>, ) -> Option { - let meta = self.regions.get_mut(&id).unwrap(); + let meta = regions_map.mut_region_meta(id).unwrap(); let prev_state = meta.state; assert!( meta.region.overlaps(evict_region), @@ -706,7 +787,7 @@ impl RegionManager { evict_region ); if prev_state == RegionState::Pending { - let meta = self.remove_region(id); + let meta = regions_map.remove_region(id); info!( "ime evict overlap pending region in cache range engine"; "reason" => ?evict_reason, @@ -736,25 +817,23 @@ impl RegionManager { "new_state" => ?meta.state, ); - if meta.state == RegionState::PendingEvict - && Self::region_ready_to_evict(meta, &self.historical_regions) - { - meta.set_state(RegionState::Evicting); - return Some(meta.region.clone()); + if meta.state == RegionState::PendingEvict { + let snap_list = meta.region_snapshot_list.lock().unwrap(); + let historical_regions = self.historical_regions.lock().unwrap(); + if Self::region_ready_to_evict(meta, &snap_list, &historical_regions) { + drop(snap_list); + meta.set_state(RegionState::Evicting); + return Some(meta.region.clone()); + } } None } - fn remove_region(&mut self, id: u64) -> CacheRegionMeta { - let meta = self.regions.remove(&id).unwrap(); - self.regions_by_range.remove(&meta.region.end).unwrap(); - meta - } - - pub fn on_delete_regions(&mut self, regions: &[CacheRegion]) { + pub fn on_delete_regions(&self, regions: &[CacheRegion]) { fail::fail_point!("in_memory_engine_on_delete_regions"); + let mut regions_map = self.regions_map.write(); for r in regions { - let meta = self.remove_region(r.id); + let meta = regions_map.remove_region(r.id); assert_eq!(meta.region.epoch_version, r.epoch_version); let evict_info = meta.evict_info.unwrap(); @@ -780,58 +859,29 @@ impl RegionManager { .is_ok() } - pub(crate) fn is_overlapped_with_regions_being_written(&self, region: &CacheRegion) -> bool { - self.regions_being_written.iter().any(|(_, ranges)| { - ranges - .iter() - .any(|range_being_written| range_being_written.overlaps(region)) - }) - } - - pub(crate) fn record_in_region_being_written( - &mut self, - write_batch_id: u64, - region: CacheRegion, - ) { - self.regions_being_written - .entry(write_batch_id) - .or_default() - .push(region); - } - - pub(crate) fn clear_regions_in_being_written( - &mut self, - write_batch_id: u64, - has_entry_applied: bool, - ) { - let regions = self.regions_being_written.remove(&write_batch_id); - if has_entry_applied { - assert!(!regions.unwrap().is_empty()); + pub(crate) fn clear_regions_in_being_written(&self, regions: &[CacheRegion]) { + let regions_map = self.regions_map.read(); + for r in regions { + regions_map.on_all_overlapped_regions(r, |meta| { + assert!(r.contains_range(&meta.region)); + debug_assert!(meta.is_written()); + meta.is_written.store(false, Ordering::Release); + }); } } - pub fn load_region(&mut self, cache_region: CacheRegion) -> Result<(), LoadFailedReason> { - use RegionState::*; - if let Some(state) = self.check_overlap_with_region(&cache_region) { - let reason = match state { - Pending | Loading => LoadFailedReason::PendingRange, - Active => LoadFailedReason::Overlapped, - LoadingCanceled | PendingEvict | Evicting => LoadFailedReason::Evicting, - }; - return Err(reason); - } - let meta = CacheRegionMeta::new(cache_region); - self.new_region_meta(meta); - Ok(()) + pub fn load_region(&self, cache_region: CacheRegion) -> Result<(), LoadFailedReason> { + self.regions_map.write().load_region(cache_region) } // return `true` is the region is evicted. pub(crate) fn split_region( - &mut self, + &self, source_region: &CacheRegion, mut new_regions: Vec, ) { - if let Some(region_meta) = self.region_meta(source_region.id) { + let mut regions_map = self.regions_map.write(); + if let Some(region_meta) = regions_map.region_meta(source_region.id) { // if region is evicting, skip handling split for simplicity. if region_meta.state.is_evict() { info!("ime region is evicted, skip split"; @@ -843,7 +893,7 @@ impl RegionManager { return; } - let region_meta = self.remove_region(source_region.id); + let region_meta = regions_map.remove_region(source_region.id); assert!(!region_meta.state.is_evict()); if region_meta.region.epoch_version != source_region.epoch_version { // for pending regions, we keep regions that still fall in this range if epoch @@ -864,13 +914,14 @@ impl RegionManager { for r in new_regions { let meta = CacheRegionMeta::derive_from(r, ®ion_meta); - self.new_region_meta(meta); + regions_map.new_region_meta(meta); } // if there are still active snapshot, we need to put the orginal region // into `historical_regions` to track these snapshots. - if !region_meta.region_snapshot_list.is_empty() { - self.historical_regions.insert( + let snapshot_empty = region_meta.region_snapshot_list.lock().unwrap().is_empty(); + if !snapshot_empty { + self.historical_regions.lock().unwrap().insert( KeyAndVersion( region_meta.region.end.clone(), region_meta.region.epoch_version, @@ -881,17 +932,6 @@ impl RegionManager { } } -#[cfg(test)] -impl Drop for RegionManager { - fn drop(&mut self) { - // check regions and regions by range matches with each other. - for (key, id) in &self.regions_by_range { - let meta = self.regions.get(id).unwrap(); - assert_eq!(key, &meta.region.end); - } - } -} - #[derive(Debug, PartialEq)] pub enum LoadFailedReason { Overlapped, @@ -915,7 +955,7 @@ mod tests { #[test] fn test_range_manager() { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, "k00", b"k10"); range_mgr.new_region(r1.clone()); @@ -938,28 +978,39 @@ mod tests { let r_right = CacheRegion::new(3, 2, b"k06", b"k10"); range_mgr.split_region(&r1, vec![r_left.clone(), r_evict.clone(), r_right.clone()]); range_mgr.evict_region(&r_evict, EvictReason::AutoEvict, None); - let meta1 = range_mgr - .historical_regions - .get(&KeyAndVersion(r1.end.clone(), 0)) - .unwrap(); - assert_eq!( - range_mgr.regions.get(&r_evict.id).unwrap().state, - RegionState::PendingEvict, - ); - assert_eq!( - range_mgr.regions_by_range.get(&r1.end).unwrap(), - &r_right.id - ); - let meta2 = range_mgr.regions.get(&r_left.id).unwrap(); - let meta3 = range_mgr.regions.get(&r_right.id).unwrap(); - assert!(meta1.safe_point == meta2.safe_point && meta1.safe_point == meta3.safe_point); + + { + let regions_map = range_mgr.regions_map.read(); + let history_regions = range_mgr.historical_regions.lock().unwrap(); + let meta1 = history_regions + .get(&KeyAndVersion(r1.end.clone(), 0)) + .unwrap(); + assert_eq!( + regions_map.regions.get(&r_evict.id).unwrap().state, + RegionState::PendingEvict, + ); + assert_eq!( + regions_map.regions_by_range.get(&r1.end).unwrap(), + &r_right.id + ); + + let meta2 = regions_map.regions.get(&r_left.id).unwrap(); + let meta3 = regions_map.regions.get(&r_right.id).unwrap(); + assert!(meta1.safe_point == meta2.safe_point && meta1.safe_point == meta3.safe_point); + } // evict a range with accurate match range_mgr.region_snapshot(r_left.id, 2, 10).unwrap(); let snapshot3 = RangeCacheSnapshotMeta::new(r_left.clone(), 10, 3); range_mgr.evict_region(&r_left, EvictReason::AutoEvict, None); assert_eq!( - range_mgr.regions.get(&r_left.id).unwrap().state, + range_mgr + .regions_map + .read() + .regions + .get(&r_left.id) + .unwrap() + .state, RegionState::PendingEvict, ); assert!(range_mgr.remove_region_snapshot(&snapshot1).is_empty()); @@ -967,21 +1018,31 @@ mod tests { let regions = range_mgr.remove_region_snapshot(&snapshot2); assert_eq!(regions, vec![r_evict.clone()]); assert_eq!( - range_mgr.region_meta(r_evict.id).unwrap().get_state(), + range_mgr + .regions_map + .read() + .region_meta(r_evict.id) + .unwrap() + .get_state(), RegionState::Evicting ); let regions = range_mgr.remove_region_snapshot(&snapshot3); assert_eq!(regions, vec![r_left.clone()]); assert_eq!( - range_mgr.region_meta(r_left.id).unwrap().get_state(), + range_mgr + .regions_map + .read() + .region_meta(r_left.id) + .unwrap() + .get_state(), RegionState::Evicting ); } #[test] fn test_range_load() { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let mut r2 = CacheRegion::new(2, 2, b"k10", b"k20"); let r3 = CacheRegion::new(3, 0, b"k20", b"k30"); @@ -1012,7 +1073,7 @@ mod tests { #[test] fn test_range_load_overlapped() { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); range_mgr.new_region(r1.clone()); @@ -1046,7 +1107,7 @@ mod tests { #[test] fn test_evict_regions() { { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); @@ -1065,7 +1126,7 @@ mod tests { } { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); @@ -1083,14 +1144,16 @@ mod tests { ); assert!( range_mgr - .regions() + .regions_map + .read() + .regions .values() .all(|m| m.get_state() == RegionState::Evicting) ); } { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r2 = CacheRegion::new(2, 0, b"k20", b"k30"); let r3 = CacheRegion::new(3, 0, b"k40", b"k50"); @@ -1105,7 +1168,9 @@ mod tests { ); assert_eq!( range_mgr - .regions() + .regions_map + .read() + .regions .values() .filter(|m| m.get_state() == RegionState::Active) .count(), @@ -1114,7 +1179,7 @@ mod tests { } { - let mut range_mgr = RegionManager::default(); + let range_mgr = RegionManager::default(); let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); let r2 = CacheRegion::new(2, 0, b"k30", b"k40"); let r3 = CacheRegion::new(3, 0, b"k50", b"k60"); @@ -1129,7 +1194,9 @@ mod tests { ); assert_eq!( range_mgr - .regions() + .regions_map + .read() + .regions .values() .filter(|m| m.get_state() == RegionState::Active) .count(), diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index b42b07a5b5e..d648b717de6 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -74,12 +74,13 @@ impl RangeCacheSnapshot { read_ts: u64, seq_num: u64, ) -> result::Result { - let mut core = engine.core.write(); - core.range_manager + engine + .core + .region_manager .region_snapshot(region.id, region.epoch_version, read_ts)?; Ok(RangeCacheSnapshot { snapshot_meta: RangeCacheSnapshotMeta::new(region, read_ts, seq_num), - skiplist_engine: core.engine.clone(), + skiplist_engine: engine.core.engine.clone(), engine: engine.clone(), }) } @@ -87,12 +88,12 @@ impl RangeCacheSnapshot { impl Drop for RangeCacheSnapshot { fn drop(&mut self) { - let mut core = self.engine.core.write(); - let regions_removable = core - .range_manager + let regions_removable = self + .engine + .core + .region_manager .remove_region_snapshot(&self.snapshot_meta); if !regions_removable.is_empty() { - drop(core); if let Err(e) = self .engine .bg_worker_manager() @@ -701,11 +702,13 @@ mod tests { engine.new_region(region.clone()); let verify_snapshot_count = |snapshot_ts, count| { - let core = engine.core.read(); + let regions_map = engine.core.region_manager.regions_map.read(); if count > 0 { assert_eq!( - *core.range_manager.regions()[®ion.id] + *regions_map.regions()[®ion.id] .region_snapshot_list() + .lock() + .unwrap() .0 .get(&snapshot_ts) .unwrap(), @@ -713,8 +716,10 @@ mod tests { ); } else { assert!( - core.range_manager.regions()[®ion.id] + regions_map.regions()[®ion.id] .region_snapshot_list() + .lock() + .unwrap() .0 .get(&snapshot_ts) .is_none() @@ -725,10 +730,7 @@ mod tests { let cache_region = CacheRegion::from_region(®ion); let s1 = engine.snapshot(cache_region.clone(), 5, u64::MAX).unwrap(); - { - let mut core = engine.core.write(); - assert!(core.range_manager.set_safe_point(region.id, 5)); - } + assert!(engine.core.region_manager.set_safe_point(region.id, 5)); assert_eq!( engine .snapshot(cache_region.clone(), 5, u64::MAX) @@ -752,10 +754,14 @@ mod tests { verify_snapshot_count(10, 1); drop(s3); { - let core = engine.core.write(); + let regions_map = engine.core.region_manager.regions_map.read(); assert!( - core.range_manager.regions()[®ion.id] + regions_map + .region_meta(region.id) + .unwrap() .region_snapshot_list() + .lock() + .unwrap() .is_empty() ); } @@ -883,14 +889,10 @@ mod tests { let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); - { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); - - put_key_val(&sl, "b", "val", 10, 5); - put_key_val(&sl, "c", "vall", 10, 5); - } + engine.core.region_manager().set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); + put_key_val(&sl, "b", "val", 10, 5); + put_key_val(&sl, "c", "vall", 10, 5); let snapshot = engine.snapshot(range.clone(), u64::MAX, 100).unwrap(); let mut iter_opt = IterOptions::default(); @@ -922,14 +924,11 @@ mod tests { let cache_region = CacheRegion::from_region(®ion); engine.new_region(region.clone()); - { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); - fill_data_in_skiplist(sl.clone(), (1..10).step_by(1), 1..50, 1); - // k1 is deleted at seq_num 150 while k49 is deleted at seq num 101 - delete_data_in_skiplist(sl, (1..10).step_by(1), 1..50, 100); - } + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); + fill_data_in_skiplist(sl.clone(), (1..10).step_by(1), 1..50, 1); + // k1 is deleted at seq_num 150 while k49 is deleted at seq num 101 + delete_data_in_skiplist(sl, (1..10).step_by(1), 1..50, 100); let opts = ReadOptions::default(); { @@ -1003,14 +1002,11 @@ mod tests { let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); - let step: i32 = 2; - { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); - fill_data_in_skiplist(sl.clone(), (1..100).step_by(step as usize), 1..10, 1); - delete_data_in_skiplist(sl, (1..100).step_by(step as usize), 1..10, 200); - } + let step = 2; + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); + fill_data_in_skiplist(sl.clone(), (1..100).step_by(step), 1..10, 1); + delete_data_in_skiplist(sl, (1..100).step_by(step), 1..10, 200); let mut iter_opt = IterOptions::default(); let snapshot = engine.snapshot(range.clone(), 10, u64::MAX).unwrap(); @@ -1033,20 +1029,14 @@ mod tests { let snapshot = engine.snapshot(range.clone(), 100, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); iter.seek_to_first().unwrap(); - verify_key_values( - &mut iter, - (1..100).step_by(step as usize), - (1..10).rev(), - true, - true, - ); + verify_key_values(&mut iter, (1..100).step_by(step), (1..10).rev(), true, true); // seek key that is in the skiplist let seek_key = construct_key(11, u64::MAX); iter.seek(&seek_key).unwrap(); verify_key_values( &mut iter, - (11..100).step_by(step as usize), + (11..100).step_by(step), (1..10).rev(), true, true, @@ -1057,7 +1047,7 @@ mod tests { iter.seek(&seek_key).unwrap(); verify_key_values( &mut iter, - (13..100).step_by(step as usize), + (13..100).step_by(step), (1..10).rev(), true, true, @@ -1071,7 +1061,7 @@ mod tests { iter.seek_to_first().unwrap(); verify_key_values( &mut iter, - (63..100).step_by(step as usize), + (63..100).step_by(step), (1..10).rev(), true, true, @@ -1114,24 +1104,12 @@ mod tests { let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_first().unwrap()); - verify_key_values( - &mut iter, - (21..40).step_by(step as usize), - (1..10).rev(), - true, - true, - ); + verify_key_values(&mut iter, (21..40).step_by(step), (1..10).rev(), true, true); // seek a key that is below the lower bound is the same with seek_to_first let seek_key = construct_key(19, u64::MAX); assert!(iter.seek(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (21..40).step_by(step as usize), - (1..10).rev(), - true, - true, - ); + verify_key_values(&mut iter, (21..40).step_by(step), (1..10).rev(), true, true); // seek a key that is larger or equal to upper bound won't get any key let seek_key = construct_key(41, u64::MAX); @@ -1140,13 +1118,7 @@ mod tests { let seek_key = construct_key(32, u64::MAX); assert!(iter.seek(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (33..40).step_by(step as usize), - (1..10).rev(), - true, - true, - ); + verify_key_values(&mut iter, (33..40).step_by(step), (1..10).rev(), true, true); } // with bounds, some deletions (seq_num 215) @@ -1190,14 +1162,13 @@ mod tests { let region = new_region(1, b"", b"z"); let range = CacheRegion::from_region(®ion); engine.new_region(region.clone()); - let step: i32 = 2; + let step = 2; { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); - fill_data_in_skiplist(sl.clone(), (1..100).step_by(step as usize), 1..10, 1); - delete_data_in_skiplist(sl, (1..100).step_by(step as usize), 1..10, 200); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); + fill_data_in_skiplist(sl.clone(), (1..100).step_by(step), 1..10, 1); + delete_data_in_skiplist(sl, (1..100).step_by(step), 1..10, 200); } let mut iter_opt = IterOptions::default(); @@ -1211,35 +1182,17 @@ mod tests { let snapshot = engine.snapshot(range.clone(), 10, 150).unwrap(); let mut iter = snapshot.iterator_opt("write", iter_opt.clone()).unwrap(); assert!(iter.seek_to_last().unwrap()); - verify_key_values( - &mut iter, - (1..100).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (1..100).step_by(step).rev(), 1..10, false, true); // seek key that is in the skiplist let seek_key = construct_key(81, 0); assert!(iter.seek_for_prev(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (1..82).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (1..82).step_by(step).rev(), 1..10, false, true); // seek key that is in the skiplist let seek_key = construct_key(80, 0); assert!(iter.seek_for_prev(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (1..80).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (1..80).step_by(step).rev(), 1..10, false, true); } let lower_bound = construct_user_key(21); @@ -1251,24 +1204,12 @@ mod tests { let mut iter = snapshot.iterator_opt("write", iter_opt).unwrap(); assert!(iter.seek_to_last().unwrap()); - verify_key_values( - &mut iter, - (21..38).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (21..38).step_by(step).rev(), 1..10, false, true); // seek a key that is above the upper bound is the same with seek_to_last let seek_key = construct_key(40, 0); assert!(iter.seek_for_prev(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (21..38).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (21..38).step_by(step).rev(), 1..10, false, true); // seek a key that is less than the lower bound won't get any key let seek_key = construct_key(20, u64::MAX); @@ -1277,13 +1218,7 @@ mod tests { let seek_key = construct_key(26, 0); assert!(iter.seek_for_prev(&seek_key).unwrap()); - verify_key_values( - &mut iter, - (21..26).step_by(step as usize).rev(), - 1..10, - false, - true, - ); + verify_key_values(&mut iter, (21..26).step_by(step).rev(), 1..10, false, true); } } @@ -1297,9 +1232,8 @@ mod tests { engine.new_region(region.clone()); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "aaa", "va1", 10, 1); put_key_val(&sl, "aaa", "va2", 10, 3); @@ -1421,9 +1355,8 @@ mod tests { engine.new_region(region.clone()); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "aaa", "va1", 10, 2); put_key_val(&sl, "aaa", "va2", 10, 4); @@ -1523,9 +1456,8 @@ mod tests { )); engine.new_region(region.clone()); let sl = { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - core.engine.data[cf_to_id("write")].clone() + engine.core.region_manager.set_safe_point(region.id, 5); + engine.core.engine.data[cf_to_id("write")].clone() }; let mut s = 1; @@ -1561,9 +1493,8 @@ mod tests { )); engine.new_region(region.clone()); let sl = { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - core.engine.data[cf_to_id("write")].clone() + engine.core.region_manager.set_safe_point(region.id, 5); + engine.core.engine.data[cf_to_id("write")].clone() }; let mut s = 1; @@ -1592,9 +1523,8 @@ mod tests { )); engine.new_region(region.clone()); let sl = { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - core.engine.data[cf_to_id("write")].clone() + engine.core.region_manager.set_safe_point(region.id, 5); + engine.core.engine.data[cf_to_id("write")].clone() }; put_key_val(&sl, "a", "val", 10, 1); for i in 2..50 { @@ -1625,9 +1555,8 @@ mod tests { )); engine.new_region(region.clone()); let sl = { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - core.engine.data[cf_to_id("write")].clone() + engine.core.region_manager.set_safe_point(region.id, 5); + engine.core.engine.data[cf_to_id("write")].clone() }; let mut s = 1; for seq in 2..50 { @@ -1660,9 +1589,8 @@ mod tests { engine.new_region(region.clone()); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); let guard = &epoch::pin(); for i in 1..5 { @@ -1757,14 +1685,15 @@ mod tests { || { !engine .core + .region_manager() + .regions_map .read() - .range_manager() .regions() .values() .any(|m| m.get_state().is_evict()) }, ); - let write_handle = engine.core.read().engine.cf_handle("write"); + let write_handle = engine.core.engine.cf_handle("write"); let start_key = encode_seek_key(®ion.start, u64::MAX); let mut iter = write_handle.iterator(); @@ -1785,9 +1714,8 @@ mod tests { let guard = &epoch::pin(); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); for i in 0..30 { let user_key = construct_key(i, 10); let internal_key = encode_key(&user_key, 10, ValueType::Value); @@ -1855,9 +1783,8 @@ mod tests { let guard = &epoch::pin(); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); for i in 0..30 { let user_key = construct_key(i, 10); let internal_key = encode_key(&user_key, 10, ValueType::Value); @@ -1902,8 +1829,9 @@ mod tests { assert_eq!( engine .core + .region_manager() + .regions_map .read() - .range_manager() .region_meta(evict_region.id) .unwrap() .get_state(), @@ -1917,8 +1845,9 @@ mod tests { assert_eq!( engine .core + .region_manager() + .regions_map .read() - .range_manager() .region_meta(evict_region.id) .unwrap() .get_state(), @@ -1943,9 +1872,8 @@ mod tests { engine.new_region(region.clone()); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); delete_key(&sl, "a", 10, 5); delete_key(&sl, "b", 10, 5); @@ -1988,9 +1916,8 @@ mod tests { engine.new_region(region.clone()); { - let mut core = engine.core.write(); - core.range_manager.set_safe_point(region.id, 5); - let sl = core.engine.data[cf_to_id("write")].clone(); + engine.core.region_manager.set_safe_point(region.id, 5); + let sl = engine.core.engine.data[cf_to_id("write")].clone(); put_key_val(&sl, "a", "val", 10, 5); put_key_val(&sl, "b", "vall", 10, 5); diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index 96ba517b14b..f88f6db7cbb 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -45,10 +45,6 @@ const DELETE_ENTRY_VAL: &[u8] = b""; // delegate. It sets `range_cache_status` which is used to determine whether the // writes of this peer should be buffered. pub struct RangeCacheWriteBatch { - // `id` strictly incrementing and is used as the key in `ranges_being_written`, which records - // the ranges that are being written, so that when the write batch is consumed, we can - // quickly remove the ranges involved. - id: u64, // `range_cache_status` indicates whether the range is cached, loading data, or not cached. If // it is cached, we should buffer the write in `buffer` which is consumed during the write // is written in the kv engine. If it is loading data, we should buffer the write in @@ -64,6 +60,8 @@ pub struct RangeCacheWriteBatch { region_save_point: usize, current_region_evicted: bool, current_region: Option, + // all the regions this write batch is written. + written_regions: Vec, // record the total durations of the prepare work for write in the write batch prepare_for_write_duration: Duration, @@ -82,7 +80,6 @@ impl std::fmt::Debug for RangeCacheWriteBatch { impl From<&RangeCacheMemoryEngine> for RangeCacheWriteBatch { fn from(engine: &RangeCacheMemoryEngine) -> Self { Self { - id: engine.alloc_write_batch_id(), range_cache_status: RangeCacheStatus::NotInCache, buffer: Vec::new(), engine: engine.clone(), @@ -94,6 +91,7 @@ impl From<&RangeCacheMemoryEngine> for RangeCacheWriteBatch { current_region_evicted: false, prepare_for_write_duration: Duration::default(), current_region: None, + written_regions: vec![], } } } @@ -101,7 +99,6 @@ impl From<&RangeCacheMemoryEngine> for RangeCacheWriteBatch { impl RangeCacheWriteBatch { pub fn with_capacity(engine: &RangeCacheMemoryEngine, cap: usize) -> Self { Self { - id: engine.alloc_write_batch_id(), range_cache_status: RangeCacheStatus::NotInCache, buffer: Vec::with_capacity(cap), // cache_buffer should need small capacity @@ -114,6 +111,7 @@ impl RangeCacheWriteBatch { current_region_evicted: false, prepare_for_write_duration: Duration::default(), current_region: None, + written_regions: vec![], } } @@ -172,34 +170,34 @@ impl RangeCacheWriteBatch { // the RocksDB, which will be incremented automatically for each key, so // that all keys have unique sequence numbers. fn write_impl(&mut self, mut seq: u64) -> Result<()> { + // record last region before flush. + self.record_last_written_region(); + fail::fail_point!("on_range_cache_write_batch_write_impl"); let guard = &epoch::pin(); let start = Instant::now(); let mut lock_modification: u64 = 0; - let mut have_entry_applied = false; - let engine = self.engine.core.read().engine(); + let engine = self.engine.core.engine(); // Some entries whose ranges may be marked as evicted above, but it does not // matter, they will be deleted later. - let res = std::mem::take(&mut self.buffer) - .into_iter() - .try_for_each(|e| { - have_entry_applied = true; - if is_lock_cf(e.cf) { - lock_modification += e.data_size() as u64; - } - seq += 1; - e.write_to_memory(seq - 1, &engine, self.memory_controller.clone(), guard) - }); + std::mem::take(&mut self.buffer).into_iter().for_each(|e| { + if is_lock_cf(e.cf) { + lock_modification += e.data_size() as u64; + } + e.write_to_memory(seq, &engine, self.memory_controller.clone(), guard); + seq += 1; + }); let duration = start.saturating_elapsed_secs(); WRITE_DURATION_HISTOGRAM.observe(duration); fail::fail_point!("in_memory_engine_write_batch_consumed"); fail::fail_point!("before_clear_ranges_in_being_written"); - { - let mut core = self.engine.core.write(); - core.mut_range_manager() - .clear_regions_in_being_written(self.id, have_entry_applied); + if !self.written_regions.is_empty() { + self.engine + .core + .region_manager() + .clear_regions_in_being_written(&self.written_regions); } self.engine @@ -209,7 +207,7 @@ impl RangeCacheWriteBatch { RANGE_PREPARE_FOR_WRITE_DURATION_HISTOGRAM .observe(self.prepare_for_write_duration.as_secs_f64()); - res + Ok(()) } #[inline] @@ -303,6 +301,16 @@ impl RangeCacheWriteBatch { } true } + + #[inline] + fn record_last_written_region(&mut self) { + // NOTE: event if the region is evcited due to memory limit, we still + // need to track it because its "in written" flag has been set. + if self.range_cache_status != RangeCacheStatus::NotInCache { + let last_region = self.current_region.take().unwrap(); + self.written_regions.push(last_region); + } + } } #[derive(Clone, Debug)] @@ -400,15 +408,13 @@ impl RangeCacheWriteBatchEntry { skiplist_engine: &SkiplistEngine, memory_controller: Arc, guard: &epoch::Guard, - ) -> Result<()> { + ) { let handle = skiplist_engine.cf_handle(id_to_cf(self.cf)); let (mut key, mut value) = self.encode(seq); key.set_memory_controller(memory_controller.clone()); value.set_memory_controller(memory_controller); handle.insert(key, value, guard); - - Ok(()) } } @@ -454,13 +460,16 @@ impl WriteBatch for RangeCacheWriteBatch { } fn clear(&mut self) { + self.range_cache_status = RangeCacheStatus::NotInCache; self.buffer.clear(); self.save_points.clear(); self.sequence_number = None; - self.prepare_for_write_duration = Duration::ZERO; - self.current_region = None; - self.current_region_evicted = false; + self.memory_usage_reach_hard_limit = false; self.region_save_point = 0; + self.current_region_evicted = false; + self.current_region = None; + self.written_regions.clear(); + self.prepare_for_write_duration = Duration::ZERO; } fn set_save_point(&mut self) { @@ -490,8 +499,11 @@ impl WriteBatch for RangeCacheWriteBatch { fn prepare_for_region(&mut self, region: CacheRegion) { let time = Instant::now(); + // record last region for clearing region in written flags. + self.record_last_written_region(); + // TODO: remote range. - self.set_range_cache_status(self.engine.prepare_for_apply(self.id, ®ion)); + self.set_range_cache_status(self.engine.prepare_for_apply(®ion)); self.current_region = Some(region); self.memory_usage_reach_hard_limit = false; self.region_save_point = self.buffer.len(); @@ -579,17 +591,14 @@ mod tests { ))); let r = new_region(1, b"", b"z"); engine.new_region(r.clone()); - { - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r.id, 10); - } + engine.core.region_manager().set_safe_point(r.id, 10); + let mut wb = RangeCacheWriteBatch::from(&engine); - wb.range_cache_status = RangeCacheStatus::Cached; wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"aaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); assert_eq!(wb.write().unwrap(), 1); - let sl = engine.core.read().engine().data[cf_to_id(CF_DEFAULT)].clone(); + let sl = engine.core.engine().data[cf_to_id(CF_DEFAULT)].clone(); let guard = &crossbeam::epoch::pin(); let val = get_value(&sl, &encode_key(b"aaa", 2, ValueType::Value), guard).unwrap(); assert_eq!(&b"bbb"[..], val.as_slice()); @@ -602,12 +611,9 @@ mod tests { ))); let r = new_region(1, b"", b"z"); engine.new_region(r.clone()); - { - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r.id, 10); - } + engine.core.region_manager().set_safe_point(r.id, 10); + let mut wb = RangeCacheWriteBatch::from(&engine); - wb.range_cache_status = RangeCacheStatus::Cached; wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"aaa", b"bbb").unwrap(); wb.set_save_point(); @@ -616,7 +622,7 @@ mod tests { wb.rollback_to_save_point().unwrap(); wb.set_sequence_number(1).unwrap(); assert_eq!(wb.write().unwrap(), 1); - let sl = engine.core.read().engine().data[cf_to_id(CF_DEFAULT)].clone(); + let sl = engine.core.engine().data[cf_to_id(CF_DEFAULT)].clone(); let guard = &crossbeam::epoch::pin(); let val = get_value(&sl, &encode_key(b"aaa", 1, ValueType::Value), guard).unwrap(); assert_eq!(&b"bbb"[..], val.as_slice()); @@ -629,13 +635,13 @@ mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let r = new_region(1, b"", b"z"); - engine.new_region(r.clone()); - { - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r.id, 10); - } + engine + .core + .region_manager() + .new_region(CacheRegion::from_region(&r)); + engine.core.region_manager().set_safe_point(r.id, 10); + let mut wb = RangeCacheWriteBatch::from(&engine); - wb.range_cache_status = RangeCacheStatus::Cached; wb.prepare_for_region(CacheRegion::from_region(&r)); wb.put(b"zaaa", b"bbb").unwrap(); wb.set_sequence_number(1).unwrap(); @@ -678,7 +684,15 @@ mod tests { r1_new.mut_region_epoch().version = 2; let mut wb = RangeCacheWriteBatch::from(&engine); wb.prepare_for_region(CacheRegion::from_region(&r1_new)); - assert!(engine.core().read().range_manager().regions().is_empty()); + assert!( + engine + .core + .region_manager() + .regions_map + .read() + .regions() + .is_empty() + ); wb.put(b"zk01", b"val1").unwrap(); wb.put(b"zk03", b"val1").unwrap(); wb.put(b"zk05", b"val1").unwrap(); @@ -686,7 +700,7 @@ mod tests { wb.write().unwrap(); } // pending region is removed, no data should write to skiplist. - let skip_engine = engine.core.read().engine(); + let skip_engine = engine.core.engine(); assert_eq!(skip_engine.node_count(), 0); // epoch changes but new range is contained by the pending region, will update @@ -698,8 +712,8 @@ mod tests { let mut wb = RangeCacheWriteBatch::from(&engine); wb.prepare_for_region(cache_r1_new.clone()); { - let core = engine.core.read(); - let region_meta = core.range_manager().region_meta(1).unwrap(); + let regions_map = engine.core.region_manager().regions_map.read(); + let region_meta = regions_map.region_meta(1).unwrap(); assert_eq!(region_meta.get_region(), &cache_r1_new); assert_eq!(region_meta.get_state(), RegionState::Loading); } @@ -712,8 +726,8 @@ mod tests { Duration::from_millis(50), Duration::from_millis(1000), || { - let core = engine.core.read(); - core.range_manager().region_meta(1).unwrap().get_state() == RegionState::Active + let regions_map = engine.core.region_manager().regions_map.read(); + regions_map.region_meta(1).unwrap().get_state() == RegionState::Active }, ); let snapshot = engine.snapshot(cache_r1_new.clone(), u64::MAX, 6).unwrap(); @@ -725,8 +739,6 @@ mod tests { assert!(res.is_none()); } } - - let skip_engine = engine.core.read().engine(); assert_eq!(skip_engine.node_count(), 2); let mut wb = RangeCacheWriteBatch::from(&engine); @@ -739,8 +751,8 @@ mod tests { // evict region, data should not be updated. { - let mut core = engine.core.write(); - core.mut_range_manager() + let mut regions_map = engine.core.region_manager().regions_map.write(); + regions_map .mut_region_meta(1) .unwrap() .set_state(RegionState::PendingEvict); @@ -759,10 +771,8 @@ mod tests { Duration::from_millis(100), Duration::from_millis(2000), || { - !engine - .core - .read() - .range_manager() + let regions_map = engine.core.region_manager.regions_map().read(); + !regions_map .regions() .values() .any(|meta| meta.get_state().is_evict()) @@ -788,10 +798,7 @@ mod tests { ]; for r in ®ions { engine.new_region(r.clone()); - { - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r.id, 10); - } + engine.core.region_manager().set_safe_point(r.id, 10); let _ = engine .snapshot(CacheRegion::from_region(r), 1000, 1000) .unwrap(); @@ -899,10 +906,7 @@ mod tests { let r2 = new_region(2, b"kk10".to_vec(), b"kk20".to_vec()); for r in [&r1, &r2] { engine.new_region(r.clone()); - { - let mut core = engine.core.write(); - core.mut_range_manager().set_safe_point(r.id, 10); - } + engine.core.region_manager().set_safe_point(r.id, 10); let _ = engine .snapshot(CacheRegion::from_region(r), 1000, 1000) .unwrap(); @@ -972,12 +976,7 @@ mod tests { let r1 = CacheRegion::new(1, 0, b"k00", b"k10"); - engine - .core() - .write() - .mut_range_manager() - .load_region(r1) - .unwrap(); + engine.core().region_manager().load_region(r1).unwrap(); // load a region with a newer epoch and small range, should trigger replace. let r_new = CacheRegion::new(1, 1, b"k00", b"k05"); @@ -985,13 +984,10 @@ mod tests { wb.prepare_for_region(r_new.clone()); { - let core = engine.core().read(); - let cache_meta = core.range_manager.region_meta(1).unwrap(); + let regions_map = engine.core.region_manager.regions_map().read(); + let cache_meta = regions_map.region_meta(1).unwrap(); assert_eq!(cache_meta.get_region(), &r_new); - let meta_by_range = core - .range_manager - .region_meta_by_end_key(&r_new.end) - .unwrap(); + let meta_by_range = regions_map.region_meta_by_end_key(&r_new.end).unwrap(); assert_eq!(meta_by_range.get_region(), &r_new); } } diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 73f3de4969f..6c0ee124f10 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -62,13 +62,13 @@ fn test_gc_worker() { VersionTrack::new(config), ))); let memory_controller = engine.memory_controller(); - let (write, default) = { - let mut core = engine.core().write(); - core.mut_range_manager() - .new_region(CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY)); - let engine = core.engine(); - (engine.cf_handle(CF_WRITE), engine.cf_handle(CF_DEFAULT)) - }; + engine + .core() + .region_manager() + .new_region(CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY)); + let skip_engine = engine.core().engine(); + let write = skip_engine.cf_handle(CF_WRITE); + let default = skip_engine.cf_handle(CF_DEFAULT); fail::cfg("in_memory_engine_gc_oldest_seqno", "return(1000)").unwrap(); @@ -192,7 +192,7 @@ fn test_clean_up_tombstone() { wb.set_sequence_number(120).unwrap(); wb.write().unwrap(); - let lock_handle = engine.core().read().engine().cf_handle("lock"); + let lock_handle = engine.core().engine().cf_handle("lock"); assert_eq!(lock_handle.len(), 13); engine @@ -202,7 +202,7 @@ fn test_clean_up_tombstone() { rx.recv_timeout(Duration::from_secs(5)).unwrap(); - let mut iter = engine.core().read().engine().cf_handle("lock").iterator(); + let mut iter = engine.core().engine().cf_handle("lock").iterator(); let mut first = true; let guard = &epoch::pin(); @@ -346,11 +346,11 @@ fn test_cached_write_batch_cleared_when_load_failed() { Duration::from_millis(100), Duration::from_millis(2000), || { - let core = engine.core().read(); + let regions_map = engine.core().region_manager().regions_map().read(); // all failed regions should be removed. [1, 2] .into_iter() - .all(|i| core.range_manager().region_meta(i).is_none()) + .all(|i| regions_map.region_meta(i).is_none()) }, ); } @@ -447,7 +447,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { engine.evict_region(&cache_region2, EvictReason::AutoEvict, None); let verify_data = |r: &Region, expected_num: u64| { - let handle = engine.core().read().engine().cf_handle(CF_LOCK); + let handle = engine.core().engine().cf_handle(CF_LOCK); let (start, end) = encode_key_for_boundary_without_mvcc(&CacheRegion::from_region(r)); let mut iter = handle.iterator(); let guard = &epoch::pin(); @@ -627,7 +627,7 @@ fn test_load_with_gc() { load_rx.recv_timeout(Duration::from_secs(5)).unwrap(); let expects = vec![(b"k1", 5), (b"k3", 7), (b"k3", 4)]; - let write_handle = engine.core().read().engine().cf_handle(CF_WRITE); + let write_handle = engine.core().engine().cf_handle(CF_WRITE); let mut iter = write_handle.iterator(); let guard = &epoch::pin(); @@ -700,8 +700,9 @@ fn test_region_split_before_batch_loading_start() { assert_eq!( engine .core() + .region_manager() + .regions_map() .read() - .range_manager() .region_meta(1) .unwrap() .get_state(), @@ -723,10 +724,10 @@ fn test_region_split_before_batch_loading_start() { }; engine.on_region_event(event); { - let core = engine.core().read(); + let regions_map = engine.core().region_manager().regions_map().read(); for i in 1..=3 { assert_eq!( - core.range_manager().region_meta(i).unwrap().get_state(), + regions_map.region_meta(i).unwrap().get_state(), RegionState::Loading ); } @@ -740,10 +741,8 @@ fn test_region_split_before_batch_loading_start() { Duration::from_millis(50), Duration::from_millis(2000), || { - let core = engine.core().read(); - (1..=3).all(|i| { - core.range_manager().region_meta(i).unwrap().get_state() == RegionState::Active - }) + let regions_map = engine.core().region_manager().regions_map().read(); + (1..=3).all(|i| regions_map.region_meta(i).unwrap().get_state() == RegionState::Active) }, ); } @@ -784,7 +783,7 @@ fn test_cb_on_eviction() { let _ = rx.recv(); { - let core = engine.core().read(); - assert!(core.range_manager().region_meta(1).is_none()); + let regions_map = engine.core().region_manager().regions_map().read(); + assert!(regions_map.region_meta(1).is_none()); } } diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index 422891ef2a6..b9517c0549b 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -71,10 +71,14 @@ fn test_put_copr_get() { { let region = cluster.get_region(b"k"); let rid = region.id; - let mut core = range_cache_engine.core().write(); - core.mut_range_manager() + range_cache_engine + .core() + .region_manager() .new_region(CacheRegion::from_region(®ion)); - core.mut_range_manager().set_safe_point(rid, current_ts); + range_cache_engine + .core() + .region_manager() + .set_safe_point(rid, current_ts); } let product = ProductTable::new(); @@ -125,14 +129,19 @@ fn test_load() { let r1 = cluster.get_region(&split_keys[0]); let r2 = cluster.get_region(&split_keys[1]); let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - core.mut_range_manager() + range_cache_engine + .core() + .region_manager() .load_region(CacheRegion::from_region(&r)) .unwrap(); - core.mut_range_manager() + range_cache_engine + .core() + .region_manager() .load_region(CacheRegion::from_region(&r1)) .unwrap(); - core.mut_range_manager() + range_cache_engine + .core() + .region_manager() .load_region(CacheRegion::from_region(&r2)) .unwrap(); } @@ -189,11 +198,12 @@ fn test_load_with_split() { // load range { let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); // Load the whole range as if it is not splitted. Loading process should handle // it correctly. let cache_range = new_region(1, "", ""); - core.mut_range_manager() + range_cache_engine + .core() + .region_manager() .load_region(CacheRegion::from_region(&cache_range)) .unwrap(); } @@ -295,14 +305,13 @@ fn test_load_with_split2() { handle_put_rx.recv_timeout(Duration::from_secs(5)).unwrap(); std::thread::sleep(Duration::from_secs(1)); - { - let mut core = range_cache_engine.core().write(); - // try to load a region with old epoch and bigger range, - // it should be updated to the real region range. - core.mut_range_manager() - .load_region(CacheRegion::new(r_split.id, 0, DATA_MIN_KEY, DATA_MAX_KEY)) - .unwrap(); - } + // try to load a region with old epoch and bigger range, + // it should be updated to the real region range. + range_cache_engine + .core() + .region_manager() + .load_region(CacheRegion::new(r_split.id, 0, DATA_MIN_KEY, DATA_MAX_KEY)) + .unwrap(); let (tx, rx) = sync_channel(1); fail::cfg_callback("on_snapshot_load_finished", move || { @@ -317,8 +326,12 @@ fn test_load_with_split2() { { let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let core = range_cache_engine.core().read(); - let meta = core.range_manager().region_meta(r_split.id).unwrap(); + let regions_map = range_cache_engine + .core() + .region_manager() + .regions_map() + .read(); + let meta = regions_map.region_meta(r_split.id).unwrap(); let split_range = CacheRegion::from_region(&r_split); assert_eq!(&split_range, meta.get_region()); } @@ -357,14 +370,15 @@ fn test_load_with_eviction() { let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); cluster.run(); // load range - { - let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - // Load the whole range as if it is not splitted. Loading process should handle - // it correctly. - let cache_range = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); - core.mut_range_manager().load_region(cache_range).unwrap(); - } + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); + // Load the whole range as if it is not splitted. Loading process should handle + // it correctly. + let cache_range = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); + range_cache_engine + .core() + .region_manager() + .load_region(cache_range) + .unwrap(); let product1 = ProductTable::new(); let product2 = ProductTable::new(); @@ -458,13 +472,11 @@ fn test_evictions_after_transfer_leader() { cluster.must_transfer_leader(r.id, new_peer(1, 1)); let cache_region = CacheRegion::new(1, 0, DATA_MIN_KEY, DATA_MAX_KEY); - let range_cache_engine = { - let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(cache_region.clone()); - drop(core); - range_cache_engine - }; + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); + range_cache_engine + .core() + .region_manager() + .new_region(cache_region.clone()); range_cache_engine .snapshot(cache_region.clone(), 100, 100) @@ -488,14 +500,15 @@ fn test_eviction_after_merge() { let r2 = cluster.get_region(b"key1"); let range2 = CacheRegion::from_region(&r2); - let range_cache_engine = { - let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(range1.clone()); - core.mut_range_manager().new_region(range2.clone()); - drop(core); - range_cache_engine - }; + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); + range_cache_engine + .core() + .region_manager() + .new_region(range1.clone()); + range_cache_engine + .core() + .region_manager() + .new_region(range2.clone()); range_cache_engine .snapshot(range1.clone(), 100, 100) @@ -528,13 +541,11 @@ fn test_eviction_after_ingest_sst() { // Add region r to cache. let region = cluster.get_region(b""); let cache_region = CacheRegion::from_region(®ion); - let range_cache_engine = { - let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); - let mut core = range_cache_engine.core().write(); - core.mut_range_manager().new_region(cache_region.clone()); - drop(core); - range_cache_engine - }; + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); + range_cache_engine + .core() + .region_manager() + .new_region(cache_region.clone()); range_cache_engine .snapshot(cache_region.clone(), 100, 100) From 4e5724afcf4cf5ef1d19f82d23815cbc4ea7fb85 Mon Sep 17 00:00:00 2001 From: Ling Jin <7138436+3AceShowHand@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:31:32 +0800 Subject: [PATCH 062/144] cdc: return sink congested error explictly (#17507) close tikv/tikv#17503 TiKV-CDC report `Congested` error if allocate memory quota failed meet `MemoryQuotaExceed` * Convert the `SendError::Congested` to `cdcpb::Error::Congested` Signed-off-by: 3AceShowHand --- Cargo.lock | 2 +- components/cdc/src/channel.rs | 20 +++++++----- components/cdc/src/delegate.rs | 4 +++ components/cdc/src/errors.rs | 32 +++++++++++-------- .../tests/integrations/test_flow_control.rs | 2 +- components/cdc/tests/mod.rs | 2 +- 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19c95ce2607..c7009a19164 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2845,7 +2845,7 @@ dependencies = [ [[package]] name = "kvproto" version = "0.0.2" -source = "git+https://github.com/pingcap/kvproto.git#0b10bdf8ba4b5f71b8cb74daee97e302f7e146e2" +source = "git+https://github.com/pingcap/kvproto.git#1a933d30690a1cd7a4642f569be473329c756f8a" dependencies = [ "futures 0.3.15", "grpcio", diff --git a/components/cdc/src/channel.rs b/components/cdc/src/channel.rs index ad9ebdd0d44..98520dc7b02 100644 --- a/components/cdc/src/channel.rs +++ b/components/cdc/src/channel.rs @@ -214,8 +214,12 @@ pub fn channel(conn_id: ConnId, buffer: usize, memory_quota: Arc) - #[derive(Clone, Debug, PartialEq)] pub enum SendError { + // Full is returned by the sender if the channel is full, this should only happen to the + // bounded sender. Full, + // Disconnected is returned by the sender if the channel is disconnected. Disconnected, + // Congested is returned if memory quota exceeded. Congested, } @@ -573,10 +577,10 @@ mod tests { #[test] fn test_congest() { - let mut e = kvproto::cdcpb::Event::default(); + let mut e = Event::default(); e.region_id = 1; let event = CdcEvent::Event(e.clone()); - assert!(event.size() != 0); + assert_ne!(event.size(), 0); // 1KB let max_pending_bytes = 1024; let buffer = max_pending_bytes / event.size(); @@ -590,10 +594,10 @@ mod tests { #[test] fn test_set_capacity() { - let mut e = kvproto::cdcpb::Event::default(); + let mut e = Event::default(); e.region_id = 1; let event = CdcEvent::Event(e.clone()); - assert!(event.size() != 0); + assert_ne!(event.size(), 0); // 1KB let max_pending_bytes = 1024; let buffer = max_pending_bytes / event.size(); @@ -641,10 +645,10 @@ mod tests { #[test] fn test_force_send() { - let mut e = kvproto::cdcpb::Event::default(); + let mut e = Event::default(); e.region_id = 1; let event = CdcEvent::Event(e.clone()); - assert!(event.size() != 0); + assert_ne!(event.size(), 0); // 1KB let max_pending_bytes = 1024; let buffer = max_pending_bytes / event.size(); @@ -664,10 +668,10 @@ mod tests { #[test] fn test_channel_memory_leak() { - let mut e = kvproto::cdcpb::Event::default(); + let mut e = Event::default(); e.region_id = 1; let event = CdcEvent::Event(e.clone()); - assert!(event.size() != 0); + assert_ne!(event.size(), 0); // 1KB let max_pending_bytes = 1024; let buffer = max_pending_bytes / event.size() + 1; diff --git a/components/cdc/src/delegate.rs b/components/cdc/src/delegate.rs index cbc8ad3118f..beff91f7b45 100644 --- a/components/cdc/src/delegate.rs +++ b/components/cdc/src/delegate.rs @@ -1500,6 +1500,10 @@ mod tests { let err = receive_error(); assert!(err.has_region_not_found()); + delegate.stop(Error::Sink(SendError::Congested)); + let err = receive_error(); + assert!(err.has_congested()); + let mut err_header = ErrorHeader::default(); err_header.set_epoch_not_match(Default::default()); delegate.stop(Error::request(err_header)); diff --git a/components/cdc/src/errors.rs b/components/cdc/src/errors.rs index e7bd7605e7d..075dc4377f0 100644 --- a/components/cdc/src/errors.rs +++ b/components/cdc/src/errors.rs @@ -3,7 +3,7 @@ use std::{error, io::Error as IoError, result}; use engine_traits::Error as EngineTraitsError; -use kvproto::{cdcpb::Error as ErrorEvent, errorpb}; +use kvproto::{cdcpb, cdcpb::Error as ErrorEvent, errorpb}; use thiserror::Error; use tikv::storage::{ kv::{Error as KvError, ErrorInner as EngineErrorInner}, @@ -78,7 +78,7 @@ impl Error { ) } - pub fn extract_region_error(self) -> errorpb::Error { + fn extract_region_error(self) -> errorpb::Error { match self { Error::Kv(KvError(box EngineErrorInner::Request(e))) | Error::Txn(TxnError(box TxnErrorInner::Engine(KvError( @@ -99,18 +99,24 @@ impl Error { pub fn into_error_event(self, region_id: u64) -> ErrorEvent { let mut err_event = ErrorEvent::default(); - let mut err = self.extract_region_error(); - if err.has_not_leader() { - let not_leader = err.take_not_leader(); - err_event.set_not_leader(not_leader); - } else if err.has_epoch_not_match() { - let epoch_not_match = err.take_epoch_not_match(); - err_event.set_epoch_not_match(epoch_not_match); + if matches!(self, Error::Sink(SendError::Congested)) { + let mut congested = cdcpb::Congested::default(); + congested.set_region_id(region_id); + err_event.set_congested(congested); } else { - // TODO: Add more errors to the cdc protocol - let mut region_not_found = errorpb::RegionNotFound::default(); - region_not_found.set_region_id(region_id); - err_event.set_region_not_found(region_not_found); + let mut err = self.extract_region_error(); + if err.has_not_leader() { + let not_leader = err.take_not_leader(); + err_event.set_not_leader(not_leader); + } else if err.has_epoch_not_match() { + let epoch_not_match = err.take_epoch_not_match(); + err_event.set_epoch_not_match(epoch_not_match); + } else { + // TODO: Add more errors to the cdc protocol + let mut region_not_found = errorpb::RegionNotFound::default(); + region_not_found.set_region_id(region_id); + err_event.set_region_not_found(region_not_found); + } } err_event } diff --git a/components/cdc/tests/integrations/test_flow_control.rs b/components/cdc/tests/integrations/test_flow_control.rs index fdfd136d9c7..77edbcc7e2d 100644 --- a/components/cdc/tests/integrations/test_flow_control.rs +++ b/components/cdc/tests/integrations/test_flow_control.rs @@ -75,7 +75,7 @@ fn test_cdc_congest() { match events.pop().unwrap().event.unwrap() { Event_oneof_event::Error(e) => { // Unknown errors are translated into region_not_found. - assert!(e.has_region_not_found(), "{:?}", e); + assert!(e.has_congested(), "{:?}", e); } other => panic!("unknown event {:?}", other), } diff --git a/components/cdc/tests/mod.rs b/components/cdc/tests/mod.rs index efe6bca2492..25d9121c8bf 100644 --- a/components/cdc/tests/mod.rs +++ b/components/cdc/tests/mod.rs @@ -108,7 +108,7 @@ fn create_event_feed( return ChangeDataEvent::default(); }; let change_data = - if let Some(event) = recv_timeout(&mut events_rx, Duration::from_secs(5)).unwrap() { + if let Some(event) = recv_timeout(&mut events_rx, Duration::from_secs(20)).unwrap() { event } else { return ChangeDataEvent::default(); From 3b9857d04ded8db337ab4a0a5c8dd8da2e2348e9 Mon Sep 17 00:00:00 2001 From: Ling Jin <7138436+3AceShowHand@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:25:36 +0800 Subject: [PATCH 063/144] cdc: fix unstable test_cdc_pipeline_dml (#17533) close tikv/tikv#17534 * fix the unstable unit test test_cdc_pipeline_dml * return `congested` when meet MemoryQuotaExceed error, this happens when push pending locks Signed-off-by: 3AceShowHand --- components/cdc/src/errors.rs | 5 ++++- components/cdc/tests/failpoints/test_endpoint.rs | 1 + components/cdc/tests/failpoints/test_memory_quota.rs | 8 ++++---- components/cdc/tests/mod.rs | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/components/cdc/src/errors.rs b/components/cdc/src/errors.rs index 075dc4377f0..fa0458bc5c6 100644 --- a/components/cdc/src/errors.rs +++ b/components/cdc/src/errors.rs @@ -99,7 +99,10 @@ impl Error { pub fn into_error_event(self, region_id: u64) -> ErrorEvent { let mut err_event = ErrorEvent::default(); - if matches!(self, Error::Sink(SendError::Congested)) { + if matches!( + self, + Error::Sink(SendError::Congested) | Error::MemoryQuotaExceeded(MemoryQuotaExceeded) + ) { let mut congested = cdcpb::Congested::default(); congested.set_region_id(region_id); err_event.set_congested(congested); diff --git a/components/cdc/tests/failpoints/test_endpoint.rs b/components/cdc/tests/failpoints/test_endpoint.rs index 2e11018ba8d..d6e3c904fd2 100644 --- a/components/cdc/tests/failpoints/test_endpoint.rs +++ b/components/cdc/tests/failpoints/test_endpoint.rs @@ -688,6 +688,7 @@ fn test_cdc_pipeline_dml() { req.request_id = 1; req.checkpoint_ts = cf_tso.into_inner(); block_on(req_tx.send((req, WriteFlags::default()))).unwrap(); + sleep_ms(100); let (k, v) = (b"key".to_vec(), vec![b'y'; 16]); let mut mutation = Mutation::default(); diff --git a/components/cdc/tests/failpoints/test_memory_quota.rs b/components/cdc/tests/failpoints/test_memory_quota.rs index bcc86d0b159..3d331deda3d 100644 --- a/components/cdc/tests/failpoints/test_memory_quota.rs +++ b/components/cdc/tests/failpoints/test_memory_quota.rs @@ -78,7 +78,7 @@ fn test_resolver_track_lock_memory_quota_exceeded() { match events.pop().unwrap().event.unwrap() { Event_oneof_event::Error(e) => { // Unknown errors are translated into region_not_found. - assert!(e.has_region_not_found(), "{:?}", e); + assert!(e.has_congested(), "{:?}", e); } other => panic!("unknown event {:?}", other), } @@ -130,7 +130,7 @@ fn test_pending_on_region_ready_memory_quota_exceeded() { match events.pop().unwrap().event.unwrap() { Event_oneof_event::Error(e) => { // Unknown errors are translated into region_not_found. - assert!(e.has_region_not_found(), "{:?}", e); + assert!(e.has_congested(), "{:?}", e); } other => panic!("unknown event {:?}", other), } @@ -194,7 +194,7 @@ fn test_pending_push_lock_memory_quota_exceeded() { match events.pop().unwrap().event.unwrap() { Event_oneof_event::Error(e) => { // Unknown errors are translated into region_not_found. - assert!(e.has_region_not_found(), "{:?}", e); + assert!(e.has_congested(), "{:?}", e); } other => panic!("unknown event {:?}", other), } @@ -255,7 +255,7 @@ fn test_scan_lock_memory_quota_exceeded() { match events.pop().unwrap().event.unwrap() { Event_oneof_event::Error(e) => { // Unknown errors are translated into region_not_found. - assert!(e.has_region_not_found(), "{:?}", e); + assert!(e.has_congested(), "{:?}", e); } other => panic!("unknown event {:?}", other), } diff --git a/components/cdc/tests/mod.rs b/components/cdc/tests/mod.rs index 25d9121c8bf..efe6bca2492 100644 --- a/components/cdc/tests/mod.rs +++ b/components/cdc/tests/mod.rs @@ -108,7 +108,7 @@ fn create_event_feed( return ChangeDataEvent::default(); }; let change_data = - if let Some(event) = recv_timeout(&mut events_rx, Duration::from_secs(20)).unwrap() { + if let Some(event) = recv_timeout(&mut events_rx, Duration::from_secs(5)).unwrap() { event } else { return ChangeDataEvent::default(); From 7944da687fab2e760f10933259140774a50ae356 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:58:05 +0800 Subject: [PATCH 064/144] In-memory engine: optimize eviction on soft limit reached (#17512) ref tikv/tikv#16141 Optimize eviction on soft-limi-threshold reached. When memory usage reaches soft-limi-threshold, evict regions with less read flows until the memory usage below the soft-limi-threshold. Signed-off-by: SpadeA-Tang Signed-off-by: Neil Shen Co-authored-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 1 + .../range_cache_memory_engine/Cargo.toml | 1 + .../src/background.rs | 111 ++---- .../range_cache_memory_engine/src/engine.rs | 31 +- .../range_cache_memory_engine/src/lib.rs | 1 + .../src/range_manager.rs | 54 +-- .../src/range_stats.rs | 339 ++++++++++++------ .../tests/failpoints/test_memory_engine.rs | 24 +- 8 files changed, 342 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7009a19164..76da4f1b686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4523,6 +4523,7 @@ dependencies = [ "test_util", "thiserror", "tikv_util", + "tokio", "txn_types", "yatp", ] diff --git a/components/range_cache_memory_engine/Cargo.toml b/components/range_cache_memory_engine/Cargo.toml index eb5a03848e8..561f084404d 100644 --- a/components/range_cache_memory_engine/Cargo.toml +++ b/components/range_cache_memory_engine/Cargo.toml @@ -47,6 +47,7 @@ thiserror = "1.0" online_config = { workspace = true } libc = "0.2" rand = "0.8" +tokio = { version = "1.5", features = ["rt-multi-thread"] } [dev-dependencies] tempfile = "3.0" diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 71da8480b27..6b8bba2ccf9 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -37,7 +37,7 @@ use crate::{ GC_FILTERED_STATIC, RANGE_CACHE_COUNT, RANGE_CACHE_MEMORY_USAGE, RANGE_GC_TIME_HISTOGRAM, RANGE_LOAD_TIME_HISTOGRAM, }, - range_manager::{CacheRegionMeta, RegionState}, + range_manager::{AsyncFnOnce, CacheRegionMeta, RegionState}, range_stats::{RangeStatsManager, DEFAULT_EVICT_MIN_DURATION}, region_label::{ KeyRangeRule, LabelRule, RegionLabelAddedCb, RegionLabelRulesManager, @@ -596,74 +596,6 @@ impl BackgroundRunnerCore { } } - /// Eviction on soft limit reached: - /// - /// When soft limit is reached, collect the candidates for eviction, and - /// keep evicting until either all candidates are evicted, or the total - /// approximated size of evicted regions is equal to or greater than the - /// excess memory usage. - fn evict_on_soft_limit_reached(&self, delete_range_scheduler: &Scheduler) { - if self.range_stats_manager.is_none() { - warn!("ime range stats manager is not initialized, cannot evict on soft limit reached"); - return; - } - let range_stats_manager = self.range_stats_manager.as_ref().unwrap(); - let mut remaining = self - .memory_controller - .mem_usage() - .saturating_sub(self.memory_controller.soft_limit_threshold()); - if remaining == 0 { - return; - } - - let mut regions_to_evict = Vec::with_capacity(256); - - // TODO (afeinberg, low): consider returning just an iterator and using scan - // below for cleaner code. - range_stats_manager.collect_candidates_for_eviction(&mut regions_to_evict, |region| { - self.engine.region_manager().contains_region(region.id) - }); - - let mut regions_to_delete = vec![]; - // TODO (afeinberg): approximate size may differ from size in in-memory cache, - // consider taking the actual size into account. - for (region, approx_size) in regions_to_evict { - if remaining == 0 { - break; - } - let cache_region = CacheRegion::from_region(®ion); - let deleteable_regions = self.engine.region_manager().evict_region( - &cache_region, - EvictReason::MemoryLimitReached, - None, - ); - if !deleteable_regions.is_empty() { - info!( - "ime evict on soft limit reached"; - "region_to_evict" => ?cache_region, - "regions_evicted" => ?&deleteable_regions, - "approx_size" => approx_size, - "remaining" => remaining - ); - remaining = remaining.saturating_sub(approx_size as usize); - range_stats_manager.handle_region_evicted(®ion); - regions_to_delete.extend(deleteable_regions); - } - } - - if !regions_to_delete.is_empty() { - if let Err(e) = delete_range_scheduler - .schedule_force(BackgroundTask::DeleteRegions(regions_to_delete)) - { - error!( - "ime schedule deletet range failed"; - "err" => ?e, - ); - assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); - } - } - } - /// Periodically load top regions. /// /// If the soft limit is exceeded, evict (some) regions no longer considered @@ -1072,17 +1004,50 @@ impl Runnable for BackgroundRunner { self.range_load_remote.spawn(f); } BackgroundTask::MemoryCheckAndEvict => { - let mem_usage = self.core.memory_controller.mem_usage(); + let mem_usage_before_check = self.core.memory_controller.mem_usage(); info!( "ime start memory usage check and evict"; - "mem_usage(MB)" => ReadableSize(mem_usage as u64).as_mb() + "mem_usage(MB)" => ReadableSize(mem_usage_before_check as u64).as_mb() ); - if mem_usage > self.core.memory_controller.soft_limit_threshold() { + if mem_usage_before_check > self.core.memory_controller.soft_limit_threshold() { let delete_range_scheduler = self.delete_range_scheduler.clone(); let core = self.core.clone(); let task = async move { - core.evict_on_soft_limit_reached(&delete_range_scheduler); + if let Some(range_stats_manager) = &core.range_stats_manager { + let cached_region_ids = core + .engine + .region_manager + .regions_map + .read() + .cached_regions(); + + let evict_fn = |evict_region: &CacheRegion, + evict_reason: EvictReason, + cb: Option>| + -> Vec { + core.engine.region_manager.evict_region( + evict_region, + evict_reason, + cb, + ) + }; + + range_stats_manager + .evict_on_soft_limit_reached( + evict_fn, + &delete_range_scheduler, + cached_region_ids, + &core.memory_controller, + ) + .await; + } core.memory_controller.set_memory_checking(false); + let mem_usage = core.memory_controller.mem_usage(); + info!( + "ime memory usage check and evict completes"; + "mem_usage(MB)" => ReadableSize(mem_usage as u64).as_mb(), + "mem_usage_before_check(MB)" => ReadableSize(mem_usage_before_check as u64).as_mb() + ); }; self.load_evict_remote.spawn(task); } else { diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index b33a0e79f9f..94ec8196f32 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -28,7 +28,7 @@ use crate::{ encode_key_for_boundary_with_mvcc, encode_key_for_boundary_without_mvcc, InternalBytes, }, memory_controller::MemoryController, - range_manager::{LoadFailedReason, RangeCacheStatus, RegionManager, RegionState}, + range_manager::{AsyncFnOnce, LoadFailedReason, RangeCacheStatus, RegionManager, RegionState}, read::{RangeCacheIterator, RangeCacheSnapshot}, statistics::Statistics, RangeCacheEngineConfig, RangeCacheEngineContext, @@ -303,7 +303,7 @@ impl RangeCacheMemoryEngine { &self, region: &CacheRegion, evict_reason: EvictReason, - cb: Option>, + cb: Option>, ) { let deleteable_regions = self .core @@ -527,10 +527,7 @@ impl Iterable for RangeCacheMemoryEngine { #[cfg(test)] pub mod tests { - use std::{ - sync::{mpsc::sync_channel, Arc}, - time::Duration, - }; + use std::{sync::Arc, time::Duration}; use crossbeam::epoch; use engine_rocks::util::new_engine; @@ -539,6 +536,11 @@ pub mod tests { WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; + use tokio::{ + runtime::Builder, + sync::{mpsc, Mutex}, + time::timeout, + }; use super::SkiplistEngine; use crate::{ @@ -805,18 +807,27 @@ pub mod tests { let snap = engine.snapshot(cache_region.clone(), 100, 100).unwrap(); - let (tx, rx) = sync_channel(0); + let (tx, rx) = mpsc::channel(1); engine.evict_region( &cache_region, EvictReason::BecomeFollower, Some(Box::new(move || { - let _ = tx.send(true); + Box::pin(async move { + let _ = tx.send(()).await; + }) })), ); - rx.recv_timeout(Duration::from_secs(1)).unwrap_err(); + let rt = Builder::new_current_thread().enable_all().build().unwrap(); + let rx = Arc::new(Mutex::new(rx)); + let rx_clone = rx.clone(); + rt.block_on(async move { + timeout(Duration::from_secs(1), rx_clone.lock().await.recv()) + .await + .unwrap_err() + }); drop(snap); - let _ = rx.recv(); + rt.block_on(async move { rx.lock().await.recv().await.unwrap() }); { let regions_map = engine.core().region_manager().regions_map().read(); diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index 7407febd3ea..e3724d573f3 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -5,6 +5,7 @@ #![allow(internal_features)] #![feature(core_intrinsics)] #![feature(slice_pattern)] +#![feature(trait_alias)] use std::{sync::Arc, time::Duration}; diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 8f1afc23c3b..732bcd423f5 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -7,6 +7,8 @@ use std::{ Bound::{self, Excluded, Unbounded}, }, fmt::Debug, + future::Future, + pin::Pin, result, sync::{ atomic::{AtomicBool, Ordering}, @@ -16,11 +18,14 @@ use std::{ use collections::HashMap; use engine_traits::{CacheRegion, EvictReason, FailedReason}; +use futures::executor::block_on; use parking_lot::RwLock; use tikv_util::{info, time::Instant, warn}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; +pub(crate) trait AsyncFnOnce = FnOnce() -> Pin + Send>>; + #[derive(PartialEq, Eq, Debug, Clone, Copy, Default, Hash)] pub enum RegionState { // waiting to be load. @@ -110,7 +115,7 @@ struct EvictInfo { start: Instant, reason: EvictReason, // called when eviction finishes - cb: Option>, + cb: Option>, } impl Debug for EvictInfo { @@ -195,7 +200,7 @@ impl CacheRegionMeta { &mut self, state: RegionState, reason: EvictReason, - cb: Option>, + cb: Option>, ) { use RegionState::*; assert_matches!(self.state, Loading | Active | LoadingCanceled); @@ -730,7 +735,7 @@ impl RegionManager { &self, evict_region: &CacheRegion, evict_reason: EvictReason, - mut cb: Option>, + mut cb: Option>, ) -> Vec { info!( "ime try to evict region"; @@ -776,7 +781,7 @@ impl RegionManager { evict_region: &CacheRegion, evict_reason: EvictReason, regions_map: &mut RegionMetaMap, - cb: Option>, + cb: Option>, ) -> Option { let meta = regions_map.mut_region_meta(id).unwrap(); let prev_state = meta.state; @@ -831,25 +836,34 @@ impl RegionManager { pub fn on_delete_regions(&self, regions: &[CacheRegion]) { fail::fail_point!("in_memory_engine_on_delete_regions"); - let mut regions_map = self.regions_map.write(); - for r in regions { - let meta = regions_map.remove_region(r.id); - assert_eq!(meta.region.epoch_version, r.epoch_version); + let mut cbs = vec![]; + { + let mut regions_map = self.regions_map.write(); + for r in regions { + let meta = regions_map.remove_region(r.id); + assert_eq!(meta.region.epoch_version, r.epoch_version); + + let evict_info = meta.evict_info.unwrap(); + observe_eviction_duration( + evict_info.start.saturating_elapsed_secs(), + evict_info.reason, + ); + if let Some(cb) = evict_info.cb { + cbs.push(cb); + } - let evict_info = meta.evict_info.unwrap(); - observe_eviction_duration( - evict_info.start.saturating_elapsed_secs(), - evict_info.reason, - ); - if let Some(cb) = evict_info.cb { - cb(); + info!( + "ime range eviction done"; + "region" => ?r, + ); } - - info!( - "ime range eviction done"; - "region" => ?r, - ); } + + block_on(async { + for cb in cbs { + cb().await; + } + }); } // return whether the operation is successful. diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 30fcf345065..44c466c9b74 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -12,12 +12,15 @@ use std::{ use collections::HashMap; use crossbeam::sync::ShardedLock; +use engine_traits::{CacheRegion, EvictReason}; use kvproto::metapb::Region; use parking_lot::Mutex; use raftstore::coprocessor::RegionInfoProvider; -use tikv_util::{info, smoother::Smoother}; +use slog_global::error; +use tikv_util::{info, smoother::Smoother, worker::Scheduler}; +use tokio::sync::mpsc; -use crate::memory_controller::MemoryController; +use crate::{memory_controller::MemoryController, range_manager::AsyncFnOnce, BackgroundTask}; /// Do not evict a region if has been cached for less than this duration. pub const DEFAULT_EVICT_MIN_DURATION: Duration = Duration::from_secs(60 * 5); @@ -89,53 +92,6 @@ impl RangeStatsManager { self.num_regions.load(Ordering::Relaxed) } - /// Collect candidates for eviction sorted by activity in creasing order: - /// - /// 1. Get all the regions sorted (decreasing) by region activity using - /// [raftstore::coprocessor::RegionCollector::handle_get_top_regions]. - /// 2. Remove all regions where `is_cached_pred` returns false when passed - /// the region's range or those that have been loaded for less than - /// `self.evict_min_duration`. - /// 3. Reverse the list so that it is now sorted in the order of increasing - /// activity. - /// 4. Store the results in `ranges_out` using [Vec::extend]. - pub fn collect_candidates_for_eviction( - &self, - regions_out: &mut Vec<(Region, u64)>, - is_cached_pred: F, - ) where - F: Fn(&Region) -> bool, - { - // Gets all of the regions, sorted by activity. - let all_regions = self.info_provider.get_top_regions(None).unwrap(); - let regions_loaded = self.region_loaded_at.read().unwrap(); - regions_out.extend( - all_regions - .iter() - .filter_map(|(region, approx_size)| { - is_cached_pred(region) - .then(|| { - match regions_loaded.get(®ion.get_id()) { - // Do not evict ranges that were loaded less than - // `EVICT_MIN_DURATION` ago. - Some(&time_loaded) - if Instant::now() - time_loaded < self.evict_min_duration => - { - None - } - Some(_) | None => - // None indicates range loaded from a hint, not by this manager. - { - Some((region.clone(), approx_size.approximate_size)) - } - } - }) - .flatten() - }) - .rev(), - ); - } - /// This method should be called when `evicted_range` is succesfully evicted /// to remove any internal `RegionStatsManager` that corresponds to the /// range. @@ -381,15 +337,139 @@ impl RangeStatsManager { }; (regions_to_load, regions_to_evict) } + + // Evict regions with less read flow until the memory usage is below the soft + // limit threshold. + pub(crate) async fn evict_on_soft_limit_reached( + &self, + mut evict_region: F, + delete_range_scheduler: &Scheduler, + cached_region_ids: Vec, + memory_controller: &MemoryController, + ) where + F: FnMut( + &CacheRegion, + EvictReason, + Option>, + ) -> Vec, + { + // Get regions' stat of the cached region and sort them by next + prev in + // descending order. + let regions_activity = self + .info_provider + .get_regions_stat(cached_region_ids.clone()) + .unwrap(); + if regions_activity.is_empty() { + return; + } + + // Use the average mvcc amplification to filter the regions with high mvcc + // amplification + let avg_mvcc_amplification = regions_activity + .iter() + .map(|(_, ra)| ra.cop_detail.mvcc_amplification()) + .sum::() + / regions_activity.len() as f64; + + let evict_candidates: Vec<_> = { + let mut regions_loaded = self.region_loaded_at.write().unwrap(); + let mut evict_candidates = regions_activity; + info!( + "ime evict candidate count before filter"; + "count" => evict_candidates.len(), + ); + let mut filter_by_time = 0; + let mut filter_by_mvcc_amplification = 0; + evict_candidates.retain(|(r, ra)| { + let time_loaded = regions_loaded.entry(r.id).or_insert(Instant::now()); + // Do not evict regions with high mvcc amplification + if ra.cop_detail.mvcc_amplification() > avg_mvcc_amplification { + filter_by_mvcc_amplification += 1; + return false; + } + let now = Instant::now(); + // Do not evict regions that are loaded recently + if now - *time_loaded < self.evict_min_duration { + filter_by_time += 1; + return false; + } + true + }); + evict_candidates.sort_by(|a, b| { + let next_prev_a = a.1.cop_detail.iterated_count(); + let next_prev_b = b.1.cop_detail.iterated_count(); + next_prev_a.cmp(&next_prev_b) + }); + + info!( + "ime evict candidate count after filter"; + "count" => evict_candidates.len(), + "filter_by_time" => filter_by_time, + "filter_by_mvcc_amplification" => filter_by_mvcc_amplification, + ); + + evict_candidates.into_iter().map(|(r, _)| r).collect() + }; + // Evict two regions each time to reduce the probability that an un-dropped + // ongoing snapshot blocks the process + for regions in evict_candidates.chunks(2) { + let mut deleteable_regions = vec![]; + + let (tx, mut rx) = mpsc::channel(3); + for r in regions { + info!( + "ime evict on soft limit reached"; + "region_to_evict" => ?r, + ); + + let tx_clone = tx.clone(); + deleteable_regions.extend(evict_region( + &CacheRegion::from_region(r), + EvictReason::MemoryLimitReached, + // This callback will be executed when eviction finishes at `on_delete_regions` + // and when the reletive rx.recv() returns, we know some memory are freed. + Some(Box::new(move || { + Box::pin(async move { + let _ = tx_clone.send(()).await; + }) + })), + )); + self.handle_region_evicted(r); + } + if !deleteable_regions.is_empty() { + if let Err(e) = delete_range_scheduler + .schedule_force(BackgroundTask::DeleteRegions(deleteable_regions)) + { + error!( + "ime schedule deletet range failed"; + "err" => ?e, + ); + assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); + } + } + for _ in 0..regions.len() { + // It's better to use `timeout(Duration, rx.recv())` but which needs to use + // tokio runtime with timer enabled while yatp does not. + if rx.recv().await.is_none() { + break; + } + } + if !memory_controller.reached_stop_load_limit() { + return; + } + } + } } #[cfg(test)] pub mod tests { + use futures::executor::block_on; use pd_client::{RegionStat, RegionWriteCfCopDetail}; use raftstore::coprocessor::{self, region_info_accessor::TopRegions, RegionInfoProvider}; use tikv_util::{ box_err, config::{ReadableSize, VersionTrack}, + worker::dummy_scheduler, }; use super::*; @@ -553,68 +633,101 @@ pub mod tests { assert_eq!(&removed, &[region_3.clone()]); } - // todo(SpadeA): fix this in the next PR (optimize eviction when soft - // limit reached) - // #[test] - // fn test_collect_candidates_for_eviction() { - // let skiplist_engine = SkiplistEngine::new(); - // let mut config = RangeCacheEngineConfig::config_for_test(); - // config.stop_load_limit_threshold = Some(ReadableSize::kb(1)); - // let config = Arc::new(VersionTrack::new(config)); - // let mc = MemoryController::new(config, skiplist_engine); - - // fn make_region_vec(rs: &[&Region]) -> TopRegions { - // let mut stat = RegionStat::default(); - // stat.approximate_size = 42; - // rs.iter().map(|&r| (r.clone(), stat)).collect::>() - // } - - // let region_1 = new_region(1, b"k1", b"k2"); - // let region_2 = new_region(2, b"k3", b"k4"); - // let region_3 = new_region(3, b"k5", b"k6"); - // let region_4 = new_region(4, b"k7", b"k8"); - // let region_5 = new_region(5, b"k9", b"k10"); - // let region_6 = new_region(6, b"k11", b"k12"); - - // let all_regions = make_region_vec(&[ - // ®ion_1, ®ion_2, ®ion_3, ®ion_4, ®ion_5, ®ion_6, - // ]); - - // let sim = Arc::new(RegionInfoSimulator { - // regions: Mutex::new(all_regions.clone()), - // region_stats: Mutex::default(), - // }); - // // 10 ms min duration eviction for testing purposes. - // let rsm = RangeStatsManager::new( - // 5, - // Duration::from_millis(10), - // RangeCacheEngineConfig::config_for_test().expected_region_size(), - // 10, - // sim.clone(), - // ); - // let r_i_p: Arc = sim.clone(); - // let check_is_cached = move |r: &Region| -> bool { - // r_i_p.find_region_by_key(&r.start_key).unwrap().get_id() <= 5 - // }; - // let mut _added = Vec::new(); - // let mut _removed = Vec::new(); - // rsm.collect_regions_to_load_and_evict(&mut _added, vec![], &mc); - // let mut candidates_for_eviction = Vec::new(); - // rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, - // &check_is_cached); assert!(candidates_for_eviction.is_empty()); - // std::thread::sleep(Duration::from_millis(100)); - // rsm.collect_candidates_for_eviction(&mut candidates_for_eviction, - // &check_is_cached); let expected_candidates_for_eviction = - // all_regions .iter() - // .rev() - // .filter_map(|(r, s)| { - // if r.get_id() <= 5 { - // Some((r.clone(), *s)) - // } else { - // None - // } - // }) - // .collect::>(); - // assert_eq!(expected_candidates_for_eviction, - // candidates_for_eviction); } + #[test] + fn test_collect_candidates_for_eviction() { + let skiplist_engine = SkiplistEngine::new(); + let mut config = RangeCacheEngineConfig::config_for_test(); + config.stop_load_limit_threshold = Some(ReadableSize::kb(1)); + let config = Arc::new(VersionTrack::new(config)); + let mc = MemoryController::new(config, skiplist_engine); + let (scheduler, _rx) = dummy_scheduler(); + + fn make_region_vec(rs: &[Region], stats: &[RegionStat]) -> TopRegions { + rs.iter() + .zip(stats.iter()) + .map(|(r, stat)| (r.clone(), stat.clone())) + .collect::>() + } + + let region_1 = new_region(1, b"k01", b"k02"); + let region_2 = new_region(2, b"k03", b"k04"); + let region_3 = new_region(3, b"k05", b"k06"); + let region_4 = new_region(4, b"k07", b"k08"); + let region_5 = new_region(5, b"k09", b"k10"); + let region_6 = new_region(6, b"k11", b"k12"); + let regions = vec![region_1, region_2, region_3, region_4, region_5, region_6]; + + let region_stats = vec![ + new_region_stat(100, 6), + new_region_stat(10000, 1000), + new_region_stat(100000, 100000), + new_region_stat(100, 50), // will be evicted + new_region_stat(1000, 120), + new_region_stat(200, 120), // will be evicted + ]; + + let all_regions = make_region_vec(®ions, ®ion_stats); + let region_stats: HashMap = all_regions + .iter() + .map(|top_region| { + ( + top_region.0.id, + (top_region.0.clone(), top_region.1.clone()), + ) + }) + .collect(); + + let sim = Arc::new(RegionInfoSimulator { + regions: Mutex::new(all_regions), + region_stats: Mutex::new(region_stats), + }); + // 10 ms min duration eviction for testing purposes. + let rsm = RangeStatsManager::new( + 10, + Duration::from_millis(10), + RangeCacheEngineConfig::config_for_test().expected_region_size(), + 10, + sim.clone(), + ); + rsm.collect_regions_to_load_and_evict(vec![], &mc); + std::thread::sleep(Duration::from_millis(100)); + + let evicted_regions = Arc::new(Mutex::new(vec![])); + let cbs = Arc::new(Mutex::new(vec![])); + + let evicted_regions2 = evicted_regions.clone(); + let cbs2 = cbs.clone(); + let evict_fn = move |evict_region: &CacheRegion, + _: EvictReason, + cb: Option>| + -> Vec { + evicted_regions2.lock().push(evict_region.id); + cbs2.lock().push(cb.unwrap()); + vec![] + }; + + let handle = std::thread::spawn(move || { + block_on(async { + rsm.evict_on_soft_limit_reached(evict_fn, &scheduler, vec![1, 2, 3, 4, 5, 6], &mc) + .await + }); + }); + + let t = Instant::now(); + while t.elapsed() < Duration::from_secs(2) { + std::thread::sleep(Duration::from_millis(100)); + let mut cb_lock = cbs.lock(); + if cb_lock.len() == 2 { + let evicted_regions_lock = evicted_regions.lock(); + assert_eq!(*evicted_regions_lock, vec![4, 6]); + block_on(async { + cb_lock.pop().unwrap()().await; + cb_lock.pop().unwrap()().await; + }); + break; + } + } + + let _ = handle.join(); + } } diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 6c0ee124f10..8cb122b0291 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -21,6 +21,10 @@ use range_cache_memory_engine::{ }; use tempfile::Builder; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; +use tokio::{ + sync::{mpsc, Mutex}, + time::timeout, +}; use txn_types::{Key, TimeStamp, WriteType}; #[test] @@ -769,18 +773,30 @@ fn test_cb_on_eviction() { fail::cfg("in_memory_engine_on_delete_regions", "pause").unwrap(); - let (tx, rx) = sync_channel(0); + let (tx, rx) = mpsc::channel(1); engine.evict_region( &cache_region, EvictReason::BecomeFollower, Some(Box::new(move || { - let _ = tx.send(true); + Box::pin(async move { + let _ = tx.send(()).await; + }) })), ); - rx.recv_timeout(Duration::from_secs(1)).unwrap_err(); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let rx = Arc::new(Mutex::new(rx)); + let rx_clone = rx.clone(); + rt.block_on(async move { + timeout(Duration::from_secs(1), rx_clone.lock().await.recv()) + .await + .unwrap_err() + }); fail::remove("in_memory_engine_on_delete_regions"); - let _ = rx.recv(); + rt.block_on(async move { rx.lock().await.recv().await.unwrap() }); { let regions_map = engine.core().region_manager().regions_map().read(); From e77aabc3c8b2acb59d33b5d4d7f175e5191dd591 Mon Sep 17 00:00:00 2001 From: glorv Date: Fri, 13 Sep 2024 12:53:30 +0800 Subject: [PATCH 065/144] in-memory-engine fix incorrect region count gauge when count becomes 0 (#17524) ref tikv/tikv#16141 Fix incorrect RANGE_CACHE_COUNT metrics by always set gauge values of all types. Signed-off-by: glorv --- Cargo.lock | 1 + .../range_cache_memory_engine/Cargo.toml | 1 + .../src/background.rs | 18 +++++++----- .../src/range_manager.rs | 29 ++++++++++++++----- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76da4f1b686..4daaebd4c82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4517,6 +4517,7 @@ dependencies = [ "serde_json", "slog", "slog-global", + "strum 0.20.0", "tempfile", "test_pd", "test_pd_client", diff --git a/components/range_cache_memory_engine/Cargo.toml b/components/range_cache_memory_engine/Cargo.toml index 561f084404d..b41347579c8 100644 --- a/components/range_cache_memory_engine/Cargo.toml +++ b/components/range_cache_memory_engine/Cargo.toml @@ -34,6 +34,7 @@ serde_derive = "1.0" serde_json = "1.0" slog-global = { workspace = true } slog = { workspace = true } +strum = { version = "0.20", features = ["derive"] } engine_rocks = { workspace = true } fail = "0.5" yatp = { workspace = true } diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 6b8bba2ccf9..3f84d88216f 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -1,6 +1,6 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::HashMap, fmt::Display, sync::Arc, time::Duration}; +use std::{fmt::Display, sync::Arc, time::Duration}; use bytes::Bytes; use crossbeam::{ @@ -16,6 +16,7 @@ use hex::FromHexError; use pd_client::{PdClient, RpcClient}; use raftstore::coprocessor::RegionInfoProvider; use slog_global::{error, info, warn}; +use strum::EnumCount; use tikv_util::{ config::ReadableSize, future::block_on_timeout, @@ -1150,13 +1151,16 @@ impl RunnableWithTimer for BackgroundRunner { let mem_usage = self.core.memory_controller.mem_usage(); RANGE_CACHE_MEMORY_USAGE.set(mem_usage as i64); - let regions_map = self.core.engine.region_manager().regions_map.read(); - let mut count_by_state = HashMap::new(); - for m in regions_map.regions().values() { - *count_by_state.entry(m.get_state()).or_default() += 1; + let mut count_by_state = [0; RegionState::COUNT]; + { + let regions_map = self.core.engine.region_manager().regions_map.read(); + for m in regions_map.regions().values() { + count_by_state[m.get_state() as usize] += 1; + } } - drop(regions_map); - for (state, count) in count_by_state { + + for (i, count) in count_by_state.into_iter().enumerate() { + let state = RegionState::from_usize(i); RANGE_CACHE_COUNT .with_label_values(&[state.as_str()]) .set(count); diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 732bcd423f5..0bdd258e1da 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -20,29 +20,31 @@ use collections::HashMap; use engine_traits::{CacheRegion, EvictReason, FailedReason}; use futures::executor::block_on; use parking_lot::RwLock; +use strum::EnumCount; use tikv_util::{info, time::Instant, warn}; use crate::{metrics::observe_eviction_duration, read::RangeCacheSnapshotMeta}; pub(crate) trait AsyncFnOnce = FnOnce() -> Pin + Send>>; -#[derive(PartialEq, Eq, Debug, Clone, Copy, Default, Hash)] +#[derive(PartialEq, Eq, Debug, Clone, Copy, Default, Hash, EnumCount)] +#[repr(usize)] pub enum RegionState { // waiting to be load. // NOTE: in this state, the region's epoch may be older than // target region in raftstore. #[default] - Pending, + Pending = 0, // Region is handling batch loading from rocksdb snapshot. - Loading, + Loading = 1, // Region is cached, ready to handle foreground read. - Active, + Active = 2, // region should be evicted, but batch loading is possible still running. - LoadingCanceled, + LoadingCanceled = 3, // region should be evicted, but there are possible active snapshot or gc task. - PendingEvict, + PendingEvict = 4, // evicting event is running, the region will be removed after the evict task finished. - Evicting, + Evicting = 5, } impl RegionState { @@ -58,6 +60,19 @@ impl RegionState { } } + pub fn from_usize(v: usize) -> Self { + use RegionState::*; + match v { + 0 => Pending, + 1 => Loading, + 2 => Active, + 3 => LoadingCanceled, + 4 => PendingEvict, + 5 => Evicting, + _ => panic!("unknown RegionState value {}", v), + } + } + pub fn is_evict(&self) -> bool { use RegionState::*; matches!(*self, LoadingCanceled | PendingEvict | Evicting) From 3eb9ba7caeda6475f2f4e99a39ce5e1d42854cbe Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 13 Sep 2024 13:21:20 +0800 Subject: [PATCH 066/144] metrics: add IME thread cpu panel (#17527) ref tikv/tikv#16141 Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- metrics/grafana/tikv_details.dashboard.py | 28 + metrics/grafana/tikv_details.json | 1020 ++++++++++++--------- metrics/grafana/tikv_details.json.sha256 | 2 +- 3 files changed, 613 insertions(+), 437 deletions(-) diff --git a/metrics/grafana/tikv_details.dashboard.py b/metrics/grafana/tikv_details.dashboard.py index 073f2854e20..d6da6cf3a4d 100644 --- a/metrics/grafana/tikv_details.dashboard.py +++ b/metrics/grafana/tikv_details.dashboard.py @@ -1444,6 +1444,34 @@ def ThreadCPU() -> RowPanel: ), ] ) + layout.row( + [ + graph_panel( + title="IME CPU", + description="The CPU utilization of IME threads", + yaxes=yaxes(left_format=UNITS.PERCENT_UNIT), + targets=[ + target( + expr=expr_sum_rate( + "tikv_thread_cpu_seconds_total", + label_selectors=['name=~"ime.*"'], + by_labels=["instance"], + ), + legend_format="{{instance}}", + ), + target( + expr=expr_sum_rate( + "tikv_thread_cpu_seconds_total", + label_selectors=['name=~"ime.*"'], + by_labels=["instance", "name"], + ), + legend_format="{{instance}}-{{name}}", + hide=True, + ), + ], + ), + ] + ) return layout.row_panel diff --git a/metrics/grafana/tikv_details.json b/metrics/grafana/tikv_details.json index 81050501887..f2ac089991c 100644 --- a/metrics/grafana/tikv_details.json +++ b/metrics/grafana/tikv_details.json @@ -13309,6 +13309,154 @@ "align": false, "alignLevel": 0 } + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "datasource": "${DS_TEST-CLUSTER}", + "description": "The CPU utilization of IME threads", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [] + } + } + }, + "fill": 1, + "fillGradient": 1, + "grid": { + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 63 + }, + "height": null, + "hideTimeOverride": false, + "id": 98, + "interval": null, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "max", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxDataPoints": null, + "maxPerRow": null, + "minSpan": null, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true, + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": null, + "seriesOverrides": [], + "span": null, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "sum(rate(\n tikv_thread_cpu_seconds_total\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",name=~\"ime.*\"}\n [$__rate_interval]\n)) by (instance) ", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "metric": "", + "query": "sum(rate(\n tikv_thread_cpu_seconds_total\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",name=~\"ime.*\"}\n [$__rate_interval]\n)) by (instance) ", + "refId": "", + "step": 10, + "target": "" + }, + { + "datasource": "${DS_TEST-CLUSTER}", + "expr": "sum(rate(\n tikv_thread_cpu_seconds_total\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",name=~\"ime.*\"}\n [$__rate_interval]\n)) by (instance, name) ", + "format": "time_series", + "hide": true, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{instance}}-{{name}}", + "metric": "", + "query": "sum(rate(\n tikv_thread_cpu_seconds_total\n {k8s_cluster=\"$k8s_cluster\",tidb_cluster=\"$tidb_cluster\",instance=~\"$instance\",name=~\"ime.*\"}\n [$__rate_interval]\n)) by (instance, name) ", + "refId": "", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "IME CPU", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transformations": [], + "transparent": false, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": 0 + } } ], "repeat": null, @@ -13345,7 +13493,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 98, + "id": 99, "interval": null, "links": [], "maxDataPoints": 100, @@ -13384,7 +13532,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 99, + "id": 100, "interval": null, "isNew": true, "legend": { @@ -13532,7 +13680,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 100, + "id": 101, "interval": null, "isNew": true, "legend": { @@ -13680,7 +13828,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 101, + "id": 102, "interval": null, "isNew": true, "legend": { @@ -13813,7 +13961,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 102, + "id": 103, "interval": null, "isNew": true, "legend": { @@ -13964,7 +14112,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 103, + "id": 104, "interval": null, "links": [], "maxDataPoints": 100, @@ -14003,7 +14151,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 104, + "id": 105, "interval": null, "isNew": true, "legend": { @@ -14204,7 +14352,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 105, + "id": 106, "interval": null, "isNew": true, "legend": { @@ -14405,7 +14553,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 106, + "id": 107, "interval": null, "isNew": true, "legend": { @@ -14606,7 +14754,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 107, + "id": 108, "interval": null, "isNew": true, "legend": { @@ -14807,7 +14955,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 108, + "id": 109, "interval": null, "isNew": true, "legend": { @@ -15008,7 +15156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 109, + "id": 110, "interval": null, "isNew": true, "legend": { @@ -15209,7 +15357,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 110, + "id": 111, "interval": null, "isNew": true, "legend": { @@ -15410,7 +15558,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 111, + "id": 112, "interval": null, "isNew": true, "legend": { @@ -15611,7 +15759,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 112, + "id": 113, "interval": null, "isNew": true, "legend": { @@ -15812,7 +15960,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 113, + "id": 114, "interval": null, "isNew": true, "legend": { @@ -16013,7 +16161,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 114, + "id": 115, "interval": null, "isNew": true, "legend": { @@ -16214,7 +16362,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 115, + "id": 116, "interval": null, "isNew": true, "legend": { @@ -16415,7 +16563,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 116, + "id": 117, "interval": null, "isNew": true, "legend": { @@ -16619,7 +16767,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 117, + "id": 118, "interval": null, "links": [], "maxDataPoints": 100, @@ -16665,7 +16813,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 118, + "id": 119, "interval": null, "legend": { "show": false @@ -16762,7 +16910,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 119, + "id": 120, "interval": null, "isNew": true, "legend": { @@ -16970,7 +17118,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 120, + "id": 121, "interval": null, "legend": { "show": false @@ -17067,7 +17215,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 121, + "id": 122, "interval": null, "isNew": true, "legend": { @@ -17275,7 +17423,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 122, + "id": 123, "interval": null, "legend": { "show": false @@ -17372,7 +17520,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 123, + "id": 124, "interval": null, "isNew": true, "legend": { @@ -17580,7 +17728,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 124, + "id": 125, "interval": null, "legend": { "show": false @@ -17677,7 +17825,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 125, + "id": 126, "interval": null, "isNew": true, "legend": { @@ -17885,7 +18033,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 126, + "id": 127, "interval": null, "legend": { "show": false @@ -17982,7 +18130,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 127, + "id": 128, "interval": null, "isNew": true, "legend": { @@ -18190,7 +18338,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 128, + "id": 129, "interval": null, "legend": { "show": false @@ -18287,7 +18435,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 129, + "id": 130, "interval": null, "isNew": true, "legend": { @@ -18488,7 +18636,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 130, + "id": 131, "interval": null, "isNew": true, "legend": { @@ -18636,7 +18784,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 131, + "id": 132, "interval": null, "isNew": true, "legend": { @@ -18772,7 +18920,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 132, + "id": 133, "interval": null, "links": [], "maxDataPoints": 100, @@ -18811,7 +18959,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 133, + "id": 134, "interval": null, "isNew": true, "legend": { @@ -18944,7 +19092,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 134, + "id": 135, "interval": null, "isNew": true, "legend": { @@ -19077,7 +19225,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 135, + "id": 136, "interval": null, "isNew": true, "legend": { @@ -19210,7 +19358,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 136, + "id": 137, "interval": null, "isNew": true, "legend": { @@ -19350,7 +19498,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 137, + "id": 138, "interval": null, "legend": { "show": false @@ -19447,7 +19595,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 138, + "id": 139, "interval": null, "isNew": true, "legend": { @@ -19655,7 +19803,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 139, + "id": 140, "interval": null, "legend": { "show": false @@ -19752,7 +19900,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 140, + "id": 141, "interval": null, "isNew": true, "legend": { @@ -19960,7 +20108,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 141, + "id": 142, "interval": null, "legend": { "show": false @@ -20057,7 +20205,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 142, + "id": 143, "interval": null, "isNew": true, "legend": { @@ -20265,7 +20413,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 143, + "id": 144, "interval": null, "legend": { "show": false @@ -20369,7 +20517,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 144, + "id": 145, "interval": null, "legend": { "show": false @@ -20466,7 +20614,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 145, + "id": 146, "interval": null, "isNew": true, "legend": { @@ -20599,7 +20747,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 146, + "id": 147, "interval": null, "isNew": true, "legend": { @@ -20750,7 +20898,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 147, + "id": 148, "interval": null, "links": [], "maxDataPoints": 100, @@ -20789,7 +20937,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 148, + "id": 149, "interval": null, "isNew": true, "legend": { @@ -20937,7 +21085,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 149, + "id": 150, "interval": null, "isNew": true, "legend": { @@ -21092,7 +21240,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 150, + "id": 151, "interval": null, "legend": { "show": false @@ -21196,7 +21344,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 151, + "id": 152, "interval": null, "legend": { "show": false @@ -21293,7 +21441,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 152, + "id": 153, "interval": null, "isNew": true, "legend": { @@ -21426,7 +21574,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 153, + "id": 154, "interval": null, "isNew": true, "legend": { @@ -21577,7 +21725,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 154, + "id": 155, "interval": null, "links": [], "maxDataPoints": 100, @@ -21616,7 +21764,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 155, + "id": 156, "interval": null, "isNew": true, "legend": { @@ -21749,7 +21897,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 156, + "id": 157, "interval": null, "isNew": true, "legend": { @@ -21882,7 +22030,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 157, + "id": 158, "interval": null, "isNew": true, "legend": { @@ -22015,7 +22163,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 158, + "id": 159, "interval": null, "isNew": true, "legend": { @@ -22148,7 +22296,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 159, + "id": 160, "interval": null, "isNew": true, "legend": { @@ -22281,7 +22429,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 160, + "id": 161, "interval": null, "isNew": true, "legend": { @@ -22432,7 +22580,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 161, + "id": 162, "interval": null, "links": [], "maxDataPoints": 100, @@ -22471,7 +22619,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 162, + "id": 163, "interval": null, "isNew": true, "legend": { @@ -22604,7 +22752,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 163, + "id": 164, "interval": null, "isNew": true, "legend": { @@ -22737,7 +22885,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 164, + "id": 165, "interval": null, "isNew": true, "legend": { @@ -22870,7 +23018,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 165, + "id": 166, "interval": null, "isNew": true, "legend": { @@ -23003,7 +23151,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 166, + "id": 167, "interval": null, "isNew": true, "legend": { @@ -23136,7 +23284,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 167, + "id": 168, "interval": null, "isNew": true, "legend": { @@ -23299,7 +23447,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 168, + "id": 169, "interval": null, "isNew": true, "legend": { @@ -23435,7 +23583,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 169, + "id": 170, "interval": null, "links": [], "maxDataPoints": 100, @@ -23474,7 +23622,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 170, + "id": 171, "interval": null, "isNew": true, "legend": { @@ -23622,7 +23770,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 171, + "id": 172, "interval": null, "isNew": true, "legend": { @@ -23770,7 +23918,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 172, + "id": 173, "interval": null, "isNew": true, "legend": { @@ -23903,7 +24051,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 173, + "id": 174, "interval": null, "isNew": true, "legend": { @@ -24036,7 +24184,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 174, + "id": 175, "interval": null, "isNew": true, "legend": { @@ -24169,7 +24317,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 175, + "id": 176, "interval": null, "isNew": true, "legend": { @@ -24302,7 +24450,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 176, + "id": 177, "interval": null, "isNew": true, "legend": { @@ -24435,7 +24583,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 177, + "id": 178, "interval": null, "isNew": true, "legend": { @@ -24568,7 +24716,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 178, + "id": 179, "interval": null, "isNew": true, "legend": { @@ -24745,7 +24893,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 179, + "id": 180, "interval": null, "links": [], "maxDataPoints": 100, @@ -24784,7 +24932,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 180, + "id": 181, "interval": null, "isNew": true, "legend": { @@ -24947,7 +25095,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 181, + "id": 182, "interval": null, "isNew": true, "legend": { @@ -25148,7 +25296,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 182, + "id": 183, "interval": null, "isNew": true, "legend": { @@ -25296,7 +25444,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 183, + "id": 184, "interval": null, "isNew": true, "legend": { @@ -25459,7 +25607,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 184, + "id": 185, "interval": null, "isNew": true, "legend": { @@ -25660,7 +25808,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 185, + "id": 186, "interval": null, "isNew": true, "legend": { @@ -25838,7 +25986,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 186, + "id": 187, "interval": null, "isNew": true, "legend": { @@ -26001,7 +26149,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 187, + "id": 188, "interval": null, "isNew": true, "legend": { @@ -26164,7 +26312,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 188, + "id": 189, "interval": null, "isNew": true, "legend": { @@ -26297,7 +26445,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 189, + "id": 190, "interval": null, "isNew": true, "legend": { @@ -26501,7 +26649,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 190, + "id": 191, "interval": null, "links": [], "maxDataPoints": 100, @@ -26540,7 +26688,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 191, + "id": 192, "interval": null, "isNew": true, "legend": { @@ -26733,7 +26881,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 192, + "id": 193, "interval": null, "isNew": true, "legend": { @@ -26911,7 +27059,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 193, + "id": 194, "interval": null, "isNew": true, "legend": { @@ -27119,7 +27267,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 194, + "id": 195, "interval": null, "isNew": true, "legend": { @@ -27297,7 +27445,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 195, + "id": 196, "interval": null, "isNew": true, "legend": { @@ -27460,7 +27608,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 196, + "id": 197, "interval": null, "isNew": true, "legend": { @@ -27638,7 +27786,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 197, + "id": 198, "interval": null, "isNew": true, "legend": { @@ -27771,7 +27919,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 198, + "id": 199, "interval": null, "isNew": true, "legend": { @@ -27949,7 +28097,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 199, + "id": 200, "interval": null, "isNew": true, "legend": { @@ -28082,7 +28230,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 200, + "id": 201, "interval": null, "isNew": true, "legend": { @@ -28260,7 +28408,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 201, + "id": 202, "interval": null, "isNew": true, "legend": { @@ -28393,7 +28541,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 202, + "id": 203, "interval": null, "isNew": true, "legend": { @@ -28571,7 +28719,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 203, + "id": 204, "interval": null, "isNew": true, "legend": { @@ -28749,7 +28897,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 204, + "id": 205, "interval": null, "isNew": true, "legend": { @@ -28927,7 +29075,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 205, + "id": 206, "interval": null, "isNew": true, "legend": { @@ -29060,7 +29208,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 206, + "id": 207, "interval": null, "isNew": true, "legend": { @@ -29193,7 +29341,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 207, + "id": 208, "interval": null, "isNew": true, "legend": { @@ -29326,7 +29474,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 208, + "id": 209, "interval": null, "isNew": true, "legend": { @@ -29549,7 +29697,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 209, + "id": 210, "interval": null, "isNew": true, "legend": { @@ -29742,7 +29890,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 210, + "id": 211, "interval": null, "isNew": true, "legend": { @@ -29905,7 +30053,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 211, + "id": 212, "interval": null, "isNew": true, "legend": { @@ -30098,7 +30246,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 212, + "id": 213, "interval": null, "isNew": true, "legend": { @@ -30246,7 +30394,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 213, + "id": 214, "interval": null, "isNew": true, "legend": { @@ -30379,7 +30527,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 214, + "id": 215, "interval": null, "isNew": true, "legend": { @@ -30527,7 +30675,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 215, + "id": 216, "interval": null, "isNew": true, "legend": { @@ -30705,7 +30853,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 216, + "id": 217, "interval": null, "isNew": true, "legend": { @@ -30868,7 +31016,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 217, + "id": 218, "interval": null, "isNew": true, "legend": { @@ -31046,7 +31194,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 218, + "id": 219, "interval": null, "isNew": true, "legend": { @@ -31179,7 +31327,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 219, + "id": 220, "interval": null, "isNew": true, "legend": { @@ -31312,7 +31460,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 220, + "id": 221, "interval": null, "isNew": true, "legend": { @@ -31445,7 +31593,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 221, + "id": 222, "interval": null, "isNew": true, "legend": { @@ -31578,7 +31726,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 222, + "id": 223, "interval": null, "isNew": true, "legend": { @@ -31711,7 +31859,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 223, + "id": 224, "interval": null, "isNew": true, "legend": { @@ -31851,7 +31999,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 224, + "id": 225, "interval": null, "legend": { "show": false @@ -31948,7 +32096,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 225, + "id": 226, "interval": null, "isNew": true, "legend": { @@ -32149,7 +32297,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 226, + "id": 227, "interval": null, "isNew": true, "legend": { @@ -32282,7 +32430,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 227, + "id": 228, "interval": null, "isNew": true, "legend": { @@ -32460,7 +32608,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 228, + "id": 229, "interval": null, "isNew": true, "legend": { @@ -32593,7 +32741,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 229, + "id": 230, "interval": null, "isNew": true, "legend": { @@ -32729,7 +32877,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 230, + "id": 231, "interval": null, "links": [], "maxDataPoints": 100, @@ -32768,7 +32916,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 231, + "id": 232, "interval": null, "isNew": true, "legend": { @@ -32916,7 +33064,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 232, + "id": 233, "interval": null, "isNew": true, "legend": { @@ -33064,7 +33212,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 233, + "id": 234, "interval": null, "isNew": true, "legend": { @@ -33197,7 +33345,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 234, + "id": 235, "interval": null, "isNew": true, "legend": { @@ -33330,7 +33478,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 235, + "id": 236, "interval": null, "isNew": true, "legend": { @@ -33508,7 +33656,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 236, + "id": 237, "interval": null, "isNew": true, "legend": { @@ -33686,7 +33834,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 237, + "id": 238, "interval": null, "isNew": true, "legend": { @@ -33864,7 +34012,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 238, + "id": 239, "interval": null, "isNew": true, "legend": { @@ -33997,7 +34145,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 239, + "id": 240, "interval": null, "isNew": true, "legend": { @@ -34175,7 +34323,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 240, + "id": 241, "interval": null, "isNew": true, "legend": { @@ -34308,7 +34456,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 241, + "id": 242, "interval": null, "isNew": true, "legend": { @@ -34471,7 +34619,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 242, + "id": 243, "interval": null, "isNew": true, "legend": { @@ -34649,7 +34797,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 243, + "id": 244, "interval": null, "isNew": true, "legend": { @@ -34827,7 +34975,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 244, + "id": 245, "interval": null, "isNew": true, "legend": { @@ -35005,7 +35153,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 245, + "id": 246, "interval": null, "isNew": true, "legend": { @@ -35138,7 +35286,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 246, + "id": 247, "interval": null, "isNew": true, "legend": { @@ -35316,7 +35464,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 247, + "id": 248, "interval": null, "isNew": true, "legend": { @@ -35449,7 +35597,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 248, + "id": 249, "interval": null, "isNew": true, "legend": { @@ -35627,7 +35775,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 249, + "id": 250, "interval": null, "isNew": true, "legend": { @@ -35760,7 +35908,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 250, + "id": 251, "interval": null, "isNew": true, "legend": { @@ -35893,7 +36041,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 251, + "id": 252, "interval": null, "isNew": true, "legend": { @@ -36071,7 +36219,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 252, + "id": 253, "interval": null, "isNew": true, "legend": { @@ -36249,7 +36397,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 253, + "id": 254, "interval": null, "isNew": true, "legend": { @@ -36382,7 +36530,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 254, + "id": 255, "interval": null, "isNew": true, "legend": { @@ -36560,7 +36708,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 255, + "id": 256, "interval": null, "isNew": true, "legend": { @@ -36693,7 +36841,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 256, + "id": 257, "interval": null, "isNew": true, "legend": { @@ -36871,7 +37019,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 257, + "id": 258, "interval": null, "isNew": true, "legend": { @@ -37007,7 +37155,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 258, + "id": 259, "interval": null, "links": [], "maxDataPoints": 100, @@ -37046,7 +37194,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 259, + "id": 260, "interval": null, "isNew": true, "legend": { @@ -37179,7 +37327,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 260, + "id": 261, "interval": null, "isNew": true, "legend": { @@ -37312,7 +37460,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 261, + "id": 262, "interval": null, "isNew": true, "legend": { @@ -37445,7 +37593,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 262, + "id": 263, "interval": null, "isNew": true, "legend": { @@ -37578,7 +37726,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 263, + "id": 264, "interval": null, "isNew": true, "legend": { @@ -37718,7 +37866,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 264, + "id": 265, "interval": null, "legend": { "show": false @@ -37822,7 +37970,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 265, + "id": 266, "interval": null, "legend": { "show": false @@ -37919,7 +38067,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 266, + "id": 267, "interval": null, "isNew": true, "legend": { @@ -38059,7 +38207,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 267, + "id": 268, "interval": null, "legend": { "show": false @@ -38156,7 +38304,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 268, + "id": 269, "interval": null, "isNew": true, "legend": { @@ -38296,7 +38444,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 269, + "id": 270, "interval": null, "legend": { "show": false @@ -38393,7 +38541,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 270, + "id": 271, "interval": null, "isNew": true, "legend": { @@ -38601,7 +38749,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 271, + "id": 272, "interval": null, "legend": { "show": false @@ -38698,7 +38846,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 272, + "id": 273, "interval": null, "isNew": true, "legend": { @@ -38899,7 +39047,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 273, + "id": 274, "interval": null, "isNew": true, "legend": { @@ -39107,7 +39255,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 274, + "id": 275, "interval": null, "isNew": true, "legend": { @@ -39288,7 +39436,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 275, + "id": 276, "interval": null, "links": [], "maxDataPoints": 100, @@ -39327,7 +39475,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 276, + "id": 277, "interval": null, "isNew": true, "legend": { @@ -39475,7 +39623,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 277, + "id": 278, "interval": null, "isNew": true, "legend": { @@ -39615,7 +39763,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 278, + "id": 279, "interval": null, "legend": { "show": false @@ -39712,7 +39860,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 279, + "id": 280, "interval": null, "isNew": true, "legend": { @@ -39845,7 +39993,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 280, + "id": 281, "interval": null, "isNew": true, "legend": { @@ -39978,7 +40126,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 281, + "id": 282, "interval": null, "isNew": true, "legend": { @@ -40156,7 +40304,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 282, + "id": 283, "interval": null, "isNew": true, "legend": { @@ -40319,7 +40467,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 283, + "id": 284, "interval": null, "isNew": true, "legend": { @@ -40467,7 +40615,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 284, + "id": 285, "interval": null, "isNew": true, "legend": { @@ -40600,7 +40748,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 285, + "id": 286, "interval": null, "isNew": true, "legend": { @@ -40736,7 +40884,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 286, + "id": 287, "interval": null, "links": [], "maxDataPoints": 100, @@ -40775,7 +40923,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 287, + "id": 288, "interval": null, "isNew": true, "legend": { @@ -40923,7 +41071,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 288, + "id": 289, "interval": null, "isNew": true, "legend": { @@ -41056,7 +41204,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 289, + "id": 290, "interval": null, "isNew": true, "legend": { @@ -41189,7 +41337,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 290, + "id": 291, "interval": null, "isNew": true, "legend": { @@ -41322,7 +41470,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 291, + "id": 292, "interval": null, "isNew": true, "legend": { @@ -41455,7 +41603,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 292, + "id": 293, "interval": null, "isNew": true, "legend": { @@ -41610,7 +41758,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 293, + "id": 294, "interval": null, "legend": { "show": false @@ -41710,7 +41858,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 294, + "id": 295, "interval": null, "links": [], "maxDataPoints": 100, @@ -41749,7 +41897,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 295, + "id": 296, "interval": null, "isNew": true, "legend": { @@ -41897,7 +42045,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 296, + "id": 297, "interval": null, "isNew": true, "legend": { @@ -42098,7 +42246,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 297, + "id": 298, "interval": null, "isNew": true, "legend": { @@ -42299,7 +42447,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 298, + "id": 299, "interval": null, "isNew": true, "legend": { @@ -42500,7 +42648,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 299, + "id": 300, "interval": null, "isNew": true, "legend": { @@ -42701,7 +42849,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 300, + "id": 301, "interval": null, "isNew": true, "legend": { @@ -42834,7 +42982,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 301, + "id": 302, "interval": null, "isNew": true, "legend": { @@ -42967,7 +43115,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 302, + "id": 303, "interval": null, "isNew": true, "legend": { @@ -43100,7 +43248,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 303, + "id": 304, "interval": null, "isNew": true, "legend": { @@ -43233,7 +43381,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 304, + "id": 305, "interval": null, "isNew": true, "legend": { @@ -43441,7 +43589,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 305, + "id": 306, "interval": null, "legend": { "show": false @@ -43541,7 +43689,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 306, + "id": 307, "interval": null, "links": [], "maxDataPoints": 100, @@ -43587,7 +43735,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 307, + "id": 308, "interval": null, "legend": { "show": false @@ -43684,7 +43832,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 308, + "id": 309, "interval": null, "isNew": true, "legend": { @@ -43885,7 +44033,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 309, + "id": 310, "interval": null, "isNew": true, "legend": { @@ -44018,7 +44166,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 310, + "id": 311, "interval": null, "isNew": true, "legend": { @@ -44151,7 +44299,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 311, + "id": 312, "interval": null, "isNew": true, "legend": { @@ -44284,7 +44432,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 312, + "id": 313, "interval": null, "isNew": true, "legend": { @@ -44485,7 +44633,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 313, + "id": 314, "interval": null, "isNew": true, "legend": { @@ -44618,7 +44766,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 314, + "id": 315, "interval": null, "isNew": true, "legend": { @@ -44751,7 +44899,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 315, + "id": 316, "interval": null, "isNew": true, "legend": { @@ -44887,7 +45035,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 316, + "id": 317, "interval": null, "links": [], "maxDataPoints": 100, @@ -44926,7 +45074,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 317, + "id": 318, "interval": null, "isNew": true, "legend": { @@ -45127,7 +45275,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 318, + "id": 319, "interval": null, "isNew": true, "legend": { @@ -45328,7 +45476,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 319, + "id": 320, "interval": null, "isNew": true, "legend": { @@ -45529,7 +45677,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 320, + "id": 321, "interval": null, "isNew": true, "legend": { @@ -45730,7 +45878,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 321, + "id": 322, "interval": null, "isNew": true, "legend": { @@ -45863,7 +46011,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 322, + "id": 323, "interval": null, "isNew": true, "legend": { @@ -45996,7 +46144,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 323, + "id": 324, "interval": null, "isNew": true, "legend": { @@ -46129,7 +46277,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 324, + "id": 325, "interval": null, "isNew": true, "legend": { @@ -46262,7 +46410,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 325, + "id": 326, "interval": null, "isNew": true, "legend": { @@ -46395,7 +46543,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 326, + "id": 327, "interval": null, "isNew": true, "legend": { @@ -46535,7 +46683,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 327, + "id": 328, "interval": null, "legend": { "show": false @@ -46632,7 +46780,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 328, + "id": 329, "interval": null, "isNew": true, "legend": { @@ -46836,7 +46984,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 329, + "id": 330, "interval": null, "links": [], "maxDataPoints": 100, @@ -46875,7 +47023,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 330, + "id": 331, "interval": null, "isNew": true, "legend": { @@ -47008,7 +47156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 331, + "id": 332, "interval": null, "isNew": true, "legend": { @@ -47141,7 +47289,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 332, + "id": 333, "interval": null, "isNew": true, "legend": { @@ -47281,7 +47429,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 333, + "id": 334, "interval": null, "legend": { "show": false @@ -47378,7 +47526,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 334, + "id": 335, "interval": null, "isNew": true, "legend": { @@ -47579,7 +47727,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 335, + "id": 336, "interval": null, "isNew": true, "legend": { @@ -47780,7 +47928,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 336, + "id": 337, "interval": null, "isNew": true, "legend": { @@ -47984,7 +48132,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 337, + "id": 338, "interval": null, "links": [], "maxDataPoints": 100, @@ -48023,7 +48171,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 338, + "id": 339, "interval": null, "isNew": true, "legend": { @@ -48201,7 +48349,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 339, + "id": 340, "interval": null, "isNew": true, "legend": { @@ -48402,7 +48550,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 340, + "id": 341, "interval": null, "isNew": true, "legend": { @@ -48535,7 +48683,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 341, + "id": 342, "interval": null, "isNew": true, "legend": { @@ -48668,7 +48816,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 342, + "id": 343, "interval": null, "isNew": true, "legend": { @@ -48801,7 +48949,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 343, + "id": 344, "interval": null, "isNew": true, "legend": { @@ -48934,7 +49082,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 344, + "id": 345, "interval": null, "isNew": true, "legend": { @@ -49067,7 +49215,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 345, + "id": 346, "interval": null, "isNew": true, "legend": { @@ -49196,7 +49344,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 346, + "id": 347, "interval": null, "links": [], "maxDataPoints": 100, @@ -49271,7 +49419,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 347, + "id": 348, "interval": null, "links": [], "maxDataPoints": 100, @@ -49350,7 +49498,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 348, + "id": 349, "interval": null, "isNew": true, "legend": { @@ -49603,7 +49751,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 349, + "id": 350, "interval": null, "isNew": true, "legend": { @@ -49736,7 +49884,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 350, + "id": 351, "interval": null, "isNew": true, "legend": { @@ -49872,7 +50020,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 351, + "id": 352, "interval": null, "links": [], "maxDataPoints": 100, @@ -49911,7 +50059,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 352, + "id": 353, "interval": null, "isNew": true, "legend": { @@ -50059,7 +50207,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 353, + "id": 354, "interval": null, "isNew": true, "legend": { @@ -50192,7 +50340,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 354, + "id": 355, "interval": null, "isNew": true, "legend": { @@ -50393,7 +50541,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 355, + "id": 356, "interval": null, "isNew": true, "legend": { @@ -50541,7 +50689,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 356, + "id": 357, "interval": null, "isNew": true, "legend": { @@ -50742,7 +50890,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 357, + "id": 358, "interval": null, "isNew": true, "legend": { @@ -50875,7 +51023,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 358, + "id": 359, "interval": null, "isNew": true, "legend": { @@ -51008,7 +51156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 359, + "id": 360, "interval": null, "isNew": true, "legend": { @@ -51141,7 +51289,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 360, + "id": 361, "interval": null, "isNew": true, "legend": { @@ -51274,7 +51422,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 361, + "id": 362, "interval": null, "isNew": true, "legend": { @@ -51414,7 +51562,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 362, + "id": 363, "interval": null, "legend": { "show": false @@ -51511,7 +51659,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 363, + "id": 364, "interval": null, "isNew": true, "legend": { @@ -51715,7 +51863,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 364, + "id": 365, "interval": null, "links": [], "maxDataPoints": 100, @@ -51754,7 +51902,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 365, + "id": 366, "interval": null, "isNew": true, "legend": { @@ -51887,7 +52035,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 366, + "id": 367, "interval": null, "isNew": true, "legend": { @@ -52020,7 +52168,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 367, + "id": 368, "interval": null, "isNew": true, "legend": { @@ -52153,7 +52301,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 368, + "id": 369, "interval": null, "isNew": true, "legend": { @@ -52289,7 +52437,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 369, + "id": 370, "interval": null, "links": [], "maxDataPoints": 100, @@ -52328,7 +52476,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 370, + "id": 371, "interval": null, "isNew": true, "legend": { @@ -52461,7 +52609,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 371, + "id": 372, "interval": null, "isNew": true, "legend": { @@ -52594,7 +52742,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 372, + "id": 373, "interval": null, "isNew": true, "legend": { @@ -52742,7 +52890,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 373, + "id": 374, "interval": null, "isNew": true, "legend": { @@ -52875,7 +53023,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 374, + "id": 375, "interval": null, "isNew": true, "legend": { @@ -53008,7 +53156,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 375, + "id": 376, "interval": null, "isNew": true, "legend": { @@ -53141,7 +53289,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 376, + "id": 377, "interval": null, "isNew": true, "legend": { @@ -53277,7 +53425,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 377, + "id": 378, "interval": null, "links": [], "maxDataPoints": 100, @@ -53316,7 +53464,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 378, + "id": 379, "interval": null, "isNew": true, "legend": { @@ -53449,7 +53597,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 379, + "id": 380, "interval": null, "isNew": true, "legend": { @@ -53582,7 +53730,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 380, + "id": 381, "interval": null, "isNew": true, "legend": { @@ -53715,7 +53863,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 381, + "id": 382, "interval": null, "isNew": true, "legend": { @@ -53848,7 +53996,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 382, + "id": 383, "interval": null, "isNew": true, "legend": { @@ -53981,7 +54129,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 383, + "id": 384, "interval": null, "isNew": true, "legend": { @@ -54117,7 +54265,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 384, + "id": 385, "interval": null, "links": [], "maxDataPoints": 100, @@ -54156,7 +54304,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 385, + "id": 386, "interval": null, "isNew": true, "legend": { @@ -54289,7 +54437,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 386, + "id": 387, "interval": null, "isNew": true, "legend": { @@ -54422,7 +54570,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 387, + "id": 388, "interval": null, "isNew": true, "legend": { @@ -54570,7 +54718,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 388, + "id": 389, "interval": null, "isNew": true, "legend": { @@ -54733,7 +54881,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 389, + "id": 390, "interval": null, "isNew": true, "legend": { @@ -54866,7 +55014,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 390, + "id": 391, "interval": null, "isNew": true, "legend": { @@ -54999,7 +55147,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 391, + "id": 392, "interval": null, "isNew": true, "legend": { @@ -55147,7 +55295,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 392, + "id": 393, "interval": null, "isNew": true, "legend": { @@ -55295,7 +55443,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 393, + "id": 394, "interval": null, "isNew": true, "legend": { @@ -55431,7 +55579,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 394, + "id": 395, "interval": null, "links": [], "maxDataPoints": 100, @@ -55470,7 +55618,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 395, + "id": 396, "interval": null, "isNew": true, "legend": { @@ -55603,7 +55751,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 396, + "id": 397, "interval": null, "isNew": true, "legend": { @@ -55736,7 +55884,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 397, + "id": 398, "interval": null, "isNew": true, "legend": { @@ -55869,7 +56017,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 398, + "id": 399, "interval": null, "isNew": true, "legend": { @@ -56002,7 +56150,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 399, + "id": 400, "interval": null, "isNew": true, "legend": { @@ -56135,7 +56283,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 400, + "id": 401, "interval": null, "isNew": true, "legend": { @@ -56268,7 +56416,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 401, + "id": 402, "interval": null, "isNew": true, "legend": { @@ -56401,7 +56549,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 402, + "id": 403, "interval": null, "isNew": true, "legend": { @@ -56534,7 +56682,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 403, + "id": 404, "interval": null, "isNew": true, "legend": { @@ -56674,7 +56822,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 404, + "id": 405, "interval": null, "legend": { "show": false @@ -56771,7 +56919,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 405, + "id": 406, "interval": null, "isNew": true, "legend": { @@ -56904,7 +57052,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 406, + "id": 407, "interval": null, "isNew": true, "legend": { @@ -57052,7 +57200,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 407, + "id": 408, "interval": null, "isNew": true, "legend": { @@ -57200,7 +57348,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 408, + "id": 409, "interval": null, "isNew": true, "legend": { @@ -57340,7 +57488,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 409, + "id": 410, "interval": null, "legend": { "show": false @@ -57437,7 +57585,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 410, + "id": 411, "interval": null, "isNew": true, "legend": { @@ -57570,7 +57718,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 411, + "id": 412, "interval": null, "isNew": true, "legend": { @@ -57706,7 +57854,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 412, + "id": 413, "interval": null, "links": [], "maxDataPoints": 100, @@ -57745,7 +57893,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 413, + "id": 414, "interval": null, "isNew": true, "legend": { @@ -57878,7 +58026,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 414, + "id": 415, "interval": null, "isNew": true, "legend": { @@ -58041,7 +58189,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 415, + "id": 416, "interval": null, "isNew": true, "legend": { @@ -58189,7 +58337,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 416, + "id": 417, "interval": null, "isNew": true, "legend": { @@ -58322,7 +58470,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 417, + "id": 418, "interval": null, "isNew": true, "legend": { @@ -58462,7 +58610,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 418, + "id": 419, "interval": null, "legend": { "show": false @@ -58566,7 +58714,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 419, + "id": 420, "interval": null, "legend": { "show": false @@ -58670,7 +58818,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 420, + "id": 421, "interval": null, "legend": { "show": false @@ -58767,7 +58915,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 421, + "id": 422, "interval": null, "isNew": true, "legend": { @@ -58907,7 +59055,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 422, + "id": 423, "interval": null, "legend": { "show": false @@ -59011,7 +59159,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 423, + "id": 424, "interval": null, "legend": { "show": false @@ -59115,7 +59263,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 424, + "id": 425, "interval": null, "legend": { "show": false @@ -59212,7 +59360,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 425, + "id": 426, "interval": null, "isNew": true, "legend": { @@ -59345,7 +59493,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 426, + "id": 427, "interval": null, "isNew": true, "legend": { @@ -59478,7 +59626,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 427, + "id": 428, "interval": null, "isNew": true, "legend": { @@ -59618,7 +59766,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 428, + "id": 429, "interval": null, "legend": { "show": false @@ -59715,7 +59863,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 429, + "id": 430, "interval": null, "isNew": true, "legend": { @@ -59851,7 +59999,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 430, + "id": 431, "interval": null, "links": [], "maxDataPoints": 100, @@ -59890,7 +60038,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 431, + "id": 432, "interval": null, "isNew": true, "legend": { @@ -60053,7 +60201,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 432, + "id": 433, "interval": null, "isNew": true, "legend": { @@ -60186,7 +60334,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 433, + "id": 434, "interval": null, "isNew": true, "legend": { @@ -60326,7 +60474,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 434, + "id": 435, "interval": null, "legend": { "show": false @@ -60430,7 +60578,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 435, + "id": 436, "interval": null, "legend": { "show": false @@ -60527,7 +60675,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 436, + "id": 437, "interval": null, "isNew": true, "legend": { @@ -60682,7 +60830,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 437, + "id": 438, "interval": null, "legend": { "show": false @@ -60786,7 +60934,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 438, + "id": 439, "interval": null, "legend": { "show": false @@ -60890,7 +61038,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 439, + "id": 440, "interval": null, "legend": { "show": false @@ -60987,7 +61135,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 440, + "id": 441, "interval": null, "isNew": true, "legend": { @@ -61157,7 +61305,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 441, + "id": 442, "interval": null, "legend": { "show": false @@ -61254,7 +61402,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 442, + "id": 443, "interval": null, "isNew": true, "legend": { @@ -61455,7 +61603,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 443, + "id": 444, "interval": null, "isNew": true, "legend": { @@ -61656,7 +61804,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 444, + "id": 445, "interval": null, "isNew": true, "legend": { @@ -61789,7 +61937,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 445, + "id": 446, "interval": null, "isNew": true, "legend": { @@ -61952,7 +62100,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 446, + "id": 447, "interval": null, "isNew": true, "legend": { @@ -62085,7 +62233,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 447, + "id": 448, "interval": null, "isNew": true, "legend": { @@ -62218,7 +62366,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 448, + "id": 449, "interval": null, "isNew": true, "legend": { @@ -62419,7 +62567,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 449, + "id": 450, "interval": null, "isNew": true, "legend": { @@ -62552,7 +62700,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 450, + "id": 451, "interval": null, "isNew": true, "legend": { @@ -62692,7 +62840,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 451, + "id": 452, "interval": null, "legend": { "show": false @@ -62796,7 +62944,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 452, + "id": 453, "interval": null, "legend": { "show": false @@ -62900,7 +63048,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 453, + "id": 454, "interval": null, "legend": { "show": false @@ -63004,7 +63152,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 454, + "id": 455, "interval": null, "legend": { "show": false @@ -63108,7 +63256,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 455, + "id": 456, "interval": null, "legend": { "show": false @@ -63212,7 +63360,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 456, + "id": 457, "interval": null, "legend": { "show": false @@ -63316,7 +63464,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 457, + "id": 458, "interval": null, "legend": { "show": false @@ -63413,7 +63561,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 458, + "id": 459, "interval": null, "isNew": true, "legend": { @@ -63561,7 +63709,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 459, + "id": 460, "interval": null, "isNew": true, "legend": { @@ -63694,7 +63842,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 460, + "id": 461, "interval": null, "isNew": true, "legend": { @@ -63827,7 +63975,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 461, + "id": 462, "interval": null, "isNew": true, "legend": { @@ -63975,7 +64123,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 462, + "id": 463, "interval": null, "isNew": true, "legend": { @@ -64111,7 +64259,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 463, + "id": 464, "interval": null, "links": [], "maxDataPoints": 100, @@ -64162,7 +64310,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 464, + "id": 465, "interval": null, "links": [], "maxDataPoints": 100, @@ -64258,7 +64406,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 465, + "id": 466, "interval": null, "links": [], "maxDataPoints": 100, @@ -64333,7 +64481,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 466, + "id": 467, "interval": null, "links": [], "maxDataPoints": 100, @@ -64408,7 +64556,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 467, + "id": 468, "interval": null, "links": [], "maxDataPoints": 100, @@ -64483,7 +64631,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 468, + "id": 469, "interval": null, "links": [], "maxDataPoints": 100, @@ -64558,7 +64706,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 469, + "id": 470, "interval": null, "links": [], "maxDataPoints": 100, @@ -64633,7 +64781,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 470, + "id": 471, "interval": null, "links": [], "maxDataPoints": 100, @@ -64708,7 +64856,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 471, + "id": 472, "interval": null, "links": [], "maxDataPoints": 100, @@ -64787,7 +64935,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 472, + "id": 473, "interval": null, "isNew": true, "legend": { @@ -64920,7 +65068,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 473, + "id": 474, "interval": null, "isNew": true, "legend": { @@ -65053,7 +65201,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 474, + "id": 475, "interval": null, "isNew": true, "legend": { @@ -65186,7 +65334,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 475, + "id": 476, "interval": null, "isNew": true, "legend": { @@ -65319,7 +65467,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 476, + "id": 477, "interval": null, "isNew": true, "legend": { @@ -65452,7 +65600,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 477, + "id": 478, "interval": null, "isNew": true, "legend": { @@ -65600,7 +65748,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 478, + "id": 479, "interval": null, "isNew": true, "legend": { @@ -65733,7 +65881,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 479, + "id": 480, "interval": null, "isNew": true, "legend": { @@ -65866,7 +66014,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 480, + "id": 481, "interval": null, "isNew": true, "legend": { @@ -66032,7 +66180,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 481, + "id": 482, "interval": null, "legend": { "show": false @@ -66136,7 +66284,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 482, + "id": 483, "interval": null, "legend": { "show": false @@ -66240,7 +66388,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 483, + "id": 484, "interval": null, "legend": { "show": false @@ -66344,7 +66492,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 484, + "id": 485, "interval": null, "legend": { "show": false @@ -66448,7 +66596,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 485, + "id": 486, "interval": null, "legend": { "show": false @@ -66552,7 +66700,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 486, + "id": 487, "interval": null, "legend": { "show": false @@ -66656,7 +66804,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 487, + "id": 488, "interval": null, "legend": { "show": false @@ -66760,7 +66908,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 488, + "id": 489, "interval": null, "legend": { "show": false @@ -66857,7 +67005,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 489, + "id": 490, "interval": null, "isNew": true, "legend": { @@ -66990,7 +67138,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 490, + "id": 491, "interval": null, "isNew": true, "legend": { @@ -67123,7 +67271,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 491, + "id": 492, "interval": null, "isNew": true, "legend": { @@ -67256,7 +67404,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 492, + "id": 493, "interval": null, "isNew": true, "legend": { @@ -67389,7 +67537,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 493, + "id": 494, "interval": null, "isNew": true, "legend": { @@ -67522,7 +67670,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 494, + "id": 495, "interval": null, "isNew": true, "legend": { @@ -67655,7 +67803,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 495, + "id": 496, "interval": null, "isNew": true, "legend": { @@ -67788,7 +67936,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 496, + "id": 497, "interval": null, "isNew": true, "legend": { @@ -67928,7 +68076,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 497, + "id": 498, "interval": null, "legend": { "show": false @@ -68032,7 +68180,7 @@ "hideTimeOverride": false, "hideZeroBuckets": true, "highlightCards": true, - "id": 498, + "id": 499, "interval": null, "legend": { "show": false @@ -68129,7 +68277,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 499, + "id": 500, "interval": null, "isNew": true, "legend": { @@ -68262,7 +68410,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 500, + "id": 501, "interval": null, "isNew": true, "legend": { @@ -68395,7 +68543,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 501, + "id": 502, "interval": null, "isNew": true, "legend": { @@ -68528,7 +68676,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 502, + "id": 503, "interval": null, "isNew": true, "legend": { @@ -68661,7 +68809,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 503, + "id": 504, "interval": null, "isNew": true, "legend": { @@ -68794,7 +68942,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 504, + "id": 505, "interval": null, "isNew": true, "legend": { @@ -68930,7 +69078,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 505, + "id": 506, "interval": null, "links": [], "maxDataPoints": 100, @@ -68969,7 +69117,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 506, + "id": 507, "interval": null, "isNew": true, "legend": { @@ -69117,7 +69265,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 507, + "id": 508, "interval": null, "isNew": true, "legend": { @@ -69250,7 +69398,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 508, + "id": 509, "interval": null, "isNew": true, "legend": { @@ -69383,7 +69531,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 509, + "id": 510, "interval": null, "isNew": true, "legend": { @@ -69519,7 +69667,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 510, + "id": 511, "interval": null, "links": [], "maxDataPoints": 100, @@ -69558,7 +69706,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 511, + "id": 512, "interval": null, "isNew": true, "legend": { @@ -69691,7 +69839,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 512, + "id": 513, "interval": null, "isNew": true, "legend": { @@ -69824,7 +69972,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 513, + "id": 514, "interval": null, "isNew": true, "legend": { @@ -69957,7 +70105,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 514, + "id": 515, "interval": null, "isNew": true, "legend": { @@ -70090,7 +70238,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 515, + "id": 516, "interval": null, "isNew": true, "legend": { @@ -70223,7 +70371,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 516, + "id": 517, "interval": null, "isNew": true, "legend": { @@ -70359,7 +70507,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 517, + "id": 518, "interval": null, "links": [], "maxDataPoints": 100, @@ -70398,7 +70546,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 518, + "id": 519, "interval": null, "isNew": true, "legend": { @@ -70599,7 +70747,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 519, + "id": 520, "interval": null, "isNew": true, "legend": { @@ -70735,7 +70883,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 520, + "id": 521, "interval": null, "links": [], "maxDataPoints": 100, @@ -70774,7 +70922,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 521, + "id": 522, "interval": null, "isNew": true, "legend": { @@ -70907,7 +71055,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 522, + "id": 523, "interval": null, "isNew": true, "legend": { @@ -71040,7 +71188,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 523, + "id": 524, "interval": null, "isNew": true, "legend": { @@ -71173,7 +71321,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 524, + "id": 525, "interval": null, "isNew": true, "legend": { @@ -71306,7 +71454,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 525, + "id": 526, "interval": null, "isNew": true, "legend": { @@ -71454,7 +71602,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 526, + "id": 527, "interval": null, "isNew": true, "legend": { @@ -71658,7 +71806,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 527, + "id": 528, "interval": null, "links": [], "maxDataPoints": 100, @@ -71697,7 +71845,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 528, + "id": 529, "interval": null, "isNew": true, "legend": { @@ -71830,7 +71978,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 529, + "id": 530, "interval": null, "isNew": true, "legend": { @@ -71963,7 +72111,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 530, + "id": 531, "interval": null, "isNew": true, "legend": { @@ -72096,7 +72244,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 531, + "id": 532, "interval": null, "isNew": true, "legend": { @@ -72229,7 +72377,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 532, + "id": 533, "interval": null, "isNew": true, "legend": { @@ -72426,7 +72574,7 @@ }, "height": null, "hideTimeOverride": false, - "id": 533, + "id": 534, "interval": null, "links": [], "maxDataPoints": 100, diff --git a/metrics/grafana/tikv_details.json.sha256 b/metrics/grafana/tikv_details.json.sha256 index d22d98615a6..d6ef39611f5 100644 --- a/metrics/grafana/tikv_details.json.sha256 +++ b/metrics/grafana/tikv_details.json.sha256 @@ -1 +1 @@ -56699194c49baa1d686f33f734a553fbfe50c76b1bf8bfe0b61ce64a242dba65 ./metrics/grafana/tikv_details.json +1e46671f95cc621b79bc09f72f97afaa6c569a924265a85861b034f203cf742f ./metrics/grafana/tikv_details.json From 8a75d3b22f9f8afc73c44d8a984416fda96d3cd4 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 13 Sep 2024 21:26:21 +0800 Subject: [PATCH 067/144] In-memory Engine: reload manual loaded regions after leader transfer (#17296) ref tikv/tikv#16966 This PR addresses the problem where manually loaded ranges were not automatically reloaded after a leader transfer. To resolve this, a "manual-load-range" has been introduced, ensuring that regions covered by this range are properly reloaded when they handle write requests. Signed-off-by: Neil Shen --- .../engine_traits/src/range_cache_engine.rs | 46 ++- components/hybrid_engine/Cargo.toml | 6 +- .../{eviction.rs => load_eviction.rs} | 163 +++++----- components/hybrid_engine/src/observer/mod.rs | 4 +- .../tests/failpoints/test_write_batch.rs | 7 +- .../src/background.rs | 160 +++++----- .../range_cache_memory_engine/src/engine.rs | 34 ++- .../range_cache_memory_engine/src/metrics.rs | 4 + .../src/range_manager.rs | 281 +++++++++++++++++- .../src/region_label.rs | 42 +-- .../src/write_batch.rs | 6 +- .../tests/failpoints/test_memory_engine.rs | 23 +- components/server/src/server.rs | 5 +- components/test_raftstore/src/server.rs | 4 +- .../cases/test_range_cache_engine.rs | 42 +++ 15 files changed, 625 insertions(+), 202 deletions(-) rename components/hybrid_engine/src/observer/{eviction.rs => load_eviction.rs} (70%) diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 0b958668f75..6d51615e8fb 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -28,6 +28,9 @@ pub enum RegionEvent { source: CacheRegion, new_regions: Vec, }, + TryLoad { + region: CacheRegion, + }, Eviction { region: CacheRegion, reason: EvictReason, @@ -51,6 +54,7 @@ pub enum EvictReason { Merge, Disabled, ApplySnapshot, + Manual, } /// RangeCacheEngine works as a range cache caching some ranges (in Memory or @@ -101,7 +105,7 @@ pub trait RangeCacheEngineExt { /// as it continues to evolve to handle eviction, using stats. pub trait RangeHintService: Send + Sync {} -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Hash)] pub struct CacheRegion { // target region id pub id: u64, @@ -163,6 +167,46 @@ impl CacheRegion { pub fn overlaps(&self, other: &CacheRegion) -> bool { self.start < other.end && other.start < self.end } + + pub fn union(&self, other: &CacheRegion) -> Option { + if self.overlaps(other) { + Some(CacheRegion { + id: 0, + epoch_version: 0, + start: std::cmp::min(&self.start, &other.start).clone(), + end: std::cmp::max(&self.end, &other.end).clone(), + }) + } else { + None + } + } + + pub fn difference(&self, other: &CacheRegion) -> (Option, Option) { + if !self.overlaps(other) { + return (None, None); + } + let left = if self.start < other.start { + Some(CacheRegion { + id: 0, + epoch_version: 0, + start: self.start.clone(), + end: other.start.clone(), + }) + } else { + None + }; + let right = if self.end > other.end { + Some(CacheRegion { + id: 0, + epoch_version: 0, + start: other.end.clone(), + end: self.end.clone(), + }) + } else { + None + }; + (left, right) + } } #[cfg(test)] diff --git a/components/hybrid_engine/Cargo.toml b/components/hybrid_engine/Cargo.toml index d49c06e4568..84b211344e0 100644 --- a/components/hybrid_engine/Cargo.toml +++ b/components/hybrid_engine/Cargo.toml @@ -25,12 +25,14 @@ range_cache_memory_engine = { workspace = true } slog = { workspace = true } slog-global = { workspace = true } tempfile = "3.0" -prometheus = { version = "0.13", default-features = false, features = ["nightly"] } +prometheus = { version = "0.13", default-features = false, features = [ + "nightly", +] } prometheus-static-metric = "0.5" lazy_static = "1.4.0" crossbeam = { workspace = true } fail = "0.5" -raftstore = { workspace = true } +raftstore = { workspace = true, features = ["testexport"] } raft = { workspace = true } kvproto = { workspace = true } diff --git a/components/hybrid_engine/src/observer/eviction.rs b/components/hybrid_engine/src/observer/load_eviction.rs similarity index 70% rename from components/hybrid_engine/src/observer/eviction.rs rename to components/hybrid_engine/src/observer/load_eviction.rs index cf9ac7e02e6..9deb491cdd7 100644 --- a/components/hybrid_engine/src/observer/eviction.rs +++ b/components/hybrid_engine/src/observer/load_eviction.rs @@ -1,41 +1,30 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use engine_traits::{CacheRegion, EvictReason, KvEngine, RangeCacheEngineExt, RegionEvent}; -use kvproto::{metapb::Region, raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; +use kvproto::{raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; use raft::StateRole; use raftstore::coprocessor::{ AdminObserver, ApplyCtxInfo, ApplySnapshotObserver, BoxAdminObserver, BoxApplySnapshotObserver, - BoxCmdObserver, BoxQueryObserver, BoxRoleObserver, Cmd, CmdBatch, CmdObserver, Coprocessor, - CoprocessorHost, ObserveLevel, ObserverContext, QueryObserver, RegionState, RoleObserver, + BoxQueryObserver, BoxRoleObserver, Cmd, Coprocessor, CoprocessorHost, ObserverContext, + QueryObserver, RegionState, RoleObserver, }; use tikv_util::info; #[derive(Clone)] -pub struct EvictionObserver { - // observer is per thread so there is no need to use mutex here, - // but current inteface only provides `&self` but not `&mut self`, - // so we use mutex to workaround this restriction. - // TODO: change Observer's interface to `&mut self`. - pending_events: Arc>>, +pub struct LoadEvictionObserver { cache_engine: Arc, } -impl EvictionObserver { +impl LoadEvictionObserver { pub fn new(cache_engine: Arc) -> Self { - EvictionObserver { - pending_events: Arc::default(), - cache_engine, - } + LoadEvictionObserver { cache_engine } } pub fn register_to(&self, coprocessor_host: &mut CoprocessorHost) { // This observer does not need high priority, use the default 100. let priority = 100; - coprocessor_host - .registry - .register_cmd_observer(priority, BoxCmdObserver::new(self.clone())); // Evict cache when a peer applies ingest sst. coprocessor_host .registry @@ -86,13 +75,7 @@ impl EvictionObserver { "is_ingest_sst" => apply.pending_handle_ssts.is_some(), "admin_command" => ?cmd.request.get_admin_request().get_cmd_type(), ); - self.pending_events - .lock() - .unwrap() - .push(RegionEvent::Eviction { - region: cache_region, - reason: EvictReason::Merge, - }); + self.evict_region(cache_region, EvictReason::Merge) } // there are new_regions, this must be a split event. if !state.new_regions.is_empty() { @@ -106,48 +89,38 @@ impl EvictionObserver { "new_regions" => ?state.new_regions, ); - self.pending_events - .lock() - .unwrap() - .push(RegionEvent::Split { - source: CacheRegion::from_region(ctx.region()), - new_regions: state - .new_regions - .iter() - .map(CacheRegion::from_region) - .collect(), - }); + self.split_region( + CacheRegion::from_region(ctx.region()), + state + .new_regions + .iter() + .map(CacheRegion::from_region) + .collect(), + ); } } - fn on_flush_cmd(&self) { - let events = std::mem::take(&mut *self.pending_events.lock().unwrap()); - for e in events { - self.cache_engine.on_region_event(e); - } + fn split_region(&self, source: CacheRegion, new_regions: Vec) { + self.cache_engine.on_region_event(RegionEvent::Split { + source, + new_regions, + }); } - fn evict_region_range(&self, region: &Region, reason: EvictReason) { - let cache_region = CacheRegion::from_region(region); - info!( - "ime evict region"; - "region" => ?cache_region, - "reason" => ?reason, - "epoch" => ?region.get_region_epoch(), - ); - self.pending_events - .lock() - .unwrap() - .push(RegionEvent::Eviction { - region: cache_region, - reason, - }); + fn try_load_region(&self, region: CacheRegion) { + self.cache_engine + .on_region_event(RegionEvent::TryLoad { region }); + } + + fn evict_region(&self, region: CacheRegion, reason: EvictReason) { + self.cache_engine + .on_region_event(RegionEvent::Eviction { region, reason }); } } -impl Coprocessor for EvictionObserver {} +impl Coprocessor for LoadEvictionObserver {} -impl QueryObserver for EvictionObserver { +impl QueryObserver for LoadEvictionObserver { fn post_exec_query( &self, ctx: &mut ObserverContext<'_>, @@ -163,7 +136,7 @@ impl QueryObserver for EvictionObserver { } } -impl AdminObserver for EvictionObserver { +impl AdminObserver for LoadEvictionObserver { fn post_exec_admin( &self, ctx: &mut ObserverContext<'_>, @@ -179,7 +152,7 @@ impl AdminObserver for EvictionObserver { } } -impl ApplySnapshotObserver for EvictionObserver { +impl ApplySnapshotObserver for LoadEvictionObserver { fn post_apply_snapshot( &self, ctx: &mut ObserverContext<'_>, @@ -189,45 +162,50 @@ impl ApplySnapshotObserver for EvictionObserver { ) { // While currently, we evict cached region after leader step down. // A region can may still be loaded when it's leader. E.g, to pre-load - // some hot regions before transfering leader. - self.evict_region_range(ctx.region(), EvictReason::ApplySnapshot) + // some hot regions before transferring leader. + let cache_region = CacheRegion::from_region(ctx.region()); + self.evict_region(cache_region, EvictReason::ApplySnapshot) } } -impl RoleObserver for EvictionObserver { +impl RoleObserver for LoadEvictionObserver { fn on_role_change( &self, ctx: &mut ObserverContext<'_>, change: &raftstore::coprocessor::RoleChange, ) { - if let StateRole::Follower = change.state + if let StateRole::Leader = change.state { + // Currently, it is only used by the manual load. + let cache_region = CacheRegion::from_region(ctx.region()); + info!( + "ime load region due to became leader"; + "region" => ?cache_region, + ); + self.try_load_region(cache_region); + } else if let StateRole::Follower = change.state && change.initialized { - self.evict_region_range(ctx.region(), EvictReason::BecomeFollower) + let cache_region = CacheRegion::from_region(ctx.region()); + info!( + "ime evict region due to became follower"; + "region" => ?cache_region, + ); + self.evict_region(cache_region, EvictReason::BecomeFollower); } } } -impl CmdObserver for EvictionObserver { - fn on_flush_applied_cmd_batch( - &self, - _max_level: ObserveLevel, - _cmd_batches: &mut Vec, - _engine: &E, - ) { - self.on_flush_cmd(); - } - fn on_applied_current_term(&self, role: StateRole, region: &Region) {} -} - #[cfg(test)] mod tests { + use std::sync::Mutex; + use engine_traits::{RegionEvent, SstMetaInfo}; use kvproto::{ import_sstpb::SstMeta, - metapb::Peer, + metapb::{Peer, Region}, raft_cmdpb::{RaftCmdRequest, RaftCmdResponse}, }; + use raftstore::coprocessor::RoleChange; use super::*; @@ -250,9 +228,9 @@ mod tests { } #[test] - fn test_do_not_evict_range_region_split() { + fn test_do_not_evict_region_region_split() { let cache_engine = Arc::new(MockRangeCacheEngine::default()); - let observer = EvictionObserver::new(cache_engine.clone()); + let observer = LoadEvictionObserver::new(cache_engine.clone()); let mut region = Region::default(); region.set_id(1); @@ -274,15 +252,13 @@ mod tests { // Must not evict range for region split. observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); - observer.on_flush_cmd(); - let expected = CacheRegion::from_region(®ion); assert!(&cache_engine.region_events.lock().unwrap().is_empty()); } #[test] - fn test_evict_range_ingest_sst() { + fn test_evict_region_ingest_sst() { let cache_engine = Arc::new(MockRangeCacheEngine::default()); - let observer = EvictionObserver::new(cache_engine.clone()); + let observer = LoadEvictionObserver::new(cache_engine.clone()); let mut region = Region::default(); region.set_id(1); @@ -310,7 +286,6 @@ mod tests { let cmd = Cmd::new(0, 0, request, response); observer.post_exec_cmd(&mut ctx, &cmd, &RegionState::default(), &mut apply); - observer.on_flush_cmd(); let cached_region = CacheRegion::from_region(®ion); let expected = RegionEvent::Eviction { region: cached_region, @@ -318,4 +293,22 @@ mod tests { }; assert_eq!(&cache_engine.region_events.lock().unwrap()[0], &expected); } + + #[test] + fn test_load_region_became_leader() { + let cache_engine = Arc::new(MockRangeCacheEngine::default()); + let observer = LoadEvictionObserver::new(cache_engine.clone()); + + let mut region = Region::default(); + region.set_id(1); + region.mut_peers().push(Peer::default()); + let mut ctx = ObserverContext::new(®ion); + let role_change = RoleChange::new(StateRole::Leader); + observer.on_role_change(&mut ctx, &role_change); + let cached_region = CacheRegion::from_region(®ion); + let expected = RegionEvent::TryLoad { + region: cached_region, + }; + assert_eq!(&cache_engine.region_events.lock().unwrap()[0], &expected); + } } diff --git a/components/hybrid_engine/src/observer/mod.rs b/components/hybrid_engine/src/observer/mod.rs index fb35590185c..b9e6fe44589 100644 --- a/components/hybrid_engine/src/observer/mod.rs +++ b/components/hybrid_engine/src/observer/mod.rs @@ -1,9 +1,9 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -mod eviction; +mod load_eviction; mod snapshot; mod write_batch; -pub use eviction::EvictionObserver; +pub use load_eviction::LoadEvictionObserver; pub use snapshot::{HybridSnapshotObserver, RangeCacheSnapshotPin}; pub use write_batch::RegionCacheWriteBatchObserver; diff --git a/components/hybrid_engine/tests/failpoints/test_write_batch.rs b/components/hybrid_engine/tests/failpoints/test_write_batch.rs index 2db925ba248..ef071c9e3da 100644 --- a/components/hybrid_engine/tests/failpoints/test_write_batch.rs +++ b/components/hybrid_engine/tests/failpoints/test_write_batch.rs @@ -35,9 +35,10 @@ fn test_sequence_number_unique() { // during the load let r2 = new_region(2, b"k5", b"k7"); let r3 = new_region(3, b"k7", b"k9"); - - engine.load_region(r2.clone()).unwrap(); - engine.load_region(r3.clone()).unwrap(); + let cache_region2 = CacheRegion::from_region(&r2); + let cache_region3 = CacheRegion::from_region(&r3); + engine.load_region(cache_region2.clone()).unwrap(); + engine.load_region(cache_region3.clone()).unwrap(); // The sequence number of write batch should be increased one by one, otherwise // if a delete and a put of the same key occurs in the same write batch, diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 3f84d88216f..2b10a09db7c 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -12,7 +12,7 @@ use engine_traits::{ CacheRegion, EvictReason, IterOptions, Iterable, Iterator, MiscExt, RangeHintService, SnapshotMiscExt, CF_DEFAULT, CF_WRITE, DATA_CFS, }; -use hex::FromHexError; +use keys::{origin_end_key, origin_key}; use pd_client::{PdClient, RpcClient}; use raftstore::coprocessor::RegionInfoProvider; use slog_global::{error, info, warn}; @@ -41,8 +41,7 @@ use crate::{ range_manager::{AsyncFnOnce, CacheRegionMeta, RegionState}, range_stats::{RangeStatsManager, DEFAULT_EVICT_MIN_DURATION}, region_label::{ - KeyRangeRule, LabelRule, RegionLabelAddedCb, RegionLabelRulesManager, - RegionLabelServiceBuilder, + LabelRule, RegionLabelChangedCallback, RegionLabelRulesManager, RegionLabelServiceBuilder, }, write_batch::RangeCacheWriteBatchEntry, }; @@ -163,46 +162,41 @@ impl PdRangeHintService { /// label is removed or no longer set to always. pub fn start(&self, remote: Remote, range_manager_load_cb: F) where - F: Fn(&[u8], &[u8]) + Send + Sync + 'static, + F: Fn(&CacheRegion, bool) + Send + Sync + 'static, { - let parse_range = |key_range: &KeyRangeRule| { - let start = hex::decode(&key_range.start_key)?; - let end = hex::decode(&key_range.end_key)?; - Ok::<_, FromHexError>((start, end)) - }; - let pd_client = self.0.clone(); - let region_label_added_cb: RegionLabelAddedCb = Arc::new(move |label_rule: &LabelRule| { - if !label_rule - .labels - .iter() - .any(|e| e.key == CACHE_LABEL_RULE_KEY && e.value == CACHE_LABEL_RULE_ALWAYS) - { - // not related to caching, skip. - return; - } - for key_range in &label_rule.data { - match parse_range(key_range) { - Ok((start, end)) => { - info!("ime requested to cache range"; - "start" => ?log_wrappers::Value(&start), - "end" => ?log_wrappers::Value(&end)); - range_manager_load_cb(&start, &end); - } - Err(e) => { - error!("ime unable to convert key_range rule to cache range"; "err" => ?e); + let region_label_changed_cb: RegionLabelChangedCallback = Arc::new( + move |label_rule: &LabelRule, is_add: bool| { + if !label_rule + .labels + .iter() + .any(|e| e.key == CACHE_LABEL_RULE_KEY && e.value == CACHE_LABEL_RULE_ALWAYS) + { + // not related to caching, skip. + return; + } + for key_range in &label_rule.data { + match CacheRegion::try_from(key_range) { + Ok(cache_range) => { + info!("ime requested to cache range"; "range" => ?&cache_range); + range_manager_load_cb(&cache_range, is_add); + } + Err(e) => { + error!("ime unable to convert key_range rule to cache range"; "error" => ?e); + } } } - } - }); + }, + ); let mut region_label_svc = RegionLabelServiceBuilder::new( Arc::new(RegionLabelRulesManager { - region_label_added_cb: Some(region_label_added_cb), + region_label_change_cb: Some(region_label_changed_cb), ..RegionLabelRulesManager::default() }), pd_client, ) .rule_filter_fn(|label_rule| { + info!("dbg rule"; "rule" => ?label_rule); label_rule .labels .iter() @@ -266,39 +260,65 @@ impl BgWorkManager { pub fn start_bg_hint_service(&self, range_hint_service: PdRangeHintService) { let core = self.core.clone(); let region_info_provider = self.region_info_provider.clone(); - range_hint_service.start(self.worker.remote(), move |start: &[u8], end: &[u8]| { - let Some(ref info_provider) = region_info_provider else { - warn!("ime region info provider is none, skip load pinned range."); - return; - }; - - let regions = match info_provider.get_regions_in_range(start, end) { - Ok(r) => r, - Err(e) => { - warn!( - "ime get regions in range failed"; "err" => ?e, - "start" => ?log_wrappers::Value(start), - "end" => ?log_wrappers::Value(end) - ); + range_hint_service.start( + self.worker.remote(), + move |cache_range: &CacheRegion, is_add: bool| { + let region_manager = core.region_manager(); + if !is_add { + region_manager + .regions_map() + .write() + .remove_manual_load_range(cache_range.clone()); + region_manager.evict_region(cache_range, EvictReason::Manual, None); return; } - }; - if regions.is_empty() { - return; - } + region_manager + .regions_map() + .write() + .add_manual_load_range(cache_range.clone()); + + let Some(ref info_provider) = region_info_provider else { + warn!("ime region info provider is none, skip manual load range."); + return; + }; + + let start = origin_key(&cache_range.start); + let end = origin_end_key(&cache_range.end); + let regions = match info_provider.get_regions_in_range(start, end) { + Ok(r) => r, + Err(e) => { + warn!( + "ime get regions in range failed"; "err" => ?e, + "start" => ?log_wrappers::Value(start), + "end" => ?log_wrappers::Value(end) + ); + return; + } + }; - for r in regions { - let cache_region = CacheRegion::from_region(&r); - if let Err(e) = core.region_manager().load_region(cache_region) { - warn!("ime load region by label failed"; "err" => ?e, "region" => ?r); + let total = regions.len(); + let mut failed = 0; + for r in regions { + // TODO: Only load region leaders. + let cache_region = CacheRegion::from_region(&r); + if let Err(e) = region_manager.load_region(cache_region) { + failed += 1; + warn!("ime load region failed"; "err" => ?e, "region" => ?r); + } } - } - // TODO (afeinberg): This does not actually load the range. The load - // happens the apply thread begins to apply raft - // entries. To force this (for read-only use-cases) we - // should propose a No-Op command. - }); + info!( + "ime manual load summary"; + "range" => ?cache_range, + "success" => total - failed, + "failed" => failed, + ); + // TODO (afeinberg): This does not actually load the range. The + // load happens the apply thread begins to apply + // raft entries. To force this (for read-only + // use-cases) we should propose a No-Op command. + }, + ); } fn start_tick( @@ -2780,8 +2800,9 @@ pub mod tests { rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); for r in [®ion1, ®ion2] { - engine.load_region(r.clone()).unwrap(); - engine.prepare_for_apply(&CacheRegion::from_region(r)); + let cache_region = CacheRegion::from_region(r); + engine.load_region(cache_region.clone()).unwrap(); + engine.prepare_for_apply(&cache_region); } // ensure all ranges are finshed @@ -2857,8 +2878,9 @@ pub mod tests { rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); for r in [®ion1, ®ion2, ®ion3] { - engine.load_region(r.clone()).unwrap(); - engine.prepare_for_apply(&CacheRegion::from_region(r)); + let cache_region = CacheRegion::from_region(r); + engine.load_region(cache_region.clone()).unwrap(); + engine.prepare_for_apply(&cache_region); } // ensure all ranges are finshed @@ -2894,6 +2916,7 @@ pub mod tests { let mem_controller = engine.memory_controller(); let region1 = new_region(1, construct_region_key(1), construct_region_key(3)); + let cache_region1 = CacheRegion::from_region(®ion1); // Memory for one put is 17(key) + 3(val) + 8(Seqno) + 16(Memory controller in // key and val) + 96(Node overhead) = 140 let key = construct_key(1, 10); @@ -2906,8 +2929,8 @@ pub mod tests { rocks_engine.put_cf(CF_LOCK, &key, b"val").unwrap(); rocks_engine.put_cf(CF_WRITE, &key, b"val").unwrap(); // After loading range1, the memory usage should be 140*6=840 - engine.load_region(region1.clone()).unwrap(); - engine.prepare_for_apply(&CacheRegion::from_region(®ion1)); + engine.load_region(cache_region1.clone()).unwrap(); + engine.prepare_for_apply(&cache_region1); let region2 = new_region(2, construct_region_key(3), construct_region_key(5)); let key = construct_key(3, 10); @@ -2931,8 +2954,9 @@ pub mod tests { config_manager.dispatch(config_change).unwrap(); assert_eq!(config.value().hard_limit_threshold(), 2000); - engine.load_region(region2.clone()).unwrap(); - engine.prepare_for_apply(&CacheRegion::from_region(®ion2)); + let cache_region2 = CacheRegion::from_region(®ion2); + engine.load_region(cache_region2.clone()).unwrap(); + engine.prepare_for_apply(&cache_region2); // ensure all ranges are finshed test_util::eventually(Duration::from_millis(100), Duration::from_secs(2), || { diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 94ec8196f32..e0dd4e735df 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -20,7 +20,7 @@ use engine_traits::{ use kvproto::metapb::Region; use raftstore::coprocessor::RegionInfoProvider; use slog_global::error; -use tikv_util::{config::VersionTrack, info}; +use tikv_util::{config::VersionTrack, info, warn}; use crate::{ background::{BackgroundTask, BgWorkManager, PdRangeHintService}, @@ -291,8 +291,7 @@ impl RangeCacheMemoryEngine { self.core.region_manager.new_region(cache_region); } - pub fn load_region(&self, region: Region) -> result::Result<(), LoadFailedReason> { - let cache_region = CacheRegion::from_region(®ion); + pub fn load_region(&self, cache_region: CacheRegion) -> result::Result<(), LoadFailedReason> { self.core.region_manager().load_region(cache_region) } @@ -491,6 +490,27 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { RegionEvent::Eviction { region, reason } => { self.evict_region(®ion, reason, None); } + RegionEvent::TryLoad { region } => { + if self + .core + .region_manager() + .regions_map() + .read() + .overlap_with_manual_load_range(®ion) + { + info!( + "try to load region in manual load range"; + "region" => ?region, + ); + if let Err(e) = self.load_region(region.clone()) { + warn!( + "ime load region failed"; + "err" => ?e, + "region" => ?region, + ); + } + } + } RegionEvent::Split { source, new_regions, @@ -562,7 +582,8 @@ pub mod tests { VersionTrack::new(RangeCacheEngineConfig::config_for_test()), ))); let region1 = new_region(1, b"k1", b"k3"); - engine.load_region(region1).unwrap(); + let cache_region1 = CacheRegion::from_region(®ion1); + engine.load_region(cache_region1).unwrap(); let mut region2 = new_region(1, b"k1", b"k5"); region2.mut_region_epoch().version = 2; @@ -575,7 +596,8 @@ pub mod tests { ); let region1 = new_region(1, b"k1", b"k3"); - engine.load_region(region1).unwrap(); + let cache_region1 = CacheRegion::from_region(®ion1); + engine.load_region(cache_region1).unwrap(); let mut region2 = new_region(1, b"k2", b"k5"); region2.mut_region_epoch().version = 2; @@ -710,7 +732,7 @@ pub mod tests { let region = new_region(1, b"k00", b"k30"); let cache_region = CacheRegion::from_region(®ion); - engine.load_region(region).unwrap(); + engine.load_region(cache_region.clone()).unwrap(); assert!(engine.core.region_manager.is_active()); let mut wb = engine.write_batch(); diff --git a/components/range_cache_memory_engine/src/metrics.rs b/components/range_cache_memory_engine/src/metrics.rs index 6d9769c1ba1..da4535d2e04 100644 --- a/components/range_cache_memory_engine/src/metrics.rs +++ b/components/range_cache_memory_engine/src/metrics.rs @@ -41,6 +41,7 @@ make_auto_flush_static_metric! { memory_limit_reached, disabled, apply_snapshot, + manual, } pub struct GcFilteredCountVec: LocalIntCounter { @@ -208,5 +209,8 @@ pub(crate) fn observe_eviction_duration(secs: f64, evict_reason: EvictReason) { EvictReason::ApplySnapshot => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC .apply_snapshot .observe(secs), + EvictReason::Manual => RANGE_EVICTION_DURATION_HISTOGRAM_STATIC + .manual + .observe(secs), } } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 0bdd258e1da..4169095a2f2 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -282,6 +282,8 @@ pub struct RegionMetaMap { regions: HashMap, // active flag, cloned from RegionManager, is_active: Arc, + + manual_load_range: Vec, } impl RegionMetaMap { @@ -454,6 +456,59 @@ impl RegionMetaMap { pub(crate) fn regions(&self) -> &HashMap { &self.regions } + + pub fn overlap_with_manual_load_range(&self, range: &CacheRegion) -> bool { + self.manual_load_range.iter().any(|r| r.overlaps(range)) + } + + pub fn add_manual_load_range(&mut self, range: CacheRegion) { + let mut union = range; + self.manual_load_range.retain(|r| { + let Some(u) = r.union(&union) else { + return true; + }; + union = u; + // The intersected range need to be removed before updating + // the union range. + false + }); + info!("ime add manual load range"; "range" => ?union); + self.manual_load_range.push(union); + } + + pub fn remove_manual_load_range(&mut self, range: CacheRegion) { + let mut diffs = Vec::new(); + self.manual_load_range.retain(|r| { + match r.difference(&range) { + (None, None) => { + // Remove the range if it is overlapped with the range. + if !r.overlaps(&range) { + return true; + } + } + others => diffs.push(others), + }; + // The intersected range need to be removed before updating + // the union range. + false + }); + info!("ime remove manual load range"; "range" => ?range); + assert!(diffs.len() <= 2, "{:?}", diffs); + for (left, right) in diffs.into_iter() { + if let Some(left) = left { + info!("ime update manual load range"; "range" => ?left); + self.manual_load_range.push(left); + } + if let Some(right) = right { + info!("ime update manual load range"; "range" => ?right); + self.manual_load_range.push(right); + } + } + const GC_THRESHOLD: usize = 64; + if self.manual_load_range.capacity() - self.manual_load_range.len() > GC_THRESHOLD { + self.manual_load_range.shrink_to_fit(); + } + } } #[cfg(test)] @@ -516,6 +571,7 @@ impl Default for RegionManager { regions_by_range: BTreeMap::default(), regions: HashMap::default(), is_active: is_active.clone(), + manual_load_range: Vec::default(), }); Self { regions_map, @@ -528,7 +584,7 @@ impl Default for RegionManager { impl RegionManager { // load a new region directly in the active state. - // This fucntion is used for unit/integration tests only. + // This function is used for unit/integration tests only. pub fn new_region(&self, region: CacheRegion) { let mut range_meta = CacheRegionMeta::new(region); range_meta.state = RegionState::Active; @@ -1233,4 +1289,227 @@ mod tests { ); } } + + #[test] + fn test_overlap_with_manual_load_range() { + let range_mgr = RegionManager::default(); + range_mgr + .regions_map() + .write() + .add_manual_load_range(CacheRegion::new(0, 0, b"k00".to_vec(), b"k10".to_vec())); + range_mgr + .regions_map() + .write() + .add_manual_load_range(CacheRegion::new(0, 0, b"k20".to_vec(), b"k30".to_vec())); + range_mgr + .regions_map() + .write() + .add_manual_load_range(CacheRegion::new(0, 0, b"k30".to_vec(), b"k50".to_vec())); + + struct Case { + name: &'static str, + range: (&'static [u8], &'static [u8]), + expected: bool, + } + let cases = [ + Case { + name: "left intersect 1", + range: (b"k00", b"k05"), + expected: true, + }, + Case { + name: "left intersect 2", + range: (b"k15", b"k25"), + expected: true, + }, + Case { + name: "cover all", + range: (b"k00", b"k60"), + expected: true, + }, + Case { + name: "right intersect", + range: (b"k05", b"k15"), + expected: true, + }, + Case { + name: "left and right intersect", + range: (b"k25", b"k45"), + expected: true, + }, + Case { + name: "not overlap 1", + range: (b"k15", b"k20"), + expected: false, + }, + Case { + name: "not overlap 2", + range: (b"k", b"k0"), + expected: false, + }, + Case { + name: "not overlap 3", + range: (b"k60", b"k70"), + expected: false, + }, + ]; + + for case in cases { + let range = CacheRegion::new(0, 0, case.range.0.to_vec(), case.range.1.to_vec()); + assert_eq!( + range_mgr + .regions_map() + .read() + .overlap_with_manual_load_range(&range), + case.expected, + "{}", + case.name + ); + } + } + + #[test] + fn test_manual_load_range_add_remove() { + struct Case { + name: &'static str, + build: Vec<(&'static [u8], &'static [u8])>, + remove: Vec<(&'static [u8], &'static [u8])>, + add: Vec<(&'static [u8], &'static [u8])>, + result: Vec<(&'static [u8], &'static [u8])>, + } + let cases = [ + Case { + name: "remove empty", + build: vec![], + remove: vec![(b"k00", b"k10")], + add: vec![], + result: vec![], + }, + Case { + name: "add empty", + build: vec![], + remove: vec![], + add: vec![(b"k00", b"k10")], + result: vec![(b"k00", b"k10")], + }, + // Test remove + Case { + name: "remove one range", + build: vec![(b"k00", b"k10"), (b"k20", b"k30"), (b"k40", b"k50")], + remove: vec![(b"k20", b"k30")], + add: vec![], + result: vec![(b"k00", b"k10"), (b"k40", b"k50")], + }, + Case { + name: "remove left intersected ranges", + build: vec![(b"k00", b"k10"), (b"k20", b"k30"), (b"k40", b"k50")], + remove: vec![(b"k", b"k05")], + add: vec![], + result: vec![(b"k05", b"k10"), (b"k20", b"k30"), (b"k40", b"k50")], + }, + Case { + name: "remove left and right intersected ranges", + build: vec![(b"k00", b"k10"), (b"k20", b"k30"), (b"k40", b"k50")], + remove: vec![(b"k05", b"k45")], + add: vec![], + result: vec![(b"k00", b"k05"), (b"k45", b"k50")], + }, + Case { + name: "remove right intersected ranges", + build: vec![(b"k00", b"k10"), (b"k20", b"k30"), (b"k40", b"k50")], + remove: vec![(b"k45", b"k60")], + add: vec![], + result: vec![(b"k00", b"k10"), (b"k20", b"k30"), (b"k40", b"k45")], + }, + // Test add + Case { + name: "add left intersected ranges 1", + build: vec![(b"k00", b"k10"), (b"k20", b"k30")], + add: vec![(b"k", b"k05")], + remove: vec![], + result: vec![(b"k", b"k10"), (b"k20", b"k30")], + }, + Case { + name: "add left intersected ranges 2", + build: vec![(b"k00", b"k10"), (b"k20", b"k30")], + add: vec![(b"k", b"k25")], + remove: vec![], + result: vec![(b"k", b"k30")], + }, + Case { + name: "add right intersected ranges 1", + build: vec![(b"k20", b"k30"), (b"k40", b"k50")], + add: vec![(b"k45", b"k55")], + remove: vec![], + result: vec![(b"k20", b"k30"), (b"k40", b"k55")], + }, + Case { + name: "add right intersected ranges 2", + build: vec![(b"k20", b"k30"), (b"k40", b"k50")], + add: vec![(b"k25", b"k55")], + remove: vec![], + result: vec![(b"k20", b"k55")], + }, + Case { + name: "add left and right intersected ranges 1", + build: vec![(b"k20", b"k30")], + add: vec![(b"k10", b"k50")], + remove: vec![], + result: vec![(b"k10", b"k50")], + }, + Case { + name: "add left and right intersected ranges 2", + build: vec![(b"k10", b"k20"), (b"k20", b"k30")], + add: vec![(b"k10", b"k50")], + remove: vec![], + result: vec![(b"k10", b"k50")], + }, + Case { + name: "add adjacent ranges", + build: vec![(b"k10", b"k20")], + add: vec![(b"k00", b"k10"), (b"k20", b"k30")], + remove: vec![], + result: vec![(b"k00", b"k10"), (b"k10", b"k20"), (b"k20", b"k30")], + }, + ]; + + for case in cases { + // Build + let range_mgr = RegionManager::default(); + for (start, end) in case.build { + let r = CacheRegion::new(0, 0, start.to_vec(), end.to_vec()); + range_mgr.regions_map().write().add_manual_load_range(r); + } + + // Remove + for (start, end) in case.remove { + let r = CacheRegion::new(0, 0, start.to_vec(), end.to_vec()); + range_mgr.regions_map().write().remove_manual_load_range(r); + } + + // Add + for (start, end) in case.add { + let r = CacheRegion::new(0, 0, start.to_vec(), end.to_vec()); + range_mgr.regions_map().write().add_manual_load_range(r); + } + + // Check + let map = range_mgr.regions_map.read(); + assert_eq!( + map.manual_load_range.len(), + case.result.len(), + "case: {}", + case.name + ); + for r in case.result { + assert!( + map.manual_load_range + .iter() + .any(|range| range.start.as_slice() == r.0 && range.end.as_slice() == r.1), + "case: {}", + case.name + ); + } + } + } } diff --git a/components/range_cache_memory_engine/src/region_label.rs b/components/range_cache_memory_engine/src/region_label.rs index 3f842440629..c6e643beb53 100644 --- a/components/range_cache_memory_engine/src/region_label.rs +++ b/components/range_cache_memory_engine/src/region_label.rs @@ -59,12 +59,12 @@ impl TryFrom<&KeyRangeRule> for CacheRegion { Ok(CacheRegion::new(0, 0, start_key, end_key)) } } -pub type RegionLabelAddedCb = Arc; +pub type RegionLabelChangedCallback = Arc; #[derive(Default)] pub struct RegionLabelRulesManager { pub(crate) region_labels: DashMap, - pub(crate) region_label_added_cb: Option, + pub(crate) region_label_change_cb: Option, } impl RegionLabelRulesManager { @@ -72,19 +72,19 @@ impl RegionLabelRulesManager { let old_value = self .region_labels .insert(label_rule.id.clone(), label_rule.clone()); - if let Some(cb) = self.region_label_added_cb.as_ref() { + if let Some(cb) = self.region_label_change_cb.as_ref() { match old_value.as_ref() { // If a watch fires twice on an identical label rule, ignore the second invocation. Some(old_value) if old_value == label_rule => { info!("ime identical region label rule added twice; ignoring."; "rule_id" => &label_rule.id) } - _ => cb(label_rule), + _ => cb(label_rule, true), } } } - #[allow(dead_code)] + #[cfg(test)] pub fn region_labels(&self) -> Vec { self.region_labels .iter() @@ -92,11 +92,14 @@ impl RegionLabelRulesManager { .collect::>() } - pub fn remove_region_label(&self, label_rule_id: &String) { - let _ = self.region_labels.remove(label_rule_id); + pub fn remove_region_label(&self, label_rule: &LabelRule) { + let _ = self.region_labels.remove(&label_rule.id); + if let Some(cb) = self.region_label_change_cb.as_ref() { + cb(label_rule, false); + } } - #[allow(dead_code)] + #[cfg(test)] pub fn get_region_label(&self, label_rule_id: &str) -> Option { self.region_labels .get(label_rule_id) @@ -147,12 +150,6 @@ impl RegionLabelServiceBuilder { } } - #[allow(dead_code)] - pub fn path_suffix(mut self, suffix: String) -> Self { - self.path_suffix = Some(suffix); - self - } - pub fn rule_filter_fn(mut self, rule_filter_fn: F) -> Self where F: Fn(&LabelRule) -> bool + Send + Sync + 'static, @@ -185,7 +182,7 @@ impl RegionLabelService { ) } - fn on_label_rule(&mut self, label_rule: &LabelRule) { + fn on_label_rule_add(&mut self, label_rule: &LabelRule) { let should_add_label = self .rule_filter_fn .as_ref() @@ -194,6 +191,15 @@ impl RegionLabelService { self.manager.add_region_label(label_rule) } } + fn on_label_rule_delete(&mut self, label_rule: &LabelRule) { + let should_remove_label = self + .rule_filter_fn + .as_ref() + .map_or_else(|| true, |r_f_fn| r_f_fn(label_rule)); + if should_remove_label { + self.manager.remove_region_label(label_rule) + } + } pub async fn watch_region_labels(&mut self) { self.reload_all_region_labels().await; 'outer: loop { @@ -218,7 +224,7 @@ impl RegionLabelService { match serde_json::from_slice::( event.get_kv().get_value(), ) { - Ok(label_rule) => self.on_label_rule(&label_rule), + Ok(label_rule) => self.on_label_rule_add(&label_rule), Err(e) => error!("ime parse put region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), } } @@ -226,7 +232,7 @@ impl RegionLabelService { match serde_json::from_slice::( event.get_prev_kv().get_value() ) { - Ok(label_rule) => self.manager.remove_region_label(&label_rule.id), + Ok(label_rule) => self.on_label_rule_delete(&label_rule), Err(e) => error!("ime parse delete region label event failed"; "name" => ?event.get_kv().get_key(), "err" => ?e), } } @@ -263,7 +269,7 @@ impl RegionLabelService { let kvs = resp.take_kvs().into_iter().collect::>(); for g in kvs.iter() { match serde_json::from_slice::(g.get_value()) { - Ok(label_rule) => self.on_label_rule(&label_rule), + Ok(label_rule) => self.on_label_rule_add(&label_rule), Err(e) => { error!("ime parse label rule failed"; "name" => ?g.get_key(), "err" => ?e); diff --git a/components/range_cache_memory_engine/src/write_batch.rs b/components/range_cache_memory_engine/src/write_batch.rs index f88f6db7cbb..b431a4fdaae 100644 --- a/components/range_cache_memory_engine/src/write_batch.rs +++ b/components/range_cache_memory_engine/src/write_batch.rs @@ -679,7 +679,8 @@ mod tests { let r1 = new_region(1, b"k01".to_vec(), b"k05".to_vec()); { // load region with epoch and range change, will remove the pending region. - engine.load_region(r1.clone()).unwrap(); + let cache_r1 = CacheRegion::from_region(&r1); + engine.load_region(cache_r1).unwrap(); let mut r1_new = new_region(1, b"k01".to_vec(), b"k06".to_vec()); r1_new.mut_region_epoch().version = 2; let mut wb = RangeCacheWriteBatch::from(&engine); @@ -705,7 +706,8 @@ mod tests { // epoch changes but new range is contained by the pending region, will update // the region. - engine.load_region(r1.clone()).unwrap(); + let cache_r1 = CacheRegion::from_region(&r1); + engine.load_region(cache_r1).unwrap(); let mut r1_new = new_region(1, b"k01".to_vec(), b"k05".to_vec()); r1_new.mut_region_epoch().version = 2; let cache_r1_new = CacheRegion::from_region(&r1_new); diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 8cb122b0291..6f3c0072815 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -270,13 +270,13 @@ fn test_evict_with_loading_range() { }) .unwrap(); - engine.load_region(r1.clone()).unwrap(); - engine.load_region(r2.clone()).unwrap(); - engine.load_region(r3.clone()).unwrap(); - let cache_region1 = CacheRegion::from_region(&r1); let cache_region2 = CacheRegion::from_region(&r2); let cache_region3 = CacheRegion::from_region(&r3); + engine.load_region(cache_region1.clone()).unwrap(); + engine.load_region(cache_region2.clone()).unwrap(); + engine.load_region(cache_region3.clone()).unwrap(); + let mut wb = engine.write_batch(); // prepare range to trigger loading wb.prepare_for_region(cache_region1.clone()); @@ -329,8 +329,10 @@ fn test_cached_write_batch_cleared_when_load_failed() { // canceled at begin let r1 = new_region(1, b"k00", b"k10"); let r2 = new_region(2, b"k20", b"k30"); - engine.load_region(r1.clone()).unwrap(); - engine.load_region(r2.clone()).unwrap(); + let cache_region1 = CacheRegion::from_region(&r1); + let cache_region2 = CacheRegion::from_region(&r2); + engine.load_region(cache_region1.clone()).unwrap(); + engine.load_region(cache_region2.clone()).unwrap(); let mut wb = engine.write_batch(); // range1 starts to load @@ -409,7 +411,7 @@ fn test_concurrency_between_delete_range_and_write_to_memory() { engine.new_region(r1.clone()); engine.new_region(r2.clone()); - engine.load_region(r3.clone()).unwrap(); + engine.load_region(cache_region3.clone()).unwrap(); let engine_clone = engine.clone(); let (range_prepared_tx, range_prepared_rx) = sync_channel(0); @@ -548,7 +550,8 @@ fn test_double_delete_range_schedule() { engine.new_region(r1.clone()); engine.new_region(r2.clone()); - engine.load_region(r3.clone()).unwrap(); + let cache_region3 = CacheRegion::from_region(&r3); + engine.load_region(cache_region3.clone()).unwrap(); let snap1 = engine .snapshot(CacheRegion::from_region(&r1), 100, 100) @@ -622,7 +625,7 @@ fn test_load_with_gc() { let region = new_region(1, b"", b"z"); let range = CacheRegion::from_region(®ion); - engine.load_region(region.clone()).unwrap(); + engine.load_region(range.clone()).unwrap(); let mut wb = engine.write_batch(); wb.prepare_for_region(range.clone()); wb.set_sequence_number(100).unwrap(); @@ -691,7 +694,7 @@ fn test_region_split_before_batch_loading_start() { ); } - engine.load_region(region.clone()).unwrap(); + engine.load_region(cache_region.clone()).unwrap(); // use write batch to trigger scheduling pending region loading task. let mut wb = engine.write_batch(); diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 283c180461e..0d4a89263aa 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -43,7 +43,7 @@ use grpcio::{EnvBuilder, Environment}; use health_controller::HealthController; use hybrid_engine::{ observer::{ - EvictionObserver as HybridEngineObserver, HybridSnapshotObserver, + HybridSnapshotObserver, LoadEvictionObserver as HybridEngineLoadEvictionObserver, RegionCacheWriteBatchObserver, }, HybridEngine, @@ -1654,7 +1654,8 @@ where ); // Hybrid engine observer. - let eviction_observer = HybridEngineObserver::new(Arc::new(in_memory_engine.clone())); + let eviction_observer = + HybridEngineLoadEvictionObserver::new(Arc::new(in_memory_engine.clone())); eviction_observer.register_to(self.coprocessor_host.as_mut().unwrap()); let write_batch_observer = RegionCacheWriteBatchObserver::new(in_memory_engine.range_cache_engine().clone()); diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index 343e5e13281..a1d8be1e9f7 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -21,7 +21,7 @@ use futures::executor::block_on; use grpcio::{ChannelBuilder, EnvBuilder, Environment, Error as GrpcError, Service}; use health_controller::HealthController; use hybrid_engine::observer::{ - EvictionObserver, HybridSnapshotObserver, RegionCacheWriteBatchObserver, + HybridSnapshotObserver, LoadEvictionObserver, RegionCacheWriteBatchObserver, }; use kvproto::{ deadlock::create_deadlock, @@ -342,7 +342,7 @@ impl ServerCluster { Some(Arc::new(region_info_accessor.clone())), ); // Eviction observer - let observer = EvictionObserver::new(Arc::new(in_memory_engine.clone())); + let observer = LoadEvictionObserver::new(Arc::new(in_memory_engine.clone())); observer.register_to(&mut coprocessor_host); // Write batch observer let write_batch_observer = diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index b9517c0549b..d57aa25eb63 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -23,6 +23,7 @@ use test_raftstore::{ get_tso, new_peer, new_server_cluster_with_hybrid_engine_with_no_range_cache, Cluster, ServerCluster, }; +use test_util::eventually; use tikv_util::{mpsc::unbounded, HandyRwLock}; use tipb::SelectResponse; use txn_types::Key; @@ -524,6 +525,47 @@ fn test_eviction_after_merge() { range_cache_engine.snapshot(range2, 100, 100).unwrap_err(); } +#[test] +fn test_manual_load_range_after_transfer_leader() { + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 2); + cluster.run(); + + let r = cluster.get_region(b""); + cluster.must_transfer_leader(r.id, new_peer(1, 1)); + + // Set manual load range on store 2. + let cache_range = CacheRegion::new( + r.id, + r.get_region_epoch().version, + DATA_MIN_KEY.to_vec(), + DATA_MAX_KEY.to_vec(), + ); + let range_cache_engine = { + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(2); + range_cache_engine + .core() + .region_manager() + .regions_map() + .write() + .add_manual_load_range(cache_range.clone()); + range_cache_engine + }; + + range_cache_engine + .snapshot(cache_range.clone(), 100, 100) + .unwrap_err(); + + // For region in manual load range, it must load cache automatically after + // leader transfer. + cluster.must_transfer_leader(r.id, new_peer(2, 2)); + + eventually(Duration::from_millis(100), Duration::from_secs(5), || { + range_cache_engine + .snapshot(cache_range.clone(), 100, 100) + .is_ok() + }); +} + #[test] fn test_eviction_after_ingest_sst() { let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 1); From 7c612787d0bfc57a339907ebcb26777dc296fd5f Mon Sep 17 00:00:00 2001 From: Bisheng Huang Date: Sat, 14 Sep 2024 18:23:35 +0800 Subject: [PATCH 068/144] raftstore: fix panic due to stale peer handling snapshot (#17535) close tikv/tikv#17469 The commit fixes a panic in TiKV that occurs in a rare scenario that involves region splits and immediate removal of the new peer. When a region splits, the new peer on a follower can be created in two ways: (1) By receiving a Raft message from the new region (`fn maybe_create_peer`) (2) By applying the split operation locally (`fn on_ready_split_region`). Depending on timing, a new peer might first be created by a Raft message and then again when the split is applied. This is a known situation. When it happens, the second peer replaces the first, and the first peer is dicarded. However, the discarded peer may continue processing existing messages, leading to unexpected states. The panic can be reproduced with the following sequence of events: 1. The first peer is created by a Raft message and is waiting for a Raft snapshot. 2. The second peer (of the same reason) is created by `on_ready_split_region` when the split operation is applied, replacing the first peer and closing its mailbox (as expected). 3. The second peer is immediately removed (a rare situation). This removes the region metadata. 4. The first peer continues processing the Raft snapshot message, expecting the metadata of the region to exist, causing the panic. Signed-off-by: Bisheng Huang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/raftstore/src/store/fsm/peer.rs | 50 ++++++++- tests/failpoints/cases/test_split_region.rs | 109 ++++++++++++++++++++ 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/components/raftstore/src/store/fsm/peer.rs b/components/raftstore/src/store/fsm/peer.rs index 4131dcae60e..930c40cd9b2 100644 --- a/components/raftstore/src/store/fsm/peer.rs +++ b/components/raftstore/src/store/fsm/peer.rs @@ -2645,13 +2645,40 @@ where "is_initialized_peer" => is_initialized_peer, ); + let msg_type = msg.get_message().get_msg_type(); + let fp_enable = |target_msg_type: MessageType| -> bool { + self.fsm.region_id() == 1000 + && self.store_id() == 2 + && !is_initialized_peer + && msg_type == target_msg_type + }; + fail_point!( + "on_snap_msg_1000_2", + fp_enable(MessageType::MsgSnapshot), + |_| Ok(()) + ); + fail_point!( + "on_vote_msg_1000_2", + fp_enable(MessageType::MsgRequestVote), + |_| Ok(()) + ); + fail_point!( + "on_append_msg_1000_2", + fp_enable(MessageType::MsgAppend), + |_| Ok(()) + ); + fail_point!( + "on_heartbeat_msg_1000_2", + fp_enable(MessageType::MsgHeartbeat), + |_| Ok(()) + ); + if self.fsm.peer.pending_remove || self.fsm.stopped { return Ok(()); } self.handle_reported_disk_usage(&msg); - let msg_type = msg.get_message().get_msg_type(); if matches!(self.ctx.self_disk_usage, DiskUsage::AlreadyFull) && MessageType::MsgTimeoutNow == msg_type { @@ -3436,7 +3463,24 @@ where } let mut meta = self.ctx.store_meta.lock().unwrap(); - if meta.regions[&self.region_id()] != *self.region() { + // Check if the region matches the metadata. A mismatch means another + // peer has replaced the current peer, which can happen during a split: a + // peer is first created via raft message, then replaced by another peer + // (of the same region) when the split is applied. + let region_mismatch = match meta.regions.get(&self.region_id()) { + Some(region) => *region != *self.region(), + None => { + // If the region doesn't exist, treat it as a mismatch. This can + // happen in rare situations (e.g. #17469). + warn!( + "region not found in meta"; + "region_id" => self.fsm.region_id(), + "peer_id" => self.fsm.peer_id(), + ); + true + } + }; + if region_mismatch { if !self.fsm.peer.is_initialized() { info!( "stale delegate detected, skip"; @@ -3450,7 +3494,7 @@ where panic!( "{} meta corrupted: {:?} != {:?}", self.fsm.peer.tag, - meta.regions[&self.region_id()], + meta.regions.get(&self.region_id()), self.region() ); } diff --git a/tests/failpoints/cases/test_split_region.rs b/tests/failpoints/cases/test_split_region.rs index 6a1b135ecb6..02911a942da 100644 --- a/tests/failpoints/cases/test_split_region.rs +++ b/tests/failpoints/cases/test_split_region.rs @@ -552,6 +552,115 @@ fn test_split_not_to_split_existing_tombstone_region() { must_get_equal(&cluster.get_engine(2), b"k1", b"v1"); } +#[test] +fn test_stale_peer_handle_snap() { + test_stale_peer_handle_raft_msg("on_snap_msg_1000_2"); +} + +#[test] +fn test_stale_peer_handle_vote() { + test_stale_peer_handle_raft_msg("on_vote_msg_1000_2"); +} + +#[test] +fn test_stale_peer_handle_append() { + test_stale_peer_handle_raft_msg("on_append_msg_1000_2"); +} + +#[test] +fn test_stale_peer_handle_heartbeat() { + test_stale_peer_handle_raft_msg("on_heartbeat_msg_1000_2"); +} + +fn test_stale_peer_handle_raft_msg(on_handle_raft_msg_1000_2_fp: &str) { + // The following diagram represents the final state of the test: + // + // ┌───────────┐ ┌───────────┐ ┌───────────┐ + // │ │ │ │ │ │ + // Region 1 │ Peer 1 │ │ Peer 2 │ │ Peer 3 │ + // [k2, +∞) │ │ │ │ │ │ + // ───────────────────┼───────────┼──┼───────────┼──┼───────────┼── + // │ │ │ │ │ │ + // Region 1000 │ Peer 1001 │ │ Peer 1003 │ │ Peer 1002 │ + // (-∞, k2) │ │ │ │ │ │ + // └───────────┘ └───────────┘ └───────────┘ + // Store 1 Store 2 Store 3 + // + // In this test, there is a split operation and Peer 1003 will be created + // twice (by raft message and by split). The new Peer 1003 will replace the + // old Peer 1003 and but it will be immediately removed. This test verifies + // that TiKV would not panic if the old Peer 1003 continues to process a + // remaining raft message (which may be a snapshot/vote/heartbeat/append + // message). + + let mut cluster = new_node_cluster(0, 3); + configure_for_merge(&mut cluster.cfg); + cluster.cfg.raft_store.right_derive_when_split = true; + cluster.cfg.raft_store.store_batch_system.max_batch_size = Some(1); + cluster.cfg.raft_store.store_batch_system.pool_size = 2; + cluster.cfg.raft_store.apply_batch_system.max_batch_size = Some(1); + cluster.cfg.raft_store.apply_batch_system.pool_size = 2; + let pd_client = Arc::clone(&cluster.pd_client); + pd_client.disable_default_operator(); + + fail::cfg("on_raft_gc_log_tick", "return()").unwrap(); + let r1 = cluster.run_conf_change(); + // Add Peer 3 + pd_client.must_add_peer(r1, new_peer(3, 3)); + assert_eq!(r1, 1); + + // Pause the snapshot apply of Peer 2. + let before_check_snapshot_1_2_fp = "before_check_snapshot_1_2"; + fail::cfg(before_check_snapshot_1_2_fp, "pause").unwrap(); + + // Add Peer 2. The peer will be created but stuck at applying snapshot due + // to the failpoint above. + pd_client.must_add_peer(r1, new_peer(2, 2)); + cluster.must_put(b"k1", b"v1"); + + // Before the split, pause Peer 1003 when processing a certain raft message. + // The message type depends on the failpoint name input. + fail::cfg(on_handle_raft_msg_1000_2_fp, "pause").unwrap(); + + // Split the region into Region 1 and Region 1000. Peer 1003 will be created + // for the first time when it receives a raft message from Peer 1001, but it + // will remain uninitialized because it's paused due to the failpoint above. + let region = pd_client.get_region(b"k1").unwrap(); + + cluster.must_split(®ion, b"k2"); + cluster.must_put(b"k22", b"v22"); + + // Check that Store 2 doesn't have any data yet. + must_get_none(&cluster.get_engine(2), b"k1"); + must_get_none(&cluster.get_engine(2), b"k22"); + + // Unblock Peer 2. It will proceed to apply the split operation, which + // creates Peer 1003 for the second time and replaces the old Peer 1003. + fail::remove(before_check_snapshot_1_2_fp); + + // Verify that data can be accessed from Peer 2 and the new Peer 1003. + must_get_equal(&cluster.get_engine(2), b"k1", b"v1"); + must_get_equal(&cluster.get_engine(2), b"k22", b"v22"); + + // Immediately remove the new Peer 1003. This removes the region metadata. + let left = pd_client.get_region(b"k1").unwrap(); + let left_peer_2 = find_peer(&left, 2).cloned().unwrap(); + pd_client.must_remove_peer(left.get_id(), left_peer_2); + must_get_none(&cluster.get_engine(2), b"k1"); + must_get_equal(&cluster.get_engine(2), b"k22", b"v22"); + + // Unblock the old Peer 1003 so that it can continue to process its raft + // message. It would lead to a panic when it processes a snapshot message if + // #17469 is not fixed. + fail::remove(on_handle_raft_msg_1000_2_fp); + + // Waiting for the stale peer to handle its raft message. + sleep_ms(300); + + must_get_none(&cluster.get_engine(2), b"k1"); + must_get_equal(&cluster.get_engine(2), b"k22", b"v22"); +} + // TiKV uses memory lock to control the order between spliting and creating // new peer. This case test if tikv continues split if the peer is destroyed // after memory lock check. From d2bf2b0510d17bfe5cefab67a074bc7d564b8906 Mon Sep 17 00:00:00 2001 From: glorv Date: Wed, 18 Sep 2024 13:58:54 +0800 Subject: [PATCH 069/144] In-memory Engine: fix panic that new region has the same id with evicting region (#17550) close tikv/tikv#17487, close tikv/tikv#17493, close tikv/tikv#17548 Fix the bug that in-memory-engine may panic when load new region whose id is the same with a cached region that is being evicted. This can happen when a region is evicted by region merge, and the merged region is split and then load again while the cached region is still in evicting state. Signed-off-by: glorv --- .../engine_traits/src/range_cache_engine.rs | 2 +- .../src/range_manager.rs | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index 6d51615e8fb..e2a2017536e 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -114,7 +114,7 @@ pub struct CacheRegion { pub epoch_version: u64, // data start key of the region range, equals to data_key(region.start_key). pub start: Vec, - // data start key of the region range, equals to data_end_key(region.start_key). + // data end key of the region range, equals to data_end_key(region.end_key). pub end: Vec, } diff --git a/components/range_cache_memory_engine/src/range_manager.rs b/components/range_cache_memory_engine/src/range_manager.rs index 4169095a2f2..b968af2e046 100644 --- a/components/range_cache_memory_engine/src/range_manager.rs +++ b/components/range_cache_memory_engine/src/range_manager.rs @@ -291,8 +291,10 @@ impl RegionMetaMap { assert!(!self.overlaps_with(&meta.region)); let id = meta.region.id; let data_end_key = meta.region.end.clone(); - self.regions.insert(id, meta); - self.regions_by_range.insert(data_end_key, id); + let old_meta = self.regions.insert(id, meta); + assert!(old_meta.is_none(), "old_meta: {:?}", old_meta.unwrap()); + let old_id = self.regions_by_range.insert(data_end_key, id); + assert!(old_id.is_none(), "old_region_id: {}", old_id.unwrap()); if self.regions.len() == 1 { assert!(!self.is_active.load(Ordering::Relaxed)); self.is_active.store(true, Ordering::Relaxed); @@ -312,6 +314,7 @@ impl RegionMetaMap { }; return Err(reason); } + info!("ime load new region"; "region" => ?cache_region); let meta = CacheRegionMeta::new(cache_region); self.new_region_meta(meta); Ok(()) @@ -376,7 +379,24 @@ impl RegionMetaMap { for id in removed_regions { self.remove_region(id); } - overlapped_region_state + if overlapped_region_state.is_some() { + return overlapped_region_state; + } + + // check region with same id. It is possible that there is a cached region with + // outdated epoch that is still in the (pending_)evicting state, and a new load + // is triggered after the region is merged and split for multiple times. + // Thus, the new pending region's range may not overlap with the old + // cached region but their region ids are the same. + // While in theory we should keep the new region as it doesn't overlap with any + // other region, but because we use region_id as the unique identifier, we do + // not load it for implementation simplicity as this kind of scenario + // should be very rare. + if let Some(region) = self.regions.get(®ion.id) { + return Some(region.state); + } + + None } fn on_all_overlapped_regions(&self, region: &CacheRegion, mut f: impl FnMut(&CacheRegionMeta)) { @@ -913,6 +933,7 @@ impl RegionManager { for r in regions { let meta = regions_map.remove_region(r.id); assert_eq!(meta.region.epoch_version, r.epoch_version); + info!("ime remove evicted region"; "meta" => ?meta); let evict_info = meta.evict_info.unwrap(); observe_eviction_duration( @@ -1187,6 +1208,13 @@ mod tests { range_mgr.load_region(r).unwrap_err(), LoadFailedReason::PendingRange ); + + // test range overlap but id overlap + let r = CacheRegion::new(1, 2, b"k20", b"k30"); + assert_eq!( + range_mgr.load_region(r).unwrap_err(), + LoadFailedReason::Evicting + ); } #[test] From 12e03b787c621d822fa14dc6abc0feb3c0fe1bbd Mon Sep 17 00:00:00 2001 From: lucasliang Date: Wed, 18 Sep 2024 23:13:58 +0800 Subject: [PATCH 070/144] raftstore: directly write kvs rafther than ingestion when merging small regions. (#17408) close tikv/tikv#17412 Previously, snapshots of regions, with the exception of the `lock_cf` column family, were flushed to SST files, while `lock_cf` was flushed to plain files. This approach could lead to a high volume of `ingest` tasks for merging regions, especially when the TiKV node contained a large number of small-sized regions. As we all know, an excess of `ingest` tasks can significantly impair the overall performance of the TiKV node. To address this issue, this pull request introduces a new configuration option called `snap_min_ingest_size`. When a region's size is below the threshold set by `snap_min_ingest_size`, its corresponding snapshot will now be applied without `ingest` SST files. This change is expected to reduce the frequency of ingest tasks and thereby enhance the TiKV node's processing efficiency. Signed-off-by: lucasliang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/pd_client/src/util.rs | 9 +- components/raftstore/src/store/fsm/peer.rs | 14 ++- components/raftstore/src/store/mod.rs | 2 +- components/raftstore/src/store/peer.rs | 24 ++++- components/raftstore/src/store/snap.rs | 73 +++++++++++--- components/raftstore/src/store/snap/io.rs | 111 +++++++++++++++++++-- components/server/src/server.rs | 1 + components/test_raftstore/src/node.rs | 1 + components/test_raftstore/src/server.rs | 1 + src/server/config.rs | 5 + src/server/snap.rs | 10 +- tests/integrations/raftstore/test_snap.rs | 73 ++++++++++++++ tests/integrations/storage/test_titan.rs | 8 +- 13 files changed, 287 insertions(+), 45 deletions(-) diff --git a/components/pd_client/src/util.rs b/components/pd_client/src/util.rs index e0de84b3b01..1ac1d80321b 100644 --- a/components/pd_client/src/util.rs +++ b/components/pd_client/src/util.rs @@ -732,10 +732,11 @@ impl PdConnector { // There are 3 kinds of situations we will return the new client: // 1. the force is true which represents the client is newly created or the - // original connection has some problem 2. the previous forwarded host is - // not empty and it can connect the leader now which represents the network - // partition problem to leader may be recovered 3. the member information of - // PD has been changed + // original connection has some problem. + // 2. the previous forwarded host is not empty and it can connect the leader + // now which represents the network partition problem to leader may be + // recovered. + // 3. the member information of PD has been changed. pub async fn reconnect_pd( &self, members_resp: GetMembersResponse, diff --git a/components/raftstore/src/store/fsm/peer.rs b/components/raftstore/src/store/fsm/peer.rs index 930c40cd9b2..92863fe13ba 100644 --- a/components/raftstore/src/store/fsm/peer.rs +++ b/components/raftstore/src/store/fsm/peer.rs @@ -4387,14 +4387,12 @@ where share_size = self .fsm .peer - .split_check_trigger - .approximate_size + .approximate_size() .map(|v| v / new_region_count); share_keys = self .fsm .peer - .split_check_trigger - .approximate_keys + .approximate_keys() .map(|v| v / new_region_count); } @@ -4410,8 +4408,8 @@ where let is_leader = self.fsm.peer.is_leader(); if is_leader { if share_source_region_size { - self.fsm.peer.split_check_trigger.approximate_size = share_size; - self.fsm.peer.split_check_trigger.approximate_keys = share_keys; + self.fsm.peer.set_approximate_size(share_size); + self.fsm.peer.set_approximate_keys(share_keys); } self.fsm.peer.heartbeat_pd(self.ctx); // Notify pd immediately to let it update the region meta. @@ -4546,8 +4544,8 @@ where new_peer.has_ready |= campaigned; if is_leader { - new_peer.peer.split_check_trigger.approximate_size = share_size; - new_peer.peer.split_check_trigger.approximate_keys = share_keys; + new_peer.peer.set_approximate_size(share_size); + new_peer.peer.set_approximate_keys(share_keys); *new_peer.peer.txn_ext.pessimistic_locks.write() = locks; // The new peer is likely to become leader, send a heartbeat immediately to // reduce client query miss. diff --git a/components/raftstore/src/store/mod.rs b/components/raftstore/src/store/mod.rs index 971c9038594..2c1f69d8eb4 100644 --- a/components/raftstore/src/store/mod.rs +++ b/components/raftstore/src/store/mod.rs @@ -71,7 +71,7 @@ pub use self::{ replication_mode::{GlobalReplicationState, StoreGroup}, snap::{ check_abort, copy_snapshot, - snap_io::{apply_sst_cf_file, build_sst_cf_file_list}, + snap_io::{apply_sst_cf_files_by_ingest, build_sst_cf_file_list}, ApplyOptions, CfFile, Error as SnapError, SnapEntry, SnapKey, SnapManager, SnapManagerBuilder, Snapshot, SnapshotStatistics, TabletSnapKey, TabletSnapManager, }, diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index c63627ed7a3..b22b3c2ad2d 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -1700,6 +1700,26 @@ where self.raft_group.mut_store() } + #[inline] + pub fn approximate_size(&self) -> Option { + self.split_check_trigger.approximate_size + } + + #[inline] + pub fn approximate_keys(&self) -> Option { + self.split_check_trigger.approximate_keys + } + + #[inline] + pub fn set_approximate_size(&mut self, approximate_size: Option) { + self.split_check_trigger.approximate_size = approximate_size; + } + + #[inline] + pub fn set_approximate_keys(&mut self, approximate_keys: Option) { + self.split_check_trigger.approximate_keys = approximate_keys; + } + /// Whether the snapshot is handling. /// See the comments of `check_snap_status` for more details. #[inline] @@ -5579,8 +5599,8 @@ where pending_peers: self.collect_pending_peers(ctx), written_bytes: self.peer_stat.written_bytes, written_keys: self.peer_stat.written_keys, - approximate_size: self.split_check_trigger.approximate_size, - approximate_keys: self.split_check_trigger.approximate_keys, + approximate_size: self.approximate_size(), + approximate_keys: self.approximate_keys(), replication_status: self.region_replication_status(ctx), wait_data_peers: self.wait_data_peers.clone(), }); diff --git a/components/raftstore/src/store/snap.rs b/components/raftstore/src/store/snap.rs index f19b730e55f..60e4b3ae2ed 100644 --- a/components/raftstore/src/store/snap.rs +++ b/components/raftstore/src/store/snap.rs @@ -37,7 +37,9 @@ use protobuf::Message; use raft::eraftpb::Snapshot as RaftSnapshot; use thiserror::Error; use tikv_util::{ - box_err, box_try, debug, error, info, + box_err, box_try, + config::ReadableSize, + debug, error, info, time::{duration_to_sec, Instant, Limiter, UnixSecs}, warn, HandyRwLock, }; @@ -1110,6 +1112,9 @@ impl Snapshot { } pub fn apply(&mut self, options: ApplyOptions) -> Result<()> { + let apply_without_ingest = self + .mgr + .can_apply_cf_without_ingest(self.total_size(), self.total_count()); let post_check = |cf_file: &CfFile, offset: usize| { if !plain_file_used(cf_file.cf) { let file_paths = cf_file.file_paths(); @@ -1136,27 +1141,27 @@ impl Snapshot { let abort_checker = ApplyAbortChecker(options.abort); let coprocessor_host = options.coprocessor_host; let region = options.region; - let key_mgr = self.mgr.encryption_key_manager.as_ref(); + let key_mgr = self.mgr.encryption_key_manager.clone(); + let batch_size = options.write_batch_size; for cf_file in &mut self.cf_files { if cf_file.size.is_empty() { // Skip empty cf file. continue; } let cf = cf_file.cf; + let mut cb = |kv: &[(Vec, Vec)]| { + coprocessor_host.post_apply_plain_kvs_from_snapshot(®ion, cf, kv) + }; if plain_file_used(cf_file.cf) { let path = &cf_file.file_paths()[0]; - let batch_size = options.write_batch_size; - let cb = |kv: &[(Vec, Vec)]| { - coprocessor_host.post_apply_plain_kvs_from_snapshot(®ion, cf, kv) - }; snap_io::apply_plain_cf_file( path, - key_mgr, + key_mgr.as_ref(), &abort_checker, &options.db, cf, batch_size, - cb, + &mut cb, )?; } else { let path = cf_file.path.to_str().unwrap(); // path is not used at all @@ -1165,8 +1170,22 @@ impl Snapshot { .iter() .map(|s| s.as_str()) .collect::>(); - snap_io::apply_sst_cf_file(clone_files.as_slice(), &options.db, cf)?; - coprocessor_host.post_apply_sst_from_snapshot(®ion, cf, path); + if apply_without_ingest { + // Apply the snapshot without ingest, to accelerate the applying process. + snap_io::apply_sst_cf_files_without_ingest( + clone_files.as_slice(), + &options.db, + cf, + key_mgr.clone(), + &abort_checker, + batch_size, + &mut cb, + )?; + } else { + // Apply the snapshot by ingest. + snap_io::apply_sst_cf_files_by_ingest(clone_files.as_slice(), &options.db, cf)?; + coprocessor_host.post_apply_sst_from_snapshot(®ion, cf, path); + } } } Ok(()) @@ -1440,6 +1459,9 @@ struct SnapManagerCore { max_per_file_size: Arc, enable_multi_snapshot_files: Arc, stats: Arc>>, + // Minimal column family size & kv counts for applying by ingest. + min_ingest_cf_size: u64, + min_ingest_cf_kvs: u64, } /// `SnapManagerCore` trace all current processing snapshots. @@ -1773,6 +1795,11 @@ impl SnapManager { self.core.recv_concurrency_limiter.set_limit(limit); } + pub fn set_min_ingest_cf_limit(&mut self, bytes: ReadableSize) { + self.core.min_ingest_cf_size = bytes.0; + self.core.min_ingest_cf_kvs = std::cmp::max(10000, (bytes.as_mb_f64() * 10000.0) as u64); + } + pub fn collect_stat(&self, snap: SnapshotStat) { debug!( "collect snapshot stat"; @@ -1995,6 +2022,16 @@ impl SnapManagerCore { } u64::MAX } + + pub fn can_apply_cf_without_ingest(&self, cf_size: u64, cf_kvs: u64) -> bool { + if self.min_ingest_cf_size == 0 { + return false; + } + // If the size and the count of keys of cf are relatively small, it's + // recommended to directly write it into kvdb rather than ingest, + // for mitigating performance issue when ingesting snapshot. + cf_size <= self.min_ingest_cf_size && cf_kvs <= self.min_ingest_cf_kvs + } } /// `SnapRecvConcurrencyLimiter` enforces a limit on the number of simultaneous @@ -2100,6 +2137,8 @@ pub struct SnapManagerBuilder { enable_receive_tablet_snapshot: bool, key_manager: Option>, concurrent_recv_snap_limit: usize, + min_ingest_snapshot_size: u64, + min_ingest_snapshot_kvs: u64, } impl SnapManagerBuilder { @@ -2132,6 +2171,13 @@ impl SnapManagerBuilder { self.enable_receive_tablet_snapshot = enabled; self } + pub fn min_ingest_snapshot_limit(mut self, bytes: ReadableSize) -> SnapManagerBuilder { + self.min_ingest_snapshot_size = bytes.0; + // Keeps the same assumptions in region size, "Assume the average size of KVs is + // 100B". So, it calculate the count of kvs with `bytes / `MiB` * 10000`. + self.min_ingest_snapshot_kvs = std::cmp::max(10000, (bytes.as_mb_f64() * 10000.0) as u64); + self + } #[must_use] pub fn encryption_key_manager(mut self, m: Option>) -> SnapManagerBuilder { self.key_manager = m; @@ -2174,6 +2220,8 @@ impl SnapManagerBuilder { self.enable_multi_snapshot_files, )), stats: Default::default(), + min_ingest_cf_size: self.min_ingest_snapshot_size, + min_ingest_cf_kvs: self.min_ingest_snapshot_kvs, }, max_total_size: Arc::new(AtomicU64::new(max_total_size)), tablet_snap_manager, @@ -2482,9 +2530,6 @@ pub mod tests { use tikv_util::time::Limiter; use super::*; - // ApplyOptions, SnapEntry, SnapKey, SnapManager, SnapManagerBuilder, SnapManagerCore, - // Snapshot, SnapshotStatistics, META_FILE_SUFFIX, SNAPSHOT_CFS, SNAP_GEN_PREFIX, - // }; use crate::{ coprocessor::CoprocessorHost, store::{peer_storage::JOB_STATUS_RUNNING, INIT_EPOCH_CONF_VER, INIT_EPOCH_VER}, @@ -2664,6 +2709,8 @@ pub mod tests { max_per_file_size: Arc::new(AtomicU64::new(max_per_file_size)), enable_multi_snapshot_files: Arc::new(AtomicBool::new(true)), stats: Default::default(), + min_ingest_cf_size: 0, + min_ingest_cf_kvs: 0, } } diff --git a/components/raftstore/src/store/snap/io.rs b/components/raftstore/src/store/snap/io.rs index ad2c687c9fa..3460adc8672 100644 --- a/components/raftstore/src/store/snap/io.rs +++ b/components/raftstore/src/store/snap/io.rs @@ -9,8 +9,8 @@ use std::{ use encryption::{DataKeyManager, DecrypterReader, EncrypterWriter, Iv}; use engine_traits::{ - CfName, Error as EngineError, Iterable, KvEngine, Mutable, SstCompressionType, SstReader, - SstWriter, SstWriterBuilder, WriteBatch, + CfName, Error as EngineError, IterOptions, Iterable, Iterator, KvEngine, Mutable, RefIterable, + SstCompressionType, SstReader, SstWriter, SstWriterBuilder, WriteBatch, }; use fail::fail_point; use file_system::{File, OpenOptions}; @@ -245,7 +245,7 @@ pub fn apply_plain_cf_file( db: &E, cf: &str, batch_size: usize, - mut callback: F, + callback: &mut F, ) -> Result<(), Error> where E: KvEngine, @@ -295,13 +295,13 @@ where } } -pub fn apply_sst_cf_file(files: &[&str], db: &E, cf: &str) -> Result<(), Error> +pub fn apply_sst_cf_files_by_ingest(files: &[&str], db: &E, cf: &str) -> Result<(), Error> where E: KvEngine, { if files.len() > 1 { info!( - "apply_sst_cf_file starts on cf {}. All files {:?}", + "apply_sst_cf_files_by_ingest starts on cf {}. All files {:?}", cf, files ); } @@ -309,6 +309,87 @@ where Ok(()) } +fn apply_sst_cf_file_without_ingest( + path: &str, + db: &E, + cf: &str, + key_mgr: Option>, + stale_detector: &impl StaleDetector, + batch_size: usize, + callback: &mut F, +) -> Result<(), Error> +where + E: KvEngine, + F: for<'r> FnMut(&'r [(Vec, Vec)]), +{ + let sst_reader = E::SstReader::open(path, key_mgr)?; + let mut iter = sst_reader.iter(IterOptions::default())?; + iter.seek_to_first()?; + + let mut wb = db.write_batch(); + let mut write_to_db = |batch: &mut Vec<(Vec, Vec)>| -> Result<(), EngineError> { + batch.iter().try_for_each(|(k, v)| wb.put_cf(cf, k, v))?; + wb.write()?; + wb.clear(); + callback(batch); + batch.clear(); + Ok(()) + }; + + // Collect keys to a vec rather than wb so that we can invoke the callback less + // times. + let mut batch = Vec::with_capacity(1024); + let mut batch_data_size = 0; + loop { + if stale_detector.is_stale() { + return Err(Error::Abort); + } + if !iter.valid()? { + break; + } + let key = iter.key().to_vec(); + let value = iter.value().to_vec(); + batch_data_size += key.len() + value.len(); + batch.push((key, value)); + if batch_data_size >= batch_size { + box_try!(write_to_db(&mut batch)); + batch_data_size = 0; + } + iter.next()?; + } + if !batch.is_empty() { + box_try!(write_to_db(&mut batch)); + } + Ok(()) +} + +pub fn apply_sst_cf_files_without_ingest( + files: &[&str], + db: &E, + cf: &str, + key_mgr: Option>, + stale_detector: &impl StaleDetector, + batch_size: usize, + callback: &mut F, +) -> Result<(), Error> +where + E: KvEngine, + F: for<'r> FnMut(&'r [(Vec, Vec)]), +{ + for path in files { + box_try!(apply_sst_cf_file_without_ingest( + path, + db, + cf, + key_mgr.clone(), + stale_detector, + batch_size, + callback + )); + } + Ok(()) +} + fn create_sst_file_writer(engine: &E, cf: CfName, path: &str) -> Result where E: KvEngine, @@ -406,11 +487,19 @@ mod tests { let detector = TestStaleDetector {}; let tmp_file_path = &cf_file.tmp_file_paths()[0]; - apply_plain_cf_file(tmp_file_path, None, &detector, &db1, cf, 16, |v| { - v.iter() - .cloned() - .for_each(|pair| applied_keys.entry(cf).or_default().push(pair)) - }) + apply_plain_cf_file( + tmp_file_path, + None, + &detector, + &db1, + cf, + 16, + &mut |v: &[(Vec, Vec)]| { + v.iter() + .cloned() + .for_each(|pair| applied_keys.entry(cf).or_default().push(pair)) + }, + ) .unwrap(); } @@ -498,7 +587,7 @@ mod tests { .iter() .map(|s| s.as_str()) .collect::>(); - apply_sst_cf_file(&tmp_file_paths, &db1, CF_DEFAULT).unwrap(); + apply_sst_cf_files_by_ingest(&tmp_file_paths, &db1, CF_DEFAULT).unwrap(); assert_eq_db(&db, &db1); } } diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 0d4a89263aa..8a377366f72 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -751,6 +751,7 @@ where .enable_receive_tablet_snapshot( self.core.config.raft_store.enable_v2_compatible_learner, ) + .min_ingest_snapshot_limit(self.core.config.server.snap_min_ingest_size) .build(snap_path); // Create coprocessor endpoint. diff --git a/components/test_raftstore/src/node.rs b/components/test_raftstore/src/node.rs index 620d1420ef9..f52efd23dce 100644 --- a/components/test_raftstore/src/node.rs +++ b/components/test_raftstore/src/node.rs @@ -286,6 +286,7 @@ impl Simulator for NodeCluster { .max_per_file_size(cfg.raft_store.max_snapshot_file_raw_size.0) .enable_multi_snapshot_files(true) .enable_receive_tablet_snapshot(cfg.raft_store.enable_v2_compatible_learner) + .min_ingest_snapshot_limit(cfg.server.snap_min_ingest_size) .build(tmp.path().to_str().unwrap()); (snap_mgr, Some(tmp)) } else { diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index a1d8be1e9f7..32e9a5bcc50 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -522,6 +522,7 @@ impl ServerCluster { .max_per_file_size(cfg.raft_store.max_snapshot_file_raw_size.0) .enable_multi_snapshot_files(true) .enable_receive_tablet_snapshot(cfg.raft_store.enable_v2_compatible_learner) + .min_ingest_snapshot_limit(cfg.server.snap_min_ingest_size) .build(tmp_str); self.snap_mgrs.insert(node_id, snap_mgr.clone()); let server_cfg = Arc::new(VersionTrack::new(cfg.server.clone())); diff --git a/src/server/config.rs b/src/server/config.rs index 1f7832799fa..0e54626f63d 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -173,6 +173,10 @@ pub struct Config { #[serde(alias = "snap-max-write-bytes-per-sec")] pub snap_io_max_bytes_per_sec: ReadableSize, pub snap_max_total_size: ReadableSize, + /// Minimal size of snapshot for applying with ingestion. + /// If the size of snapshot is smaller than this value, it will be applied + /// without ingestion, just bulk write kvs to kvdb. + pub snap_min_ingest_size: ReadableSize, #[online_config(skip)] pub stats_concurrency: usize, #[online_config(skip)] @@ -284,6 +288,7 @@ impl Default for Config { end_point_memory_quota: *DEFAULT_ENDPOINT_MEMORY_QUOTA, snap_io_max_bytes_per_sec: ReadableSize(DEFAULT_SNAP_MAX_BYTES_PER_SEC), snap_max_total_size: ReadableSize(0), + snap_min_ingest_size: ReadableSize::mb(2), stats_concurrency: 1, // 75 means a gRPC thread is under heavy load if its total CPU usage // is greater than 75%. diff --git a/src/server/snap.rs b/src/server/snap.rs index 3db888da843..0238bd2ef75 100644 --- a/src/server/snap.rs +++ b/src/server/snap.rs @@ -477,9 +477,13 @@ impl Runner { }; self.snap_mgr.set_speed_limit(limit); self.snap_mgr.set_max_total_snap_size(max_total_size); - info!("refresh snapshot manager config"; - "speed_limit"=> limit, - "max_total_snap_size"=> max_total_size); + self.snap_mgr + .set_min_ingest_cf_limit(incoming.snap_min_ingest_size); + info!( + "refresh snapshot manager config"; + "speed_limit" => limit, + "max_total_snap_size" => max_total_size, + "min_ingest_cf_size" => ?incoming.snap_min_ingest_size); if incoming.concurrent_recv_snap_limit > 0 { self.snap_mgr .set_concurrent_recv_snap_limit(incoming.concurrent_recv_snap_limit); diff --git a/tests/integrations/raftstore/test_snap.rs b/tests/integrations/raftstore/test_snap.rs index ca1b028da18..69cb3d1c9e5 100644 --- a/tests/integrations/raftstore/test_snap.rs +++ b/tests/integrations/raftstore/test_snap.rs @@ -1187,3 +1187,76 @@ fn test_leader_step_down_after_requesting_snapshot() { std::thread::sleep(election_timeout); send_rx.try_recv().unwrap_err(); } + +#[test_case(test_raftstore::new_node_cluster)] +#[test_case(test_raftstore::new_server_cluster)] +fn test_node_apply_snapshot_by_or_without_ingest() { + let validate_sst_files = |dir: &std::path::Path| -> bool { + let mut sst_file_count = 0_usize; + for entry in fs::read_dir(dir).unwrap() { + let path = entry.unwrap().path(); + if path.is_file() && path.ends_with(".sst") { + sst_file_count += 1; + } + } + sst_file_count > 0 + }; + let check_snap_count = |snap_dir: &str| -> usize { + let mut valid_snap_count = 0_usize; + for entry in fs::read_dir(snap_dir).unwrap() { + let path = entry.unwrap().path(); + if path.is_dir() && validate_sst_files(&path) { + valid_snap_count += 1; + } + } + valid_snap_count + }; + for snap_min_ingest_size in [ReadableSize::mb(1), ReadableSize::default()] { + let mut cluster = new_cluster(0, 4); + cluster.cfg.raft_store.raft_log_gc_tick_interval = ReadableDuration::millis(20); + cluster.cfg.raft_store.raft_log_gc_count_limit = Some(2); + cluster.cfg.raft_store.merge_max_log_gap = 1; + cluster.cfg.raft_store.snap_mgr_gc_tick_interval = ReadableDuration::millis(50); + cluster.cfg.server.snap_min_ingest_size = snap_min_ingest_size; + + let pd_client = Arc::clone(&cluster.pd_client); + // Disable default max peer count check. + pd_client.disable_default_operator(); + cluster.run(); + + // In case of removing leader, let's transfer leader to some node first. + cluster.must_transfer_leader(1, new_peer(1, 1)); + cluster.must_put(b"k1", b"v1"); + cluster.must_put(b"k2", b"v2"); + pd_client.must_remove_peer(1, new_peer(4, 4)); + pd_client.add_peer(1, new_peer(4, 5)); + let snap_dir = cluster.get_snap_dir(4); + // Verify that the snap has been received. + for _ in 0..10 { + if check_snap_count(&snap_dir) > 0 { + return; + } + std::thread::sleep(Duration::from_millis(50)); + } + let engine4 = cluster.get_engine(4); + must_get_equal(&engine4, b"k1", b"v1"); + must_get_equal(&engine4, b"k2", b"v2"); + + pd_client.must_remove_peer(1, new_peer(3, 3)); + pd_client.must_remove_peer(1, new_peer(4, 5)); + cluster.must_put(b"k3", b"v3"); + cluster.must_put(b"k3", b"v3"); + pd_client.add_peer(1, new_peer(3, 6)); + let engine3 = cluster.get_engine(3); + must_get_equal(&engine3, b"k3", b"v3"); + must_get_equal(&engine3, b"k3", b"v3"); + // Verify that the snap will be gced. + let snap_dir = cluster.get_snap_dir(3); + for _ in 0..10 { + if check_snap_count(&snap_dir) == 0 { + return; + } + std::thread::sleep(Duration::from_millis(50)); + } + } +} diff --git a/tests/integrations/storage/test_titan.rs b/tests/integrations/storage/test_titan.rs index 455713062b3..e902b4a0cd4 100644 --- a/tests/integrations/storage/test_titan.rs +++ b/tests/integrations/storage/test_titan.rs @@ -16,7 +16,9 @@ use engine_traits::{ }; use keys::data_key; use kvproto::metapb::{Peer, Region}; -use raftstore::store::{apply_sst_cf_file, build_sst_cf_file_list, CfFile, RegionSnapshot}; +use raftstore::store::{ + apply_sst_cf_files_by_ingest, build_sst_cf_file_list, CfFile, RegionSnapshot, +}; use tempfile::Builder; use test_raftstore::*; use tikv::{ @@ -409,13 +411,13 @@ fn test_delete_files_in_range_for_titan() { .iter() .map(|s| s.as_str()) .collect::>(); - apply_sst_cf_file(&tmp_file_paths, &engines1.kv, CF_DEFAULT).unwrap(); + apply_sst_cf_files_by_ingest(&tmp_file_paths, &engines1.kv, CF_DEFAULT).unwrap(); let tmp_file_paths = cf_file_write.tmp_file_paths(); let tmp_file_paths = tmp_file_paths .iter() .map(|s| s.as_str()) .collect::>(); - apply_sst_cf_file(&tmp_file_paths, &engines1.kv, CF_WRITE).unwrap(); + apply_sst_cf_files_by_ingest(&tmp_file_paths, &engines1.kv, CF_WRITE).unwrap(); // Do scan on other DB. let mut r = Region::default(); From 5abe1dd188192c37f9759b6ae3be21f23c06fb36 Mon Sep 17 00:00:00 2001 From: cfzjywxk Date: Thu, 19 Sep 2024 11:37:45 +0800 Subject: [PATCH 071/144] support change in memory pessimistic lock memory size dynamically (#17545) close tikv/tikv#17542 Support changing the in-memory pessimistic lock memory size limit dynamically. Signed-off-by: cfzjywxk --- components/raftstore/src/store/txn_ext.rs | 97 +++++++++++++------ src/server/lock_manager/config.rs | 33 ++++++- src/server/lock_manager/mod.rs | 17 +++- src/storage/mod.rs | 12 +++ src/storage/txn/scheduler.rs | 17 +++- tests/failpoints/cases/test_merge.rs | 60 ++++++++---- tests/failpoints/cases/test_split_region.rs | 11 ++- tests/failpoints/cases/test_transaction.rs | 8 +- .../failpoints/cases/test_transfer_leader.rs | 88 ++++++++++------- .../config/dynamic/pessimistic_txn.rs | 40 ++++++++ tests/integrations/config/mod.rs | 2 + .../integrations/raftstore/test_flashback.rs | 30 +++--- tests/integrations/raftstore/test_merge.rs | 22 ++++- tests/integrations/raftstore/test_multi.rs | 30 +++--- .../raftstore/test_split_region.rs | 14 ++- .../raftstore/test_transfer_leader.rs | 16 ++- 16 files changed, 373 insertions(+), 124 deletions(-) diff --git a/components/raftstore/src/store/txn_ext.rs b/components/raftstore/src/store/txn_ext.rs index 120cc87b349..e791b520c05 100644 --- a/components/raftstore/src/store/txn_ext.rs +++ b/components/raftstore/src/store/txn_ext.rs @@ -49,19 +49,13 @@ impl fmt::Debug for TxnExt { } lazy_static! { - pub static ref GLOBAL_MEM_SIZE: IntGauge = register_int_gauge!( + pub static ref INSTANCE_MEM_SIZE: IntGauge = register_int_gauge!( "tikv_pessimistic_lock_memory_size", "Total memory size of pessimistic locks in bytes." ) .unwrap(); } -const GLOBAL_MEM_SIZE_LIMIT: usize = 100 << 20; // 100 MiB - -// 512 KiB, so pessimistic locks in one region can be proposed in a single -// command. -const PEER_MEM_SIZE_LIMIT: usize = 512 << 10; - /// Pessimistic locks of a region peer. #[derive(PartialEq)] pub struct PeerPessimisticLocks { @@ -156,7 +150,12 @@ impl PeerPessimisticLocks { /// Inserts pessimistic locks into the map. /// /// Returns whether the operation succeeds. - pub fn insert(&mut self, pairs: Vec

) -> Result<(), Vec

> { + pub fn insert( + &mut self, + pairs: Vec

, + peer_mem_size_limit: usize, + instance_mem_size_limit: usize, + ) -> Result<(), Vec

> { let mut incr = 0; // Pre-check the memory limit of pessimistic locks. for pair in &pairs { @@ -168,8 +167,8 @@ impl PeerPessimisticLocks { incr += key.len() + lock.memory_size(); } } - if self.memory_size + incr > PEER_MEM_SIZE_LIMIT - || GLOBAL_MEM_SIZE.get() as usize + incr > GLOBAL_MEM_SIZE_LIMIT + if self.memory_size + incr > peer_mem_size_limit + || INSTANCE_MEM_SIZE.get() as usize + incr > instance_mem_size_limit { return Err(pairs); } @@ -179,7 +178,7 @@ impl PeerPessimisticLocks { self.map.insert(key, (lock, false)); } self.memory_size += incr; - GLOBAL_MEM_SIZE.add(incr as i64); + INSTANCE_MEM_SIZE.add(incr as i64); Ok(()) } @@ -187,13 +186,13 @@ impl PeerPessimisticLocks { if let Some((lock, _)) = self.map.remove(key) { let desc = key.len() + lock.memory_size(); self.memory_size -= desc; - GLOBAL_MEM_SIZE.sub(desc as i64); + INSTANCE_MEM_SIZE.sub(desc as i64); } } pub fn clear(&mut self) { self.map = BTreeMap::default(); - GLOBAL_MEM_SIZE.sub(self.memory_size as i64); + INSTANCE_MEM_SIZE.sub(self.memory_size as i64); self.memory_size = 0; } @@ -322,7 +321,7 @@ impl<'a> IntoIterator for &'a PeerPessimisticLocks { impl Drop for PeerPessimisticLocks { fn drop(&mut self) { - GLOBAL_MEM_SIZE.sub(self.memory_size as i64); + INSTANCE_MEM_SIZE.sub(self.memory_size as i64); } } @@ -394,12 +393,26 @@ mod tests { let k1 = Key::from_raw(b"k1"); let k2 = Key::from_raw(b"k22"); let k3 = Key::from_raw(b"k333"); + let peer_mem_size_limit = 512 << 10; + let instance_mem_size_limit = 100 << 20; // Test the memory size of peer pessimistic locks after inserting. - locks1.insert(vec![(k1.clone(), lock(b"k1"))]).unwrap(); + locks1 + .insert( + vec![(k1.clone(), lock(b"k1"))], + peer_mem_size_limit, + instance_mem_size_limit, + ) + .unwrap(); assert_eq!(locks1.get(&k1), Some(&(lock(b"k1"), false))); assert_eq!(locks1.memory_size, k1.len() + lock(b"k1").memory_size()); - locks1.insert(vec![(k2.clone(), lock(b"k1"))]).unwrap(); + locks1 + .insert( + vec![(k2.clone(), lock(b"k1"))], + peer_mem_size_limit, + instance_mem_size_limit, + ) + .unwrap(); assert_eq!(locks1.get(&k2), Some(&(lock(b"k1"), false))); assert_eq!( locks1.memory_size, @@ -407,22 +420,34 @@ mod tests { ); // Test the global memory size after inserting. - locks2.insert(vec![(k3.clone(), lock(b"k1"))]).unwrap(); + locks2 + .insert( + vec![(k3.clone(), lock(b"k1"))], + peer_mem_size_limit, + instance_mem_size_limit, + ) + .unwrap(); assert_eq!(locks2.get(&k3), Some(&(lock(b"k1"), false))); assert_eq!( - GLOBAL_MEM_SIZE.get() as usize, + INSTANCE_MEM_SIZE.get() as usize, locks1.memory_size + locks2.memory_size ); // Test the memory size after replacing, it should not change. - locks1.insert(vec![(k2.clone(), lock(b"k2"))]).unwrap(); + locks1 + .insert( + vec![(k2.clone(), lock(b"k2"))], + peer_mem_size_limit, + instance_mem_size_limit, + ) + .unwrap(); assert_eq!(locks1.get(&k2), Some(&(lock(b"k2"), false))); assert_eq!( locks1.memory_size, k1.len() + k2.len() + 2 * lock(b"k1").memory_size() ); assert_eq!( - GLOBAL_MEM_SIZE.get() as usize, + INSTANCE_MEM_SIZE.get() as usize, locks1.memory_size + locks2.memory_size ); @@ -431,7 +456,7 @@ mod tests { assert!(locks1.get(&k1).is_none()); assert_eq!(locks1.memory_size, k2.len() + lock(b"k2").memory_size()); assert_eq!( - GLOBAL_MEM_SIZE.get() as usize, + INSTANCE_MEM_SIZE.get() as usize, locks1.memory_size + locks2.memory_size ); @@ -439,33 +464,47 @@ mod tests { locks2.clear(); assert!(locks2.is_empty()); assert_eq!(locks2.memory_size, 0); - assert_eq!(GLOBAL_MEM_SIZE.get() as usize, locks1.memory_size); + assert_eq!(INSTANCE_MEM_SIZE.get() as usize, locks1.memory_size); // Test the global memory size after dropping. drop(locks1); drop(locks2); - assert_eq!(GLOBAL_MEM_SIZE.get(), 0); + assert_eq!(INSTANCE_MEM_SIZE.get(), 0); } #[test] fn test_insert_checking_memory_limit() { let _guard = TEST_MUTEX.lock().unwrap(); - defer!(GLOBAL_MEM_SIZE.set(0)); + defer!(INSTANCE_MEM_SIZE.set(0)); + let peer_mem_size_limit = 512 << 10; + let instance_mem_size_limit = 100 << 20; let mut locks = PeerPessimisticLocks::default(); locks - .insert(vec![(Key::from_raw(b"k1"), lock(&[0; 512000]))]) + .insert( + vec![(Key::from_raw(b"k1"), lock(&[0; 512000]))], + peer_mem_size_limit, + instance_mem_size_limit, + ) .unwrap(); // Exceeding the region limit locks - .insert(vec![(Key::from_raw(b"k2"), lock(&[0; 32000]))]) + .insert( + vec![(Key::from_raw(b"k2"), lock(&[0; 32000]))], + peer_mem_size_limit, + instance_mem_size_limit, + ) .unwrap_err(); assert!(locks.get(&Key::from_raw(b"k2")).is_none()); // Not exceeding the region limit, but exceeding the global limit - GLOBAL_MEM_SIZE.set(101 << 20); - let res = locks.insert(vec![(Key::from_raw(b"k2"), lock(b"abc"))]); + INSTANCE_MEM_SIZE.set(101 << 20); + let res = locks.insert( + vec![(Key::from_raw(b"k2"), lock(b"abc"))], + peer_mem_size_limit, + instance_mem_size_limit, + ); res.unwrap_err(); assert!(locks.get(&Key::from_raw(b"k2")).is_none()); } @@ -479,7 +518,7 @@ mod tests { region } let _guard = TEST_MUTEX.lock().unwrap(); - defer!(GLOBAL_MEM_SIZE.set(0)); + defer!(INSTANCE_MEM_SIZE.set(0)); let mut original = PeerPessimisticLocks::from_locks(vec![ lock_with_key(b"a", true), diff --git a/src/server/lock_manager/config.rs b/src/server/lock_manager/config.rs index 6464c3cb1cd..cdb6d159f17 100644 --- a/src/server/lock_manager/config.rs +++ b/src/server/lock_manager/config.rs @@ -10,7 +10,7 @@ use std::{ use online_config::{ConfigChange, ConfigManager, OnlineConfig}; use serde::de::{Deserialize, Deserializer, IntoDeserializer}; -use tikv_util::config::ReadableDuration; +use tikv_util::config::{ReadableDuration, ReadableSize}; use super::{ deadlock::Scheduler as DeadlockScheduler, waiter_manager::Scheduler as WaiterMgrScheduler, @@ -31,6 +31,12 @@ pub struct Config { /// assume that the success rate of pessimistic transactions is important /// to people who disable the pipelined pessimistic lock feature. pub in_memory: bool, + /// The maximum size of the in-memory pessimistic locks in the TiKV + /// instance. + pub in_memory_peer_size_limit: ReadableSize, + /// The maximum size of the in-memory pessimistic locks in the TiKV + /// instance. + pub in_memory_instance_size_limit: ReadableSize, } // u64 is for backward compatibility since v3.x uses it. @@ -62,6 +68,8 @@ impl Default for Config { wake_up_delay_duration: ReadableDuration::millis(20), pipelined: true, in_memory: true, + in_memory_peer_size_limit: ReadableSize::kb(512), + in_memory_instance_size_limit: ReadableSize::mb(100), } } } @@ -81,6 +89,8 @@ pub struct LockManagerConfigManager { pub pipelined: Arc, pub in_memory: Arc, pub wake_up_delay_duration_ms: Arc, + pub in_memory_peer_size_limit: Arc, + pub in_memory_instance_size_limit: Arc, } impl LockManagerConfigManager { @@ -90,6 +100,8 @@ impl LockManagerConfigManager { pipelined: Arc, in_memory: Arc, wake_up_delay_duration_ms: Arc, + in_memory_peer_size_limit: Arc, + in_memory_instance_size_limit: Arc, ) -> Self { LockManagerConfigManager { waiter_mgr_scheduler, @@ -97,6 +109,8 @@ impl LockManagerConfigManager { pipelined, in_memory, wake_up_delay_duration_ms, + in_memory_peer_size_limit, + in_memory_instance_size_limit, } } } @@ -124,6 +138,19 @@ impl ConfigManager for LockManagerConfigManager { if let Some(p) = change.remove("in_memory").map(Into::into) { self.in_memory.store(p, Ordering::Relaxed); } + if let Some(p) = change + .remove("in_memory_peer_size_limit") + .map(ReadableSize::from) + { + self.in_memory_peer_size_limit.store(p.0, Ordering::Relaxed); + } + if let Some(p) = change + .remove("in_memory_instance_size_limit") + .map(ReadableSize::from) + { + self.in_memory_instance_size_limit + .store(p.0, Ordering::Relaxed); + } Ok(()) } } @@ -140,6 +167,8 @@ mod tests { wake-up-delay-duration = 100 pipelined = false in-memory = false + in-memory-peer-size-limit = "512KiB" + in-memory-instance-size-limit = "100MiB" "#; let config: Config = toml::from_str(conf).unwrap(); @@ -147,5 +176,7 @@ mod tests { assert_eq!(config.wake_up_delay_duration.as_millis(), 100); assert_eq!(config.pipelined, false); assert_eq!(config.in_memory, false); + assert_eq!(config.in_memory_peer_size_limit.0, 512 << 10); + assert_eq!(config.in_memory_instance_size_limit.0, 100 << 20); } } diff --git a/src/server/lock_manager/mod.rs b/src/server/lock_manager/mod.rs index c42531ae0fd..a992d2ca1cf 100644 --- a/src/server/lock_manager/mod.rs +++ b/src/server/lock_manager/mod.rs @@ -64,6 +64,9 @@ pub struct LockManager { in_memory: Arc, wake_up_delay_duration_ms: Arc, + + in_memory_peer_size_limit: Arc, + in_memory_instance_size_limit: Arc, } impl Clone for LockManager { @@ -78,6 +81,8 @@ impl Clone for LockManager { pipelined: self.pipelined.clone(), in_memory: self.in_memory.clone(), wake_up_delay_duration_ms: self.wake_up_delay_duration_ms.clone(), + in_memory_peer_size_limit: self.in_memory_peer_size_limit.clone(), + in_memory_instance_size_limit: self.in_memory_instance_size_limit.clone(), } } } @@ -99,6 +104,10 @@ impl LockManager { wake_up_delay_duration_ms: Arc::new(AtomicU64::new( cfg.wake_up_delay_duration.as_millis(), )), + in_memory_peer_size_limit: Arc::new(AtomicU64::new(cfg.in_memory_peer_size_limit.0)), + in_memory_instance_size_limit: Arc::new(AtomicU64::new( + cfg.in_memory_instance_size_limit.0, + )), } } @@ -221,6 +230,8 @@ impl LockManager { self.pipelined.clone(), self.in_memory.clone(), self.wake_up_delay_duration_ms.clone(), + self.in_memory_peer_size_limit.clone(), + self.in_memory_instance_size_limit.clone(), ) } @@ -229,6 +240,8 @@ impl LockManager { pipelined_pessimistic_lock: self.pipelined.clone(), in_memory_pessimistic_lock: self.in_memory.clone(), wake_up_delay_duration_ms: self.wake_up_delay_duration_ms.clone(), + in_memory_peer_size_limit: self.in_memory_peer_size_limit.clone(), + in_memory_instance_size_limit: self.in_memory_instance_size_limit.clone(), } } } @@ -312,7 +325,7 @@ mod tests { use raft::StateRole; use raftstore::coprocessor::RegionChangeEvent; use security::SecurityConfig; - use tikv_util::config::ReadableDuration; + use tikv_util::config::{ReadableDuration, ReadableSize}; use tracker::{TrackerToken, INVALID_TRACKER_TOKEN}; use txn_types::Key; @@ -328,6 +341,8 @@ mod tests { wake_up_delay_duration: ReadableDuration::millis(100), pipelined: false, in_memory: false, + in_memory_peer_size_limit: ReadableSize::kb(512), + in_memory_instance_size_limit: ReadableSize::mb(100), }; let mut lock_mgr = LockManager::new(&cfg); diff --git a/src/storage/mod.rs b/src/storage/mod.rs index aeaac73ef30..57be6099a17 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -3290,6 +3290,8 @@ pub struct DynamicConfigs { pub pipelined_pessimistic_lock: Arc, pub in_memory_pessimistic_lock: Arc, pub wake_up_delay_duration_ms: Arc, + pub in_memory_peer_size_limit: Arc, + pub in_memory_instance_size_limit: Arc, } fn get_priority_tag(priority: CommandPri) -> CommandPriority { @@ -3389,6 +3391,8 @@ pub struct TestStorageBuilder { lock_mgr: L, resource_tag_factory: ResourceTagFactory, _phantom: PhantomData, + in_memory_peer_size_limit: Arc, + in_memory_instance_size_limit: Arc, } /// TestStorageBuilder for Api V1 @@ -3527,6 +3531,8 @@ impl TestStorageBuilder { lock_mgr, resource_tag_factory: ResourceTagFactory::new_for_test(), _phantom: PhantomData, + in_memory_peer_size_limit: Arc::new(AtomicU64::new(512 << 10)), + in_memory_instance_size_limit: Arc::new(AtomicU64::new(100 << 20)), } } @@ -3596,6 +3602,8 @@ impl TestStorageBuilder { pipelined_pessimistic_lock: self.pipelined_pessimistic_lock, in_memory_pessimistic_lock: self.in_memory_pessimistic_lock, wake_up_delay_duration_ms: self.wake_up_delay_duration_ms, + in_memory_peer_size_limit: self.in_memory_peer_size_limit, + in_memory_instance_size_limit: self.in_memory_instance_size_limit, }, Arc::new(FlowController::Singleton(EngineFlowController::empty())), DummyReporter, @@ -3629,6 +3637,8 @@ impl TestStorageBuilder { pipelined_pessimistic_lock: self.pipelined_pessimistic_lock, in_memory_pessimistic_lock: self.in_memory_pessimistic_lock, wake_up_delay_duration_ms: self.wake_up_delay_duration_ms, + in_memory_peer_size_limit: self.in_memory_peer_size_limit, + in_memory_instance_size_limit: self.in_memory_instance_size_limit, }, Arc::new(FlowController::Singleton(EngineFlowController::empty())), DummyReporter, @@ -3665,6 +3675,8 @@ impl TestStorageBuilder { pipelined_pessimistic_lock: self.pipelined_pessimistic_lock, in_memory_pessimistic_lock: self.in_memory_pessimistic_lock, wake_up_delay_duration_ms: self.wake_up_delay_duration_ms, + in_memory_peer_size_limit: self.in_memory_peer_size_limit, + in_memory_instance_size_limit: self.in_memory_instance_size_limit, }, Arc::new(FlowController::Singleton(EngineFlowController::empty())), DummyReporter, diff --git a/src/storage/txn/scheduler.rs b/src/storage/txn/scheduler.rs index 536a2c3fc8a..25ec5723104 100644 --- a/src/storage/txn/scheduler.rs +++ b/src/storage/txn/scheduler.rs @@ -287,6 +287,9 @@ struct TxnSchedulerInner { txn_status_cache: TxnStatusCache, memory_quota: Arc, + + in_memory_peer_size_limit: Arc, + in_memory_instance_size_limit: Arc, } #[inline] @@ -481,6 +484,8 @@ impl TxnScheduler { feature_gate, txn_status_cache: TxnStatusCache::new(config.txn_status_cache_capacity), memory_quota: Arc::new(MemoryQuota::new(config.memory_quota.0 as _)), + in_memory_peer_size_limit: dynamic_configs.in_memory_peer_size_limit, + in_memory_instance_size_limit: dynamic_configs.in_memory_instance_size_limit, }); SCHED_TXN_MEMORY_QUOTA @@ -1901,7 +1906,13 @@ impl TxnScheduler { { return false; } - match pessimistic_locks.insert(mem::take(&mut to_be_write.modifies)) { + match pessimistic_locks.insert( + mem::take(&mut to_be_write.modifies), + self.inner.in_memory_peer_size_limit.load(Ordering::Relaxed) as usize, + self.inner + .in_memory_instance_size_limit + .load(Ordering::Relaxed) as usize, + ) { Ok(()) => { IN_MEMORY_PESSIMISTIC_LOCKING_COUNTER_STATIC.success.inc(); true @@ -2231,6 +2242,8 @@ mod tests { pipelined_pessimistic_lock: Arc::new(AtomicBool::new(true)), in_memory_pessimistic_lock: Arc::new(AtomicBool::new(false)), wake_up_delay_duration_ms: Arc::new(AtomicU64::new(0)), + in_memory_peer_size_limit: Arc::new(AtomicU64::new(512 << 10)), + in_memory_instance_size_limit: Arc::new(AtomicU64::new(100 << 20)), }, Arc::new(FlowController::Singleton(EngineFlowController::empty())), None, @@ -2581,6 +2594,8 @@ mod tests { pipelined_pessimistic_lock: Arc::new(AtomicBool::new(false)), in_memory_pessimistic_lock: Arc::new(AtomicBool::new(false)), wake_up_delay_duration_ms: Arc::new(AtomicU64::new(0)), + in_memory_peer_size_limit: Arc::new(AtomicU64::new(512 << 10)), + in_memory_instance_size_limit: Arc::new(AtomicU64::new(100 << 20)), }, Arc::new(FlowController::Singleton(EngineFlowController::empty())), None, diff --git a/tests/failpoints/cases/test_merge.rs b/tests/failpoints/cases/test_merge.rs index b07e497bd43..998f0dcc632 100644 --- a/tests/failpoints/cases/test_merge.rs +++ b/tests/failpoints/cases/test_merge.rs @@ -1392,6 +1392,8 @@ fn test_source_peer_read_delegate_after_apply() { #[test] fn test_merge_with_concurrent_pessimistic_locking() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.cfg.pessimistic_txn.pipelined = true; @@ -1417,18 +1419,22 @@ fn test_merge_with_concurrent_pessimistic_locking() { txn_ext .pessimistic_locks .write() - .insert(vec![( - Key::from_raw(b"k0"), - PessimisticLock { - primary: b"k0".to_vec().into_boxed_slice(), - start_ts: 10.into(), - ttl: 3000, - for_update_ts: 20.into(), - min_commit_ts: 30.into(), - last_change: LastChange::make_exist(15.into(), 3), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(b"k0"), + PessimisticLock { + primary: b"k0".to_vec().into_boxed_slice(), + start_ts: 10.into(), + ttl: 3000, + for_update_ts: 20.into(), + min_commit_ts: 30.into(), + last_change: LastChange::make_exist(15.into(), 3), + is_locked_with_conflict: false, + }, + )], + peer_size_limit, + instance_size_limit, + ) .unwrap(); let addr = cluster.sim.rl().get_addr(1); @@ -1480,6 +1486,8 @@ fn test_merge_with_concurrent_pessimistic_locking() { #[test] fn test_merge_pessimistic_locks_with_concurrent_prewrite() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.cfg.pessimistic_txn.pipelined = true; @@ -1520,10 +1528,14 @@ fn test_merge_pessimistic_locks_with_concurrent_prewrite() { txn_ext .pessimistic_locks .write() - .insert(vec![ - (Key::from_raw(b"k0"), lock.clone()), - (Key::from_raw(b"k1"), lock), - ]) + .insert( + vec![ + (Key::from_raw(b"k0"), lock.clone()), + (Key::from_raw(b"k1"), lock), + ], + peer_size_limit, + instance_size_limit, + ) .unwrap(); let mut mutation = Mutation::default(); @@ -1565,6 +1577,8 @@ fn test_merge_pessimistic_locks_with_concurrent_prewrite() { #[test] fn test_retry_pending_prepare_merge_fail() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.cfg.pessimistic_txn.pipelined = true; @@ -1601,7 +1615,11 @@ fn test_retry_pending_prepare_merge_fail() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"k1"), l1)]) + .insert( + vec![(Key::from_raw(b"k1"), l1)], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Pause apply and write some data to the left region @@ -1642,6 +1660,8 @@ fn test_retry_pending_prepare_merge_fail() { #[test] fn test_merge_pessimistic_locks_propose_fail() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.cfg.pessimistic_txn.pipelined = true; @@ -1677,7 +1697,11 @@ fn test_merge_pessimistic_locks_propose_fail() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"k1"), lock)]) + .insert( + vec![(Key::from_raw(b"k1"), lock)], + peer_size_limit, + instance_size_limit, + ) .unwrap(); fail::cfg("raft_propose", "pause").unwrap(); diff --git a/tests/failpoints/cases/test_split_region.rs b/tests/failpoints/cases/test_split_region.rs index 02911a942da..435f7c057b5 100644 --- a/tests/failpoints/cases/test_split_region.rs +++ b/tests/failpoints/cases/test_split_region.rs @@ -1161,6 +1161,8 @@ fn test_split_with_concurrent_pessimistic_locking() { #[test] fn test_split_pessimistic_locks_with_concurrent_prewrite() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 2); cluster.cfg.pessimistic_txn.pipelined = true; cluster.cfg.pessimistic_txn.in_memory = true; @@ -1216,10 +1218,11 @@ fn test_split_pessimistic_locks_with_concurrent_prewrite() { { let mut locks = txn_ext.pessimistic_locks.write(); locks - .insert(vec![ - (Key::from_raw(b"a"), lock_a), - (Key::from_raw(b"c"), lock_c), - ]) + .insert( + vec![(Key::from_raw(b"a"), lock_a), (Key::from_raw(b"c"), lock_c)], + peer_size_limit, + instance_size_limit, + ) .unwrap(); } diff --git a/tests/failpoints/cases/test_transaction.rs b/tests/failpoints/cases/test_transaction.rs index bb1d291e816..57b249c8087 100644 --- a/tests/failpoints/cases/test_transaction.rs +++ b/tests/failpoints/cases/test_transaction.rs @@ -563,6 +563,8 @@ fn test_pessimistic_lock_check_valid() { #[test] fn test_concurrent_write_after_transfer_leader_invalidates_locks() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 1); cluster.cfg.pessimistic_txn.pipelined = true; cluster.cfg.pessimistic_txn.in_memory = true; @@ -588,7 +590,11 @@ fn test_concurrent_write_after_transfer_leader_invalidates_locks() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"key"), lock.clone())]) + .insert( + vec![(Key::from_raw(b"key"), lock.clone())], + peer_size_limit, + instance_size_limit, + ) .unwrap(); let region = cluster.get_region(b""); diff --git a/tests/failpoints/cases/test_transfer_leader.rs b/tests/failpoints/cases/test_transfer_leader.rs index 02fb8c046c8..3139ecf06b5 100644 --- a/tests/failpoints/cases/test_transfer_leader.rs +++ b/tests/failpoints/cases/test_transfer_leader.rs @@ -119,18 +119,22 @@ macro_rules! test_delete_lock_proposed_after_proposing_locks_impl { txn_ext .pessimistic_locks .write() - .insert(vec![( - Key::from_raw(b"key"), - PessimisticLock { - primary: b"key".to_vec().into_boxed_slice(), - start_ts: 10.into(), - ttl: 1000, - for_update_ts: 10.into(), - min_commit_ts: 20.into(), - last_change: LastChange::make_exist(5.into(), 3), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(b"key"), + PessimisticLock { + primary: b"key".to_vec().into_boxed_slice(), + start_ts: 10.into(), + ttl: 1000, + for_update_ts: 10.into(), + min_commit_ts: 20.into(), + last_change: LastChange::make_exist(5.into(), 3), + is_locked_with_conflict: false, + }, + )], + 512 << 10, + 100 << 20, + ) .unwrap(); let addr = $cluster.sim.rl().get_addr(1); @@ -202,6 +206,8 @@ fn test_delete_lock_proposed_after_proposing_locks_2() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_delete_lock_proposed_before_proposing_locks() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_heartbeat_ticks = 20; cluster.run(); @@ -215,18 +221,22 @@ fn test_delete_lock_proposed_before_proposing_locks() { txn_ext .pessimistic_locks .write() - .insert(vec![( - Key::from_raw(b"key"), - PessimisticLock { - primary: b"key".to_vec().into_boxed_slice(), - start_ts: 10.into(), - ttl: 1000, - for_update_ts: 10.into(), - min_commit_ts: 20.into(), - last_change: LastChange::make_exist(5.into(), 3), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(b"key"), + PessimisticLock { + primary: b"key".to_vec().into_boxed_slice(), + start_ts: 10.into(), + ttl: 1000, + for_update_ts: 10.into(), + min_commit_ts: 20.into(), + last_change: LastChange::make_exist(5.into(), 3), + is_locked_with_conflict: false, + }, + )], + peer_size_limit, + instance_size_limit, + ) .unwrap(); let addr = cluster.sim.rl().get_addr(1); @@ -280,6 +290,8 @@ fn test_delete_lock_proposed_before_proposing_locks() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_read_lock_after_become_follower() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_heartbeat_ticks = 20; cluster.run(); @@ -300,18 +312,22 @@ fn test_read_lock_after_become_follower() { txn_ext .pessimistic_locks .write() - .insert(vec![( - Key::from_raw(b"key"), - PessimisticLock { - primary: b"key".to_vec().into_boxed_slice(), - start_ts, - ttl: 1000, - for_update_ts, - min_commit_ts: for_update_ts, - last_change: LastChange::make_exist(start_ts.prev(), 1), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(b"key"), + PessimisticLock { + primary: b"key".to_vec().into_boxed_slice(), + start_ts, + ttl: 1000, + for_update_ts, + min_commit_ts: for_update_ts, + last_change: LastChange::make_exist(start_ts.prev(), 1), + is_locked_with_conflict: false, + }, + )], + peer_size_limit, + instance_size_limit, + ) .unwrap(); let addr = cluster.sim.rl().get_addr(3); diff --git a/tests/integrations/config/dynamic/pessimistic_txn.rs b/tests/integrations/config/dynamic/pessimistic_txn.rs index dc88bbd93a3..4eede34a3cb 100644 --- a/tests/integrations/config/dynamic/pessimistic_txn.rs +++ b/tests/integrations/config/dynamic/pessimistic_txn.rs @@ -83,6 +83,8 @@ where fn test_lock_manager_cfg_update() { const DEFAULT_TIMEOUT: u64 = 3000; const DEFAULT_DELAY: u64 = 100; + const DEFAULT_IN_MEMORY_PEER_SIZE_LIMIT: u64 = 512 << 10; + const DEFAULT_IN_MEMORY_INSTANCE_SIZE_LIMIT: u64 = 100 << 20; let (mut cfg, _dir) = TikvConfig::with_tmp().unwrap(); cfg.pessimistic_txn.wait_for_lock_timeout = ReadableDuration::millis(DEFAULT_TIMEOUT); cfg.pessimistic_txn.wake_up_delay_duration = ReadableDuration::millis(DEFAULT_DELAY); @@ -166,5 +168,43 @@ fn test_lock_manager_cfg_update() { 500 ); + // update in-memory-peer-size-limit. + assert_eq!( + lock_mgr + .get_storage_dynamic_configs() + .in_memory_peer_size_limit + .load(Ordering::SeqCst), + DEFAULT_IN_MEMORY_PEER_SIZE_LIMIT + ); + cfg_controller + .update_config("pessimistic-txn.in-memory-peer-size-limit", "2MiB") + .unwrap(); + assert_eq!( + lock_mgr + .get_storage_dynamic_configs() + .in_memory_peer_size_limit + .load(Ordering::SeqCst), + 2 << 20 + ); + + // update in-memory-peer-size-limit. + assert_eq!( + lock_mgr + .get_storage_dynamic_configs() + .in_memory_instance_size_limit + .load(Ordering::SeqCst), + DEFAULT_IN_MEMORY_INSTANCE_SIZE_LIMIT + ); + cfg_controller + .update_config("pessimistic-txn.in-memory-instance-size-limit", "1GiB") + .unwrap(); + assert_eq!( + lock_mgr + .get_storage_dynamic_configs() + .in_memory_instance_size_limit + .load(Ordering::SeqCst), + 1 << 30 + ); + lock_mgr.stop(); } diff --git a/tests/integrations/config/mod.rs b/tests/integrations/config/mod.rs index 231ad2190ce..96040e9ea0e 100644 --- a/tests/integrations/config/mod.rs +++ b/tests/integrations/config/mod.rs @@ -860,6 +860,8 @@ fn test_serde_custom_tikv_config() { wake_up_delay_duration: ReadableDuration::millis(100), pipelined: false, in_memory: false, + in_memory_peer_size_limit: ReadableSize::kb(512), + in_memory_instance_size_limit: ReadableSize::mb(100), }; value.cdc = CdcConfig { min_ts_interval: ReadableDuration::secs(4), diff --git a/tests/integrations/raftstore/test_flashback.rs b/tests/integrations/raftstore/test_flashback.rs index ee19a99bcdd..30cdc3dd7e1 100644 --- a/tests/integrations/raftstore/test_flashback.rs +++ b/tests/integrations/raftstore/test_flashback.rs @@ -26,6 +26,8 @@ const TEST_VALUE: &[u8] = b"v1"; #[test_case(test_raftstore_v2::new_server_cluster)] fn test_flashback_with_in_memory_pessimistic_locks() { let mut cluster = new_cluster(0, 3); + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; cluster.cfg.raft_store.raft_heartbeat_ticks = 20; cluster.run(); cluster.must_transfer_leader(1, new_peer(1, 1)); @@ -38,18 +40,22 @@ fn test_flashback_with_in_memory_pessimistic_locks() { let mut pessimistic_locks = txn_ext.pessimistic_locks.write(); assert!(pessimistic_locks.is_writable()); pessimistic_locks - .insert(vec![( - Key::from_raw(TEST_KEY), - PessimisticLock { - primary: TEST_KEY.to_vec().into_boxed_slice(), - start_ts: 10.into(), - ttl: 3000, - for_update_ts: 20.into(), - min_commit_ts: 30.into(), - last_change: LastChange::make_exist(5.into(), 3), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(TEST_KEY), + PessimisticLock { + primary: TEST_KEY.to_vec().into_boxed_slice(), + start_ts: 10.into(), + ttl: 3000, + for_update_ts: 20.into(), + min_commit_ts: 30.into(), + last_change: LastChange::make_exist(5.into(), 3), + is_locked_with_conflict: false, + }, + )], + peer_size_limit, + instance_size_limit, + ) .unwrap(); assert_eq!(pessimistic_locks.len(), 1); } diff --git a/tests/integrations/raftstore/test_merge.rs b/tests/integrations/raftstore/test_merge.rs index 8840a1ebdfe..cfee1c9f84e 100644 --- a/tests/integrations/raftstore/test_merge.rs +++ b/tests/integrations/raftstore/test_merge.rs @@ -1451,6 +1451,8 @@ fn test_merge_snapshot_demote() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_propose_in_memory_pessimistic_locks() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.run(); @@ -1486,7 +1488,11 @@ fn test_propose_in_memory_pessimistic_locks() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"k1"), l1.clone())]) + .insert( + vec![(Key::from_raw(b"k1"), l1.clone())], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Insert lock l2 into the right region @@ -1504,7 +1510,11 @@ fn test_propose_in_memory_pessimistic_locks() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"k3"), l2.clone())]) + .insert( + vec![(Key::from_raw(b"k3"), l2.clone())], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Merge left region into the right region @@ -1582,6 +1592,8 @@ fn test_merge_pessimistic_locks_when_gap_is_too_large() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_merge_pessimistic_locks_repeated_merge() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 2); configure_for_merge(&mut cluster.cfg); cluster.cfg.pessimistic_txn.pipelined = true; @@ -1615,7 +1627,11 @@ fn test_merge_pessimistic_locks_repeated_merge() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"k1"), lock.clone())]) + .insert( + vec![(Key::from_raw(b"k1"), lock.clone())], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Filter MsgAppend, so the proposed PrepareMerge will not succeed diff --git a/tests/integrations/raftstore/test_multi.rs b/tests/integrations/raftstore/test_multi.rs index 3e18d7317d6..32104042c55 100644 --- a/tests/integrations/raftstore/test_multi.rs +++ b/tests/integrations/raftstore/test_multi.rs @@ -812,6 +812,8 @@ fn test_node_catch_up_logs() { #[test] fn test_leader_drop_with_pessimistic_lock() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_server_cluster(0, 3); cluster.run(); cluster.must_transfer_leader(1, new_peer(1, 1)); @@ -825,18 +827,22 @@ fn test_leader_drop_with_pessimistic_lock() { txn_ext .pessimistic_locks .write() - .insert(vec![( - Key::from_raw(b"k1"), - PessimisticLock { - primary: b"k1".to_vec().into_boxed_slice(), - start_ts: 10.into(), - ttl: 1000, - for_update_ts: 10.into(), - min_commit_ts: 10.into(), - last_change: LastChange::make_exist(5.into(), 3), - is_locked_with_conflict: false, - }, - )]) + .insert( + vec![( + Key::from_raw(b"k1"), + PessimisticLock { + primary: b"k1".to_vec().into_boxed_slice(), + start_ts: 10.into(), + ttl: 1000, + for_update_ts: 10.into(), + min_commit_ts: 10.into(), + last_change: LastChange::make_exist(5.into(), 3), + is_locked_with_conflict: false, + }, + )], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Isolate node 1, leader should be transferred to another node. diff --git a/tests/integrations/raftstore/test_split_region.rs b/tests/integrations/raftstore/test_split_region.rs index 28400c0ac3c..45c7fd1aab4 100644 --- a/tests/integrations/raftstore/test_split_region.rs +++ b/tests/integrations/raftstore/test_split_region.rs @@ -896,6 +896,8 @@ fn test_split_with_epoch_not_match() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_split_with_in_memory_pessimistic_locks() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 3); let pd_client = Arc::clone(&cluster.pd_client); pd_client.disable_default_operator(); @@ -932,10 +934,14 @@ fn test_split_with_in_memory_pessimistic_locks() { { let mut locks = txn_ext.pessimistic_locks.write(); locks - .insert(vec![ - (Key::from_raw(b"a"), lock_a.clone()), - (Key::from_raw(b"c"), lock_c.clone()), - ]) + .insert( + vec![ + (Key::from_raw(b"a"), lock_a.clone()), + (Key::from_raw(b"c"), lock_c.clone()), + ], + peer_size_limit, + instance_size_limit, + ) .unwrap(); } diff --git a/tests/integrations/raftstore/test_transfer_leader.rs b/tests/integrations/raftstore/test_transfer_leader.rs index 6f251d1cf8b..f33eaf836cf 100644 --- a/tests/integrations/raftstore/test_transfer_leader.rs +++ b/tests/integrations/raftstore/test_transfer_leader.rs @@ -256,6 +256,8 @@ fn test_sync_max_ts_after_leader_transfer() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_propose_in_memory_pessimistic_locks() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_heartbeat_ticks = 20; cluster.run(); @@ -279,7 +281,11 @@ fn test_propose_in_memory_pessimistic_locks() { let mut pessimistic_locks = txn_ext.pessimistic_locks.write(); assert!(pessimistic_locks.is_writable()); pessimistic_locks - .insert(vec![(Key::from_raw(b"key"), lock.clone())]) + .insert( + vec![(Key::from_raw(b"key"), lock.clone())], + peer_size_limit, + instance_size_limit, + ) .unwrap(); } @@ -298,6 +304,8 @@ fn test_propose_in_memory_pessimistic_locks() { #[test_case(test_raftstore::new_server_cluster)] #[test_case(test_raftstore_v2::new_server_cluster)] fn test_memory_pessimistic_locks_status_after_transfer_leader_failure() { + let peer_size_limit = 512 << 10; + let instance_size_limit = 100 << 20; let mut cluster = new_cluster(0, 3); cluster.cfg.raft_store.raft_heartbeat_ticks = 20; cluster.cfg.raft_store.reactive_memory_lock_tick_interval = ReadableDuration::millis(200); @@ -321,7 +329,11 @@ fn test_memory_pessimistic_locks_status_after_transfer_leader_failure() { txn_ext .pessimistic_locks .write() - .insert(vec![(Key::from_raw(b"key"), lock)]) + .insert( + vec![(Key::from_raw(b"key"), lock)], + peer_size_limit, + instance_size_limit, + ) .unwrap(); // Make it fail to transfer leader From 7a8d05ad8088120a2654516c6f6f0079bf677783 Mon Sep 17 00:00:00 2001 From: cfzjywxk Date: Thu, 19 Sep 2024 23:20:57 +0800 Subject: [PATCH 072/144] txn: fix the config comment (#17555) ref tikv/tikv#17542 Fix the comment of newly added config variable. Signed-off-by: cfzjywxk --- etc/config-template.toml | 8 ++++++++ src/server/lock_manager/config.rs | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/etc/config-template.toml b/etc/config-template.toml index 767a91e575e..e68e352f7a0 100644 --- a/etc/config-template.toml +++ b/etc/config-template.toml @@ -1340,6 +1340,14 @@ ## It only takes effect when `pessimistic-txn.pipelined` is also set to true. # in-memory = true +## Control the memory size limit of pessimistic locks for one region. The pessimistic locks +## would be written persistently if the memory usage exceeds the limit. +# in-memory-peer-size-limit = "512KiB" + +## Control the memory size limit of pessimistic locks for one TiKV instance. The pessimistic +## locks would be written persistently if the memory usage exceeds the limit. +# in-memory-instance-size-limit = "100MiB" + [gc] ## The number of keys to GC in one batch. # batch-keys = 512 diff --git a/src/server/lock_manager/config.rs b/src/server/lock_manager/config.rs index cdb6d159f17..6b7ddc7aca0 100644 --- a/src/server/lock_manager/config.rs +++ b/src/server/lock_manager/config.rs @@ -31,8 +31,7 @@ pub struct Config { /// assume that the success rate of pessimistic transactions is important /// to people who disable the pipelined pessimistic lock feature. pub in_memory: bool, - /// The maximum size of the in-memory pessimistic locks in the TiKV - /// instance. + /// The maximum size of the in-memory pessimistic locks of one region peer. pub in_memory_peer_size_limit: ReadableSize, /// The maximum size of the in-memory pessimistic locks in the TiKV /// instance. From 86ed54481d957344f5041ef3213b1b1581942f3e Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:42:42 +0800 Subject: [PATCH 073/144] In-memory engine: sync evict in auto load/evict to ensure memory reduction (#17523) close tikv/tikv#16141 sync evict in auto load/evict to ensure memory reduction Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 135 ++++++++++-------- .../range_cache_memory_engine/src/engine.rs | 5 +- .../src/memory_controller.rs | 5 - .../src/range_stats.rs | 127 ++++++---------- 4 files changed, 119 insertions(+), 153 deletions(-) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 2b10a09db7c..bd1c486d863 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -18,12 +18,13 @@ use raftstore::coprocessor::RegionInfoProvider; use slog_global::{error, info, warn}; use strum::EnumCount; use tikv_util::{ - config::ReadableSize, + config::{ReadableSize, VersionTrack}, future::block_on_timeout, keybuilder::KeyBuilder, time::Instant, worker::{Builder, Runnable, RunnableWithTimer, ScheduleError, Scheduler, Worker}, }; +use tokio::sync::mpsc; use txn_types::{Key, TimeStamp, WriteRef, WriteType}; use yatp::Remote; @@ -44,6 +45,7 @@ use crate::{ LabelRule, RegionLabelChangedCallback, RegionLabelRulesManager, RegionLabelServiceBuilder, }, write_batch::RangeCacheWriteBatchEntry, + RangeCacheEngineConfig, }; // 5 seconds should be long enough for getting a TSO from PD. @@ -212,10 +214,7 @@ impl BgWorkManager { pub fn new( core: Arc, pd_client: Arc, - gc_interval: Duration, - load_evict_interval: Duration, - expected_region_size: usize, - mvcc_amplification_threshold: usize, + config: Arc>, memory_controller: Arc, region_info_provider: Option>, ) -> Self { @@ -224,18 +223,17 @@ impl BgWorkManager { core.clone(), memory_controller, region_info_provider.clone(), - expected_region_size, - mvcc_amplification_threshold, - gc_interval, + &config, pd_client.clone(), ); + let config = config.value(); let scheduler = worker.start_with_timer("ime-bg-runner", runner); let (ticker, tx) = BgWorkManager::start_tick( scheduler.clone(), pd_client, - gc_interval, - load_evict_interval, + config.gc_interval.0, + config.load_evict_interval.0, ); Self { @@ -624,38 +622,44 @@ impl BackgroundRunnerCore { /// /// See: [`RangeStatsManager::collect_changes_ranges`] for /// algorithm details. - fn top_regions_load_evict(&self, delete_range_scheduler: &Scheduler) { + async fn top_regions_load_evict(&self, delete_range_scheduler: &Scheduler) { let range_stats_manager = match &self.range_stats_manager { Some(m) => m, None => { return; } }; - if range_stats_manager.set_checking_top_regions(true) { + if !range_stats_manager.ready_for_auto_load_and_evict() { return; } - let curr_memory_usage = self.memory_controller.mem_usage(); - let threshold = self.memory_controller.stop_load_limit_threshold(); - range_stats_manager.adjust_max_num_regions(curr_memory_usage, threshold); - - let cached_regions = self - .engine - .region_manager() - .regions_map() - .read() - .cached_regions(); + let (current_region_count, cached_regions) = { + let region_map = self.engine.region_manager().regions_map().read(); + (region_map.regions().len(), region_map.cached_regions()) + }; let (regions_to_load, regions_to_evict) = range_stats_manager - .collect_regions_to_load_and_evict(cached_regions, &self.memory_controller); + .collect_regions_to_load_and_evict( + current_region_count, + cached_regions, + &self.memory_controller, + ); - let mut regions_to_delete = Vec::with_capacity(regions_to_evict.len()); + let evict_count = regions_to_evict.len(); + let mut regions_to_delete = Vec::with_capacity(evict_count); info!("ime load_evict"; "regions_to_load" => ?®ions_to_load, "regions_to_evict" => ?®ions_to_evict); + let (tx, mut rx) = mpsc::channel(evict_count + 1); for evict_region in regions_to_evict { let cache_region = CacheRegion::from_region(&evict_region); + let tx_clone = tx.clone(); + // Bound is set to 1 so that the sender side will not be blocked let deleteable_regions = self.engine.region_manager().evict_region( &cache_region, EvictReason::AutoEvict, - None, + Some(Box::new(move || { + Box::pin(async move { + let _ = tx_clone.send(()).await; + }) + })), ); info!( "ime load_evict: auto evict"; @@ -676,14 +680,27 @@ impl BackgroundRunnerCore { assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); } } - let mut regions_map = self.engine.region_manager().regions_map.write(); - for region in regions_to_load { - let cache_region = CacheRegion::from_region(®ion); - if let Err(e) = regions_map.load_region(cache_region) { - error!("ime error loading range"; "cache_range" => ?region, "err" => ?e); + for _ in 0..evict_count { + if rx.recv().await.is_none() { + break; + } + } + if !self.memory_controller.reached_stop_load_limit() { + let expected_new_count = (self + .memory_controller + .soft_limit_threshold() + .saturating_sub(self.memory_controller.mem_usage())) + / range_stats_manager.expected_region_size; + let expected_new_count = usize::max(expected_new_count, 1); + let mut regions_map = self.engine.region_manager().regions_map.write(); + for region in regions_to_load.into_iter().take(expected_new_count) { + let cache_region = CacheRegion::from_region(®ion); + if let Err(e) = regions_map.load_region(cache_region) { + warn!("ime error loading range"; "cache_range" => ?region, "err" => ?e); + } } } - range_stats_manager.set_checking_top_regions(false); + range_stats_manager.complete_auto_load_and_evict(); info!("ime load_evict complete"); } } @@ -749,11 +766,10 @@ impl BackgroundRunner { engine: Arc, memory_controller: Arc, region_info_provider: Option>, - expected_region_size: usize, - mvcc_amplification_threshold: usize, - gc_interval: Duration, + config: &Arc>, pd_client: Arc, ) -> (Self, Scheduler) { + let config = config.value(); let range_load_worker = Builder::new("ime-load") // Range load now is implemented sequentially, so we must use exactly one thread to handle it. // todo(SpadeA): if the load speed is a bottleneck, we may consider to use multiple threads to load ranges. @@ -778,13 +794,13 @@ impl BackgroundRunner { let load_evict_worker = Worker::new("ime-evict"); let load_evict_remote = load_evict_worker.remote(); - let num_regions_to_cache = memory_controller.soft_limit_threshold() / expected_region_size; + let expected_region_size = config.expected_region_size(); let range_stats_manager = region_info_provider.map(|region_info_provider| { RangeStatsManager::new( - num_regions_to_cache, DEFAULT_EVICT_MIN_DURATION, expected_region_size, - mvcc_amplification_threshold, + config.mvcc_amplification_threshold, + config.load_evict_interval.0, region_info_provider, ) }); @@ -796,7 +812,7 @@ impl BackgroundRunner { range_stats_manager, }, pd_client, - gc_interval, + gc_interval: config.gc_interval.0, range_load_worker, range_load_remote, delete_range_worker, @@ -1081,7 +1097,8 @@ impl Runnable for BackgroundRunner { BackgroundTask::TopRegionsLoadEvict => { let delete_range_scheduler = self.delete_range_scheduler.clone(); let core = self.core.clone(); - let task = async move { core.top_regions_load_evict(&delete_range_scheduler) }; + let task = + async move { core.top_regions_load_evict(&delete_range_scheduler).await }; self.load_evict_remote.spawn(task); } BackgroundTask::CleanLockTombstone(snapshot_seqno) => { @@ -1873,13 +1890,12 @@ pub mod tests { iter_opts.set_lower_bound(&cache_region.start, 0); iter_opts.set_upper_bound(&cache_region.end, 0); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller.clone(), None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); worker.core.gc_region(&cache_region, 40, 100); @@ -1948,13 +1964,12 @@ pub mod tests { assert_eq!(3, element_count(&default)); assert_eq!(3, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller.clone(), None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); @@ -2109,13 +2124,12 @@ pub mod tests { assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller.clone(), None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); let filter = worker.core.gc_region(®ion1, 100, 100); @@ -2127,13 +2141,12 @@ pub mod tests { assert_eq!(4, element_count(&default)); assert_eq!(4, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller.clone(), None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); worker.core.gc_region(®ion2, 100, 100); @@ -2174,13 +2187,12 @@ pub mod tests { assert_eq!(1, element_count(&default)); assert_eq!(2, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller.clone(), None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); @@ -2273,13 +2285,12 @@ pub mod tests { assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller, None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); let cache_region = CacheRegion::from_region(®ion); @@ -2422,13 +2433,12 @@ pub mod tests { assert_eq!(6, element_count(&default)); assert_eq!(6, element_count(&write)); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (worker, _) = BackgroundRunner::new( engine.core.clone(), memory_controller, None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); @@ -2571,13 +2581,12 @@ pub mod tests { engine.new_region(r1); engine.new_region(r2); + let config = Arc::new(VersionTrack::new(RangeCacheEngineConfig::config_for_test())); let (runner, _) = BackgroundRunner::new( engine.core.clone(), memory_controller, None, - engine.expected_region_size(), - 0, - Duration::from_secs(100), + &config, Arc::new(MockPdClient {}), ); let regions = runner.core.regions_for_gc(); diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index e0dd4e735df..c1ded34411c 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -263,10 +263,7 @@ impl RangeCacheMemoryEngine { let bg_work_manager = Arc::new(BgWorkManager::new( core.clone(), pd_client, - config.value().gc_interval.0, - config.value().load_evict_interval.0, - config.value().expected_region_size(), - config.value().mvcc_amplification_threshold, + config.clone(), memory_controller.clone(), region_info_provider, )); diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index 924e2460743..3411996c9c0 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -90,11 +90,6 @@ impl MemoryController { self.mem_usage() >= self.config.value().stop_load_limit_threshold() } - #[inline] - pub(crate) fn stop_load_limit_threshold(&self) -> usize { - self.config.value().stop_load_limit_threshold() - } - #[inline] pub(crate) fn soft_limit_threshold(&self) -> usize { self.config.value().soft_limit_threshold() diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 44c466c9b74..26cd376d1e3 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -1,10 +1,9 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. use std::{ - cmp, collections::{BTreeMap, HashSet}, num::NonZeroUsize, sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, + atomic::{AtomicBool, Ordering}, Arc, }, time::{Duration, Instant}, @@ -31,12 +30,11 @@ const ITERATED_COUNT_FILTER_FACTOR: usize = 20; #[derive(Clone)] pub(crate) struct RangeStatsManager { - num_regions: Arc, info_provider: Arc, checking_top_regions: Arc, region_loaded_at: Arc>>, evict_min_duration: Duration, - expected_region_size: usize, + pub(crate) expected_region_size: usize, // Moving average of amplification reduction. Amplification reduction is the reduced // multiple before and after the cache. When a new top region (of course, not cached) comes in, // this moving average number is used to estimate the mvcc amplification after cache so we can @@ -45,6 +43,9 @@ pub(crate) struct RangeStatsManager { mvcc_amplification_threshold: usize, mvcc_amplification_record: Arc>>, + + load_evict_interval: Duration, + last_load_evict_time: Arc>, } impl RangeStatsManager { @@ -56,14 +57,13 @@ impl RangeStatsManager { /// * `evict_min_duration` - do not evict regions that have been loaded for /// less than this duration. pub fn new( - num_regions: usize, evict_min_duration: Duration, expected_region_size: usize, mvcc_amplification_threshold: usize, + load_evict_interval: Duration, info_provider: Arc, ) -> Self { RangeStatsManager { - num_regions: Arc::new(AtomicUsize::new(num_regions)), info_provider, checking_top_regions: Arc::new(AtomicBool::new(false)), region_loaded_at: Arc::new(ShardedLock::new(BTreeMap::new())), @@ -72,24 +72,33 @@ impl RangeStatsManager { evict_min_duration, expected_region_size, mvcc_amplification_threshold, + load_evict_interval, + last_load_evict_time: Arc::new(Mutex::new(Instant::now())), } } - /// Prevents two instances of this from running concurrently. - /// Return the previous checking status. - pub fn set_checking_top_regions(&self, v: bool) -> bool { - self.checking_top_regions.swap(v, Ordering::Relaxed) + /// If false is returned, it is not ready to check. + pub fn ready_for_auto_load_and_evict(&self) -> bool { + // The auto load and evict process can block for some time (mainly waiting for + // eviction). To avoid too check after check immediately, we check the elapsed + // time after the last check. + // Region stats update duration is one minute by default, to avoid two checks + // using the same region stats as much as possible, we set a min check interval + // of 1.5 minutes(considers there are not just one region for stat collection). + self.last_load_evict_time.lock().elapsed() + > Duration::max(self.load_evict_interval / 2, Duration::from_secs(90)) + && !self.set_checking_top_regions(true) } - fn set_max_num_regions(&self, v: usize) { - self.num_regions.store(v, Ordering::Relaxed); + pub fn complete_auto_load_and_evict(&self) { + *self.last_load_evict_time.lock() = Instant::now(); + self.set_checking_top_regions(true); } - /// Returns the maximum number of regions that can be cached. - /// - /// See also `adjust_max_num_regions` below. - pub fn max_num_regions(&self) -> usize { - self.num_regions.load(Ordering::Relaxed) + /// Prevents two instances of this from running concurrently. + /// Return the previous checking status. + fn set_checking_top_regions(&self, v: bool) -> bool { + self.checking_top_regions.swap(v, Ordering::Relaxed) } /// This method should be called when `evicted_range` is succesfully evicted @@ -105,48 +114,6 @@ impl RangeStatsManager { self.region_loaded_at.write().unwrap().remove(®ion.id); } - /// Attempt to adjust the maximum number of cached regions based on memory - /// usage: - /// - /// If `curr_memory_usage` is LESS THAN `threshold` by 3 * - /// self.expected_region_size bytes, *increase* the maximum - /// by `threshold - curr_memory_usage / 3 * self.expected_region_size`. - /// - /// If `curr_memory_usage` is GREATER THAN `threshold`, *decrease* the - /// maximum by `(curr_memory_usage - threshold) / - /// self.expected_region_size`. - pub fn adjust_max_num_regions(&self, curr_memory_usage: usize, threshold: usize) { - match curr_memory_usage.cmp(&threshold) { - cmp::Ordering::Less => { - let room_to_grow = threshold - curr_memory_usage; - if room_to_grow > self.expected_region_size * 3 { - let curr_num_regions = self.max_num_regions(); - let next_num_regions = - curr_num_regions + room_to_grow / (self.expected_region_size * 3); - info!("ime increasing number of top regions to cache"; - "from" => curr_num_regions, - "to" => next_num_regions, - ); - self.set_max_num_regions(next_num_regions); - } - } - cmp::Ordering::Greater => { - let to_shrink_by = curr_memory_usage - threshold; - let curr_num_regions = self.max_num_regions(); - let next_num_regions = curr_num_regions - .checked_sub(1.max(to_shrink_by / self.expected_region_size)) - .unwrap_or(1) - .max(1); - info!("ime decreasing number of top regions to cache"; - "from" => curr_num_regions, - "to" => next_num_regions, - ); - self.set_max_num_regions(next_num_regions); - } - _ => (), - }; - } - /// Collects regions to load and evict based on region stat, mvcc /// amplification, and memory constraints. New top regions will be /// collected in `regions_added_out` to be loaded. @@ -162,6 +129,7 @@ impl RangeStatsManager { /// (Regions to load, Regions to evict) pub fn collect_regions_to_load_and_evict( &self, + current_region_count: usize, cached_region_ids: Vec, memory_controller: &MemoryController, ) -> (Vec, Vec) { @@ -200,10 +168,17 @@ impl RangeStatsManager { "ma_mvcc_amplification_reduction" => ma_mvcc_amplification_reduction, ); - info!("ime collect_changed_ranges"; "num_regions" => self.max_num_regions()); + // Use soft-limit-threshold rather than stop-load-limit-threshold as there might + // be some regions to be evicted. + let expected_new_count = (memory_controller + .soft_limit_threshold() + .saturating_sub(memory_controller.mem_usage())) + / self.expected_region_size; + let expected_num_regions = current_region_count + expected_new_count; + info!("ime collect_changed_ranges"; "num_regions" => expected_num_regions); let curr_top_regions = self .info_provider - .get_top_regions(Some(NonZeroUsize::try_from(self.max_num_regions()).unwrap())) + .get_top_regions(Some(NonZeroUsize::try_from(expected_num_regions).unwrap())) .unwrap() // TODO (afeinberg): Potentially custom error handling here. .iter() .map(|(r, region_stats)| (r.id, (r.clone(), region_stats.clone()))) @@ -372,27 +347,18 @@ impl RangeStatsManager { / regions_activity.len() as f64; let evict_candidates: Vec<_> = { - let mut regions_loaded = self.region_loaded_at.write().unwrap(); let mut evict_candidates = regions_activity; info!( "ime evict candidate count before filter"; "count" => evict_candidates.len(), ); - let mut filter_by_time = 0; let mut filter_by_mvcc_amplification = 0; - evict_candidates.retain(|(r, ra)| { - let time_loaded = regions_loaded.entry(r.id).or_insert(Instant::now()); + evict_candidates.retain(|(_, ra)| { // Do not evict regions with high mvcc amplification if ra.cop_detail.mvcc_amplification() > avg_mvcc_amplification { filter_by_mvcc_amplification += 1; return false; } - let now = Instant::now(); - // Do not evict regions that are loaded recently - if now - *time_loaded < self.evict_min_duration { - filter_by_time += 1; - return false; - } true }); evict_candidates.sort_by(|a, b| { @@ -404,7 +370,6 @@ impl RangeStatsManager { info!( "ime evict candidate count after filter"; "count" => evict_candidates.len(), - "filter_by_time" => filter_by_time, "filter_by_mvcc_amplification" => filter_by_mvcc_amplification, ); @@ -554,20 +519,20 @@ pub mod tests { }); // 10 ms min duration eviction for testing purposes. let rsm = RangeStatsManager::new( - 10, Duration::from_millis(10), RangeCacheEngineConfig::config_for_test().expected_region_size(), 10, + Duration::from_secs(100), sim.clone(), ); - let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![], &mc); + let (added, removed) = rsm.collect_regions_to_load_and_evict(0, vec![], &mc); assert_eq!(&added, &[region_1.clone()]); assert!(removed.is_empty()); let top_regions = vec![(region_2.clone(), new_region_stat(1000, 8))]; let region_stats = vec![(region_1.clone(), new_region_stat(20, 10))]; sim.set_top_regions(&top_regions); sim.set_region_stats(®ion_stats); - let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![1], &mc); + let (added, removed) = rsm.collect_regions_to_load_and_evict(0, vec![1], &mc); assert_eq!(&added, &[region_2.clone()]); assert!(removed.is_empty()); let region_3 = new_region(3, b"k05", b"k06"); @@ -589,7 +554,7 @@ pub mod tests { ]; sim.set_top_regions(&top_regions); sim.set_region_stats(®ion_stats); - let (added, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2], &mc); + let (added, removed) = rsm.collect_regions_to_load_and_evict(0, vec![1, 2], &mc); assert!(removed.is_empty()); assert_eq!( &added, @@ -613,7 +578,7 @@ pub mod tests { ]; sim.set_top_regions(&vec![]); sim.set_region_stats(®ion_stats); - let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2, 3, 4, 5, 6, 7], &mc); + let (_, removed) = rsm.collect_regions_to_load_and_evict(0, vec![1, 2, 3, 4, 5, 6, 7], &mc); // `region_1` is no longer needed to cached, but since it was loaded less // than 10 ms ago, it should not be included in the removed ranges. assert!(removed.is_empty()); @@ -622,14 +587,14 @@ pub mod tests { sim.set_top_regions(&vec![]); sim.set_region_stats(®ion_stats); - let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![1, 2, 3, 4, 5, 6, 7], &mc); + let (_, removed) = rsm.collect_regions_to_load_and_evict(0, vec![1, 2, 3, 4, 5, 6, 7], &mc); assert_eq!(&removed, &[region_1.clone()]); let top_regions = vec![(region_8.clone(), new_region_stat(4000, 10))]; sim.set_top_regions(&top_regions); sim.set_region_stats(®ion_stats); mc.acquire(2000); - let (_, removed) = rsm.collect_regions_to_load_and_evict(vec![2, 3, 4, 5, 6, 7], &mc); + let (_, removed) = rsm.collect_regions_to_load_and_evict(0, vec![2, 3, 4, 5, 6, 7], &mc); assert_eq!(&removed, &[region_3.clone()]); } @@ -683,13 +648,13 @@ pub mod tests { }); // 10 ms min duration eviction for testing purposes. let rsm = RangeStatsManager::new( - 10, Duration::from_millis(10), RangeCacheEngineConfig::config_for_test().expected_region_size(), 10, + Duration::from_secs(10), sim.clone(), ); - rsm.collect_regions_to_load_and_evict(vec![], &mc); + rsm.collect_regions_to_load_and_evict(0, vec![], &mc); std::thread::sleep(Duration::from_millis(100)); let evicted_regions = Arc::new(Mutex::new(vec![])); From 5e7ea28c934356de1ca1b4033e1244779d8e89d8 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:37:50 +0800 Subject: [PATCH 074/144] In-memory engine: update the calculation of mvcc_amplification (#17560) ref tikv/tikv#16141 update the calculation of mvcc_amplification Signed-off-by: SpadeA-Tang --- components/pd_client/src/lib.rs | 22 ++++++++++++++----- .../src/coprocessor/region_info_accessor.rs | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/components/pd_client/src/lib.rs b/components/pd_client/src/lib.rs index 4cde27de7ce..39f80ba6dd6 100644 --- a/components/pd_client/src/lib.rs +++ b/components/pd_client/src/lib.rs @@ -602,15 +602,27 @@ impl RegionWriteCfCopDetail { ) } + #[inline] pub fn iterated_count(&self) -> usize { self.next + self.prev } + #[inline] pub fn mvcc_amplification(&self) -> f64 { - if self.processed_keys == 0 { - 0f64 - } else { - (self.next + self.prev) as f64 / self.processed_keys as f64 - } + // Sometimes, processed_keys is 0 even (next + prev) is pretty high + self.iterated_count() as f64 / (self.processed_keys as f64 + 1.0) + } +} + +#[cfg(test)] +mod tests { + use crate::RegionWriteCfCopDetail; + + #[test] + fn test_procssed_key_0() { + let mut cop_detail = RegionWriteCfCopDetail::default(); + cop_detail.next = 11; + + assert_eq!(cop_detail.mvcc_amplification(), 11.0); } } diff --git a/components/raftstore/src/coprocessor/region_info_accessor.rs b/components/raftstore/src/coprocessor/region_info_accessor.rs index 26e14c2cd1c..9252f536a71 100644 --- a/components/raftstore/src/coprocessor/region_info_accessor.rs +++ b/components/raftstore/src/coprocessor/region_info_accessor.rs @@ -689,8 +689,8 @@ impl RegionCollector { top_regions.retain(|(_, s)| { s.cop_detail.iterated_count() >= iterated_count_to_filter // plus processed_keys by 1 to make it not 0 - && (s.cop_detail.iterated_count()) / (s.cop_detail.processed_keys + 1) - >= self.mvcc_amplification_threshold + && s.cop_detail.mvcc_amplification() + >= self.mvcc_amplification_threshold as f64 }); // TODO(SpadeA): remove it when auto load/evict is stable From 3d022221860a61464ddd7dd2ae66289d2926de52 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:02:39 +0800 Subject: [PATCH 075/144] In-memory engine: try best to preload when transfer leader (#17433) ref tikv/tikv#16141, close tikv/tikv#17551 try best to preload when transfer leader Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- .../engine_traits/src/range_cache_engine.rs | 9 ++- .../src/observer/load_eviction.rs | 58 +++++++++++++--- .../hybrid_engine/src/range_cache_engine.rs | 10 +++ .../raftstore/src/coprocessor/dispatcher.rs | 56 +++++++++++++--- components/raftstore/src/coprocessor/mod.rs | 15 +++-- components/raftstore/src/store/fsm/peer.rs | 9 +++ components/raftstore/src/store/peer.rs | 44 ++++++++---- .../raftstore/src/store/snapshot_backup.rs | 9 ++- .../src/background.rs | 4 +- .../range_cache_memory_engine/src/engine.rs | 67 +++++++++++++------ .../range_cache_memory_engine/src/read.rs | 4 +- .../tests/failpoints/test_memory_engine.rs | 4 +- .../cases/test_range_cache_engine.rs | 33 ++++++++- 14 files changed, 255 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4daaebd4c82..57e46ed0d67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2845,7 +2845,7 @@ dependencies = [ [[package]] name = "kvproto" version = "0.0.2" -source = "git+https://github.com/pingcap/kvproto.git#1a933d30690a1cd7a4642f569be473329c756f8a" +source = "git+https://github.com/pingcap/kvproto.git#199f352dc2b3bdfdc3b96e01bc3bca81148b0171" dependencies = [ "futures 0.3.15", "grpcio", diff --git a/components/engine_traits/src/range_cache_engine.rs b/components/engine_traits/src/range_cache_engine.rs index e2a2017536e..5a1c2702516 100644 --- a/components/engine_traits/src/range_cache_engine.rs +++ b/components/engine_traits/src/range_cache_engine.rs @@ -30,6 +30,7 @@ pub enum RegionEvent { }, TryLoad { region: CacheRegion, + for_manual_range: bool, }, Eviction { region: CacheRegion, @@ -60,7 +61,7 @@ pub enum EvictReason { /// RangeCacheEngine works as a range cache caching some ranges (in Memory or /// NVME for instance) to improve the read performance. pub trait RangeCacheEngine: - WriteBatchExt + Iterable + Debug + Clone + Unpin + Send + Sync + 'static + RangeCacheEngineExt + WriteBatchExt + Iterable + Debug + Clone + Unpin + Send + Sync + 'static { type Snapshot: Snapshot; @@ -87,14 +88,16 @@ pub trait RangeCacheEngine: fn enabled(&self) -> bool { false } - - fn on_region_event(&self, event: RegionEvent); } pub trait RangeCacheEngineExt { // TODO(SpadeA): try to find a better way to reduce coupling degree of range // cache engine and kv engine fn on_region_event(&self, event: RegionEvent); + + fn region_cached(&self, range: &Region) -> bool; + + fn load_region(&self, range: &Region); } /// A service that should run in the background to retrieve and apply cache diff --git a/components/hybrid_engine/src/observer/load_eviction.rs b/components/hybrid_engine/src/observer/load_eviction.rs index 9deb491cdd7..059930d3886 100644 --- a/components/hybrid_engine/src/observer/load_eviction.rs +++ b/components/hybrid_engine/src/observer/load_eviction.rs @@ -3,12 +3,17 @@ use std::sync::Arc; use engine_traits::{CacheRegion, EvictReason, KvEngine, RangeCacheEngineExt, RegionEvent}; -use kvproto::{raft_cmdpb::AdminCmdType, raft_serverpb::RaftApplyState}; +use kvproto::{ + metapb::Region, + raft_cmdpb::AdminCmdType, + raft_serverpb::{ExtraMessage, ExtraMessageType, RaftApplyState}, +}; use raft::StateRole; use raftstore::coprocessor::{ - AdminObserver, ApplyCtxInfo, ApplySnapshotObserver, BoxAdminObserver, BoxApplySnapshotObserver, - BoxQueryObserver, BoxRoleObserver, Cmd, Coprocessor, CoprocessorHost, ObserverContext, - QueryObserver, RegionState, RoleObserver, + dispatcher::BoxExtraMessageObserver, AdminObserver, ApplyCtxInfo, ApplySnapshotObserver, + BoxAdminObserver, BoxApplySnapshotObserver, BoxQueryObserver, BoxRoleObserver, Cmd, + Coprocessor, CoprocessorHost, ExtraMessageObserver, ObserverContext, QueryObserver, + RegionState, RoleObserver, }; use tikv_util::info; @@ -44,6 +49,10 @@ impl LoadEvictionObserver { coprocessor_host .registry .register_role_observer(priority, BoxRoleObserver::new(self.clone())); + // Pre load region in transfer leader + coprocessor_host + .registry + .register_extra_message_observer(priority, BoxExtraMessageObserver::new(self.clone())); } fn post_exec_cmd( @@ -107,9 +116,12 @@ impl LoadEvictionObserver { }); } + // Try to load region. It will be loaded if it's overlapped with maunal range fn try_load_region(&self, region: CacheRegion) { - self.cache_engine - .on_region_event(RegionEvent::TryLoad { region }); + self.cache_engine.on_region_event(RegionEvent::TryLoad { + region, + for_manual_range: true, + }); } fn evict_region(&self, region: CacheRegion, reason: EvictReason) { @@ -150,6 +162,19 @@ impl AdminObserver for LoadEvictionObserver { // immediately, so return false. false } + + fn pre_transfer_leader( + &self, + ctx: &mut ObserverContext<'_>, + _tr: &kvproto::raft_cmdpb::TransferLeaderRequest, + ) -> raftstore::coprocessor::Result> { + if !self.cache_engine.region_cached(ctx.region()) { + return Ok(None); + } + let mut msg = ExtraMessage::new(); + msg.set_type(ExtraMessageType::MsgPreLoadRegionRequest); + Ok(Some(msg)) + } } impl ApplySnapshotObserver for LoadEvictionObserver { @@ -178,7 +203,7 @@ impl RoleObserver for LoadEvictionObserver { // Currently, it is only used by the manual load. let cache_region = CacheRegion::from_region(ctx.region()); info!( - "ime load region due to became leader"; + "ime try to load region due to became leader"; "region" => ?cache_region, ); self.try_load_region(cache_region); @@ -187,7 +212,7 @@ impl RoleObserver for LoadEvictionObserver { { let cache_region = CacheRegion::from_region(ctx.region()); info!( - "ime evict region due to became follower"; + "ime try to evict region due to became follower"; "region" => ?cache_region, ); self.evict_region(cache_region, EvictReason::BecomeFollower); @@ -195,6 +220,14 @@ impl RoleObserver for LoadEvictionObserver { } } +impl ExtraMessageObserver for LoadEvictionObserver { + fn on_extra_message(&self, r: &Region, extra_msg: &ExtraMessage) { + if extra_msg.get_type() == ExtraMessageType::MsgPreLoadRegionRequest { + self.cache_engine.load_region(r); + } + } +} + #[cfg(test)] mod tests { use std::sync::Mutex; @@ -217,6 +250,14 @@ mod tests { fn on_region_event(&self, event: RegionEvent) { self.region_events.lock().unwrap().push(event); } + + fn region_cached(&self, range: &Region) -> bool { + unreachable!() + } + + fn load_region(&self, range: &Region) { + unreachable!() + } } fn new_admin_request_batch_split() -> RaftCmdRequest { @@ -308,6 +349,7 @@ mod tests { let cached_region = CacheRegion::from_region(®ion); let expected = RegionEvent::TryLoad { region: cached_region, + for_manual_range: true, }; assert_eq!(&cache_engine.region_events.lock().unwrap()[0], &expected); } diff --git a/components/hybrid_engine/src/range_cache_engine.rs b/components/hybrid_engine/src/range_cache_engine.rs index cf8730a5345..22d6e6959eb 100644 --- a/components/hybrid_engine/src/range_cache_engine.rs +++ b/components/hybrid_engine/src/range_cache_engine.rs @@ -13,4 +13,14 @@ where fn on_region_event(&self, event: RegionEvent) { self.range_cache_engine().on_region_event(event); } + + #[inline] + fn region_cached(&self, region: &kvproto::metapb::Region) -> bool { + self.range_cache_engine().region_cached(region) + } + + #[inline] + fn load_region(&self, region: &kvproto::metapb::Region) { + self.range_cache_engine().load_region(region) + } } diff --git a/components/raftstore/src/coprocessor/dispatcher.rs b/components/raftstore/src/coprocessor/dispatcher.rs index 2ac4d62731d..bb34838a480 100644 --- a/components/raftstore/src/coprocessor/dispatcher.rs +++ b/components/raftstore/src/coprocessor/dispatcher.rs @@ -290,7 +290,16 @@ impl_box_observer_g!( ConsistencyCheckObserver, WrappedConsistencyCheckObserver ); -impl_box_observer!(BoxMessageObserver, MessageObserver, WrappedMessageObserver); +impl_box_observer!( + BoxRaftMessageObserver, + RaftMessageObserver, + WrappedRaftMessageObserver +); +impl_box_observer!( + BoxExtraMessageObserver, + ExtraMessageObserver, + WrappedExtraMessageObserver +); impl_box_observer!( BoxRegionHeartbeatObserver, RegionHeartbeatObserver, @@ -324,7 +333,8 @@ where read_index_observers: Vec>, pd_task_observers: Vec>, update_safe_ts_observers: Vec>, - message_observers: Vec>, + raft_message_observers: Vec>, + extra_message_observers: Vec>, region_heartbeat_observers: Vec>, // For now, `write_batch_observer` and `snapshot_observer` can only have one // observer solely because of simplicity. However, it is possible to have @@ -348,7 +358,8 @@ impl Default for Registry { read_index_observers: Default::default(), pd_task_observers: Default::default(), update_safe_ts_observers: Default::default(), - message_observers: Default::default(), + raft_message_observers: Default::default(), + extra_message_observers: Default::default(), region_heartbeat_observers: Default::default(), write_batch_observer: None, snapshot_observer: None, @@ -421,8 +432,12 @@ impl Registry { push!(priority, qo, self.update_safe_ts_observers); } - pub fn register_message_observer(&mut self, priority: u32, qo: BoxMessageObserver) { - push!(priority, qo, self.message_observers); + pub fn register_raft_message_observer(&mut self, priority: u32, qo: BoxRaftMessageObserver) { + push!(priority, qo, self.raft_message_observers); + } + + pub fn register_extra_message_observer(&mut self, priority: u32, qo: BoxExtraMessageObserver) { + push!(priority, qo, self.extra_message_observers); } pub fn register_region_heartbeat_observer( @@ -710,8 +725,22 @@ impl CoprocessorHost { ); } - pub fn pre_transfer_leader(&self, r: &Region, tr: &TransferLeaderRequest) -> Result<()> { - try_loop_ob!(r, &self.registry.admin_observers, pre_transfer_leader, tr) + pub fn pre_transfer_leader( + &self, + r: &Region, + tr: &TransferLeaderRequest, + ) -> Result> { + let mut ctx = ObserverContext::new(r); + let mut msgs = vec![]; + for o in &self.registry.admin_observers { + if let Some(msg) = (o.observer).inner().pre_transfer_leader(&mut ctx, tr)? { + msgs.push(msg); + } + if ctx.bypass { + break; + } + } + Ok(msgs) } pub fn post_apply_snapshot( @@ -855,9 +884,16 @@ impl CoprocessorHost { true } + pub fn on_extra_message(&self, r: &Region, msg: &ExtraMessage) { + for observer in &self.registry.extra_message_observers { + let observer = observer.observer.inner(); + observer.on_extra_message(r, msg); + } + } + /// Returns false if the message should not be stepped later. pub fn on_raft_message(&self, msg: &RaftMessage) -> bool { - for observer in &self.registry.message_observers { + for observer in &self.registry.raft_message_observers { let observer = observer.observer.inner(); if !observer.on_raft_message(msg) { return false; @@ -1247,7 +1283,7 @@ mod tests { } } - impl MessageObserver for TestCoprocessor { + impl RaftMessageObserver for TestCoprocessor { fn on_raft_message(&self, _: &RaftMessage) -> bool { self.called .fetch_add(ObserverIndex::OnRaftMessage as usize, Ordering::SeqCst); @@ -1292,7 +1328,7 @@ mod tests { host.registry .register_update_safe_ts_observer(1, BoxUpdateSafeTsObserver::new(ob.clone())); host.registry - .register_message_observer(1, BoxMessageObserver::new(ob.clone())); + .register_raft_message_observer(1, BoxRaftMessageObserver::new(ob.clone())); let mut index: usize = 0; let region = Region::default(); diff --git a/components/raftstore/src/coprocessor/mod.rs b/components/raftstore/src/coprocessor/mod.rs index 7b4d8909c71..2b6d5186f0b 100644 --- a/components/raftstore/src/coprocessor/mod.rs +++ b/components/raftstore/src/coprocessor/mod.rs @@ -17,7 +17,7 @@ use kvproto::{ AdminRequest, AdminResponse, RaftCmdRequest, RaftCmdResponse, Request, TransferLeaderRequest, }, - raft_serverpb::RaftApplyState, + raft_serverpb::{ExtraMessage, RaftApplyState}, }; use pd_client::RegionStat; use raft::{eraftpb, StateRole}; @@ -38,7 +38,7 @@ pub use self::{ consistency_check::{ConsistencyCheckObserver, Raw as RawConsistencyCheckObserver}, dispatcher::{ BoxAdminObserver, BoxApplySnapshotObserver, BoxCmdObserver, BoxConsistencyCheckObserver, - BoxMessageObserver, BoxPdTaskObserver, BoxQueryObserver, BoxRegionChangeObserver, + BoxPdTaskObserver, BoxQueryObserver, BoxRaftMessageObserver, BoxRegionChangeObserver, BoxRoleObserver, BoxSplitCheckObserver, BoxUpdateSafeTsObserver, CoprocessorHost, Registry, StoreHandle, }, @@ -145,8 +145,8 @@ pub trait AdminObserver: Coprocessor { &self, _ctx: &mut ObserverContext<'_>, _tr: &TransferLeaderRequest, - ) -> Result<()> { - Ok(()) + ) -> Result> { + Ok(None) } } @@ -362,13 +362,18 @@ pub trait RegionHeartbeatObserver: Coprocessor { fn on_region_heartbeat(&self, _: &mut ObserverContext<'_>, _: &RegionStat) {} } -pub trait MessageObserver: Coprocessor { +pub trait RaftMessageObserver: Coprocessor { /// Returns false if the message should not be stepped later. fn on_raft_message(&self, _: &RaftMessage) -> bool { true } } +// +pub trait ExtraMessageObserver: Coprocessor { + fn on_extra_message(&self, _: &Region, _: &ExtraMessage) {} +} + #[derive(Clone, Debug, Default)] pub struct Cmd { pub index: u64, diff --git a/components/raftstore/src/store/fsm/peer.rs b/components/raftstore/src/store/fsm/peer.rs index 92863fe13ba..1facb7320c6 100644 --- a/components/raftstore/src/store/fsm/peer.rs +++ b/components/raftstore/src/store/fsm/peer.rs @@ -3011,6 +3011,9 @@ where } fn on_extra_message(&mut self, mut msg: RaftMessage) { + self.ctx + .coprocessor_host + .on_extra_message(self.fsm.peer.region(), msg.get_extra_msg()); match msg.get_extra_msg().get_type() { ExtraMessageType::MsgRegionWakeUp | ExtraMessageType::MsgCheckStalePeer => { if msg.get_extra_msg().forcely_awaken { @@ -3108,6 +3111,12 @@ where } } } + ExtraMessageType::MsgPreLoadRegionRequest => { + // It has been handled in on_extra_message in coprocessor_host + } + ExtraMessageType::MsgPreLoadRegionResponse => { + // Ignore now + } } } diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index b22b3c2ad2d..1cd528c870d 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -3915,7 +3915,12 @@ where self.should_wake_up = true; } - fn pre_transfer_leader(&mut self, peer: &metapb::Peer) -> bool { + fn pre_transfer_leader( + &mut self, + peer: &metapb::Peer, + extra_msgs: Vec, + ctx: &mut PollContext, + ) -> bool { // Checks if safe to transfer leader. if self.raft_group.raft.has_pending_conf() { info!( @@ -3941,6 +3946,17 @@ where // forbids setting it for MsgTransferLeader messages. msg.set_log_term(self.term()); self.raft_group.raft.msgs.push(msg); + + extra_msgs.into_iter().for_each(|extra_msg| { + let mut msg = RaftMessage::default(); + msg.set_region_id(self.region_id); + msg.set_from_peer(self.peer.clone()); + msg.set_to_peer(peer.clone()); + msg.set_region_epoch(self.region().get_region_epoch().clone()); + msg.set_extra_msg(extra_msg); + self.send_raft_messages(ctx, vec![msg]); + }); + true } @@ -4794,27 +4810,29 @@ where /// to do the remaining work. /// /// See also: tikv/rfcs#37. - fn propose_transfer_leader( + fn propose_transfer_leader( &mut self, ctx: &mut PollContext, req: RaftCmdRequest, cb: Callback, ) -> bool { let transfer_leader = get_transfer_leader_cmd(&req).unwrap(); - if let Err(err) = ctx + let extra_msgs = match ctx .coprocessor_host .pre_transfer_leader(self.region(), transfer_leader) { - warn!("Coprocessor rejected transfer leader."; "err" => ?err, + Err(err) => { + warn!("Coprocessor rejected transfer leader."; "err" => ?err, "region_id" => self.region_id, "peer_id" => self.peer.get_id(), "transferee" => transfer_leader.get_peer().get_id()); - let mut resp = RaftCmdResponse::new(); - *resp.mut_header().mut_error() = Error::from(err).into(); - cb.invoke_with_response(resp); - return false; - } - + let mut resp = RaftCmdResponse::new(); + *resp.mut_header().mut_error() = Error::from(err).into(); + cb.invoke_with_response(resp); + return false; + } + Ok(msgs) => msgs, + }; ctx.raft_metrics.propose.transfer_leader.inc(); let prs = self.raft_group.raft.prs(); @@ -4846,7 +4864,7 @@ where let transferred = if peer.id == self.peer.id { false } else { - self.pre_transfer_leader(peer) + self.pre_transfer_leader(peer, extra_msgs, ctx) }; // transfer leader command doesn't need to replicate log and apply, so we @@ -5239,7 +5257,7 @@ where // Check disk usages for the peer itself and other peers in the raft group. // The return value indicates whether the proposal is allowed or not. - fn check_normal_proposal_with_disk_full_opt( + fn check_normal_proposal_with_disk_full_opt( &mut self, ctx: &mut PollContext, disk_full_opt: DiskFullOpt, @@ -5275,7 +5293,7 @@ where "peer_id" => self.peer.get_id(), "target_peer_id" => p.get_id(), ); - self.pre_transfer_leader(&p); + self.pre_transfer_leader(&p, vec![], ctx); } } } else { diff --git a/components/raftstore/src/store/snapshot_backup.rs b/components/raftstore/src/store/snapshot_backup.rs index 710ac281e8a..7643df09edb 100644 --- a/components/raftstore/src/store/snapshot_backup.rs +++ b/components/raftstore/src/store/snapshot_backup.rs @@ -10,7 +10,10 @@ use std::{ use engine_traits::{KvEngine, RaftEngine}; use futures::channel::mpsc::UnboundedSender; -use kvproto::{brpb::CheckAdminResponse, metapb::RegionEpoch, raft_cmdpb::AdminCmdType}; +use kvproto::{ + brpb::CheckAdminResponse, metapb::RegionEpoch, raft_cmdpb::AdminCmdType, + raft_serverpb::ExtraMessage, +}; use tikv_util::{info, warn}; use tokio::sync::oneshot; @@ -263,9 +266,9 @@ impl AdminObserver for Arc { &self, _ctx: &mut crate::coprocessor::ObserverContext<'_>, _tr: &kvproto::raft_cmdpb::TransferLeaderRequest, - ) -> crate::coprocessor::Result<()> { + ) -> crate::coprocessor::Result> { if self.allowed() { - return Ok(()); + return Ok(None); } metrics::SNAP_BR_SUSPEND_COMMAND_TYPE .with_label_values(&["TransferLeader"]) diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index bd1c486d863..1357490ffa4 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -1541,8 +1541,8 @@ pub mod tests { use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRegion, IterOptions, Iterable, Iterator, RangeCacheEngine, RegionEvent, SyncMutable, - CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + CacheRegion, IterOptions, Iterable, Iterator, RangeCacheEngine, RangeCacheEngineExt, + RegionEvent, SyncMutable, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use futures::future::ready; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index c1ded34411c..e2bfc0b5b16 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -15,7 +15,7 @@ use crossbeam_skiplist::{ use engine_rocks::RocksEngine; use engine_traits::{ CacheRegion, EvictReason, FailedReason, IterOptions, Iterable, KvEngine, RangeCacheEngine, - RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + RangeCacheEngineExt, RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use kvproto::metapb::Region; use raftstore::coprocessor::RegionInfoProvider; @@ -481,31 +481,44 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { fn enabled(&self) -> bool { self.config.value().enabled } +} +impl RangeCacheEngineExt for RangeCacheMemoryEngine { fn on_region_event(&self, event: RegionEvent) { match event { RegionEvent::Eviction { region, reason } => { self.evict_region(®ion, reason, None); } - RegionEvent::TryLoad { region } => { - if self - .core - .region_manager() - .regions_map() - .read() - .overlap_with_manual_load_range(®ion) - { - info!( - "try to load region in manual load range"; - "region" => ?region, - ); - if let Err(e) = self.load_region(region.clone()) { - warn!( - "ime load region failed"; - "err" => ?e, + RegionEvent::TryLoad { + region, + for_manual_range, + } => { + if for_manual_range { + if self + .core + .region_manager() + .regions_map() + .read() + .overlap_with_manual_load_range(®ion) + { + info!( + "try to load region in manual load range"; "region" => ?region, ); + if let Err(e) = self.load_region(region.clone()) { + warn!( + "ime load region failed"; + "err" => ?e, + "region" => ?region, + ); + } } + } else if let Err(e) = self.core.region_manager().load_region(region.clone()) { + warn!( + "ime load region failed"; + "error" => ?e, + "region" => ?region, + ); } } RegionEvent::Split { @@ -531,6 +544,22 @@ impl RangeCacheEngine for RangeCacheMemoryEngine { } } } + + fn region_cached(&self, region: &Region) -> bool { + let regions_map = self.core.region_manager().regions_map().read(); + if let Some(meta) = regions_map.region_meta(region.get_id()) { + matches!(meta.get_state(), RegionState::Active | RegionState::Loading) + } else { + false + } + } + + fn load_region(&self, region: &Region) { + self.on_region_event(RegionEvent::TryLoad { + region: CacheRegion::from_region(region), + for_manual_range: false, + }); + } } impl Iterable for RangeCacheMemoryEngine { @@ -549,8 +578,8 @@ pub mod tests { use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRegion, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, - WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + CacheRegion, EvictReason, Mutable, RangeCacheEngine, RangeCacheEngineExt, RegionEvent, + WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; use tokio::{ diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index d648b717de6..5a520d66461 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -671,8 +671,8 @@ mod tests { }; use engine_traits::{ CacheRegion, EvictReason, FailedReason, IterMetricsCollector, IterOptions, Iterable, - Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, ReadOptions, RegionEvent, - WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, + Iterator, MetricsExt, Mutable, Peekable, RangeCacheEngine, RangeCacheEngineExt, + ReadOptions, RegionEvent, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, }; use keys::DATA_PREFIX_KEY; use tempfile::Builder; diff --git a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs index 6f3c0072815..67c0adbdba5 100644 --- a/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs +++ b/components/range_cache_memory_engine/tests/failpoints/test_memory_engine.rs @@ -8,8 +8,8 @@ use std::{ use crossbeam::epoch; use engine_rocks::util::new_engine; use engine_traits::{ - CacheRegion, EvictReason, Mutable, RangeCacheEngine, RegionEvent, WriteBatch, WriteBatchExt, - CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, + CacheRegion, EvictReason, Mutable, RangeCacheEngine, RangeCacheEngineExt, RegionEvent, + WriteBatch, WriteBatchExt, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; use kvproto::metapb::Region; diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index d57aa25eb63..ea98a7d20fe 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -7,7 +7,8 @@ use std::{ use engine_rocks::RocksSstWriterBuilder; use engine_traits::{ - CacheRegion, EvictReason, RangeCacheEngine, SstWriter, SstWriterBuilder, CF_DEFAULT, + CacheRegion, EvictReason, RangeCacheEngine, RangeCacheEngineExt, SstWriter, SstWriterBuilder, + CF_DEFAULT, }; use file_system::calc_crc32_bytes; use keys::{data_key, DATA_MAX_KEY, DATA_MIN_KEY}; @@ -634,3 +635,33 @@ fn test_eviction_after_ingest_sst() { .snapshot(cache_region, 100, 100) .unwrap_err(); } + +#[test] +fn test_pre_load_when_transfer_ledaer() { + let mut cluster = new_server_cluster_with_hybrid_engine_with_no_range_cache(0, 3); + cluster.run(); + + let (tx, rx) = unbounded(); + fail::cfg_callback("on_completes_batch_loading", move || { + tx.send(true).unwrap(); + }) + .unwrap(); + + let r = cluster.get_region(b""); + cluster.must_transfer_leader(r.id, new_peer(1, 1)); + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(1); + range_cache_engine + .load_region(CacheRegion::from_region(&r)) + .unwrap(); + // put some key to trigger load + cluster.must_put(b"k", b"val"); + let _ = rx.recv_timeout(Duration::from_secs(500)).unwrap(); + + cluster.must_transfer_leader(r.id, new_peer(2, 2)); + // put some key to trigger load + cluster.must_put(b"k2", b"val"); + let _ = rx.recv_timeout(Duration::from_secs(500)).unwrap(); + + let range_cache_engine = cluster.sim.rl().get_range_cache_engine(2); + range_cache_engine.region_cached(&r); +} From 91aeaafcc24cf689e0486c21b23419949689f0cf Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:15:29 +0800 Subject: [PATCH 076/144] In-memory engine: fix flaky test `test_load_with_split` (#17558) close tikv/tikv#17556 fix flaky test `test_load_with_split` Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- tests/failpoints/cases/test_range_cache_engine.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/failpoints/cases/test_range_cache_engine.rs b/tests/failpoints/cases/test_range_cache_engine.rs index ea98a7d20fe..076f84e5056 100644 --- a/tests/failpoints/cases/test_range_cache_engine.rs +++ b/tests/failpoints/cases/test_range_cache_engine.rs @@ -180,13 +180,6 @@ fn test_load_with_split() { cluster.cfg.raft_store.apply_batch_system.pool_size = 2; cluster.run(); - let mut tables = vec![]; - for _ in 0..3 { - let product = ProductTable::new(); - tables.push(product.clone()); - must_copr_load_data(&mut cluster, &product, 1); - } - let (tx, rx) = sync_channel(0); // let channel to make load process block at finishing loading snapshot let (tx2, rx2) = sync_channel(0); @@ -210,6 +203,13 @@ fn test_load_with_split() { .unwrap(); } + let mut tables = vec![]; + for _ in 0..3 { + let product = ProductTable::new(); + tables.push(product.clone()); + must_copr_load_data(&mut cluster, &product, 1); + } + rx.recv_timeout(Duration::from_secs(5)).unwrap(); // Now, the snapshot load is finished, and blocked before consuming cached // write batches. Let split the range. From 29e491038704522a0659bddebd86ed1a934bc911 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 20 Sep 2024 17:54:51 +0800 Subject: [PATCH 077/144] In-memory Engine: decoupling raftstore and IME (#17386) ref tikv/tikv#17181 * Do not disable snapshot cache when IME is enabled Since `async_in_memory_snapshot` always takes an in-memory engine snapshot regardless of whether the RocksDB snapshot is cached, we can safely revert #16863 and address @tonyxuqqi's concern raised in https://github.com/tikv/tikv/pull/16863#discussion_r1571496020 * Remove SnapshotContext from LocalReadRouter This commit partially reverts #16181. * Remove SnapshotContext from KvEngine::snapshot This commit partially reverts #16163. By removing `SnapshotContext` from `KvEngine::snapshot`, raftstore is no longer coupled with the In-Memory Engine. Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 - components/backup-stream/src/utils.rs | 2 +- components/cdc/src/observer.rs | 5 +- components/cdc/src/old_value.rs | 6 +- components/engine_panic/src/engine.rs | 2 +- components/engine_rocks/src/engine.rs | 8 +- components/engine_traits/src/engine.rs | 5 +- .../engine_traits_tests/src/iterator.rs | 40 +- .../src/read_consistency.rs | 6 +- .../engine_traits_tests/src/snapshot_basic.rs | 8 +- components/hybrid_engine/src/engine.rs | 50 ++- .../hybrid_engine/src/observer/snapshot.rs | 13 +- components/hybrid_engine/src/snapshot.rs | 8 +- components/hybrid_engine/src/write_batch.rs | 4 +- .../src/operation/query/capture.rs | 2 +- .../raftstore-v2/src/operation/query/local.rs | 6 +- components/raftstore/Cargo.toml | 2 - .../raftstore/src/coprocessor/dispatcher.rs | 7 +- .../src/coprocessor/read_write/snapshot.rs | 9 +- components/raftstore/src/router.rs | 21 +- .../src/store/async_io/write_tests.rs | 4 +- components/raftstore/src/store/fsm/apply.rs | 6 +- components/raftstore/src/store/peer.rs | 25 +- .../raftstore/src/store/peer_storage.rs | 4 +- .../raftstore/src/store/region_snapshot.rs | 7 +- components/raftstore/src/store/snap.rs | 16 +- components/raftstore/src/store/snap/io.rs | 4 +- .../src/store/worker/consistency_check.rs | 2 +- components/raftstore/src/store/worker/read.rs | 421 +++--------------- .../raftstore/src/store/worker/region.rs | 4 +- .../range_cache_memory_engine/src/engine.rs | 2 +- .../range_cache_memory_engine/src/read.rs | 2 +- components/server/src/server.rs | 37 +- components/test_raftstore/src/cluster.rs | 157 +------ components/test_raftstore/src/node.rs | 8 +- components/test_raftstore/src/server.rs | 11 +- .../test_raftstore/src/transport_simulate.rs | 10 +- components/test_raftstore/src/util.rs | 21 +- components/tikv_kv/src/rocksdb_engine.rs | 2 +- src/server/raft_server.rs | 2 +- src/server/raftkv/mod.rs | 33 +- tests/benches/misc/raftkv/mod.rs | 15 +- tests/failpoints/cases/test_witness.rs | 8 +- tests/integrations/raftstore/test_snap.rs | 2 +- tests/integrations/raftstore/test_witness.rs | 2 +- tests/integrations/storage/test_titan.rs | 4 +- 46 files changed, 257 insertions(+), 758 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57e46ed0d67..c90df74def1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4269,7 +4269,6 @@ dependencies = [ "getset", "grpcio-health", "health_controller", - "hybrid_engine", "into_other", "itertools", "keys", @@ -4290,7 +4289,6 @@ dependencies = [ "raft", "raft-proto", "rand 0.8.5", - "range_cache_memory_engine", "resource_control", "resource_metering", "serde", diff --git a/components/backup-stream/src/utils.rs b/components/backup-stream/src/utils.rs index f651ab6d308..9165f54053a 100644 --- a/components/backup-stream/src/utils.rs +++ b/components/backup-stream/src/utils.rs @@ -1012,7 +1012,7 @@ mod test { let (items, size) = super::with_record_read_throughput(|| { let mut items = vec![]; - let snap = engine.snapshot(None); + let snap = engine.snapshot(); snap.scan(CF_DEFAULT, b"", b"", false, |k, v| { items.push((k.to_owned(), v.to_owned())); Ok(true) diff --git a/components/cdc/src/observer.rs b/components/cdc/src/observer.rs index 6bc36e56c98..061dd9daa36 100644 --- a/components/cdc/src/observer.rs +++ b/components/cdc/src/observer.rs @@ -119,8 +119,9 @@ impl CmdObserver for CdcObserver { let mut region = Region::default(); region.mut_peers().push(Peer::default()); // Create a snapshot here for preventing the old value was GC-ed. - let snapshot = - RegionSnapshot::from_snapshot(Arc::new(engine.snapshot(None)), Arc::new(region)); + // TODO: only need it after enabling old value, may add a flag to indicate + // whether to get it. + let snapshot = RegionSnapshot::from_snapshot(Arc::new(engine.snapshot()), Arc::new(region)); let get_old_value = move |key, query_ts, old_value_cache: &mut OldValueCache, diff --git a/components/cdc/src/old_value.rs b/components/cdc/src/old_value.rs index 269a70d477e..1ab5a3a7510 100644 --- a/components/cdc/src/old_value.rs +++ b/components/cdc/src/old_value.rs @@ -310,7 +310,7 @@ mod tests { value: Option, ) -> Statistics { let key = key.clone().append_ts(ts.into()); - let snapshot = Arc::new(kv_engine.snapshot(None)); + let snapshot = Arc::new(kv_engine.snapshot()); let mut cursor = new_write_cursor_on_key(&snapshot, &key); let load_default = Either::Left(&snapshot); let mut stats = Statistics::default(); @@ -529,7 +529,7 @@ mod tests { must_commit(&mut engine, &key, 200, 201); } - let snapshot = Arc::new(kv_engine.snapshot(None)); + let snapshot = Arc::new(kv_engine.snapshot()); let mut cursor = new_old_value_cursor(&snapshot, CF_WRITE); let mut default_cursor = new_old_value_cursor(&snapshot, CF_DEFAULT); let mut load_default = |use_default_cursor: bool| { @@ -601,7 +601,7 @@ mod tests { } let key = format!("zkey-{:0>3}", 0).into_bytes(); - let snapshot = Arc::new(kv_engine.snapshot(None)); + let snapshot = Arc::new(kv_engine.snapshot()); let perf_instant = ReadPerfInstant::new(); let value = get_old_value( &snapshot, diff --git a/components/engine_panic/src/engine.rs b/components/engine_panic/src/engine.rs index 60038e3fcf8..52dc8cfb499 100644 --- a/components/engine_panic/src/engine.rs +++ b/components/engine_panic/src/engine.rs @@ -13,7 +13,7 @@ pub struct PanicEngine; impl KvEngine for PanicEngine { type Snapshot = PanicSnapshot; - fn snapshot(&self, _: Option) -> Self::Snapshot { + fn snapshot(&self) -> Self::Snapshot { panic!() } fn sync(&self) -> Result<()> { diff --git a/components/engine_rocks/src/engine.rs b/components/engine_rocks/src/engine.rs index 19f258f659b..e393f58721c 100644 --- a/components/engine_rocks/src/engine.rs +++ b/components/engine_rocks/src/engine.rs @@ -2,9 +2,7 @@ use std::{any::Any, sync::Arc}; -use engine_traits::{ - IterOptions, Iterable, KvEngine, Peekable, ReadOptions, Result, SnapshotContext, SyncMutable, -}; +use engine_traits::{IterOptions, Iterable, KvEngine, Peekable, ReadOptions, Result, SyncMutable}; use rocksdb::{DBIterator, Writable, DB}; use crate::{ @@ -184,7 +182,7 @@ impl RocksEngine { impl KvEngine for RocksEngine { type Snapshot = RocksSnapshot; - fn snapshot(&self, _: Option) -> RocksSnapshot { + fn snapshot(&self) -> RocksSnapshot { RocksSnapshot::new(self.db.clone()) } @@ -297,7 +295,7 @@ mod tests { engine.put_msg(key, &r).unwrap(); engine.put_msg_cf(cf, key, &r).unwrap(); - let snap = engine.snapshot(None); + let snap = engine.snapshot(); let mut r1: Region = engine.get_msg(key).unwrap().unwrap(); assert_eq!(r, r1); diff --git a/components/engine_traits/src/engine.rs b/components/engine_traits/src/engine.rs index a3aff48543c..a797ae7feb2 100644 --- a/components/engine_traits/src/engine.rs +++ b/components/engine_traits/src/engine.rs @@ -39,10 +39,7 @@ pub trait KvEngine: type Snapshot: Snapshot; /// Create a snapshot - /// - /// SnapCtx will only be used by some type of trait implementors (ex: - /// HybridEngine) - fn snapshot(&self, snap_ctx: Option) -> Self::Snapshot; + fn snapshot(&self) -> Self::Snapshot; /// Syncs any writes to disk fn sync(&self) -> Result<()>; diff --git a/components/engine_traits_tests/src/iterator.rs b/components/engine_traits_tests/src/iterator.rs index fee6cda6f02..714ca4cb0b4 100644 --- a/components/engine_traits_tests/src/iterator.rs +++ b/components/engine_traits_tests/src/iterator.rs @@ -41,9 +41,7 @@ fn iter_empty_engine() { #[test] fn iter_empty_snapshot() { let db = default_engine(); - iter_empty(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iter_empty(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn iter_forward(e: &E, i: IF) @@ -101,9 +99,7 @@ fn iter_forward_engine() { #[test] fn iter_forward_snapshot() { let db = default_engine(); - iter_forward(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iter_forward(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn iter_reverse(e: &E, i: IF) @@ -161,9 +157,7 @@ fn iter_reverse_engine() { #[test] fn iter_reverse_snapshot() { let db = default_engine(); - iter_reverse(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iter_reverse(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn seek_to_key_then_forward(e: &E, i: IF) @@ -204,9 +198,7 @@ fn seek_to_key_then_forward_engine() { #[test] fn seek_to_key_then_forward_snapshot() { let db = default_engine(); - seek_to_key_then_forward(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + seek_to_key_then_forward(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn seek_to_key_then_reverse(e: &E, i: IF) @@ -247,9 +239,7 @@ fn seek_to_key_then_reverse_engine() { #[test] fn seek_to_key_then_reverse_snapshot() { let db = default_engine(); - seek_to_key_then_reverse(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + seek_to_key_then_reverse(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn iter_forward_then_reverse(e: &E, i: IF) @@ -310,9 +300,7 @@ fn iter_forward_then_reverse_engine() { #[test] fn iter_forward_then_reverse_snapshot() { let db = default_engine(); - iter_forward_then_reverse(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iter_forward_then_reverse(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn iter_reverse_then_forward(e: &E, i: IF) @@ -373,9 +361,7 @@ fn iter_reverse_then_forward_engine() { #[test] fn iter_reverse_then_forward_snapshot() { let db = default_engine(); - iter_reverse_then_forward(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iter_reverse_then_forward(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } // When seek finds an exact key then seek_for_prev behaves just like seek @@ -419,9 +405,7 @@ fn seek_for_prev_engine() { #[test] fn seek_for_prev_snapshot() { let db = default_engine(); - seek_for_prev(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + seek_for_prev(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } // When Seek::Key doesn't find an exact match, @@ -456,9 +440,7 @@ fn seek_key_miss_engine() { #[test] fn seek_key_miss_snapshot() { let db = default_engine(); - seek_key_miss(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + seek_key_miss(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } fn seek_key_prev_miss(e: &E, i: IF) @@ -490,7 +472,5 @@ fn seek_key_prev_miss_engine() { #[test] fn seek_key_prev_miss_snapshot() { let db = default_engine(); - seek_key_prev_miss(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + seek_key_prev_miss(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } diff --git a/components/engine_traits_tests/src/read_consistency.rs b/components/engine_traits_tests/src/read_consistency.rs index 35d0262fbcb..8c7ab50657f 100644 --- a/components/engine_traits_tests/src/read_consistency.rs +++ b/components/engine_traits_tests/src/read_consistency.rs @@ -12,7 +12,7 @@ fn snapshot_with_writes() { db.engine.put(b"a", b"aa").unwrap(); - let snapshot = db.engine.snapshot(None); + let snapshot = db.engine.snapshot(); assert_eq!(snapshot.get_value(b"a").unwrap().unwrap(), b"aa"); @@ -77,7 +77,5 @@ fn iterator_with_writes_engine() { #[test] fn iterator_with_writes_snapshot() { let db = default_engine(); - iterator_with_writes(&db.engine, |e| { - e.snapshot(None).iterator(CF_DEFAULT).unwrap() - }); + iterator_with_writes(&db.engine, |e| e.snapshot().iterator(CF_DEFAULT).unwrap()); } diff --git a/components/engine_traits_tests/src/snapshot_basic.rs b/components/engine_traits_tests/src/snapshot_basic.rs index 83248abfb6e..c0f93480830 100644 --- a/components/engine_traits_tests/src/snapshot_basic.rs +++ b/components/engine_traits_tests/src/snapshot_basic.rs @@ -10,7 +10,7 @@ fn snapshot_get_value() { db.engine.put(b"a", b"aa").unwrap(); - let snap = db.engine.snapshot(None); + let snap = db.engine.snapshot(); let value = snap.get_value(b"a").unwrap(); let value = value.unwrap(); @@ -26,7 +26,7 @@ fn snapshot_get_value_after_put() { db.engine.put(b"a", b"aa").unwrap(); - let snap = db.engine.snapshot(None); + let snap = db.engine.snapshot(); db.engine.put(b"a", b"aaa").unwrap(); @@ -41,7 +41,7 @@ fn snapshot_get_value_cf() { db.engine.put_cf(CF_WRITE, b"a", b"aa").unwrap(); - let snap = db.engine.snapshot(None); + let snap = db.engine.snapshot(); let value = snap.get_value_cf(CF_WRITE, b"a").unwrap(); let value = value.unwrap(); @@ -57,7 +57,7 @@ fn snapshot_get_value_cf_after_put() { db.engine.put_cf(CF_WRITE, b"a", b"aa").unwrap(); - let snap = db.engine.snapshot(None); + let snap = db.engine.snapshot(); db.engine.put_cf(CF_WRITE, b"a", b"aaa").unwrap(); diff --git a/components/hybrid_engine/src/engine.rs b/components/hybrid_engine/src/engine.rs index 870b122a695..9935006b31e 100644 --- a/components/hybrid_engine/src/engine.rs +++ b/components/hybrid_engine/src/engine.rs @@ -1,7 +1,7 @@ // Copyright 2023 TiKV Project Authors. Licensed under Apache-2.0. use engine_traits::{ - FailedReason, KvEngine, Mutable, Peekable, RangeCacheEngine, ReadOptions, Result, + CacheRegion, FailedReason, KvEngine, Mutable, Peekable, RangeCacheEngine, ReadOptions, Result, SnapshotContext, SnapshotMiscExt, SyncMutable, WriteBatch, WriteBatchExt, }; @@ -52,10 +52,11 @@ where pub fn new_in_memory_snapshot( range_cache_engine: &EC, - ctx: SnapshotContext, + region: CacheRegion, + read_ts: u64, sequence_number: u64, ) -> Option { - match range_cache_engine.snapshot(ctx.region.unwrap(), ctx.read_ts, sequence_number) { + match range_cache_engine.snapshot(region, read_ts, sequence_number) { Ok(snap) => { SNAPSHOT_TYPE_COUNT_STATIC.range_cache_engine.inc(); Some(snap) @@ -95,6 +96,23 @@ where range_cache_engine, } } + + pub fn new_snapshot(&self, ctx: Option) -> HybridEngineSnapshot { + let disk_snap = self.disk_engine.snapshot(); + let range_cache_snap = if !self.range_cache_engine.enabled() { + None + } else if let Some(ctx) = ctx { + new_in_memory_snapshot( + &self.range_cache_engine, + ctx.region.unwrap(), + ctx.read_ts, + disk_snap.sequence_number(), + ) + } else { + None + }; + HybridEngineSnapshot::new(disk_snap, range_cache_snap) + } } impl HybridEngine @@ -126,20 +144,8 @@ where { type Snapshot = HybridEngineSnapshot; - fn snapshot(&self, ctx: Option) -> Self::Snapshot { - let disk_snap = self.disk_engine.snapshot(ctx.clone()); - let range_cache_snap = if !self.range_cache_engine.enabled() { - None - } else if let Some(ctx) = ctx { - new_in_memory_snapshot(&self.range_cache_engine, ctx, disk_snap.sequence_number()) - } else { - RANGE_CACHEN_SNAPSHOT_ACQUIRE_FAILED_REASON_COUNT_STAIC - .no_read_ts - .inc(); - SNAPSHOT_TYPE_COUNT_STATIC.rocksdb.inc(); - None - }; - HybridEngineSnapshot::new(disk_snap, range_cache_snap) + fn snapshot(&self) -> Self::Snapshot { + unreachable!() } fn sync(&self) -> engine_traits::Result<()> { @@ -216,7 +222,7 @@ mod tests { use std::sync::Arc; use engine_rocks::util::new_engine; - use engine_traits::{CacheRegion, KvEngine, SnapshotContext, CF_DEFAULT, CF_LOCK, CF_WRITE}; + use engine_traits::{CacheRegion, SnapshotContext, CF_DEFAULT, CF_LOCK, CF_WRITE}; use online_config::{ConfigChange, ConfigManager, ConfigValue}; use range_cache_memory_engine::{ config::RangeCacheConfigManager, test_util::new_region, RangeCacheEngineConfig, @@ -248,18 +254,18 @@ mod tests { .set_safe_point(region.id, 10); let hybrid_engine = HybridEngine::new(disk_engine, memory_engine.clone()); - let s = hybrid_engine.snapshot(None); + let s = hybrid_engine.new_snapshot(None); assert!(!s.range_cache_snapshot_available()); let mut snap_ctx = SnapshotContext { read_ts: 15, region: Some(range.clone()), }; - let s = hybrid_engine.snapshot(Some(snap_ctx.clone())); + let s = hybrid_engine.new_snapshot(Some(snap_ctx.clone())); assert!(s.range_cache_snapshot_available()); snap_ctx.read_ts = 5; - let s = hybrid_engine.snapshot(Some(snap_ctx.clone())); + let s = hybrid_engine.new_snapshot(Some(snap_ctx.clone())); assert!(!s.range_cache_snapshot_available()); let mut config_manager = RangeCacheConfigManager(config.clone()); @@ -268,7 +274,7 @@ mod tests { config_manager.dispatch(config_change).unwrap(); assert!(!config.value().enabled); snap_ctx.read_ts = 15; - let s = hybrid_engine.snapshot(Some(snap_ctx)); + let s = hybrid_engine.new_snapshot(Some(snap_ctx)); assert!(!s.range_cache_snapshot_available()); } } diff --git a/components/hybrid_engine/src/observer/snapshot.rs b/components/hybrid_engine/src/observer/snapshot.rs index 377cb856131..77f55df1a1b 100644 --- a/components/hybrid_engine/src/observer/snapshot.rs +++ b/components/hybrid_engine/src/observer/snapshot.rs @@ -1,6 +1,7 @@ // Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. -use engine_traits::{KvEngine, SnapshotContext}; +use engine_traits::{CacheRegion, KvEngine}; +use kvproto::metapb::Region; use raftstore::coprocessor::{ dispatcher::BoxSnapshotObserver, CoprocessorHost, ObservedSnapshot, SnapshotObserver, }; @@ -36,11 +37,17 @@ impl HybridSnapshotObserver { } impl SnapshotObserver for HybridSnapshotObserver { - fn on_snapshot(&self, ctx: SnapshotContext, sequence_number: u64) -> Box { + fn on_snapshot( + &self, + region: &Region, + read_ts: u64, + sequence_number: u64, + ) -> Box { // Taking a snapshot to pin data in the cache engine which prevents the // data from being evicted or deleted from the cache. // The data should be released when the snapshot is dropped. - let snap = new_in_memory_snapshot(&self.cache_engine, ctx, sequence_number); + let region = CacheRegion::from_region(region); + let snap = new_in_memory_snapshot(&self.cache_engine, region, read_ts, sequence_number); Box::new(RangeCacheSnapshotPin { snap }) } } diff --git a/components/hybrid_engine/src/snapshot.rs b/components/hybrid_engine/src/snapshot.rs index b3cc5c33781..2dbc24fb2d8 100644 --- a/components/hybrid_engine/src/snapshot.rs +++ b/components/hybrid_engine/src/snapshot.rs @@ -161,8 +161,8 @@ where mod tests { use engine_traits::{ - CacheRegion, IterOptions, Iterable, Iterator, KvEngine, Mutable, SnapshotContext, - WriteBatch, WriteBatchExt, CF_DEFAULT, + CacheRegion, IterOptions, Iterable, Iterator, Mutable, SnapshotContext, WriteBatch, + WriteBatchExt, CF_DEFAULT, }; use range_cache_memory_engine::{ test_util::new_region, RangeCacheEngineConfig, RangeCacheStatus, @@ -188,7 +188,7 @@ mod tests { }, ) .unwrap(); - let snap = hybrid_engine.snapshot(None); + let snap = hybrid_engine.new_snapshot(None); { let mut iter = snap.iterator_opt(CF_DEFAULT, iter_opt.clone()).unwrap(); assert!(!iter.seek_to_first().unwrap()); @@ -205,7 +205,7 @@ mod tests { region: Some(cache_region.clone()), read_ts: 10, }; - let snap = hybrid_engine.snapshot(Some(ctx)); + let snap = hybrid_engine.new_snapshot(Some(ctx)); { let mut iter = snap.iterator_opt(CF_DEFAULT, iter_opt).unwrap(); assert!(iter.seek_to_first().unwrap()); diff --git a/components/hybrid_engine/src/write_batch.rs b/components/hybrid_engine/src/write_batch.rs index f79101dda6e..bd737061aa1 100644 --- a/components/hybrid_engine/src/write_batch.rs +++ b/components/hybrid_engine/src/write_batch.rs @@ -152,7 +152,7 @@ mod tests { use std::time::Duration; use engine_traits::{ - CacheRegion, KvEngine, Mutable, Peekable, RangeCacheEngine, SnapshotContext, WriteBatch, + CacheRegion, Mutable, Peekable, RangeCacheEngine, SnapshotContext, WriteBatch, WriteBatchExt, }; use range_cache_memory_engine::{ @@ -190,7 +190,7 @@ mod tests { region: Some(cache_region.clone()), read_ts: 10, }; - let snap = hybrid_engine.snapshot(Some(ctx)); + let snap = hybrid_engine.new_snapshot(Some(ctx)); let actual: &[u8] = &snap.get_value(b"zhello").unwrap().unwrap(); assert_eq!(b"world", &actual); let actual: &[u8] = &snap.disk_snap().get_value(b"zhello").unwrap().unwrap(); diff --git a/components/raftstore-v2/src/operation/query/capture.rs b/components/raftstore-v2/src/operation/query/capture.rs index 868ed12ed32..4b6a8c24fc3 100644 --- a/components/raftstore-v2/src/operation/query/capture.rs +++ b/components/raftstore-v2/src/operation/query/capture.rs @@ -118,7 +118,7 @@ impl Apply { self.flush(); let (applied_index, _) = self.apply_progress(); let snap = RegionSnapshot::from_snapshot( - Arc::new(self.tablet().snapshot(None)), + Arc::new(self.tablet().snapshot()), Arc::new(self.region().clone()), ); snap.set_apply_index(applied_index); diff --git a/components/raftstore-v2/src/operation/query/local.rs b/components/raftstore-v2/src/operation/query/local.rs index dd540762a69..a474ff3e049 100644 --- a/components/raftstore-v2/src/operation/query/local.rs +++ b/components/raftstore-v2/src/operation/query/local.rs @@ -209,7 +209,7 @@ where ReadRequestPolicy::ReadLocal => { let region = Arc::clone(&delegate.region); let snap = RegionSnapshot::from_snapshot( - Arc::new(delegate.cached_tablet.cache().snapshot(None)), + Arc::new(delegate.cached_tablet.cache().snapshot()), region, ); @@ -240,7 +240,7 @@ where let region = Arc::clone(&delegate.region); let snap = RegionSnapshot::from_snapshot( - Arc::new(delegate.cached_tablet.cache().snapshot(None)), + Arc::new(delegate.cached_tablet.cache().snapshot()), region, ); @@ -264,7 +264,7 @@ where let region = Arc::clone(&delegate.region); let snap = RegionSnapshot::from_snapshot( - Arc::new(delegate.cached_tablet.cache().snapshot(None)), + Arc::new(delegate.cached_tablet.cache().snapshot()), region, ); diff --git a/components/raftstore/Cargo.toml b/components/raftstore/Cargo.toml index 258c736d178..9b2a1be33b8 100644 --- a/components/raftstore/Cargo.toml +++ b/components/raftstore/Cargo.toml @@ -96,7 +96,5 @@ encryption_export = { workspace = true } engine_panic = { workspace = true } engine_rocks = { workspace = true } engine_test = { workspace = true } -hybrid_engine = { workspace = true } panic_hook = { workspace = true } -range_cache_memory_engine = { workspace = true } test_sst_importer = { workspace = true } diff --git a/components/raftstore/src/coprocessor/dispatcher.rs b/components/raftstore/src/coprocessor/dispatcher.rs index bb34838a480..ac7bfbf5396 100644 --- a/components/raftstore/src/coprocessor/dispatcher.rs +++ b/components/raftstore/src/coprocessor/dispatcher.rs @@ -3,7 +3,7 @@ // #[PerformanceCriticalPath] called by Fsm on_ready_compute_hash use std::{borrow::Cow, marker::PhantomData, mem, ops::Deref}; -use engine_traits::{CfName, KvEngine, SnapshotContext, WriteBatch}; +use engine_traits::{CfName, KvEngine, WriteBatch}; use kvproto::{ metapb::{Region, RegionEpoch}, pdpb::CheckPolicy, @@ -960,13 +960,14 @@ impl CoprocessorHost { pub fn on_snapshot( &self, - ctx: SnapshotContext, + region: &Region, + read_ts: u64, seqno: u64, ) -> Option> { self.registry .snapshot_observer .as_ref() - .map(move |observer| observer.inner().on_snapshot(ctx, seqno)) + .map(move |observer| observer.inner().on_snapshot(region, read_ts, seqno)) } pub fn shutdown(&self) { diff --git a/components/raftstore/src/coprocessor/read_write/snapshot.rs b/components/raftstore/src/coprocessor/read_write/snapshot.rs index c982ba5894e..b65a98680b4 100644 --- a/components/raftstore/src/coprocessor/read_write/snapshot.rs +++ b/components/raftstore/src/coprocessor/read_write/snapshot.rs @@ -2,7 +2,7 @@ use std::any::Any; -use engine_traits::SnapshotContext; +use kvproto::metapb::Region; /// ObservedSnapshot is a trait that represents data that are observed during /// taking snapshot. @@ -12,5 +12,10 @@ pub trait ObservedSnapshot: Any + Send + Sync {} /// SnapshotObserver is a trait that observes the snapshot process. pub trait SnapshotObserver: Send { /// on_snapshot is called when raftstore is taking RegionSnapshot. - fn on_snapshot(&self, ctx: SnapshotContext, sequence_number: u64) -> Box; + fn on_snapshot( + &self, + region: &Region, + read_ts: u64, + sequence_number: u64, + ) -> Box; } diff --git a/components/raftstore/src/router.rs b/components/raftstore/src/router.rs index 18a33202eb3..afa8b831ba2 100644 --- a/components/raftstore/src/router.rs +++ b/components/raftstore/src/router.rs @@ -7,7 +7,7 @@ use std::{ // #[PerformanceCriticalPath] use crossbeam::channel::TrySendError; -use engine_traits::{KvEngine, RaftEngine, Snapshot, SnapshotContext}; +use engine_traits::{KvEngine, RaftEngine, Snapshot}; use error_code::ErrorCodeExt; use kvproto::{metapb, raft_cmdpb::RaftCmdRequest, raft_serverpb::RaftMessage}; use raft::SnapshotStatus; @@ -118,14 +118,24 @@ where .map_err(|e| handle_send_error(region_id, e)) } +pub struct ReadContext { + pub(crate) read_id: Option, + pub(crate) read_ts: Option, +} + +impl ReadContext { + pub fn new(read_id: Option, read_ts: Option) -> Self { + ReadContext { read_id, read_ts } + } +} + pub trait LocalReadRouter: Send + Clone where EK: KvEngine, { fn read( &mut self, - snap_ctx: Option, - read_id: Option, + ctx: ReadContext, req: RaftCmdRequest, cb: Callback, ) -> RaftStoreResult<()>; @@ -255,12 +265,11 @@ impl RaftStoreRouter for ServerRaftStoreRouter impl LocalReadRouter for ServerRaftStoreRouter { fn read( &mut self, - snap_ctx: Option, - read_id: Option, + ctx: ReadContext, req: RaftCmdRequest, cb: Callback, ) -> RaftStoreResult<()> { - self.local_reader.read(snap_ctx, read_id, req, cb); + self.local_reader.read(ctx, req, cb); Ok(()) } diff --git a/components/raftstore/src/store/async_io/write_tests.rs b/components/raftstore/src/store/async_io/write_tests.rs index bc0cde09fa8..aa6bd8aca3c 100644 --- a/components/raftstore/src/store/async_io/write_tests.rs +++ b/components/raftstore/src/store/async_io/write_tests.rs @@ -361,7 +361,7 @@ fn test_worker() { t.worker.write_to_db(true); - let snapshot = engines.kv.snapshot(None); + let snapshot = engines.kv.snapshot(); assert_eq!(snapshot.get_value(b"kv_k1").unwrap().unwrap(), b"kv_v1"); assert_eq!(snapshot.get_value(b"kv_k2").unwrap().unwrap(), b"kv_v2"); assert_eq!(snapshot.get_value(b"kv_k3").unwrap().unwrap(), b"kv_v3"); @@ -567,7 +567,7 @@ fn test_basic_flow() { must_wait_same_notifies(vec![(region_1, (1, 15)), (region_2, (2, 20))], &t.notify_rx); - let snapshot = engines.kv.snapshot(None); + let snapshot = engines.kv.snapshot(); assert!(snapshot.get_value(b"kv_k1").unwrap().is_none()); assert_eq!(snapshot.get_value(b"kv_k2").unwrap().unwrap(), b"kv_v2"); assert_eq!(snapshot.get_value(b"kv_k3").unwrap().unwrap(), b"kv_v3"); diff --git a/components/raftstore/src/store/fsm/apply.rs b/components/raftstore/src/store/fsm/apply.rs index 1a1644d07ff..86092b9e941 100644 --- a/components/raftstore/src/store/fsm/apply.rs +++ b/components/raftstore/src/store/fsm/apply.rs @@ -3287,7 +3287,7 @@ where // open files in rocksdb. // TODO: figure out another way to do consistency check without snapshot // or short life snapshot. - snap: ctx.engine.snapshot(None), + snap: ctx.engine.snapshot(), }) }, )) @@ -4263,7 +4263,7 @@ where } if let Err(e) = snap_task.generate_and_schedule_snapshot::( - apply_ctx.engine.snapshot(None), + apply_ctx.engine.snapshot(), self.delegate.applied_term, self.delegate.apply_state.clone(), &apply_ctx.region_scheduler, @@ -4335,7 +4335,7 @@ where ReadResponse { response: Default::default(), snapshot: Some(RegionSnapshot::from_snapshot( - Arc::new(apply_ctx.engine.snapshot(None)), + Arc::new(apply_ctx.engine.snapshot()), Arc::new(self.delegate.region.clone()), )), txn_extra_op: TxnExtraOp::Noop, diff --git a/components/raftstore/src/store/peer.rs b/components/raftstore/src/store/peer.rs index 1cd528c870d..0f4f25950ff 100644 --- a/components/raftstore/src/store/peer.rs +++ b/components/raftstore/src/store/peer.rs @@ -19,8 +19,8 @@ use bytes::Bytes; use collections::{HashMap, HashSet}; use crossbeam::{atomic::AtomicCell, channel::TrySendError}; use engine_traits::{ - CacheRegion, Engines, KvEngine, PerfContext, RaftEngine, Snapshot, SnapshotContext, WriteBatch, - WriteOptions, CF_DEFAULT, CF_LOCK, CF_WRITE, + Engines, KvEngine, PerfContext, RaftEngine, Snapshot, WriteBatch, WriteOptions, CF_DEFAULT, + CF_LOCK, CF_WRITE, }; use error_code::ErrorCodeExt; use fail::fail_point; @@ -90,7 +90,7 @@ use crate::{ RoleChange, }, errors::RAFTSTORE_IS_BUSY, - router::RaftStoreRouter, + router::{RaftStoreRouter, ReadContext}, store::{ async_io::{read::ReadTask, write::WriteMsg, write_router::WriteRouter}, fsm::{ @@ -5051,23 +5051,20 @@ where } } - let snap_ctx = if let Ok(read_ts) = decode_u64(&mut req.get_header().get_flag_data()) { - Some(SnapshotContext { - region: Some(CacheRegion::from_region(®ion)), - read_ts, - }) + let read_ctx = if let Ok(read_ts) = decode_u64(&mut req.get_header().get_flag_data()) { + ReadContext::new(None, Some(read_ts)) } else { - None + ReadContext::new(None, None) }; let mut reader = PollContextReader { engines: &ctx.engines, }; let mut resp = reader.execute( + &read_ctx, &req, &Arc::new(region), read_index, - snap_ctx, None, &ctx.coprocessor_host, ); @@ -6070,12 +6067,8 @@ where &self.engines.kv } - fn get_snapshot( - &mut self, - snap_ctx: Option, - _: &Option>, - ) -> Arc { - Arc::new(self.engines.kv.snapshot(snap_ctx)) + fn get_snapshot(&mut self, _: &Option>) -> Arc { + Arc::new(self.engines.kv.snapshot()) } } diff --git a/components/raftstore/src/store/peer_storage.rs b/components/raftstore/src/store/peer_storage.rs index 428f1a12229..06072c4a05f 100644 --- a/components/raftstore/src/store/peer_storage.rs +++ b/components/raftstore/src/store/peer_storage.rs @@ -377,7 +377,7 @@ where #[inline] pub fn raw_snapshot(&self) -> EK::Snapshot { - self.engines.kv.snapshot(None) + self.engines.kv.snapshot() } #[inline] @@ -1661,7 +1661,7 @@ pub mod tests { .unwrap() .unwrap(); gen_task.generate_and_schedule_snapshot::( - engines.kv.clone().snapshot(None), + engines.kv.clone().snapshot(), entry.get_term(), apply_state, sched, diff --git a/components/raftstore/src/store/region_snapshot.rs b/components/raftstore/src/store/region_snapshot.rs index f8f426aaad2..b1491444db1 100644 --- a/components/raftstore/src/store/region_snapshot.rs +++ b/components/raftstore/src/store/region_snapshot.rs @@ -76,7 +76,7 @@ where where EK: KvEngine, { - RegionSnapshot::from_snapshot(Arc::new(db.snapshot(None)), Arc::new(region)) + RegionSnapshot::from_snapshot(Arc::new(db.snapshot()), Arc::new(region)) } pub fn from_snapshot(snap: Arc, region: Arc) -> RegionSnapshot { @@ -229,11 +229,6 @@ where pub fn get_end_key(&self) -> &[u8] { self.region.get_end_key() } - - #[cfg(test)] - pub fn snap(&self) -> Arc { - self.snap.clone() - } } impl Clone for RegionSnapshot diff --git a/components/raftstore/src/store/snap.rs b/components/raftstore/src/store/snap.rs index 60e4b3ae2ed..8516703de57 100644 --- a/components/raftstore/src/store/snap.rs +++ b/components/raftstore/src/store/snap.rs @@ -2831,7 +2831,7 @@ pub mod tests { .tempdir() .unwrap(); let db = get_db(src_db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let src_dir = Builder::new() .prefix("test-snap-file-db-src") @@ -2939,7 +2939,7 @@ pub mod tests { .tempdir() .unwrap(); let db = get_db(db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let dir = Builder::new() .prefix("test-snap-validation") @@ -3072,7 +3072,7 @@ pub mod tests { .tempdir() .unwrap(); let db: KvTestEngine = open_test_db(db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let dir = Builder::new() .prefix("test-snap-corruption") @@ -3131,7 +3131,7 @@ pub mod tests { .tempdir() .unwrap(); let db: KvTestEngine = open_test_db_with_100keys(db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let dir = Builder::new() .prefix("test-snap-corruption-meta") @@ -3212,7 +3212,7 @@ pub mod tests { .tempdir() .unwrap(); let db: KvTestEngine = open_test_db(db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let key1 = SnapKey::new(1, 1, 1); let mgr_core = create_manager_core(&path, u64::MAX); let mut s1 = Snapshot::new_for_building(&path, &key1, &mgr_core).unwrap(); @@ -3283,7 +3283,7 @@ pub mod tests { .tempdir() .unwrap(); let db: KvTestEngine = open_test_db(src_db_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let key = SnapKey::new(1, 1, 1); let region = gen_test_region(1, 1, 1); @@ -3365,7 +3365,7 @@ pub mod tests { .max_total_size(max_total_size) .build::<_>(snapfiles_path.path().to_str().unwrap()); snap_mgr.init().unwrap(); - let snapshot = engine.kv.snapshot(None); + let snapshot = engine.kv.snapshot(); // Add an oldest snapshot for receiving. let recv_key = SnapKey::new(100, 100, 100); @@ -3490,7 +3490,7 @@ pub mod tests { .tempdir() .unwrap(); let db: KvTestEngine = open_test_db(kv_dir.path(), None, None).unwrap(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let key = SnapKey::new(1, 1, 1); let region = gen_test_region(1, 1, 1); diff --git a/components/raftstore/src/store/snap/io.rs b/components/raftstore/src/store/snap/io.rs index 3460adc8672..91568c6d568 100644 --- a/components/raftstore/src/store/snap/io.rs +++ b/components/raftstore/src/store/snap/io.rs @@ -459,7 +459,7 @@ mod tests { .unwrap(); let db1: KvTestEngine = open_test_empty_db(dir1.path(), db_opt, None).unwrap(); - let snap = db.snapshot(None); + let snap = db.snapshot(); for cf in SNAPSHOT_CFS { let snap_cf_dir = Builder::new().prefix("test-snap-cf").tempdir().unwrap(); let mut cf_file = CfFile { @@ -551,7 +551,7 @@ mod tests { let stats = build_sst_cf_file_list::( &mut cf_file, &db, - &db.snapshot(None), + &db.snapshot(), &keys::data_key(b"a"), &keys::data_key(b"z"), *max_file_size, diff --git a/components/raftstore/src/store/worker/consistency_check.rs b/components/raftstore/src/store/worker/consistency_check.rs index d034cd8604f..fef2bae332c 100644 --- a/components/raftstore/src/store/worker/consistency_check.rs +++ b/components/raftstore/src/store/worker/consistency_check.rs @@ -162,7 +162,7 @@ mod tests { index: 10, context: vec![ConsistencyCheckMethod::Raw as u8], region: region.clone(), - snap: db.snapshot(None), + snap: db.snapshot(), }); let mut checksum_bytes = vec![]; checksum_bytes.write_u32::(sum).unwrap(); diff --git a/components/raftstore/src/store/worker/read.rs b/components/raftstore/src/store/worker/read.rs index cf6d492b51c..269105e081b 100644 --- a/components/raftstore/src/store/worker/read.rs +++ b/components/raftstore/src/store/worker/read.rs @@ -12,9 +12,7 @@ use std::{ }; use crossbeam::{atomic::AtomicCell, channel::TrySendError}; -use engine_traits::{ - CacheRegion, KvEngine, Peekable, RaftEngine, SnapshotContext, SnapshotMiscExt, -}; +use engine_traits::{KvEngine, Peekable, RaftEngine, SnapshotMiscExt}; use fail::fail_point; use kvproto::{ errorpb, @@ -38,6 +36,7 @@ use super::metrics::*; use crate::{ coprocessor::CoprocessorHost, errors::RAFTSTORE_IS_BUSY, + router::ReadContext, store::{ cmd_resp, fsm::store::StoreMeta, @@ -60,7 +59,6 @@ pub trait ReadExecutor { /// Currently, only multi-rocksdb version may return `None`. fn get_snapshot( &mut self, - snap_ctx: Option, read_context: &Option>, ) -> Arc<::Snapshot>; @@ -68,7 +66,6 @@ pub trait ReadExecutor { &mut self, req: &Request, region: &metapb::Region, - snap_ctx: Option, read_context: &Option>, ) -> Result { let key = req.get_get().get_key(); @@ -76,7 +73,7 @@ pub trait ReadExecutor { util::check_key_in_region(key, region)?; let mut resp = Response::default(); - let snapshot = self.get_snapshot(snap_ctx, read_context); + let snapshot = self.get_snapshot(read_context); let res = if !req.get_get().get_cf().is_empty() { let cf = req.get_get().get_cf(); snapshot @@ -111,10 +108,10 @@ pub trait ReadExecutor { fn execute( &mut self, + ctx: &ReadContext, msg: &RaftCmdRequest, region: &Arc, read_index: Option, - snap_ctx: Option, local_read_ctx: Option>, host: &CoprocessorHost, ) -> ReadResponse<::Snapshot> { @@ -128,32 +125,30 @@ pub trait ReadExecutor { for req in requests { let cmd_type = req.get_cmd_type(); let mut resp = match cmd_type { - CmdType::Get => { - match self.get_value(req, region.as_ref(), snap_ctx.clone(), &local_read_ctx) { - Ok(resp) => resp, - Err(e) => { - error!(?e; - "failed to execute get command"; - "region_id" => region.get_id(), - ); - response.response = cmd_resp::new_error(e); - return response; - } + CmdType::Get => match self.get_value(req, region.as_ref(), &local_read_ctx) { + Ok(resp) => resp, + Err(e) => { + error!(?e; + "failed to execute get command"; + "region_id" => region.get_id(), + ); + response.response = cmd_resp::new_error(e); + return response; } - } + }, CmdType::Snap => { let mut snapshot = RegionSnapshot::from_snapshot( - self.get_snapshot(snap_ctx.clone(), &local_read_ctx), + self.get_snapshot(&local_read_ctx), region.clone(), ); - if let Some(snap_ctx) = snap_ctx.as_ref() { + if let Some(read_ts) = ctx.read_ts { // We only observe snapshot when it has snapshot context. // // Currently, the snapshot context is set when caller // wants an in-memory engine snapshot which requires // the snapshot and some metadata in the context. let seqno = snapshot.get_snapshot().sequence_number(); - if let Some(observed_snap) = host.on_snapshot(snap_ctx.clone(), seqno) { + if let Some(observed_snap) = host.on_snapshot(region, read_ts, seqno) { snapshot.set_observed_snapshot(observed_snap); } } @@ -246,16 +241,9 @@ where } } - // Update the snapshot in the `snap_cache` if the read_id is None or does - // not match. - // snap_ctx is used (if not None) to acquire the snapshot of the relevant region - // from region cache engine - fn maybe_update_snapshot( - &mut self, - engine: &E, - snap_ctx: Option, - delegate_last_valid_ts: Timespec, - ) -> bool { + /// Update the snapshot in the `snap_cache` if the read_id is None or does + /// not match. + fn maybe_update_snapshot(&mut self, engine: &E, delegate_last_valid_ts: Timespec) -> bool { // When the read_id is None, it means the `snap_cache` has been cleared // before and the `cached_read_id` of it is None because only a consecutive // requests will have the same cache and the cache will be cleared after the @@ -269,7 +257,7 @@ where } self.snap_cache.cached_read_id = self.read_id.clone(); - self.snap_cache.snapshot = Some(Arc::new(engine.snapshot(snap_ctx))); + self.snap_cache.snapshot = Some(Arc::new(engine.snapshot())); // Ensures the snapshot is acquired before getting the time atomic::fence(atomic::Ordering::Release); @@ -277,7 +265,7 @@ where } else { // read_id being None means the snapshot acquired will only be used in this // request - self.snapshot = Some(Arc::new(engine.snapshot(snap_ctx))); + self.snapshot = Some(Arc::new(engine.snapshot())); // Ensures the snapshot is acquired before getting the time atomic::fence(atomic::Ordering::Release); @@ -1015,26 +1003,16 @@ where /// the read response is returned, otherwise None is returned. fn try_local_leader_read( &mut self, + ctx: &ReadContext, req: &RaftCmdRequest, delegate: &mut CachedReadDelegate, - snap_ctx: Option, - read_id: Option, snap_updated: &mut bool, last_valid_ts: Timespec, ) -> Option> { - let mut local_read_ctx = LocalReadContext::new(&mut self.snap_cache, read_id); - if snap_ctx.is_some() { - // When `snap_ctx` is some, it means we want to acquire the range cache engine - // snapshot which cannot be used across different regions. So we don't use - // cache. - local_read_ctx.read_id.take(); - } + let mut local_read_ctx = LocalReadContext::new(&mut self.snap_cache, ctx.read_id.clone()); - (*snap_updated) = local_read_ctx.maybe_update_snapshot( - delegate.get_tablet(), - snap_ctx.clone(), - last_valid_ts, - ); + (*snap_updated) = + local_read_ctx.maybe_update_snapshot(delegate.get_tablet(), last_valid_ts); let snapshot_ts = local_read_ctx.snapshot_ts().unwrap(); if !delegate.is_in_leader_lease(snapshot_ts) { @@ -1042,14 +1020,8 @@ where } let region = Arc::clone(&delegate.region); - let mut response = delegate.execute( - req, - ®ion, - None, - snap_ctx, - Some(local_read_ctx), - &self.host, - ); + let mut response = + delegate.execute(ctx, req, ®ion, None, Some(local_read_ctx), &self.host); if let Some(snap) = response.snapshot.as_mut() { snap.bucket_meta = delegate.bucket_meta.clone(); } @@ -1063,6 +1035,7 @@ where /// `DataIsNotReady` error is returned. fn try_local_stale_read( &mut self, + ctx: &ReadContext, req: &RaftCmdRequest, delegate: &mut CachedReadDelegate, snap_updated: &mut bool, @@ -1074,12 +1047,12 @@ where // Stale read does not use cache, so we pass None for read_id let mut local_read_ctx = LocalReadContext::new(&mut self.snap_cache, None); (*snap_updated) = - local_read_ctx.maybe_update_snapshot(delegate.get_tablet(), None, last_valid_ts); + local_read_ctx.maybe_update_snapshot(delegate.get_tablet(), last_valid_ts); let region = Arc::clone(&delegate.region); // Getting the snapshot let mut response = - delegate.execute(req, ®ion, None, None, Some(local_read_ctx), &self.host); + delegate.execute(ctx, req, ®ion, None, Some(local_read_ctx), &self.host); if let Some(snap) = response.snapshot.as_mut() { snap.bucket_meta = delegate.bucket_meta.clone(); } @@ -1093,27 +1066,21 @@ where pub fn propose_raft_command( &mut self, - mut snap_ctx: Option, - read_id: Option, + ctx: &ReadContext, mut req: RaftCmdRequest, cb: Callback, ) { match self.pre_propose_raft_command(&req) { Ok(Some((mut delegate, policy))) => { - if let Some(ref mut ctx) = snap_ctx { - ctx.set_region(CacheRegion::from_region(&delegate.region)) - } - let mut snap_updated = false; let last_valid_ts = delegate.last_valid_ts; let mut response = match policy { // Leader can read local if and only if it is in lease. RequestPolicy::ReadLocal => { if let Some(read_resp) = self.try_local_leader_read( + ctx, &req, &mut delegate, - snap_ctx, - read_id, &mut snap_updated, last_valid_ts, ) { @@ -1128,6 +1095,7 @@ where // Replica can serve stale read if and only if its `safe_ts` >= `read_ts` RequestPolicy::StaleRead => { match self.try_local_stale_read( + ctx, &req, &mut delegate, &mut snap_updated, @@ -1157,10 +1125,9 @@ where return; } if let Some(read_resp) = self.try_local_leader_read( + ctx, &req, &mut delegate, - None, - None, &mut snap_updated, last_valid_ts, ) { @@ -1236,14 +1203,8 @@ where /// which left a snapshot cached in LocalReader. ThreadReadId is composed by /// thread_id and a thread_local incremental sequence. #[inline] - pub fn read( - &mut self, - snap_ctx: Option, - read_id: Option, - req: RaftCmdRequest, - cb: Callback, - ) { - self.propose_raft_command(snap_ctx, read_id, req, cb); + pub fn read(&mut self, ctx: ReadContext, req: RaftCmdRequest, cb: Callback) { + self.propose_raft_command(&ctx, req, cb); maybe_tls_local_read_metrics_flush(); } @@ -1278,11 +1239,7 @@ where &self.kv_engine } - fn get_snapshot( - &mut self, - _: Option, - read_context: &Option>, - ) -> Arc { + fn get_snapshot(&mut self, read_context: &Option>) -> Arc { read_context.as_ref().unwrap().snapshot().unwrap() } } @@ -1330,14 +1287,9 @@ mod tests { use crossbeam::channel::TrySendError; use engine_test::kv::{KvTestEngine, KvTestSnapshot}; use engine_traits::{MiscExt, Peekable, SyncMutable, ALL_CFS}; - use hybrid_engine::{HybridEngine, HybridEngineSnapshot}; - use keys::DATA_PREFIX; use kvproto::{metapb::RegionEpoch, raft_cmdpb::*}; - use range_cache_memory_engine::{ - RangeCacheEngineConfig, RangeCacheEngineContext, RangeCacheMemoryEngine, - }; use tempfile::{Builder, TempDir}; - use tikv_util::{codec::number::NumberEncoder, config::VersionTrack, time::monotonic_raw_now}; + use tikv_util::{codec::number::NumberEncoder, time::monotonic_raw_now}; use time::Duration; use txn_types::WriteBatchFlags; @@ -1421,9 +1373,9 @@ mod tests { rx: &Receiver>, cmd: RaftCmdRequest, ) { + let read_ctx = &ReadContext::new(None, None); reader.propose_raft_command( - None, - None, + read_ctx, cmd.clone(), Callback::read(Box::new(|resp| { panic!("unexpected invoke, {:?}", resp); @@ -1451,7 +1403,8 @@ mod tests { task: RaftCommand, read_id: Option, ) { - reader.propose_raft_command(None, read_id, task.request, task.callback); + let ctx = ReadContext::new(read_id, None); + reader.propose_raft_command(&ctx, task.request, task.callback); assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); } @@ -1460,6 +1413,7 @@ mod tests { let store_id = 2; let store_meta = Arc::new(Mutex::new(StoreMeta::new(0))); let (_tmp, mut reader, rx) = new_reader("test-local-reader", store_id, store_meta.clone()); + let read_ctx = &ReadContext::new(None, None); // region: 1, // peers: 2, 3, 4, @@ -1584,8 +1538,7 @@ mod tests { .mut_peer() .set_store_id(store_id + 1); reader.propose_raft_command( - None, - None, + read_ctx, cmd_store_id, Callback::read(Box::new(move |resp: ReadResponse| { let err = resp.response.get_header().get_error(); @@ -1609,8 +1562,7 @@ mod tests { .mut_peer() .set_id(leader2.get_id() + 1); reader.propose_raft_command( - None, - None, + read_ctx, cmd_peer_id, Callback::read(Box::new(move |resp: ReadResponse| { assert!( @@ -1635,8 +1587,7 @@ mod tests { let mut cmd_term = cmd.clone(); cmd_term.mut_header().set_term(term6 - 2); reader.propose_raft_command( - None, - None, + read_ctx, cmd_term, Callback::read(Box::new(move |resp: ReadResponse| { let err = resp.response.get_header().get_error(); @@ -1672,10 +1623,9 @@ mod tests { ); // Channel full. - reader.propose_raft_command(None, None, cmd.clone(), Callback::None); + reader.propose_raft_command(read_ctx, cmd.clone(), Callback::None); reader.propose_raft_command( - None, - None, + read_ctx, cmd.clone(), Callback::read(Box::new(move |resp: ReadResponse| { let err = resp.response.get_header().get_error(); @@ -1707,8 +1657,7 @@ mod tests { .update(Progress::applied_term(term6 + 3)); } reader.propose_raft_command( - None, - None, + read_ctx, cmd9.clone(), Callback::read(Box::new(|resp| { panic!("unexpected invoke, {:?}", resp); @@ -2084,7 +2033,7 @@ mod tests { let compare_ts = monotonic_raw_now(); // Case 1: snap_cache_context.read_id is None - assert!(read_context.maybe_update_snapshot(&db, None, Timespec::new(0, 0))); + assert!(read_context.maybe_update_snapshot(&db, Timespec::new(0, 0))); assert!(read_context.snapshot_ts().unwrap() > compare_ts); assert_eq!( read_context @@ -2099,7 +2048,7 @@ mod tests { // snap_cache_context is *not* created with read_id, so calling // `maybe_update_snapshot` again will update the snapshot let compare_ts = monotonic_raw_now(); - assert!(read_context.maybe_update_snapshot(&db, None, Timespec::new(0, 0))); + assert!(read_context.maybe_update_snapshot(&db, Timespec::new(0, 0))); assert!(read_context.snapshot_ts().unwrap() > compare_ts); let read_id = ThreadReadId::new(); @@ -2109,7 +2058,7 @@ mod tests { let compare_ts = monotonic_raw_now(); // Case 2: snap_cache_context.read_id is not None but not equals to the // snap_cache.cached_read_id - assert!(read_context.maybe_update_snapshot(&db, None, Timespec::new(0, 0))); + assert!(read_context.maybe_update_snapshot(&db, Timespec::new(0, 0))); assert!(read_context.snapshot_ts().unwrap() > compare_ts); let snap_ts = read_context.snapshot_ts().unwrap(); assert_eq!( @@ -2127,7 +2076,7 @@ mod tests { // `maybe_update_snapshot` again will *not* update the snapshot // Case 3: snap_cache_context.read_id is not None and equals to the // snap_cache.cached_read_id - assert!(!read_context.maybe_update_snapshot(&db2, None, Timespec::new(0, 0))); + assert!(!read_context.maybe_update_snapshot(&db2, Timespec::new(0, 0))); assert_eq!(read_context.snapshot_ts().unwrap(), snap_ts); assert_eq!( read_context @@ -2142,7 +2091,7 @@ mod tests { // Case 4: delegate.last_valid_ts is larger than create_time of read_id let mut last_valid_ts = read_id_clone.create_time; last_valid_ts = last_valid_ts.add(Duration::nanoseconds(1)); - assert!(read_context.maybe_update_snapshot(&db2, None, last_valid_ts)); + assert!(read_context.maybe_update_snapshot(&db2, last_valid_ts)); assert!(read_context.snapshot_ts().unwrap() > snap_ts); assert!( read_context @@ -2462,264 +2411,4 @@ mod tests { .has_data_is_not_ready() ); } - - type HybridTestEnigne = HybridEngine; - type HybridEngineTestSnapshot = HybridEngineSnapshot; - - struct HybridEngineMockRouter { - p_router: SyncSender>, - c_router: SyncSender<(u64, CasualMessage)>, - } - - impl HybridEngineMockRouter { - #[allow(clippy::type_complexity)] - fn new() -> ( - HybridEngineMockRouter, - Receiver>, - Receiver<(u64, CasualMessage)>, - ) { - let (p_ch, p_rx) = sync_channel(1); - let (c_ch, c_rx) = sync_channel(1); - ( - HybridEngineMockRouter { - p_router: p_ch, - c_router: c_ch, - }, - p_rx, - c_rx, - ) - } - } - - impl ProposalRouter for HybridEngineMockRouter { - fn send( - &self, - cmd: RaftCommand, - ) -> std::result::Result<(), TrySendError>> { - ProposalRouter::send(&self.p_router, cmd) - } - } - - impl CasualRouter for HybridEngineMockRouter { - fn send(&self, region_id: u64, msg: CasualMessage) -> Result<()> { - CasualRouter::send(&self.c_router, region_id, msg) - } - } - - #[allow(clippy::type_complexity)] - fn new_hybrid_engine_reader( - path: &str, - store_id: u64, - store_meta: Arc>, - engine_config: RangeCacheEngineConfig, - ) -> ( - TempDir, - LocalReader, - Receiver>, - RangeCacheMemoryEngine, - ) { - let path = Builder::new().prefix(path).tempdir().unwrap(); - let disk_engine = - engine_test::kv::new_engine(path.path().to_str().unwrap(), ALL_CFS).unwrap(); - let (ch, rx, _) = HybridEngineMockRouter::new(); - let config = Arc::new(VersionTrack::new(engine_config)); - let memory_engine = - RangeCacheMemoryEngine::new(RangeCacheEngineContext::new_for_tests(config)); - let engine = HybridEngine::new(disk_engine, memory_engine.clone()); - let mut reader = LocalReader::new( - engine.clone(), - StoreMetaDelegate::new(store_meta, engine), - ch, - CoprocessorHost::default(), - ); - reader.local_reader.store_id = Cell::new(Some(store_id)); - (path, reader, rx, memory_engine) - } - - fn get_snapshot( - snap_ctx: Option, - reader: &mut LocalReader, - request: RaftCmdRequest, - rx: &Receiver>, - ) -> Arc { - let (sender, receiver) = channel(); - reader.propose_raft_command( - snap_ctx, - None, - request, - Callback::read(Box::new(move |snap| { - sender.send(snap).unwrap(); - })), - ); - // no direct is expected - assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); - receiver.recv().unwrap().snapshot.unwrap().snap() - } - - #[test] - fn test_hybrid_engine_read() { - let store_id = 2; - let store_meta = Arc::new(Mutex::new(StoreMeta::new(0))); - let (_tmp, mut reader, rx, memory_engine) = new_hybrid_engine_reader( - "test-local-hybrid-engine-reader", - store_id, - store_meta.clone(), - RangeCacheEngineConfig::config_for_test(), - ); - - // set up region so we can acquire snapshot from local reader - let mut region1 = metapb::Region::default(); - region1.set_id(1); - let prs = new_peers(store_id, vec![2, 3, 4]); - region1.set_peers(prs.clone().into()); - let epoch13 = { - let mut ep = metapb::RegionEpoch::default(); - ep.set_conf_ver(1); - ep.set_version(3); - ep - }; - let leader2 = prs[0].clone(); - region1.set_region_epoch(epoch13.clone()); - memory_engine.new_region(region1.clone()); - memory_engine - .core() - .region_manager() - .set_safe_point(region1.id, 1); - let kv = (&[DATA_PREFIX, b'a'], b"b"); - reader.kv_engine.put(kv.0, kv.1).unwrap(); - let term6 = 6; - let mut lease = Lease::new(Duration::seconds(1), Duration::milliseconds(250)); // 1s is long enough. - let read_progress = Arc::new(RegionReadProgress::new(®ion1, 1, 1, 1)); - - lease.renew(monotonic_raw_now()); - let remote = lease.maybe_new_remote_lease(term6).unwrap(); - { - let mut meta = store_meta.lock().unwrap(); - let read_delegate = ReadDelegate { - tag: String::new(), - region: Arc::new(region1.clone()), - peer_id: leader2.get_id(), - term: term6, - applied_term: term6, - leader_lease: Some(remote), - last_valid_ts: Timespec::new(0, 0), - txn_extra_op: Arc::new(AtomicCell::new(TxnExtraOp::default())), - txn_ext: Arc::new(TxnExt::default()), - read_progress, - pending_remove: false, - wait_data: false, - track_ver: TrackVer::new(), - bucket_meta: None, - }; - meta.readers.insert(1, read_delegate); - } - - let mut cmd = RaftCmdRequest::default(); - let mut header = RaftRequestHeader::default(); - header.set_region_id(1); - header.set_peer(leader2); - header.set_region_epoch(epoch13); - header.set_term(term6); - cmd.set_header(header); - let mut req = Request::default(); - req.set_cmd_type(CmdType::Snap); - cmd.set_requests(vec![req].into()); - - let s = get_snapshot(None, &mut reader, cmd.clone(), &rx); - assert!(!s.range_cache_snapshot_available()); - - memory_engine - .core() - .region_manager() - .set_safe_point(region1.id, 10); - - let snap_ctx = SnapshotContext { - read_ts: 15, - region: None, - }; - - let s = get_snapshot(Some(snap_ctx.clone()), &mut reader, cmd.clone(), &rx); - assert!(s.range_cache_snapshot_available()); - assert_eq!(s.get_value(kv.0).unwrap().unwrap(), kv.1); - } - - #[test] - fn test_not_use_snap_cache_in_hybrid_engine() { - let store_id = 2; - let store_meta = Arc::new(Mutex::new(StoreMeta::new(0))); - let (_tmp, mut reader, rx, _) = new_hybrid_engine_reader( - "test-not-use-snap-cache", - store_id, - store_meta.clone(), - RangeCacheEngineConfig::config_for_test(), - ); - - let epoch13 = { - let mut ep = metapb::RegionEpoch::default(); - ep.set_conf_ver(1); - ep.set_version(3); - ep - }; - let term6 = 6; - - // Register region1 - let pr_ids1 = vec![2, 3, 4]; - let prs1 = new_peers(store_id, pr_ids1.clone()); - prepare_read_delegate( - store_id, - 1, - term6, - pr_ids1, - epoch13.clone(), - store_meta.clone(), - ); - let leader1 = prs1[0].clone(); - - let mut cmd = RaftCmdRequest::default(); - let mut header = RaftRequestHeader::default(); - header.set_region_id(1); - header.set_peer(leader1); - header.set_region_epoch(epoch13.clone()); - header.set_term(term6); - cmd.set_header(header); - let mut req = Request::default(); - req.set_cmd_type(CmdType::Snap); - cmd.set_requests(vec![req].into()); - let (snap_tx, snap_rx) = channel(); - let task = RaftCommand::::new( - cmd.clone(), - Callback::read(Box::new( - move |resp: ReadResponse| { - snap_tx.send(resp.snapshot.unwrap()).unwrap(); - }, - )), - ); - - let read_id = Some(ThreadReadId::new()); - // If snap_ctx is None and read_id is Some, it will cache the snapshot. - reader.propose_raft_command(None, read_id.clone(), task.request, task.callback); - assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); - let _ = snap_rx.recv().unwrap(); - assert!(reader.snap_cache.snapshot.is_some()); - - // Release the snapshot and try with snap_ctx - let (snap_tx, snap_rx) = channel(); - let task = RaftCommand::::new( - cmd, - Callback::read(Box::new( - move |resp: ReadResponse| { - snap_tx.send(resp.snapshot.unwrap()).unwrap(); - }, - )), - ); - reader.release_snapshot_cache(); - let snap_ctx = SnapshotContext { - read_ts: 15, - region: None, - }; - reader.propose_raft_command(Some(snap_ctx), read_id, task.request, task.callback); - assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); - let _ = snap_rx.recv().unwrap(); - assert!(reader.snap_cache.snapshot.is_none()); - } } diff --git a/components/raftstore/src/store/worker/region.rs b/components/raftstore/src/store/worker/region.rs index 2316aeb0239..b912d5d3133 100644 --- a/components/raftstore/src/store/worker/region.rs +++ b/components/raftstore/src/store/worker/region.rs @@ -1128,7 +1128,7 @@ pub(crate) mod tests { ranges.push(key); } engine.kv.put(b"k1", b"v1").unwrap(); - let snap = engine.kv.snapshot(None); + let snap = engine.kv.snapshot(); engine.kv.put(b"k2", b"v2").unwrap(); sched @@ -1241,7 +1241,7 @@ pub(crate) mod tests { sched .schedule(Task::Gen { region_id: id, - kv_snap: engine.kv.snapshot(None), + kv_snap: engine.kv.snapshot(), last_applied_term: entry.get_term(), last_applied_state: apply_state, canceled: Arc::new(AtomicBool::new(false)), diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index e2bfc0b5b16..44dd00aa3a0 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -399,7 +399,7 @@ impl RangeCacheMemoryEngine { // get snapshot and schedule loading task at last to avoid locking IME for too // long. if schedule_load { - let rocks_snap = Arc::new(self.rocks_engine.as_ref().unwrap().snapshot(None)); + let rocks_snap = Arc::new(self.rocks_engine.as_ref().unwrap().snapshot()); if let Err(e) = self .bg_work_manager .schedule_task(BackgroundTask::LoadRegion(region.clone(), rocks_snap)) diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index 5a520d66461..fd0c4b31264 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -4,7 +4,7 @@ use core::slice::SlicePattern; use std::{fmt::Debug, ops::Deref, result, sync::Arc}; use bytes::Bytes; -use crossbeam::epoch::{self}; +use crossbeam::epoch; use crossbeam_skiplist::{base::OwnedIter, SkipList}; use engine_rocks::{raw::SliceTransform, util::FixedSuffixSliceTransform}; use engine_traits::{ diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 8a377366f72..3b0eb1e2e7d 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -41,12 +41,9 @@ use file_system::{get_io_rate_limiter, BytesFetcher, MetricsManager as IoMetrics use futures::executor::block_on; use grpcio::{EnvBuilder, Environment}; use health_controller::HealthController; -use hybrid_engine::{ - observer::{ - HybridSnapshotObserver, LoadEvictionObserver as HybridEngineLoadEvictionObserver, - RegionCacheWriteBatchObserver, - }, - HybridEngine, +use hybrid_engine::observer::{ + HybridSnapshotObserver, LoadEvictionObserver as HybridEngineLoadEvictionObserver, + RegionCacheWriteBatchObserver, }; use kvproto::{ brpb::create_backup, cdcpb::create_change_data, deadlock::create_deadlock, @@ -79,8 +76,7 @@ use raftstore::{ RaftRouterCompactedEventSender, }; use range_cache_memory_engine::{ - config::RangeCacheConfigManager, RangeCacheEngineContext, RangeCacheMemoryEngine, - RangeCacheMemoryEngineStatistics, + config::RangeCacheConfigManager, RangeCacheEngineContext, RangeCacheMemoryEngineStatistics, }; use resolved_ts::{LeadershipResolver, Task}; use resource_control::ResourceGroupManager; @@ -169,8 +165,8 @@ fn run_impl( tikv.core.init_encryption(); let fetcher = tikv.core.init_io_utility(); let listener = tikv.core.init_flow_receiver(); - let (engines, engines_info, in_memory_engine) = tikv.init_raw_engines(listener); - tikv.init_engines(engines.clone(), in_memory_engine); + let (engines, engines_info) = tikv.init_raw_engines(listener); + tikv.init_engines(engines.clone()); let server_config = tikv.init_servers(); tikv.register_services(); tikv.init_metrics_flusher(fetcher, engines_info); @@ -493,11 +489,7 @@ where } } - fn init_engines( - &mut self, - engines: Engines, - in_memory_engine: Option>, - ) { + fn init_engines(&mut self, engines: Engines) { let store_meta = Arc::new(Mutex::new(StoreMeta::new(PENDING_MSG_CAP))); let engine = RaftKv::new( ServerRaftStoreRouter::new( @@ -510,7 +502,6 @@ where ), ), engines.kv.clone(), - in_memory_engine.clone(), self.region_info_accessor.region_leaders(), ); @@ -1597,11 +1588,7 @@ where fn init_raw_engines( &mut self, flow_listener: engine_rocks::FlowListener, - ) -> ( - Engines, - Arc, - Option>, - ) { + ) -> (Engines, Arc) { let block_cache = self.core.config.storage.block_cache.build_shared_cache(); let env = self .core @@ -1646,7 +1633,7 @@ where let range_cache_engine_context = RangeCacheEngineContext::new(range_cache_engine_config.clone(), self.pd_client.clone()); let range_cache_engine_statistics = range_cache_engine_context.statistics(); - let in_memory_engine = if self.core.config.range_cache_engine.enabled { + if self.core.config.range_cache_engine.enabled { let in_memory_engine = build_hybrid_engine( range_cache_engine_context, kv_engine.clone(), @@ -1664,10 +1651,6 @@ where let snapshot_observer = HybridSnapshotObserver::new(in_memory_engine.range_cache_engine().clone()); snapshot_observer.register_to(self.coprocessor_host.as_mut().unwrap()); - - Some(in_memory_engine) - } else { - None }; let range_cache_config_manager = RangeCacheConfigManager(range_cache_engine_config); self.kv_statistics = Some(factory.rocks_statistics()); @@ -1705,7 +1688,7 @@ where 180, // max_samples_to_preserve )); - (engines, engines_info, in_memory_engine) + (engines, engines_info) } } diff --git a/components/test_raftstore/src/cluster.rs b/components/test_raftstore/src/cluster.rs index 9824f02adbe..79a31c0113b 100644 --- a/components/test_raftstore/src/cluster.rs +++ b/components/test_raftstore/src/cluster.rs @@ -4,10 +4,7 @@ use std::{ collections::hash_map::Entry as MapEntry, error::Error as StdError, result, - sync::{ - mpsc::{self, sync_channel}, - Arc, Mutex, RwLock, - }, + sync::{mpsc, Arc, Mutex, RwLock}, thread, time::Duration, }; @@ -18,13 +15,11 @@ use encryption_export::DataKeyManager; use engine_rocks::{RocksEngine, RocksSnapshot, RocksStatistics}; use engine_test::raft::RaftTestEngine; use engine_traits::{ - CacheRegion, CompactExt, Engines, Iterable, ManualCompactionOptions, MiscExt, Mutable, - Peekable, RaftEngineReadOnly, SnapshotContext, SyncMutable, WriteBatch, WriteBatchExt, - CF_DEFAULT, CF_RAFT, + CompactExt, Engines, Iterable, ManualCompactionOptions, MiscExt, Mutable, Peekable, + RaftEngineReadOnly, SyncMutable, WriteBatch, WriteBatchExt, CF_DEFAULT, CF_RAFT, }; use file_system::IoRateLimiter; use futures::{self, channel::oneshot, executor::block_on, future::BoxFuture, StreamExt}; -use keys::{DATA_MAX_KEY, DATA_MIN_KEY}; use kvproto::{ errorpb::Error as PbError, kvrpcpb::{ApiVersion, Context, DiskFullOpt}, @@ -47,7 +42,6 @@ use raftstore::{ RaftBatchSystem, RaftRouter, }, transport::CasualRouter, - util::encode_start_ts_into_flag_data, *, }, Error, Result, @@ -122,21 +116,19 @@ pub trait Simulator { fn read( &mut self, - snap_ctx: Option, batch_id: Option, request: RaftCmdRequest, timeout: Duration, ) -> Result { let node_id = request.get_header().get_peer().get_store_id(); let (cb, mut rx) = make_cb(&request); - self.async_read(snap_ctx, node_id, batch_id, request, cb); + self.async_read(node_id, batch_id, request, cb); rx.recv_timeout(timeout) .map_err(|_| Error::Timeout(format!("request timeout for {:?}", timeout))) } fn async_read( &mut self, - snap_ctx: Option, node_id: u64, batch_id: Option, request: RaftCmdRequest, @@ -471,16 +463,11 @@ impl Cluster { pub fn read( &self, - snap_ctx: Option, batch_id: Option, request: RaftCmdRequest, timeout: Duration, ) -> Result { - match self - .sim - .wl() - .read(snap_ctx, batch_id, request.clone(), timeout) - { + match self.sim.wl().read(batch_id, request.clone(), timeout) { Err(e) => { warn!("failed to read {:?}: {:?}", request, e); Err(e) @@ -493,15 +480,6 @@ impl Cluster { &self, request: RaftCmdRequest, timeout: Duration, - ) -> Result { - self.call_command_with_snap_ctx(request, timeout, None) - } - - pub fn call_command_with_snap_ctx( - &self, - request: RaftCmdRequest, - timeout: Duration, - snap_ctx: Option, ) -> Result { let mut is_read = false; for req in request.get_requests() { @@ -513,7 +491,7 @@ impl Cluster { } } let ret = if is_read { - self.sim.wl().read(snap_ctx, None, request.clone(), timeout) + self.sim.wl().read(None, request.clone(), timeout) } else { self.sim.rl().call_command(request.clone(), timeout) }; @@ -526,11 +504,10 @@ impl Cluster { } } - pub fn call_command_on_leader_with_snap_ctx( + pub fn call_command_on_leader( &mut self, mut request: RaftCmdRequest, timeout: Duration, - snap_ctx: Option, ) -> Result { let timer = Instant::now(); let region_id = request.get_header().get_region_id(); @@ -540,11 +517,10 @@ impl Cluster { Some(l) => l, }; request.mut_header().set_peer(leader); - let resp = - match self.call_command_with_snap_ctx(request.clone(), timeout, snap_ctx.clone()) { - e @ Err(_) => return e, - Ok(resp) => resp, - }; + let resp = match self.call_command(request.clone(), timeout) { + e @ Err(_) => return e, + Ok(resp) => resp, + }; if self.refresh_leader_if_needed(&resp, region_id) && timer.saturating_elapsed() < timeout { @@ -558,14 +534,6 @@ impl Cluster { } } - pub fn call_command_on_leader( - &mut self, - request: RaftCmdRequest, - timeout: Duration, - ) -> Result { - self.call_command_on_leader_with_snap_ctx(request, timeout, None) - } - fn valid_leader_id(&self, region_id: u64, leader_id: u64) -> bool { let store_ids = match self.voter_store_ids_of_region(region_id) { None => return false, @@ -911,17 +879,6 @@ impl Cluster { reqs: Vec, read_quorum: bool, timeout: Duration, - ) -> RaftCmdResponse { - self.request_with_snap_ctx(key, reqs, read_quorum, timeout, None) - } - - pub fn request_with_snap_ctx( - &mut self, - key: &[u8], - reqs: Vec, - read_quorum: bool, - timeout: Duration, - snap_ctx: Option, ) -> RaftCmdResponse { let timer = Instant::now(); let mut tried_times = 0; @@ -930,16 +887,13 @@ impl Cluster { tried_times += 1; let mut region = self.get_region(key); let region_id = region.get_id(); - let mut req = new_request( + let req = new_request( region_id, region.take_region_epoch(), reqs.clone(), read_quorum, ); - if let Some(ref ctx) = snap_ctx { - encode_start_ts_into_flag_data(req.mut_header(), ctx.read_ts); - } - let result = self.call_command_on_leader_with_snap_ctx(req, timeout, snap_ctx.clone()); + let result = self.call_command_on_leader(req, timeout); let resp = match result { e @ Err(Error::Timeout(_)) @@ -1005,39 +959,15 @@ impl Cluster { } pub fn get(&mut self, key: &[u8]) -> Option> { - if !self.range_cache_engine_enabled_with_whole_range { - self.get_impl(CF_DEFAULT, key, false) - } else { - let ctx = SnapshotContext { - read_ts: u64::MAX, - region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), - }; - self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) - } + self.get_impl(CF_DEFAULT, key, false) } pub fn get_cf(&mut self, cf: &str, key: &[u8]) -> Option> { - if !self.range_cache_engine_enabled_with_whole_range { - self.get_impl(cf, key, false) - } else { - let ctx = SnapshotContext { - read_ts: u64::MAX, - region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), - }; - self.get_cf_with_snap_ctx(cf, key, true, ctx) - } + self.get_impl(cf, key, false) } pub fn must_get(&mut self, key: &[u8]) -> Option> { - if !self.range_cache_engine_enabled_with_whole_range { - self.get_impl(CF_DEFAULT, key, true) - } else { - let ctx = SnapshotContext { - read_ts: u64::MAX, - region: Some(CacheRegion::new(0, 0, DATA_MIN_KEY, DATA_MAX_KEY)), - }; - self.get_cf_with_snap_ctx(CF_DEFAULT, key, true, ctx) - } + self.get_impl(CF_DEFAULT, key, true) } fn get_impl(&mut self, cf: &str, key: &[u8], read_quorum: bool) -> Option> { @@ -1059,61 +989,6 @@ impl Cluster { } } - pub fn get_with_snap_ctx( - &mut self, - key: &[u8], - read_quorum: bool, - snap_ctx: SnapshotContext, - ) -> Option> { - self.get_cf_with_snap_ctx(CF_DEFAULT, key, read_quorum, snap_ctx) - } - - // called by range cache engine only - pub fn get_cf_with_snap_ctx( - &mut self, - cf: &str, - key: &[u8], - read_quorum: bool, - snap_ctx: SnapshotContext, - ) -> Option> { - let rx = if self.range_cache_engine_enabled_with_whole_range { - fail::remove("on_range_cache_get_value"); - let (tx, rx) = sync_channel(1); - fail::cfg_callback("on_range_cache_get_value", move || { - tx.send(true).unwrap(); - }) - .unwrap(); - Some(rx) - } else { - None - }; - - let mut resp = self.request_with_snap_ctx( - key, - vec![new_get_cf_cmd(cf, key)], - read_quorum, - Duration::from_secs(5), - Some(snap_ctx), - ); - if resp.get_header().has_error() { - panic!("response {:?} has error", resp); - } - assert_eq!(resp.get_responses().len(), 1); - assert_eq!(resp.get_responses()[0].get_cmd_type(), CmdType::Get); - let res = if resp.get_responses()[0].has_get() { - if let Some(rx) = rx { - rx.recv_timeout(Duration::from_secs(5)).unwrap(); - } - Some(resp.mut_responses()[0].mut_get().take_value()) - } else { - None - }; - if self.range_cache_engine_enabled_with_whole_range { - fail::remove("on_range_cache_get_value"); - } - res - } - pub fn async_request( &mut self, req: RaftCmdRequest, diff --git a/components/test_raftstore/src/node.rs b/components/test_raftstore/src/node.rs index f52efd23dce..305ecebdc3e 100644 --- a/components/test_raftstore/src/node.rs +++ b/components/test_raftstore/src/node.rs @@ -10,7 +10,7 @@ use concurrency_manager::ConcurrencyManager; use encryption_export::DataKeyManager; use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_test::raft::RaftTestEngine; -use engine_traits::{Engines, MiscExt, Peekable, SnapshotContext}; +use engine_traits::{Engines, MiscExt, Peekable}; use health_controller::HealthController; use kvproto::{ kvrpcpb::ApiVersion, @@ -23,7 +23,7 @@ use raft::{eraftpb::MessageType, SnapshotStatus}; use raftstore::{ coprocessor::{config::SplitCheckConfigManager, CoprocessorHost}, errors::Error as RaftError, - router::{LocalReadRouter, RaftStoreRouter, ServerRaftStoreRouter}, + router::{LocalReadRouter, RaftStoreRouter, ReadContext, ServerRaftStoreRouter}, store::{ config::RaftstoreConfigManager, fsm::{store::StoreMeta, RaftBatchSystem, RaftRouter}, @@ -460,7 +460,6 @@ impl Simulator for NodeCluster { fn async_read( &mut self, - snap_ctx: Option, node_id: u64, batch_id: Option, request: RaftCmdRequest, @@ -482,7 +481,8 @@ impl Simulator for NodeCluster { } let mut guard = self.trans.core.lock().unwrap(); let router = guard.routers.get_mut(&node_id).unwrap(); - router.read(snap_ctx, batch_id, request, cb).unwrap(); + let read_ctx = ReadContext::new(batch_id, None); + router.read(read_ctx, request, cb).unwrap(); } fn send_raft_msg(&mut self, msg: raft_serverpb::RaftMessage) -> Result<()> { diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index 32e9a5bcc50..c2858b08413 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -16,7 +16,7 @@ use concurrency_manager::ConcurrencyManager; use encryption_export::DataKeyManager; use engine_rocks::{RocksEngine, RocksSnapshot}; use engine_test::raft::RaftTestEngine; -use engine_traits::{Engines, MiscExt, SnapshotContext}; +use engine_traits::{Engines, MiscExt}; use futures::executor::block_on; use grpcio::{ChannelBuilder, EnvBuilder, Environment, Error as GrpcError, Service}; use health_controller::HealthController; @@ -37,7 +37,7 @@ use pd_client::PdClient; use raftstore::{ coprocessor::{CoprocessorHost, RegionInfoAccessor}, errors::Error as RaftError, - router::{CdcRaftRouter, LocalReadRouter, RaftStoreRouter, ServerRaftStoreRouter}, + router::{CdcRaftRouter, LocalReadRouter, RaftStoreRouter, ReadContext, ServerRaftStoreRouter}, store::{ fsm::{store::StoreMeta, ApplyRouter, RaftBatchSystem, RaftRouter}, msg::RaftCmdExtraOpts, @@ -370,7 +370,6 @@ impl ServerCluster { let mut raft_kv = RaftKv::new( sim_router.clone(), engines.kv.clone(), - in_memory_engine, region_info_accessor.region_leaders(), ); @@ -813,7 +812,6 @@ impl Simulator for ServerCluster { fn async_read( &mut self, - snap_ctx: Option, node_id: u64, batch_id: Option, request: RaftCmdRequest, @@ -827,9 +825,8 @@ impl Simulator for ServerCluster { cb.invoke_with_response(resp); } Some(meta) => { - meta.sim_router - .read(snap_ctx, batch_id, request, cb) - .unwrap(); + let read_ctx = ReadContext::new(batch_id, None); + meta.sim_router.read(read_ctx, request, cb).unwrap(); } }; } diff --git a/components/test_raftstore/src/transport_simulate.rs b/components/test_raftstore/src/transport_simulate.rs index 420826f0f60..050f735aac3 100644 --- a/components/test_raftstore/src/transport_simulate.rs +++ b/components/test_raftstore/src/transport_simulate.rs @@ -12,21 +12,20 @@ use std::{ use collections::{HashMap, HashSet}; use crossbeam::channel::TrySendError; use engine_rocks::{RocksEngine, RocksSnapshot}; -use engine_traits::SnapshotContext; use kvproto::{ raft_cmdpb::RaftCmdRequest, raft_serverpb::{ExtraMessageType, RaftMessage}, }; use raft::eraftpb::MessageType; use raftstore::{ - router::{LocalReadRouter, RaftStoreRouter}, + router::{LocalReadRouter, RaftStoreRouter, ReadContext}, store::{ Callback, CasualMessage, CasualRouter, PeerMsg, ProposalRouter, RaftCommand, SignificantMsg, SignificantRouter, StoreMsg, StoreRouter, Transport, }, DiscardReason, Error, Result as RaftStoreResult, Result, }; -use tikv_util::{time::ThreadReadId, Either, HandyRwLock}; +use tikv_util::{Either, HandyRwLock}; pub fn check_messages(msgs: &[RaftMessage]) -> Result<()> { if msgs.is_empty() { @@ -256,12 +255,11 @@ impl> RaftStoreRouter for SimulateT impl> LocalReadRouter for SimulateTransport { fn read( &mut self, - snap_ctx: Option, - read_id: Option, + ctx: ReadContext, req: RaftCmdRequest, cb: Callback, ) -> RaftStoreResult<()> { - self.ch.read(snap_ctx, read_id, req, cb) + self.ch.read(ctx, req, cb) } fn release_snapshot_cache(&mut self) { diff --git a/components/test_raftstore/src/util.rs b/components/test_raftstore/src/util.rs index 82312adb32f..ad50940b19a 100644 --- a/components/test_raftstore/src/util.rs +++ b/components/test_raftstore/src/util.rs @@ -4,10 +4,7 @@ use std::{ fmt::Write, path::Path, str::FromStr, - sync::{ - mpsc::{self}, - Arc, Mutex, - }, + sync::{mpsc, Arc, Mutex}, thread, time::Duration, }; @@ -483,7 +480,7 @@ pub fn read_on_peer( read_quorum, ); request.mut_header().set_peer(peer); - cluster.read(None, None, request, timeout) + cluster.read(None, request, timeout) } pub fn async_read_on_peer( @@ -505,10 +502,7 @@ pub fn async_read_on_peer( request.mut_header().set_replica_read(replica_read); let (tx, mut rx) = future::bounded(1, future::WakePolicy::Immediately); let cb = Callback::read(Box::new(move |resp| drop(tx.send(resp.response)))); - cluster - .sim - .wl() - .async_read(None, node_id, None, request, cb); + cluster.sim.wl().async_read(node_id, None, request, cb); Box::pin(async move { let fut = rx.next(); fut.await.unwrap() @@ -539,7 +533,7 @@ pub fn batch_read_on_peer( cluster .sim .wl() - .async_read(None, node_id, batch_id.clone(), request, cb); + .async_read(node_id, batch_id.clone(), request, cb); len += 1; } while results.len() < len { @@ -563,7 +557,7 @@ pub fn read_index_on_peer( read_quorum, ); request.mut_header().set_peer(peer); - cluster.read(None, None, request, timeout) + cluster.read(None, request, timeout) } pub fn async_read_index_on_peer( @@ -588,10 +582,7 @@ pub fn async_read_index_on_peer( request.mut_header().set_peer(peer); let (tx, mut rx) = future::bounded(1, future::WakePolicy::Immediately); let cb = Callback::read(Box::new(move |resp| drop(tx.send(resp.response)))); - cluster - .sim - .wl() - .async_read(None, node_id, None, request, cb); + cluster.sim.wl().async_read(node_id, None, request, cb); Box::pin(async move { let fut = rx.next(); fut.await.unwrap() diff --git a/components/tikv_kv/src/rocksdb_engine.rs b/components/tikv_kv/src/rocksdb_engine.rs index 404fee8ee58..e67d88bc687 100644 --- a/components/tikv_kv/src/rocksdb_engine.rs +++ b/components/tikv_kv/src/rocksdb_engine.rs @@ -64,7 +64,7 @@ impl Runnable for Runner { match t { Task::Write(modifies, cb) => cb(write_modifies(&self.0.kv, modifies)), Task::Snapshot(sender) => { - let _ = sender.send(Arc::new(self.0.kv.snapshot(None))); + let _ = sender.send(Arc::new(self.0.kv.snapshot())); } Task::Pause(dur) => std::thread::sleep(dur), } diff --git a/src/server/raft_server.rs b/src/server/raft_server.rs index fb53a98a27e..36c0cab22fc 100644 --- a/src/server/raft_server.rs +++ b/src/server/raft_server.rs @@ -290,7 +290,7 @@ where }; if should_check { // Check if there are only TiDB data in the engine - let snapshot = engines.kv.snapshot(None); + let snapshot = engines.kv.snapshot(); for cf in DATA_CFS { for (start, end) in TIDB_RANGES_COMPLEMENT { let mut unexpected_data_key = None; diff --git a/src/server/raftkv/mod.rs b/src/server/raftkv/mod.rs index 549ebcbad93..7eff47883e7 100644 --- a/src/server/raftkv/mod.rs +++ b/src/server/raftkv/mod.rs @@ -22,9 +22,9 @@ use std::{ use collections::{HashMap, HashSet}; use concurrency_manager::ConcurrencyManager; -use engine_traits::{CfName, KvEngine, MvccProperties, Snapshot, SnapshotContext}; +use engine_traits::{CfName, KvEngine, MvccProperties, Snapshot}; use futures::{future::BoxFuture, task::AtomicWaker, Future, Stream, StreamExt, TryFutureExt}; -use hybrid_engine::{HybridEngine, HybridEngineSnapshot}; +use hybrid_engine::HybridEngineSnapshot; use kvproto::{ errorpb, kvrpcpb::{Context, IsolationLevel}, @@ -43,7 +43,7 @@ use raftstore::{ dispatcher::BoxReadIndexObserver, Coprocessor, CoprocessorHost, ReadIndexObserver, }, errors::Error as RaftServerError, - router::{LocalReadRouter, RaftStoreRouter}, + router::{LocalReadRouter, RaftStoreRouter, ReadContext}, store::{ self, util::encode_start_ts_into_flag_data, Callback as StoreCallback, RaftCmdExtraOpts, ReadCallback, ReadIndexContext, ReadResponse, RegionSnapshot, StoreMsg, WriteResponse, @@ -355,7 +355,6 @@ where { router: RaftRouterWrap, engine: E, - in_memory_engine: Option>, txn_extra_scheduler: Option>, region_leaders: Arc>>, } @@ -366,16 +365,10 @@ where S: RaftStoreRouter + LocalReadRouter + 'static, { /// Create a RaftKv using specified configuration. - pub fn new( - router: S, - engine: E, - in_memory_engine: Option>, - region_leaders: Arc>>, - ) -> RaftKv { + pub fn new(router: S, engine: E, region_leaders: Arc>>) -> RaftKv { RaftKv { router: RaftRouterWrap::new(router), engine, - in_memory_engine, txn_extra_scheduler: None, region_leaders, } @@ -610,7 +603,7 @@ where type SnapshotRes = impl Future> + Send; fn async_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::SnapshotRes { - async_snapshot(&mut self.router, ctx, None) + async_snapshot(&mut self.router, ctx) } fn release_snapshot(&mut self) { @@ -620,17 +613,7 @@ where type IMSnap = RegionSnapshot>; type IMSnapshotRes = impl Future> + Send; fn async_in_memory_snapshot(&mut self, ctx: SnapContext<'_>) -> Self::IMSnapshotRes { - let snap_ctx = if self.in_memory_engine.is_some() { - // When range cache engine is enabled, we need snapshot context to determine - // whether we should use range cache engine snapshot for this request. - ctx.start_ts.map(|ts| SnapshotContext { - region: None, - read_ts: ts.into_inner(), - }) - } else { - None - }; - async_snapshot(&mut self.router, ctx, snap_ctx.clone()).map_ok(|region_snap| { + async_snapshot(&mut self.router, ctx).map_ok(|region_snap| { // TODO: Remove replace_snapshot. Taking a snapshot and replacing it // with a new one is a bit confusing. // A better way to build an in-memory snapshot is to return @@ -697,7 +680,6 @@ where fn async_snapshot( router: &mut RaftRouterWrap, mut ctx: SnapContext<'_>, - snap_ctx: Option, ) -> impl Future>> + Send where E: KvEngine, @@ -745,9 +727,10 @@ where })); let tracker = store_cb.read_tracker().unwrap(); + let read_ctx = ReadContext::new(ctx.read_id, ctx.start_ts.map(|ts| ts.into_inner())); if res.is_ok() { res = router - .read(snap_ctx, ctx.read_id, cmd, store_cb) + .read(read_ctx, cmd, store_cb) .map_err(kv::Error::from); } async move { diff --git a/tests/benches/misc/raftkv/mod.rs b/tests/benches/misc/raftkv/mod.rs index 551042f764b..092a1fc25d0 100644 --- a/tests/benches/misc/raftkv/mod.rs +++ b/tests/benches/misc/raftkv/mod.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, RwLock}; use collections::HashSet; use crossbeam::channel::TrySendError; use engine_rocks::{RocksEngine, RocksSnapshot}; -use engine_traits::{KvEngine, SnapshotContext, ALL_CFS, CF_DEFAULT}; +use engine_traits::{KvEngine, ALL_CFS, CF_DEFAULT}; use futures::future::FutureExt; use kvproto::{ kvrpcpb::{Context, ExtraOp as TxnExtraOp}, @@ -14,7 +14,7 @@ use kvproto::{ raft_serverpb::RaftMessage, }; use raftstore::{ - router::{LocalReadRouter, RaftStoreRouter}, + router::{LocalReadRouter, RaftStoreRouter, ReadContext}, store::{ cmd_resp, Callback, CasualMessage, CasualRouter, PeerMsg, ProposalRouter, RaftCmdExtraOpts, RaftCommand, ReadResponse, RegionSnapshot, SignificantMsg, SignificantRouter, StoreMsg, @@ -30,7 +30,7 @@ use tikv::{ Engine, }, }; -use tikv_util::{store::new_peer, time::ThreadReadId}; +use tikv_util::store::new_peer; use txn_types::Key; use crate::test; @@ -53,7 +53,7 @@ impl SyncBenchRouter { cmd_resp::bind_term(&mut response, 1); match cmd.callback { Callback::Read { cb, .. } => { - let snapshot = self.db.snapshot(None); + let snapshot = self.db.snapshot(); let region = Arc::new(self.region.to_owned()); cb(ReadResponse { response, @@ -121,8 +121,7 @@ impl RaftStoreRouter for SyncBenchRouter { impl LocalReadRouter for SyncBenchRouter { fn read( &mut self, - _: Option, - _: Option, + _: ReadContext, req: RaftCmdRequest, cb: Callback, ) -> Result<()> { @@ -143,7 +142,7 @@ fn new_engine() -> (TempDir, RocksEngine) { #[bench] fn bench_async_snapshots_noop(b: &mut test::Bencher) { let (_dir, db) = new_engine(); - let snapshot = db.snapshot(None); + let snapshot = db.snapshot(); let resp = ReadResponse { response: RaftCmdResponse::default(), snapshot: Some(RegionSnapshot::from_snapshot( @@ -185,7 +184,6 @@ fn bench_async_snapshot(b: &mut test::Bencher) { let mut kv = RaftKv::new( SyncBenchRouter::new(region.clone(), db.clone()), db, - None, Arc::new(RwLock::new(HashSet::default())), ); @@ -220,7 +218,6 @@ fn bench_async_write(b: &mut test::Bencher) { let kv = RaftKv::new( SyncBenchRouter::new(region.clone(), db.clone()), db, - None, Arc::new(RwLock::new(HashSet::default())), ); diff --git a/tests/failpoints/cases/test_witness.rs b/tests/failpoints/cases/test_witness.rs index 32a62c32219..33a62f0532b 100644 --- a/tests/failpoints/cases/test_witness.rs +++ b/tests/failpoints/cases/test_witness.rs @@ -52,7 +52,7 @@ fn test_witness_update_region_in_local_reader() { request.mut_header().set_replica_read(true); let resp = cluster - .read(None, None, request.clone(), Duration::from_millis(100)) + .read(None, request.clone(), Duration::from_millis(100)) .unwrap(); assert_eq!( resp.get_header().get_error().get_is_witness(), @@ -104,7 +104,7 @@ fn test_witness_not_reported_while_disabled() { request.mut_header().set_replica_read(true); let resp = cluster - .read(None, None, request.clone(), Duration::from_millis(100)) + .read(None, request.clone(), Duration::from_millis(100)) .unwrap(); assert!(resp.get_header().has_error()); assert!(!resp.get_header().get_error().has_is_witness()); @@ -491,7 +491,7 @@ fn test_non_witness_replica_read() { request.mut_header().set_replica_read(true); let resp = cluster - .read(None, None, request, Duration::from_millis(100)) + .read(None, request, Duration::from_millis(100)) .unwrap(); assert_eq!( resp.get_header().get_error().get_is_witness(), @@ -516,7 +516,7 @@ fn test_non_witness_replica_read() { request.mut_header().set_replica_read(true); let resp = cluster - .read(None, None, request, Duration::from_millis(100)) + .read(None, request, Duration::from_millis(100)) .unwrap(); assert_eq!(resp.get_header().has_error(), false); } diff --git a/tests/integrations/raftstore/test_snap.rs b/tests/integrations/raftstore/test_snap.rs index 69cb3d1c9e5..c5659b6f863 100644 --- a/tests/integrations/raftstore/test_snap.rs +++ b/tests/integrations/raftstore/test_snap.rs @@ -619,7 +619,7 @@ fn test_gen_during_heavy_recv() { let snap = do_snapshot( snap_mgr.clone(), &engine, - engine.snapshot(None), + engine.snapshot(), r2, snap_term, snap_apply_state, diff --git a/tests/integrations/raftstore/test_witness.rs b/tests/integrations/raftstore/test_witness.rs index d99f8692bcc..d4332403cea 100644 --- a/tests/integrations/raftstore/test_witness.rs +++ b/tests/integrations/raftstore/test_witness.rs @@ -473,7 +473,7 @@ fn test_witness_replica_read() { request.mut_header().set_replica_read(true); let resp = cluster - .read(None, None, request, Duration::from_millis(100)) + .read(None, request, Duration::from_millis(100)) .unwrap(); assert_eq!( resp.get_header().get_error().get_is_witness(), diff --git a/tests/integrations/storage/test_titan.rs b/tests/integrations/storage/test_titan.rs index e902b4a0cd4..86bcb609426 100644 --- a/tests/integrations/storage/test_titan.rs +++ b/tests/integrations/storage/test_titan.rs @@ -374,7 +374,7 @@ fn test_delete_files_in_range_for_titan() { build_sst_cf_file_list::( &mut cf_file, &engines.kv, - &engines.kv.snapshot(None), + &engines.kv.snapshot(), b"", b"{", u64::MAX, @@ -391,7 +391,7 @@ fn test_delete_files_in_range_for_titan() { build_sst_cf_file_list::( &mut cf_file_write, &engines.kv, - &engines.kv.snapshot(None), + &engines.kv.snapshot(), b"", b"{", u64::MAX, From 42265c809086b7e76d08bf5adfdd8305d6fcf499 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:43:14 +0800 Subject: [PATCH 078/144] In-memory engine: fix wrong set in complete checking (#17571) ref tikv/tikv#16141 fix wrong set in complete checking Signed-off-by: SpadeA-Tang --- .../src/range_stats.rs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/components/range_cache_memory_engine/src/range_stats.rs b/components/range_cache_memory_engine/src/range_stats.rs index 26cd376d1e3..bc62d0fce5c 100644 --- a/components/range_cache_memory_engine/src/range_stats.rs +++ b/components/range_cache_memory_engine/src/range_stats.rs @@ -92,7 +92,7 @@ impl RangeStatsManager { pub fn complete_auto_load_and_evict(&self) { *self.last_load_evict_time.lock() = Instant::now(); - self.set_checking_top_regions(true); + self.set_checking_top_regions(false); } /// Prevents two instances of this from running concurrently. @@ -695,4 +695,32 @@ pub mod tests { let _ = handle.join(); } + + #[test] + fn test_check_after_check() { + let sim = Arc::new(RegionInfoSimulator { + regions: Mutex::new(vec![]), + region_stats: Mutex::new(HashMap::default()), + }); + let mgr = RangeStatsManager::new( + Duration::from_secs(120), + 100, + 10, + Duration::from_secs(120), + sim, + ); + + // Interval is not enough + assert!(!mgr.ready_for_auto_load_and_evict()); + *mgr.last_load_evict_time.lock() = Instant::now() - Duration::from_secs(120); + assert!(mgr.ready_for_auto_load_and_evict()); + // Checking + assert!(!mgr.ready_for_auto_load_and_evict()); + + mgr.complete_auto_load_and_evict(); + // Interval is not enough + assert!(!mgr.ready_for_auto_load_and_evict()); + *mgr.last_load_evict_time.lock() = Instant::now() - Duration::from_secs(120); + assert!(mgr.ready_for_auto_load_and_evict()); + } } From 82019fc0e7494251147eeecdc3f1c1d09d0eedce Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Mon, 23 Sep 2024 15:27:24 +0800 Subject: [PATCH 079/144] raftstore: skip create logger in `get_entry_header` (#17564) close tikv/tikv#17563 According to the flamegraph, creating a logger takes as much time as parsing a protobuf message in `get_entry_header`. As an optimization, skip logger creation since it's only used for panic logging in `SimpleWriteReqDecoder::new`. Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../operation/command/admin/merge/prepare.rs | 2 +- .../raftstore-v2/src/operation/command/mod.rs | 4 +- .../raftstore/src/store/simple_write.rs | 46 +++++++++++-------- components/raftstore/src/store/util.rs | 6 +-- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/components/raftstore-v2/src/operation/command/admin/merge/prepare.rs b/components/raftstore-v2/src/operation/command/admin/merge/prepare.rs index 44580144dce..0aa44ea45db 100644 --- a/components/raftstore-v2/src/operation/command/admin/merge/prepare.rs +++ b/components/raftstore-v2/src/operation/command/admin/merge/prepare.rs @@ -324,7 +324,7 @@ impl Peer { } let Err(cmd) = SimpleWriteReqDecoder::new( |buf, index, term| parse_at(&self.logger, buf, index, term), - &self.logger, + Some(&self.logger), entry.get_data(), entry.get_index(), entry.get_term(), diff --git a/components/raftstore-v2/src/operation/command/mod.rs b/components/raftstore-v2/src/operation/command/mod.rs index 4103551041b..a8a3e5e0465 100644 --- a/components/raftstore-v2/src/operation/command/mod.rs +++ b/components/raftstore-v2/src/operation/command/mod.rs @@ -538,7 +538,7 @@ impl Apply { pub async fn apply_unsafe_write(&mut self, data: Box<[u8]>) { let decoder = match SimpleWriteReqDecoder::new( |buf, index, term| parse_at(&self.logger, buf, index, term), - &self.logger, + Some(&self.logger), &data, u64::MAX, u64::MAX, @@ -646,7 +646,7 @@ impl Apply { let req = match entry.get_entry_type() { EntryType::EntryNormal => match SimpleWriteReqDecoder::new( |buf, index, term| parse_at(&self.logger, buf, index, term), - &self.logger, + Some(&self.logger), entry.get_data(), log_index, entry.get_term(), diff --git a/components/raftstore/src/store/simple_write.rs b/components/raftstore/src/store/simple_write.rs index 9c3f9611675..6f2901402a6 100644 --- a/components/raftstore/src/store/simple_write.rs +++ b/components/raftstore/src/store/simple_write.rs @@ -231,7 +231,7 @@ pub struct SimpleWriteReqDecoder<'a> { impl<'a> SimpleWriteReqDecoder<'a> { pub fn new( fallback: impl FnOnce(&'a [u8], u64, u64) -> RaftCmdRequest, - logger: &Logger, + logger: Option<&Logger>, buf: &'a [u8], index: u64, term: u64, @@ -241,13 +241,22 @@ impl<'a> SimpleWriteReqDecoder<'a> { let mut is = CodedInputStream::from_bytes(&buf[1..]); let header = match is.read_message() { Ok(h) => h, - Err(e) => slog_panic!( - logger, - "data corrupted"; - "term" => term, - "index" => index, - "error" => ?e - ), + Err(e) => { + if let Some(logger) = logger { + slog_panic!( + logger, + "data corrupted"; + "term" => term, + "index" => index, + "error" => ?e + ) + } else { + panic!( + "data corrupted term: {}, index: {}, error {:?}", + term, index, e + ) + } + } }; let read = is.pos(); Ok(SimpleWriteReqDecoder { @@ -560,7 +569,7 @@ mod tests { let (bytes, _) = req_encoder.encode(); let logger = slog_global::borrow_global().new(o!()); let mut decoder = - SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bytes, 0, 0).unwrap(); + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bytes, 0, 0).unwrap(); assert_eq!(*decoder.header(), *header); let write = decoder.next().unwrap(); let SimpleWrite::Put(put) = write else { @@ -579,7 +588,8 @@ mod tests { assert_matches!(decoder.next(), None); let (bytes, _) = req_encoder2.encode(); - decoder = SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bytes, 0, 0).unwrap(); + decoder = + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bytes, 0, 0).unwrap(); let write = decoder.next().unwrap(); let SimpleWrite::DeleteRange(dr) = write else { panic!("should be delete range") @@ -615,7 +625,7 @@ mod tests { SimpleWriteReqEncoder::>::new(header, bin, 0); let (bytes, _) = req_encoder.encode(); let mut decoder = - SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bytes, 0, 0).unwrap(); + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bytes, 0, 0).unwrap(); let write = decoder.next().unwrap(); let SimpleWrite::Ingest(ssts) = write else { panic!("should be ingest") @@ -661,7 +671,7 @@ mod tests { let bytes = raft_cmd.write_to_bytes().unwrap(); let logger = slog_global::borrow_global().new(o!()); let decoded = - SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bytes, 0, 0).unwrap_err(); + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bytes, 0, 0).unwrap_err(); // SimpleWriteReqDecoder should be able to decode naive RaftCmdRequest. assert_eq!(decoded, raft_cmd); @@ -703,7 +713,7 @@ mod tests { let (bytes, _) = req_encoder.encode(); let mut decoder = - SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bytes, 0, 0).unwrap(); + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bytes, 0, 0).unwrap(); assert_eq!(*decoder.header(), *header); let req = decoder.next().unwrap(); let SimpleWrite::Put(put) = req else { @@ -732,7 +742,7 @@ mod tests { let (bin, _) = req_encoder.encode(); assert_eq!( header.as_ref(), - SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bin, 0, 0) + SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bin, 0, 0) .unwrap() .to_raft_cmd_request() .get_header(), @@ -747,7 +757,7 @@ mod tests { 512, ); let (bin, _) = req_encoder.encode(); - let req = SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bin, 0, 0) + let req = SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bin, 0, 0) .unwrap() .to_raft_cmd_request(); assert_eq!(req.get_requests().len(), 1); @@ -764,7 +774,7 @@ mod tests { 512, ); let (bin, _) = req_encoder.encode(); - let req = SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bin, 0, 0) + let req = SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bin, 0, 0) .unwrap() .to_raft_cmd_request(); assert_eq!(req.get_requests().len(), 1); @@ -780,7 +790,7 @@ mod tests { 512, ); let (bin, _) = req_encoder.encode(); - let req = SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bin, 0, 0) + let req = SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bin, 0, 0) .unwrap() .to_raft_cmd_request(); assert_eq!(req.get_requests().len(), 1); @@ -807,7 +817,7 @@ mod tests { 512, ); let (bin, _) = req_encoder.encode(); - let req = SimpleWriteReqDecoder::new(decoder_fallback, &logger, &bin, 0, 0) + let req = SimpleWriteReqDecoder::new(decoder_fallback, Some(&logger), &bin, 0, 0) .unwrap() .to_raft_cmd_request(); assert_eq!(req.get_requests().len(), 5); diff --git a/components/raftstore/src/store/util.rs b/components/raftstore/src/store/util.rs index 53884a13ba6..c0e6f299d96 100644 --- a/components/raftstore/src/store/util.rs +++ b/components/raftstore/src/store/util.rs @@ -765,10 +765,9 @@ pub fn get_entry_header(entry: &Entry) -> RaftRequestHeader { if entry.get_entry_type() != EntryType::EntryNormal { return RaftRequestHeader::default(); } - let logger = slog_global::get_global().new(slog::o!()); match SimpleWriteReqDecoder::new( |_, _, _| RaftCmdRequest::default(), - &logger, + None, entry.get_data(), entry.get_index(), entry.get_term(), @@ -818,10 +817,9 @@ pub enum RaftCmd<'a> { } pub fn parse_raft_cmd_request<'a>(data: &'a [u8], index: u64, term: u64, tag: &str) -> RaftCmd<'a> { - let logger = slog_global::get_global().new(slog::o!()); match SimpleWriteReqDecoder::new( |_, _, _| parse_data_at(data, index, tag), - &logger, + None, data, index, term, From ff78c79606a24610f96cd5b01a9d5268795027d1 Mon Sep 17 00:00:00 2001 From: CbcWestwolf <1004626265@qq.com> Date: Mon, 23 Sep 2024 15:52:27 +0800 Subject: [PATCH 080/144] charset,collation: implement `GB18030` and 2 collations (#17467) close tikv/tikv#17470 * Add a new charset `gb18030` * Add two related collations `gb18030_chinese_ci` and `gb18030_bin` Signed-off-by: cbcwestwolf <1004626265@qq.com> Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/codec/collation/charset.rs | 3 + .../codec/collation/collator/gb18030_bin.data | Bin 0 -> 4456448 bytes .../collator/gb18030_chinese_ci.data | Bin 0 -> 4456448 bytes .../collation/collator/gb18030_collation.rs | 181 ++ .../codec/collation/collator/gbk_collation.rs | 14 +- .../src/codec/collation/collator/mod.rs | 48 + .../src/codec/collation/encoding/gb18030.rs | 434 ++++ .../codec/collation/encoding/gb18030_data.rs | 2107 +++++++++++++++++ .../src/codec/collation/encoding/mod.rs | 3 + .../src/codec/collation/mod.rs | 3 + .../src/codec/mysql/charset.rs | 2 + .../tidb_query_datatype/src/def/field_type.rs | 9 + components/tidb_query_expr/src/impl_cast.rs | 4 + components/tidb_query_expr/src/impl_string.rs | 69 +- 14 files changed, 2869 insertions(+), 8 deletions(-) create mode 100644 components/tidb_query_datatype/src/codec/collation/collator/gb18030_bin.data create mode 100644 components/tidb_query_datatype/src/codec/collation/collator/gb18030_chinese_ci.data create mode 100644 components/tidb_query_datatype/src/codec/collation/collator/gb18030_collation.rs create mode 100644 components/tidb_query_datatype/src/codec/collation/encoding/gb18030.rs create mode 100644 components/tidb_query_datatype/src/codec/collation/encoding/gb18030_data.rs diff --git a/components/tidb_query_datatype/src/codec/collation/charset.rs b/components/tidb_query_datatype/src/codec/collation/charset.rs index 9ea76f16b92..2781273ae7c 100644 --- a/components/tidb_query_datatype/src/codec/collation/charset.rs +++ b/components/tidb_query_datatype/src/codec/collation/charset.rs @@ -60,3 +60,6 @@ impl Charset for CharsetUtf8mb4 { // gbk character data actually stored with utf8mb4 character encoding. pub type CharsetGbk = CharsetUtf8mb4; + +// gb18030 character data actually stored with utf8mb4 character encoding. +pub type CharsetGb18030 = CharsetUtf8mb4; diff --git a/components/tidb_query_datatype/src/codec/collation/collator/gb18030_bin.data b/components/tidb_query_datatype/src/codec/collation/collator/gb18030_bin.data new file mode 100644 index 0000000000000000000000000000000000000000..172e21ee596b2ccc5fa03260735d90ca51ea6a98 GIT binary patch literal 4456448 zcmW*U1+XmdRq$)BySuyF;(gb<*1N8L-*tC)cXz)9ArL1*5+V?HclU$@h0kGpGqdZQU0pMKf8Y0g-}n77{IUFT{PFw={E7TY{K@<&{HgqD{OSA| z{F(e&{Mr0D{JH#j{Q3L^{Du5Q{Kfnw{H6S5{N?-={FVGw{MGz5{I&db{Pp||{Ehrg z{LTC={H^?L{O$Z5{GI$=1mDkMlN^fXGW^~AJ^a1=ef<6W1N;&GDE}b;5dSd$2>&Sm z82>o`1pg%e6#q2;4F4?u9REE30{+3;!$s8~;212mdGk z7ymc^5C1R!AMpe61K-bLlN^fXGQdXfDIE-5)>f7#5r4P&AhzeniJ&lN^fXGQ>l4EH=rZ zXf8uMG=AV69{>Bz#U?ov&E?t8|Gw{gCSyAu=G-hc$@A@dE^p+x{bKWllp=d5cJYL6QlN^fX6%YLV%^{wkWwA*PMROVA zi8>aWSbSyT>p=d5cJXyzLlN^fXGQ?AKEH=rZXf8uMRmWnJ z9E#>L#82p0Y?4FKT!#2b9g9tJD4NR0Y?4FKT!wg#j>RT96wPIb=jvE&l0(s4hIpQi#U?ov&1Hz^>sV}(L(yD@c!7?^ zCOH(%Wr!E*SZtC*(Oiajk&eYCITX#CJipf*;>B7Po8(Y5mmyxFWAXL}z9!7%P&Ahz zUaDoWNe)GG8RBI+7MtWyG?yV>u4A!D4n=br;uSg;o8(Y5mmyxMW3fpNMROVARXP@% zv@ABsp=d5cyivzulN^fXGQ^v7EH=rZXf8v%S;u0N z9E#>L#9MSMHp!uAEp=d5c zyi>L#CvosHp!uAE<^m3j>RT96wPIb_v%<| zl0(s4hIpTj#U?ov&1Hz6*0IEm#m+~@R&MWwS=Xs_1DqhWNcrCBv^(^~0$)RX2@38-!yo-199)61V@;-i= zpW$bDKOf+Oe25S85yp8wYJQB5^9er5r}#ASe$NMsO>!uj%Mc&XvDhSsqPYz5K^==t zawwY15FgU9*d&LdxeW1P9g9tJD4NRe>tpXAeghM(iJ{5-$F=lDEd;1~HKU*ebeWxmW;_$puH>wJT6@-4p2cla*fV>}0+ zGUH>OD;AsNP&AhzKCWZ2Ne)GG8R8Q<7MtWyG?yVhsbjH84n=br;!`>no8(Y5mmxl_ zW3fpNMROVAGddQVRT96wPIbFY8!rl0(s4hWLt(#U?ov&1HzM>R4=& zL(yD@_?nKzCOH(%Wr(lqSZtC*(Oic3hK|K1ITX!hh;QmxY?4FKT!#3Tj>RT96wPIb zZ|hiWl0(s4hWL(-#U?ov&1H!1>R4=&L(yD@_@0i%COH(%Wr$zVvDhSsqPYz5t2!2& zu>sV}(L(yD@_zfM4O>!uj%Mib*W3fpNMROVAw{$Ev$)RX2 zL;SXm#U?ov&1Hz+(XrShhoZR*@w++}o8(Y5mmz*n$6}KlismxJ@9S7>l0(s4hWG;= zi%oJUn#-X2!(~}-l0(s4hWJ4pi%oJUn#&Lm(y`bihoZR*@k2Tmo8(Y5mmwakW3fpN zMROVAhjlDA$)RX2L;Q%2#U?ov&1Hy(=vZu$L(yD@c&LuWCOH(%Wr&CASZtC*(Oiaj zxQ@jpITX!hh)3vHY?4FKT!wh0j>RT96wPIbN9kB>l0(s4hWJq(i%oJUn#&N6*0I!uj%Mg#%vDhSsqPYz5I30^kawwY15I?44u}Ka^a~b0CIu@JcP&Ahz zo}go~Ne)GG8RCgL7MtWyG?yWMT*qRQ9E#>L#FKO^Hp!uAE<-$7$6}KlismxJQ*g$O>!uj%Mee~vDhSsqPYz5bRCOLawwY1 z5YN!D*d&LdxeW149g9tJD4NR<&(g8jB!{B84DoCoi%oJUn#&N+(XrShhoZR*@mw8? zO>!uj%Mj1gvDhSsqPYz5d>xBTawwY15HHZN*d&LdxeW0_9g9tJD4NR!uj%MdTqvDhSsqPYz5avh6JawwY15U!uj z%Mh>AvDhSsqPYz5dL4^RawwY15O2`2*d&LdxeW0}9g9tJD4NR!uj%MfqVvDhSsqPYz5b{&gNawwY15bw~j*d&Ld zxeW169g9tJD4NR<@6xf@B!{B84DoIqi%oJUn#&OH(XrShhoZR*@l!e$o8(Y5mm%J( zW3fpNMROVAeL5DK!uj%MkC^vDhSs zqPYz50Ue7?awwY15FgaB*d&LdxeW0k9g9tJD4NR!uj%Mc&evDhSsqPYz52_1_~awwY15TDes*d&LdxeW0s9g9tJ zD4NR~64n=br;sV}(L(yD@_=1kbCOH(%Wr$zYvDhSsqPYz5MIDPx zawwY15MR=<*d&LdxeW13Iu@JcP&Ahzep$z2lN^fXGQ^j4EH=rZXf8v1MaN>39E#>L z#8-7JHp!uAE<=1x$6}KlismxJ*L5s5$)RX2LwrNWVv`(-<}$=Lbu2c?p=d5cd`rh- zlN^fXGQ_uaEH=rZXf8v1N5^859E#>L#CLTpHp!uAE<=1z$6}KlismxJujp88l0(s4 zhWJ$-i%oJUn#&Nsrem>54n=br;@5R7Hp!uAE<^l=j>RT96wPIb-_)_#B!{B84Dnk! z7MtWyG?yWMTgPIP9E#>L#P8@>Y?4FKT!#2v9g9tJD4NR*P>0mmz*o$6}KlismxJgLEu5$)RX2L;R4A#U?ov z&1HxO>sV}(L(yD@_+cH3O>!uj%Md@JW3fpNMROVAAvzYDRT96wPIbAJ?(iB!{B84Dlo#i%oJUn#&MR*0I!uj%Mef1vDhSsqPYz56FL@~p=d5c zJYC0PlN^fXGQ=}L#ItlPHp!uAE<-$9$6}KlismxJb95{= z$)RX2Lp)cp=d5cJYUCRlN^fXGQL z#EWz+Hp!uAE~bSyT>p=d5cyj;g( zlN^fXGQ=x%EH=rZXf8v%QpaMG9E#>L#H(~HHp!uAEp=d5cyk5s*lN^fXGQ=BnEH=rZXf8v%QO9DF9E#>L#G7<1 zHp!uAEp=d5cyj{m)lN^fX zGQ>M{EH=rZXf8v%Q^#VH9E#>L#JhAXHp!uAER4=&L(yD@c%P2NCOH(%Wr&~FvDhSsqPYz5GddQVL#D{e(Hp!uAE<=1o z$6}KlismxJM|CVV$)RX2LwrofVv`(-<}$>`bu2c?p=d5cd_u=!lN^fXGQ=l!EH=rZ zXf8v1O2=Z89E#>L#HV#EHp!uAE<=1q$6}KlismxJ&*@lfl0(s4hWM!uj%MjntvDhSsqPYz5O&yC( zawwY15Z}_V*d&LdxeW1b9g9tJD4NR<-_fzyB!{B84DnqZi%oJUn#&O1)3MkjhoZR* z@hdtOo8(Y5mmz*t$6}KlismxJujyE9l0(s4hWK?Ii%oJUn#&Nsp<}U04n=br;x~0H zHp!uAE<^m5j>RT96wPIb-`26%B!{B84DmZU7MtWyG?yWMSI1(L9E#>L#P8`?Y?4FK zT!#349g9tJD4NR^|}YH)a^f9()v&|mmz*o$6}KlismxJgLEu5 z$)RX2L;R4A#U?ov&1HxO>sV}(L(yD@_+cH3O>!uj%Md@JW3fpNMROVAAvzYDRT96wPIbAJ?(iB!{B84Dlo# zi%oJUn#&MR*0I!uj%Mef1vDhSsqPYz56FL@~p=d5cJYC0PlN^fXGQ=}L#ItlPHp!uAE<-$9 z$6}KlismxJb95{=$)RX2Lp)cp=d5cJYUCRlN^fXGQL#EWz+Hp!uAE~ zbSyT>p=d5cyj;g(lN^fXGQ=x%EH=rZXf8v%QpaMG9E#>L#H(~HHp!uAEp=d5cyk5s*lN^fXGQ=BnEH=rZXf8v% zQO9DF9E#>L#G7<1Hp!uAE zp=d5cyj{m)lN^fXGQ>M{EH=rZXf8v%Q^#VH9E#>L#JhAXHp!uAER4=&L(yD@c%P2NCOH(%Wr&~FvDhSsqPYz5GddQV zL z#D{e(Hp!uAE<=1o$6}KlismxJM|CVV$)RX2LwrofVv`(-<}$>`bu2c?p=d5cd_u=! zlN^fXGQ=l!EH=rZXf8v1O2=Z89E#>L#HV#EHp!uAE<=1q$6}KlismxJ&*@lfl0(s4 zhWM!uj%Mjnt zvDhSsqPYz5O&yC(awwY15Z}_V*d&LdxeW1b9g9tJD4NR<-_fzyB!{B84DnqZi%oJU zn#&O1)3MkjhoZR*@hdtOo8(Y5mmz*t$6}KlismxJujyE9l0(s4hWK?Ii%oJUn#&Ns zp<}U04n=br;x~0HHp!uAE<^m5j>RT96wPIb-`26%B!{B84DmZU7MtWyG?yWMSI1(L z9E#>L#P8`?Y?4FKT!#349g9tJD4NRL#ERT96wPIbhw4~tl0(s4hIp8c#U?ov&1Hy(>sV}(L(yD@c!Z9{COH(% zWr#=WSZtC*(Oiajl#azFITX!hh#%Fl*d&LdxeW1W9g9tJD4NR39E#>L#8Y)FHp!uAE<^l; zj>RT96wPIbpVYC~B!{B84DmD_i%oJUn#&MR*Rj|nhoZR*@eCb{O>!uj%Mj1hvDhSs zqPYz5EFFtYawwY15YN`J*d&LdxeW0f9g9tJD4NR<&(*QmB!{B84Dmc2i%oJUn#&N+ z*Rj|nhoZR*@d6!-O>!uj%MdTrvDhSsqPYz5A{~oOawwY15HHrT*d&LdxeW0V9g9tJ zD4NR!uj%Mh>BvDhSsqPYz5 zDjkbWawwY15UO>!uj%MfqWvDhSsqPYz5CLN1SawwY15O3D8*d&LdxeW0Z9g9tJD4NR< zZ`HBbB!{B84DmJ{i%oJUn#&Mx*Rj|nhoZR*@eUn}O>!uj%MkC>vDhSsqPYz5E**~64n=br z;-_^iHp!uAE<^l`j>RT96wPIbpVhJ0B!{B84Do&)i%oJUn#&L$(6QJghoZR*@j)Gn zO>!uj%Mc&ZvDhSsqPYz5VI7N2awwY15FgR8*d&LdxeW199g9tJD4NR!uj%MhQ^vDhSsqPYz5X&sAAawwY15TDVp z*d&LdxeW1hIu@JcP&AhzKC5G~Ne)GG8RF-4EH=rZXf8wif{w)|ITX!hh|lR*Y?4FK zT!#3(j>RT96wPIbFX&iol0(s4hWJGti%oJUn#&Mh)UntkhoZR*@g*ILO>!uj%Mib$ zW3fpNMROVAmvt;Q$)RX2Lws4sVv`(-<}$=rbSyT>p=d5cd{xI{lN^fXGQ`((EH=rZ zXf8v1UB_aR9E#>L#5Z&-Hp!uAE<=1%$6}KlismxJw{$Ev$)RX2LwsAuVv`(-<}$>0 zbSyT>p=d5cd{@U}lN^fXGQ{_EEH=rZXf8wiijKu5ITX!hh+oyQ*d&LdxeW1ZIu@Jc zP&AhzeqG06lN^fXGQ@A_SZtC*(Oic3O&yC(awwY15Wl5ku}Ka^a~a~dbu2c?p=d5c z{Em*rCOH(%Wr*L^vDhSsqPYz5dpZ`I{%|Sl<}$<&>R4=&L(yD@c#w|8COH(%Wr!crvDhSsqPYz5U>%E1 zawwY15I?MAu}Ka^a~a}CbSyT>p=d5cJVeK0lN^fXGQ>l5EH=rZXf8uMOvhrA9E#>L z#KUzgHp!uAE<-#*$6}KlismxJBXuk`$)RX2Lp(~yVv`(-<}$>O>R4=&L(yD@c(jhi zCOH(%Wr)Y~nSZtC*(OiajnvTULITX!hh^OmVY?4FK zT!wgtj>RT96wPIbXX;pNl0(s4hIp2a#U?ov&1HyZ>sV}(L(yD@c#e+6COH(%Wr*kM zSZtC*(Oiajo{q&PITX!hi0A8AY?4FKT!wgoj>RT96wPIb7wTASl0(s4hIo;V#U?ov z&1Hxe>sV}(L(yD@c!`e1COH(%Wr&yRSZtC*(OiajnU2LKITX!hh?nbFY?4FKT!wgs zj>RT96wPIbSL#@7l0(s4hIo~Z#U?ov&1HyJ>sV}(L(yD@c#V$5COH(%Wr)}6SZtC* z(OiajosPvOITX!hh}Y{_Y?4FKT!wgqj>RT96wPIbH|khyl0(s4hIo^X#U?ov&1Hx; z>sV}(L(yD@c#Dq3COH(%Wr(-xSZtC*(Oiajn~udMITX!hh_~xlY?4FKT!wguj>RT9 z6wPIbcj{Pdl0(s4hIp5b#U?ov&1Hyp>sV}(L(yD@c#n?7COH(%Wr&~BvDhSsqPYz5 zULA`~awwY15bx8m*d&LdxeW2sIu@JcP&Ahzen!V)lN^fXGQ`j7SZtC*(OiajzmCNw zITX!hh!5ykY?4FKT!#3dj>RT96wPIb59wHJl0(s4hWN0K#U?ov&1Hy>=vZu$L(yD@ z_^6J>COH(%Wr&aISZtC*(Oic3xQ@jpITX!hh)?KPY?4FKT!#3hj>RT96wPIbPw7}} zl0(s4hWNCO#U?ov&1Hzs=vZu$L(yD@_&FVmO>!uj%MhQ{vDhSsqPYz5^Ewurp=d5cd|t<5lN^fXGQ<~jEH=rZXf8wiqK?HTITX!hh%f3` zY?4FKT!#3Pj>RT96wPIbU(&JIB!{B84Dri47MtWyG?yX1tYfiB4n=br;ww59o8(Y5 zmm$8YW3fpNMROVAYdRL22Vv`(- z<}$>u>R4=&L(yD@_%$7iO>!vS{J`&JGl%$f9g9tJD4NRw3fJo%_-SL#DjG#Hp!uAE<^mVj>RT96wPIbAJMVcB!{B84Dk>h zi%oJUn#&Lm)v?$lhoZR*@h}~WO>!uj%McIOvDhSsqPYz52px+}awwY15RcTc*d&Ld zxeW0r9g9tJD4NRp=d5cJWRT96wPIbr|MX2l0(s4hWH5`i%oJUn#&MB zsbjH84n=br;%Pb-o8(Y5mm!|6W3fpNMROVA89El5iC|9_6|@=LZfOYHN%wCkn4_cz;O9!Vn_jik|l(3UMrvMo#Ya#u4mGZZy* zHC9tGGjn%UHB~dy@^fe9dhUMX+}}AF8Ih5hH*RDEi_IY^nz%&AA70_L8O_OG@cs1t zUMux4njgII+NrjE*!&3F`tVWfkCE0z6PG#`gUMgA|A#codUHsMCN9%6_>OLx-!PxL zu#fd$w*NK{Nzwe$-^bl!#paL{O}t;nV6xa8lA?(Z=om~En?q7G z@j)Gf$zpRziY7j!V=!544oT6(hjk1li_IY^n)ry0!DO*HBt;V+)iIbXHix8W;$u1n zlf~wc6is|w$6&J99Fn4mPw4pidwjl`lf~wc6is|m%V4tD9Fn4mPw5y;7Mnv-H1TO2 zgUMoZNQx$|)G?SWHix8W;xjr1lf~wc6is|q$6&J99Fn4m&*>OU7Mnv-H1T;IgUMoZ zNS=24DD$tl{j?ch(DPTF9_D1RIV43BU(_;~JbU4`Xl@Qk(Zp3+29tl{YsfM;hoorY zOIik##paL{O?+9$V6xa8lA?*P=om~En?q7G@l_pz$zpRziYC6MV=!544oT6()j9@~ z#pZ`TpMS)U`3XPeXZ)OB@JoKhulWtfK1tEM+qU=cUf#zgT*_r!&K10$xW@ZuFj;I4 zNzuf$ItG))=8zOkT&LsLuIJzID}KwcZSvQA&ir-$27i-f+vboIODVn%R$6&J99Fn4mn{^B(i_IY^nz%*BV6xa8lA?)Qbqpqp z%^@k8xJ}1kve+DwqKVse3?_@sAt{=;L&spU*c_6gi92-+CO5iHm$^A4MRT3Mi@VNq zt~D<*2a~^b;rcc=hva5Wna%yykMg&5x0!Lb_sQRJdYHG`HqEQeYq){yxszr4<}T}F zCPfqXoaa1l`(u2Ko4Clf!DO+y&-P;`MHBZr4-6)Y&Ak^|Gb!$Iy3M#x&tUR<7d~cl zb4ZFN?$Yc)DVlg($6&J99Fn4mC(d*JzVmsJIhZUqhoorYNylU`S!@nT(Zttv3?_@sAt{>p zhK|8xu{k6~6Hnuj2f%^@k8__mh8WU)CUMHAoAF_ljQHn?q7G z@e>_`$zpRziY9)lV=!544oT6(&vXnXi_IY^n)tbn!DO*HBt;Xy&@q@SHix8W;+HxG zlf~wc6ixg}$6&J99Fn4mU+Wl57Mnv-H1Qi9gUMoZNQx$Yt79-(Yz|4$#P4(rCX3A> zDH^ZJ>weJ-ui$avSphHnrtyVGFJ8DuH2?gq{Mp3CItG))=8zOkJXgnHve+DwqKW6} z7)%zMLsB&Hd>wG_#~g=(_G1C_$;5} z^L&9Xaur|V%Y22e@-?pJIFCuu#4CIp3?_@sAt{=8rH;X5u{k6~6R*-Sm@GDjq-f&R zItG))=8zOkyhg`hve+DwqKVh)7)%zMLsB&HIvs<_Vsl7}CSI>&Fj;I4Nzud`bPOho z%^@k8c%zQNWU+ale|ulTrCi44T*3SK03YN-e3*~$Q9j1U`2?TjQ+%2$`3#@sb9|mJ z@I|iTOMIEH@KwIX)m+21T*vj?z>VC*&D_GR+{W$P!JXX2-Q2^y+{gVqz=J%*!#u*H zJjUZZ!IONQZ}1dP^9_<#BTcn%lyT%O1Cc>ynE+JCWmk<%~cB^;-d zqKUV7e+(vz&CmSY_|pqN?^`ED6K~Zsm@GDjq-f%8I)338KWA7^7Mnv-G%t1DUPip# zehemy%^~@TWBr)2ZsHyJoF6!SkvaI0^$(fWi_IY^ns}%8!C+=VzIlLsB&H zKKn43EH;OvXyOtbgUMoZNQx#d)iIbXHix8W;xZkB$zpRziY6}CF_ph>pQzu{k6~6Cc$vm@GDjq-f$}ItG))=8zOkd|bz1ve+DwqKQxF7)%zM zLsB&HNgad9Vsl7}CO)NOFj;I4Nzufobqpqp%^@k8xKhVpve+DwqKVJw7)%zMLsB&H zSsjDPVsl7}CO)TQFj;I4NzugTbqpqp%^@k8_=1kXWU)CUMH64tF_!29w3+kQ7bau46D+Yz|4$#2q>Ylf~wc6iwWzV=!544oT6(T{;Gn#paL{P28DVsl7}CcdR(Fj;I4Nzuf& zbqpqp%^@k8_>PXjWU)CUMHAoEF_+xSjS+p*c_6giRbDVOct9%QZ(^A9fQeYb4ZFN zp08stS!@nT(ZmaM3?_@sAt{=8p^m|1u{k6~6ED&+m@GDjq-f&BItG))=8zOkyhO)f zve+DwqKTL47)%zMLsB&HG981-Vsl7}CSI;%Fj;I4NzueBbPOho%^@k8c%_cPWU)CU zMH8>mF_KIHGn?q7G@j4xY$zpRziY8vK zV=!544oT6(8*~gNi_IY^ns}p*!DO*HBt;W%(lMAUHix8W;>|h+lf~wc6ivKE$6&J9 z9Fn4mx9S*77Mnv-H1ReagUMoZNQx%ju46D+Yz|4$#5;5hCX3A>DVlhvj=^NHIV43B z@6s`tEH;OvXyV;E29w3+kQ7b4N5^2Y*c_6giTCOlOct9%QZ(^C9fQeYb4ZFNF3~ZV zEH;OvXyQ^GgUMoZNQx#d(=nJVHix8W;&L5>$zpRziYBhmF_KIHGn?q7G@gW_9$zpRziY7j+V=!544oT6(M|2D(i_IY^n)s-W z!DO*HBt;V+(=nJVHix8W;^R67lf~wc6is|W$6&J99Fn4mPwE&<7Mnv-H1R1NgUMoZ zNQx#ttz$4*Yz|4$#FaV*lf~wc6is|a$6&J99Fn4m&*~UV7Mnv-H1RndgUMoZNQx#t zuVXM-Yz|4$#20i7CX3A>DVq4Aj=^NHIV43BSLql`7Mnv-H1Q=JgUMoZNQx%DtYa`) zYz|4$#8-3-CX3A>DVq4Ij=^NHIV43BU(+#|EH;OvXyR%egUMoZNQx$|(J`1THix8W z;#wVp$zpRziYBhpF_ zDVlgj$6&J99Fn4mZ|WFK7Mnv-H1RDRgUMoZNQx%Dtz$4*Yz|4$#CLQICX3A>DVq4M zj=^NHIV43B&*~UV7Mnv-H1RzhgUMoZNQx%DuVXM-Yz|4$#1C`~CX3A>DVq49j=^NH zIV43BKhiOnEH;OvXyV5@29w3+kQ7b)M8{yV*c_6giJ$5iOct9%QZ(^19fQeYb4ZFN zey(FMS!@nT(Znxw3?_@sAt{>prH;X5u{k6~6Ti|im@GDjq-f&TItG))=8zOk{6@!M zve+DwqKV(?7)%zMLsIzRwjNjFBe&6~cb1?ZwPA_xwkFEb1$2uvR@QBlk@JiP1 z!@KaRHy55sv!Cg<(Be{8y*9c}R*To^Kxplf~wc6wkA7oAClIgUMoZNQx$2sADi$ zYz|4$#EWzcCX3A>DVlh(j=^NHIV43BFVQiWEH;OvXyTljQHn?q7G@eUn>$zpRziYDHvV=!544oT6(yL1dDi_IY^ns~R4!DO*HBt;YN(J`1T zHix8W;=MXv;xVZ&8_SMW++#jAM@ujO^To?)NKV)Jf~dwUP><#LW~SD1gMeFLAg z{uH0)N&!6uktmn<{GZ$I#O2R>c^{W>DVK3MSMYv5zz6vd zALb)`l#lUoKEWsX6rbiwKEr4E9G~Y4e37g85?|&ke3h?pHP>)0*Ks{Ja3eQyGq-Rn zw{bgna3^Zs!i} z!9`5Bn?&kp>DVq48j=^NHIV43BAJQ?HEH;OvXyU^<29w3+kQ7aPM8{yV z*c_6giI3_SOct9%QZ(@~9fQeYb4ZFNKCWXhS!@nT(ZnZo3?_@sAt{>pq>jO4u{k6~ z6Q9yCm@GDjq-f&PItG))=8zOkT&ZI)S!@nT(ZpwT3?_@sAt{>ptd7BCu{k6~6Q9#D zm@GDjq-f&vItG))=8zOkd_l)xve+DwqKPl+7)%zMLsB$xm5#w=u{k6~6JOFXm@GDj zq-f&HItG))=8zOkd_~7oekbf{p5dE(i*NHCzRR8yYz|4$#LYSelf~wc6iwWs8yYz|4$#KSrUlf~wc6iqy$V=!54 z4oT6(qdEqY#paL{O+2P!Fj;I4NzugPItG))=8zOkJfUMSS!@nT(ZrKF29w3+kQ7aP zUB_Uu*c_6giEro_OctBJ?zZ|jIMzwg#8Y|(lf~wc{7w7(E&ev;bn|zt<7xXbm@GDj zq-f$99fQeYb4ZFNzNup{S!@nT(ZsiO3?{$lyexBbNQx%Dt!40cb<Ewm$s6 zb(%#J-?1Nq$zpRziYC6RV=!544oT6(vpNQo#paL{O?*$sV6xa8lA?+4>ljQHn?q7G z@dF)$$zpRziY9)jV=!544oT6(k8}(si_IY^n)tDf!DO*HBt;WH(J`1THix8W;-@+W zlf~wc6wN<$pKtt3%V4tD9Fn4mpX(S*7Mnv-H1P`^gUMoZNQx$Ysber%Yz|4$#IJM= z{(qF_JD$zpRziYDHmV=!544oT6(8+8mOi_IY^ns}3r!DO*HBt;W%)-jkYHix8W;w^FU zANX2zkvW(wHix8W;;oL!V6xa8lA?*X=@?8Fn?q7G@pc`9$zpRziYDHnV=!544oT6( zJ9P{ui_IY^ns}Fv!DO*HBt;YN)-jkYHix8W;ypSBlf~wc6ivKW$6&J99Fn4m_vsi+ z7Mnv-G;xWJKXm;KbF$bRlA?)AwG960h3`$~Vsl7}CN9%5m@GDjq-f%D9fQeYb4ZFN zuFx@psE)y8u{k6~6Ccwtm@GDjq-f&fItG))=8zOkd_u=yve+Dw zqKQxH7)%zMLsB&HDIJ5!Vsl7}CO)lWFj;I4NzufWItG))=8zOkd`8D$ve+DwqKVJy z7)%zMLsB&HIUR$^Vsl7}CO)rYFj;I4Nzud?bPOho%^@k8_@a)%WU)CUMH5%)7)%zM zLsB&HB^`swVsl7}Ccdm=Fj;I4NzuetbPOho%^@k8_^OV zFj;I4Nzuf2bPOho%^@k8_^yt@WU)CUMHA2J7)%zMLsB&HJspF|Vsl7}Ccdv@Fj;I4 zNzud)bPOho%^@k8_@R!$WU)CUMH4^LF_p zm5#w=u{k6~6Tj9m_!k%cJ!LL7hoorYH(Cah#paL{P5f5JV6xa8lA?*<=@?8Fn?q7G z;nBSpF_DVn%K z$6&J99Fn4m_v;u;7Mnv-H1Po)gUMoZNQx#tsADi$Y!1o4aa$|1i4SQROct9%QZ(^l z9fQeYb4ZFNKB8kVS!@nT(Zok}3?_@sAt{>pn2y0@u{k6~6Cc+xm@GDjq-f$3ItG)) z=8zOkd{W0?ve+DwqKQxG7)%zMLsB&HX&r;fVsl7}Ca%;mm@GDjq-f$ZItG))=8zOk zd{)O`ve+DwqKVJx7)%zMLsB&Hc^!kvVsl7}CcdC!Fj;I4Nzud?bqpqp%^@k8xJt)h zve+DwqKPl*7)%zMLsB&HWgUabVsl7}CcdI$Fj;I4Nzuetbqpqp%^@k8_?nKvWU)CU zMH5%+7)%zMLsB$xjgG-&u{k6~6W8h(Oct9%QZ#X$j=^NHIV43B*XtNe7Mnv-G;xED z!DR7oef`DVn%h$6&J99Fn4mTXYO2i_IY^nz&WR zV6xa8lA?**bPOho%^@k8xLwC!ve+DwqKP|n3?_@sAt{=;Q^#Pk*c_6giMw zDVn%j$6&J99Fl)`;roc$#64ODlf~wc6iwW#V=!544oT6(eL4n{#paL{P28_zFj;I4 zNzuduItG))=8zOkJg8$ZS!@nT(ZoYK29w3+kQ7ZktYa`)Yz|4$#3MQelf~wc6iqy; zV=!544oT6(V>$+t#paL{O+2n+Fj;I4Nzud;ItG))=8zOkJgH+aS!@nT(Zttv3?_@s zAt{>phK|8xu{k6~6HnDVq3>j=^NHIV43B-_DVq3!j=^NHIV43BKh!apEH;OvXyQjY29w3+kQ7b)SjS+p*c_6g ziJ#~gOct9%QZ(^X9fQeYb4ZFNex_qES!@nT(ZtVn3?_@sAt{>pg^s~wu{k6~6Tj3k zm@GDjq-f$-ItG))=8zOk{94Cgve+DwqKV(=7)%zMLsB&HTOEVRVsl7}CVr=5Fj;I4 zNzsJg(!YqoWU=uoRqo5X@JyT+evALYqwsWGc$+LXhoorYxjF`u#paL{O*~J>V6xa8 zlA?*{>ljQHn?q7G@d6!#$zpRziY8vDV=!544oT6(i*yVoi_IY^ns~8}!DO*HBt;W1 z(J`1THix8W;-xwUlf~wc6ivKL$6&J99Fn4mm+Kfz7Mnv-H1P@@gUMoZNQx$2sber% zYz|4$#H(}+CX3A>DVlh-j=^NHIV43BuhB7>EH;OvXyUax29w3+kQ7b4PRC%f*c_6g ziP!5GOct9%QZ(@f9fQeYb4ZFN-l$_RS!@nT(Zri{3?_@sAt{=8vyQ=Ju{k6~6K~Nm zm@GDjq-f%;ItG))=8zOkyiLbove+DwqKUWb7)%zMLsB&H4jqHZVsl7}Cf=!IFj;I4 zNzuf+bPOho%^@k8c(;zhWU)CUMHBDQF_EOdll` zfk+}#(@+f8N6B;kxvr9dNFr0yP>j$^Nkt%%$ka3xBlS^I5r`x*H4R0JK1wPAkwm7Z zp%|r)l8Qhik*R4YM(d-bA`nSrY8r|$`Y5RgL=u^rhGMKfN-6@8M5d;p7^jbtia;ch zsc9(2>!YM15J_Ze8j1<}D5(fU5}BHYVxm4uDgu#2rlz52)kjH1Ad<+`G!&EcQBo0z zBr-J(#bkYyR0JZ4Oie>EMIR*lE~CF6w~xkQW1zGGBpiFn?6b^ z0+B?frlDxpM@dB>lE~CF6w~!lQW1zGGBpjw41JVT1R{w{O+(S4kCKW&B$26UC}!%T zq#_VWWNI3US^6lc2t*Q@nuelNA0-umNFr0yP|VgxNkt%%c-}iA%bJE_j$TSC0+B?f zrlFXtkCKW&B$26UD7y4fQW1zGGBpjwJbjc@1R{w{O+ztXA0-umNFr0yP%O|#Nkt%% z$ka3x3-wV_5r`x*H4VigeUwxLB8f~*L$O#NB^7~4B2&{)EYU|vMIe&M)HD=J^-)q0 zh$J#K4aG8jlvD&FiA+sHv0NV|6@f@1Q`1na&__u{Ad<+`G!!fKQBo0zBr-J(#VUQ2 zR0JZ4Oie?vS|249fk+}#(@?C@M@dB>lE~CF6l?WSQW1zGGBpjwI(?K>1R{w{O+&F> zA0-umNFr0yP;AggNkt%%$ka3x8}(6A5r`x*H4VikeUwxLB8f~*L$O&OB^7~4B2&{) zY|%$aMIe&M)HD=Z^-)q0h$J#K4aGKnlvD&FiA+sHv0Wb}6@f@1Q`1oF&__u{Ad<+` zG!#4aQBo0zBr-J(#V&o6R0JZ4Oie?vTOTDAfk+}#(@^ZuM@dB>lE~CF6nphiQW1zG zGBpjwK7Eu_1R{w{O+&F?A0-umNFr0yP#n-lNkt%%$ka3x2lY`>5r`x*H4VifeUwxL zB8f~*LvdIiB^7~4B2&{)9MMNfMIe&M)HD=F^-)q0h$J#K4aG5ilvD&FiA+sHaa!YM15J_Ze8j4T!QBv``dm3aUk$J8AKFfyUQ~i`w1R{w{O+)dSK1wPAkwm7Z zq4-=MB^7~4B2&{)e4&q$ia;chsc9&_tUh?t`TkFqR0JZ4Oie@am3>lD5r`x*H4Vkr z`Y5RgL=u^rhTZ7D0 z5J_Ze8j8R4QBo0zBr-J(#oziUsR%?8nVN>;AAOWm1R{w{O+)doK1wPAkwm7Zq4-Z9 zB^7~4B2&{)^wdX5MIe&M)HD>m^ifg~h$J#K4MlH#lvD&FiA>E~p7BN&ee_aN5r`x* zH4Q~yeUwxLB8f~*L(xwkB^7~4B2&{)^w&p8MIe&M)HDEOdll` zfk+}#(@+f8M@dB>lE~CF6eILeQW1zGGBpjwNPU!41R{w{O+(S5kCKW&B$26UC`Rd{ zq#_VWWNI3U(fTN<2t*Q@nucPGK1wPAkwm7Zp%|-=l8Qhik*R4Y#_6M^A`nSrY8s01 z`Y5RgL=u^rhGK#~N-6@8M5d;pn5d7Eia;chsc9%$^-)q0h$J#K4aFpVlvD&FiA+sH zFELmwp-fk+}#(@=Eiqog7bNn~moikbQ-sR%?8 znVN=TmOe@<0+B?frlIK6M@dB>lE~CF6tng5j`w;gD*};3rlz5oqnDD3KqQf=X(;CE z~5r`x*H4Vi)eUwxLB8f~*Lor_;B^7~4B2&{)EYL?uMIe&M z)HDlE~CF6f5;nQW1zGGBpjwDt(kx z1R{w{O+&F-A0-umNFr0yP^{5MNkt%%$ka3xYxPl55r`x*H4Vi&eUwxLB8f~*L$O{T zB^819JO@!GGBpkF8!tBKr=%hfNn~moijDdxsR%?8nVN=TlRio+0+B?frlHuZkCKW& zB$26UD7NUMq#_VWWNI3Ut@2t*Q@nucPhUP>wgkwoT0`>16@u}d!{6@f@1Q`1oF)<;Q2Ad<+`G!%REQBo0z zBr-J(#a?}sR0JZ4Oie?vPah=}fk+}#(@^Z!M@dB>lE~CF6bJNCQW1zGGBpjwL4A}| z1R{w{O+#@=A0-umNFr0yP#o4rNkt%%$ka3xNAyur5r`x*H4Vj4eUwxLB8f~*Lvc(W zB^7~4B2&{)9M?xlMIe&M)HD<)^ifg~h$J#K4aG@)lvD&FiA+sHaY`R06@f@1Q`1nK z)<;Q2Ad<+`G!$p_QBo0zBr-J(#aVrnR0JZ4Oie>^P9G%|fk+}#(@>n(M@dB>lE~CF z6#in)|0t;lL=yhWwtuhJ{TFq*{~Pi2;olH`U~m8bKhgh8WNI3U5A{(}5r`x*H4Vi_ z`Y5RgL=u^rhT>y=lvD&FiA+sH@rgc4Dgu#2rlz6zR39Z3fk+}#(@=b-kCKW&B$26U zC_dLmNkt%%$ka3xU+ANxA`nSrY8r|!^-)q0h$J#K4aHabD5(fU5}BHY;%j}BR0JZ4 zOie@ajXp{$0+B?frlI&&A0-umNFr0yP<*G4l8Qhik*R4YzSl=dMIe&M)HD=7=%b_} z5J_Ze8j2tFQBo0zBr-J(#ZUSusR%?8nVN>;XML1Z1R{w{O+)dEK1wPAkwm8EW8ZU) zEPmBXNkt%%$ka3xzv-i-A`nSrY8r~)^-)q0h$J#K4aFb&D5(fU5}BHY;!k~)R0JZ4 zOwA|VpG6jbg%3Ve|4)`w1U@tNIZ^$E{F0>3)HD=-I}Rlkfk+}#(@^}QkCKW&Kz z%1q5ymK$08tDlmJKqQf=X(;~FM@dB>lE~CF6g|TS-`e*#{7+p{5r`x*H4Q~C`=z8J z5J_Ze8j9ZfD5(fU5}BHYqK`gGDgu#2rlz6jtB;b3KqQf=X(;;Xqog7bNn~moivId2 zsR%?8nVN=TfIdnp0+B?frlA<9kCKW&B$26UCEULPeDfk+}#(@;#%M@dB>lE~CF6chDPQW1zG zGBpiFt3FC90+B?frlFXmkCKW&B$26UC?@Npq#_VWWNI3UDf%d>2t*Q@nucPkK1wPA zkwm7Zp_rzRl8Qhik*R4Y+VoLU5r`x*H4R0(K1wPAkwm7Zp_s0Zl8Qhik*R4YX6U1& zA`nSrY8r|TeUwxLB8f~*LorhyB^7~4B2&{)%+g0mMIe&M)HD>G`Y5RgL=u^rhGMop zN-6@8M5d;pn4^!9ia;chsc9(Y>Z7D05J_Ze8j3D`lvD&FiA+sHF;5>Q6@f@1Q`1n) z*GEZ3Ad<+`G!zT;QBo0zBr-J(#X^0QR0JZ4Oie?vNFOB?fk+}#(@-qdM@dB>lE~CF z6if6`QW1zGGBpjwQhk(E1R{w{O+&FvA0-umNFr0yP%PI+Nkt%%$ka3xEA&xP5r`x* zH4Vi|eUwxLB8f~*L$OL9B^7~4B2&{)tky?KMIe&M)HD=p^ifg~h$J#K4aHi0lvD&F ziA+sHu}&W)6@f@1Q`1na*GEZ3Ad<+`G!z^3QBo0zBr-J(#YTOUR0JZ4Oie?vNgpK@ zfk+}#(@<>IM@dB>lE~CF6kGIBQW1zGGBpjwR(+II1R{w{O+&FwA0-umNFr0yP;A#n zNkt%%$ka3xJM>Xf@r&QTK}HgpnucPhUP>wgkwm7Zq1dI5l8Qhik*R4YcI%_0A`nSr zY8r|?`Y8F)`TfMt{K^kh#siT=rlz6TYg!YONH}~&%{@_pk;&1*TSRYAbY8r|Y z_CZNSAd<+`G!!TGQBo0zBr-J(#VLK1R0JZ4Oie>^S|249fk+}#(@>nzM@dB>lE~CF z6le8OQW1zGGBpjwIenB=1R{w{O+#^BA0-umNFr0yQ26WF|D&WL5J_bGlE~CF6kqA1q#_VWWNI3Uuk}$<5r`x*H4Vi#`Y5RgL=u^rhT>a&l(a7H z(WB?s9z8C2-{0e$>F@B$3%Q8H^Zf14Wj%VF>-4uiXZste3;dndmHv)ui@(pe#NX-F z)5r3WQT|@9dcX>Q2XvOd+iGmu9Dl#p*g?x@M*5qqj8YR%cgNXdR!-m+4uEwRa=i9 zH^@o0yHW1+8TyQ||M@+7oUq+Z#*Rwj(Ih}W(dODxg#!pP` z(c?YiGncwot^SU#@olcpFrV*z;~y}<*oShKdpB@lj~*YXKjsrATX$fU`{5o(Nwfu%}`Hs1+ z%`V6LUi||Cs@j(53kW5;`jocHh6|G}TEc76x#bC7fX%kqBp-}1D5?r*by=k<@} zf7xfg3}C+V9w^tDw}WK6 z94wFctV85bhB2HGjHHE=_Sfe4qtv6>}aB?VLKylLO|) zCJx!pMB}aW^lXo?pTR!!B+Eyvn=I!VKdxTknx2qTj7?>v-cy#RsoQ90nCm@lg6CD; z+cljbca3mNxxLN3lzZ)Omh5mpI^|5+NAGO)9Olx+Ja&3d%$ExotX?P=v6v++Wf`r` zWuEmtSD0%o@fnvJ-`3^4<$QB?rR?Q6YuRZ1Ip==RwK}2yy!tdft=nR5uhP4kvHFf0 zUuS%cdh?bzTe&ZRQHuzT`~LPtuh zu-|pQNPRJva4DCu+%}iXE4Y%YxSDIYmg~5lEhBwb$Q!wdRp#P8=RDdmZnk_2w{jaj zox|<&4(?>Vp81Y*-ZdGozRTF%+{3-x#|m@poO^!1dW@b2+t+M zB*$8QSU$o?^`o*y4s7%6$;T`|&Jp){y=?}L_dQ^Fi+AFaaGVt-cAply=bu@gZkx~L7wmMOzm$W`v9ILUd_#wxJ@)ghdZxOS4W5(lEKgClF^%sn z|G?M2ChgGig9Akae{pimm z%LC+GIoNx1pn4F48NyIzTQ^J&X9OcT?zwM~y?u9$lA{^JSjI7)2~4D?>(VMGF_|e$ zWg1=f-6q?a&I~%3$t*gV%_Q%PF^)AyJ(n)#*>;|s&n$Ic*ZsVCy}AZhTiM2TcCeFO>}C&p*~jtj?>{-;xgC%T zWG`b2D9;Z84j-r{ZEVTt{(!V%Pub?T#b@$!zTiu~;%mO)TfXCae&9!b z;%C;HW538>`HkQCgFpF;zxjuM`H!CTqBni$OF#NEfPoBRFhdy1ForXNk+g8iyS}&Y z*f~o*la>d`<=(4XJr^syFGd^dbdNVrFn82*Ju747=INeUIi3kDwx5ZzmFb?j{jSqN zCRv`$6h?VJPL*TyPLpl4Go2aq@xJSjGuh)>&XS!BR?n7mm}`y?b}pyPrOoy~*VrW2 zuEkiFdZnD}{7-s6Z*{LX*ymQq?ey-MXZ^`Vp26<#4&UGNEiYiQ>QS=m$Aur@~ZCZq+Y>FRxx6_?c^FZse7$J4mUwR7Gid+XmU2ikWZ^%nJ3wy~WZoN=B*T)&;_UF`AQddg=#YkZq~cHI7V8$a$o zjr4u9)wS7Uc`y4IW!v+5&#~X~0a|TyP#)qi8(p^}a*}J-(|H_KPjJ1Db+30VcdC!8 zPjJk&J1Liqb{_IHXE@6_&U3*>-ZfmvI@?|(&&}}8k(V&uK3aT^OVyWgKz+Hqf-AX- ztGR}~&ih(9#W`Llhx(jz{jR=VeFJlx-;Hwi8u!LEzezp8e4J$79Cv+A=$&KT@QL16 z)@^mI$J*uy%e(Kt`*n-)TUqWr7W$4{Vf;4B!yW5(c?YfbvC{aR>bvN2tYP+jxB4FL zWy&7gcV9OSJI*rmXte8epLNHa%l-0!?mq9h2jxRN%tG_y5&0;OvC8rp_wjM{LHGKJ z?lH%nKf(J?J=wWGC7))s@n__-%v^2`dLIt=nOYp9%dxwBhUct1YTM`K8vSe8VP3Sk z54-(VdBOOLyu{1A!mFI{9(YZz(?7y>d0qVm3+=17_wAeNw^(l-zVSz3D?=`q7^OY_r`!If(7* z!Ey*g8OCr%Fp_@eLQD6ud$QMO?C07o@wpE9EkD_uT4Mbu>qj$&u?%-_PP>;woX0BX zJ4N4A##uL>37j-Pdbw8f^g*zyX` z`+Q@Us4r!aV_qgNXOw$-z%{x;-Rc>;QeMSE{a4FtxR$xzN7u>gxq(I2-zab5W^UnD zZsT_D;7;zMuV?Y3>pIzY!rhkdVX^JE&hV~M4>J$$ll}GFFZ)^dfIR1#?Qo6O`Yd}~ zlLw7G#KR0SHq^CwL_Nai+`7U%<5A0fy_1f%n;-W7nB~VAXl^|r$H^zP`0Xl6;w0c$KX_?`!gP`nyMO$itquv)*B+&F42Qzr_jl+j7Dp`(c)2 zzhn7b-s62f;6pxQz0dfu{Df_`{Zt)QMy|K&ecIz~@<-uQgy z+)Le?KJ=v@%U$2?){Ss&7pVvPP8n@3_P1^T1LS>h=>|>D6e#~~0ED!N};*5EB#Q0J7w%zh!*Kxf54mnxRH1lsl_p#&@%Tv3@IOlV< z$qhbRm+ekC$9b+@o8ETgGvxH{YDjnM?KdwjSp~b zI&3>jz1g!c%ID}*&*rS(uv9HB) zyX(?w{Sx(3ma&`;&-e;C$-2o*p|!(jmhFr*$EVAcdM0|_Ryyt~^=j6zmUXPOpY?K% z-VJhr+$h)jY@6g}wy>3LY-a~MnXPvtTEw|EFFdmos~X&n>sIXPf<+GmF(1>KQoI z_f7Y9uJOgP)ACa5E>T~~WptU7m&+?yXWf-@j(dKUTyMF*IW}&l`>MX$*fyW<8o9x| zTVsx%_gR+N|Fy=h>mJv)*FO8&ZijjiGwpAgT*)fda=qSxz9Vjs8!d0*M)hX7ot=z! z{cbXLGq-Rnx3R-D9oyl)=~?Zb4RHNtm>;)WcL(dIy0*^YPW4^f&06wCHeKd67?Cw}G^&RO@X{EgrFgEPi@Irg9GzxbPf_?H33|C2rG zMQ=L2-}=bD^qlG5J9f)7&zb%7GuEFe=EDFvW2I-x_;K@LpyfdfW(Y$WMsLUHL*H%- zecu=x!D!1{-LH}Ak?I!NZ>sg`39jW}In%L6b@wuC8pigSGb0$N9%Fng<2dd-#>-L0 zC&-D6SGUSZOlGJ#G{M*u^;BBS+fMtMrXFFuO|~O=A{v(%j&QFqCsvQ-|F$2q}CPO;Q+mRWaNy<9HljQT9+ zIL`&2dJnVEy7|8UFH~Q|BFh)ccJHVTbMX@OrCi44T)~xG#ntR~Ew7Q+a=`C_>*Vz; zu%F4?puUltSZa9*H>+=9h5A-`8@F=@YmKesPW4^f&2is7BfJCdQSbHq-YZ*u#{1;` ztk(a4JmWe)C?DcsR+)#7$VYjM$9aM$d5WibhG%(>=hlo^L=mpC!@)9re3Y)Ea zRldd=^(r>-y5%?6sD4wv#oN5YyR0|dEulhfFvfDPjWN-S=mwxnT00SAsV1_W1VGL&kr@R|R$`(d3nlX%J9OIe5L|WP7 zc$4I0rZAOhw9($pZ}91I1|7^~n%~f~WGAzk!(6(U$9xvBkVPzJNq2hRE|tqz&I(qt ziq))PEqk5QI=P;G>J4%uM`t+?b8?e;_bpS+P5U_M zeX~UUsCAF=I8X2-yNo|2pJtPH=qTH*xBZe4?w$Lz(mp5HzTI_yM$fbKndV(1C+K}% z?$E!9iF&rk7mV$cFUk|X-(He0^9s9-zbap2mwKAxzpj3RH`#7%8*i!K<{jSUJtmk# zLma!8cl2gGTY2C32Ykp!%=0eaXZ&OJCw$6he9k)C9=7fa^_P6b*L=gbe8*;U`+NBV zKk^etY_pj0?&)CndawFt@)wft3Xcdvhwdn|9W{&)2s{KJj!*fXP0d^$c=2Gzy8f~3tQPnKV#eFK-p)cd9L0`mwUWR?q&~r*~bX? zd%rxuK@M@44U5bnd6Z)ur`_>S$djDnG-o)=InHyz=iXOb$VFVtB@A#rm&(hyoGZAJ ztGJre-r+~~cxS1vmE@*%40mv6FkXNJk2va%X2)>3%tlnyv!>sF)v<~!|iVfuc=3Q z-@Pu+cn`lJ-{dWZTK~3uhj)38_xXSi`G`5Q&1v6}AFDs%Q$FK!CYv9_?Bfgdmwd%> z&-!-nldsj^@Gal*JwNaxKQY)om${!mtAF8Fe&cuk;7|VIZ~oz5{-YdKwzGrLep~L8GyGoLC3mxjz3f-gDUZj+UlAtoa8e({&`~^>plBlc=oxFi9oKUMH?r6J?k2fzw)cg+g?8UVx60eNojbUbySSTsxR?95p9gr5VczqDc}U&m zydRdkeD-tRNsp)>1w+&A;;v^?kfJ!Nd9&o-s|KKssl+VUdnpOMdU zM&EPtd0yZ}=D5Cd9qT3a%bar^dv5oxQSbNf8()>L@j7qN$GSJ=TfEIXoVVY;##cCp zcP+n1n`?fy`@HCF-TTHqV4cr5!19OckLa)dSboB%e8%T|!F0#}Qm&ur-6Owdkp6Gv zw|vL<{J@X=#5nu^S^mPW^wK|Rj(3mxcmCi{wz$vJ&EtO7FY`Vd?swf^#{XuZu@U^E z?q@FkD+lQxYV1FCPkPatJ`6YBS1$5fs-Nsnm+c0~feh*%bBzbfAq-_0!x_OyS{TJ> z#xRzV_B&1|iFdIN&;V%Gu1J)AC%|#qKHAoA>k7^BHIR1@fS|v`{W$F!;xI=z$|SwVl6Z5zS2jr*BG5(qSoG?*@;83x5B{Xn{{E7)<==9?{6{X7|H}X9$s)_WWN-Q~ z*YYyo0e#h7>VC363)BPTK-PF>2FaPm2FoD~Wf;SmXMBVlNeiPG%^1cqj`2)jBCSkf zGErqIy2~CCX4NVmh5CUbC^pP^O(;97P5%NEVa#&ZrwG@Sk4MovWnHLVJ+)e z&jvQKiOpl6G_Z#NGT%Xmt>3+A& zH`dE@cct|UJQG*RtJz@v6!WazcgY%cf8U?i7{8WYzONT}FJGq~Y#-Ol8@Q1@b9`Rk zjW?;++U{m~Y@Fv?-pXy<&UWv^JLH`lGoS8~chh3q^Oo;XpLL$2EDu@cxwpLEyJV&P zxA;ABpXK@1@AfXdU;O~Po!5i%As%LoZ6A@N<)d=7&$`Oz*}mLd_D(-&+qu4j`uUAC z#(p2uvvZXD()}Iax}9-d78@UH`*!ck$E|;YCt2&c8)9Eish{QvmS}V%PEoW8>^=ozMQF`XydwpJN?&4(olMS1i9uhyK^(40+l)u61wL>U-VT8@$O| zwE9i-wtRp5p!vkqh+!--6Ok;@8c-DS4IOcBGYLn~UQ-6!kbXdJyJz%EyjC;|hznvwZR&sEN2BPS;cBjcJI@+Yt)ln+qH5X>)F6YHnEviKL3DCKBIao z+t|)t*LsKCZEhU$S$3*-buY7ry$rG4KDnO*^tU{agX%*JQV-{_`Uv}6$D?wvvDKcH zp>h}_m}u^el*g<;&IwL(ic!YLb6S0dvz+5Ri_O~$zBUJ}AH$wD?_|ptauMT11y?fK_*L?h=lg0o!SXfoT3XfD$?Lg+8@Y*_nPS~7@>Xu+ zcJAO#CRulvyqkNtm;1P%4)4DQi_6TFM2cAcpur9e)MMm0~y3%y7bIph|iIm*v%gHvXA{7;2?)M%n^=qjN_c(BrELulswHDR$4wQ&vBj$zVSSBAs2Bm zmvAYUaXD9TC0B7Z*KjS@aXmM1BR6p~x3JoAZk4xjJ9ls=cX2oOa4+|9KM(LAYi#$B ze3(agl*f3SC+IofvnikAX`bO(p5u95;6+~IWnSS`*6r{-$^o8{b>0cDtKXo-v(n;O zdsF=uef%Cc;`?^CxwhUjJIwOi##hYu%*uD!?>)P~zq5KzJ<)gVBJcQ4@9}xwckdhf zfCJtuAIgvTm{0hWEvwu^-)EnxKWDM$YoYI>N%r}L<^J|F*n8zmbwA@@$*=i_-uC&e z{Em|w%~#Lj8Tq~CA2_XU>oC^kS+_j0&Am6a#pfMv|1;zo-vd8c_cOonE5GqOfAA+K zU8A0Q|5E?WKm5yo40jF(e9oTgUYxc6-m(vU=|_Khx{tkG*8%E*oYQxnk$$rcvOJg} z3}v0MVX~KPPWkM^)gu^53!@m#0>4Yg$gzxLJQJ8mE4^*s>UYH?^<<_nm1*>`u1&Vn zS3O^#XRP-fQ2k#F-w^3yLPg7@@~goYPpwdy{vn^-zLlD z8gp;Db6??mWCkmYZ85JFZ1y~=SFxJm=G_{(*W6oTUaVEGqs93x(z{;0fsGut?_s{D z78>7Vd9&}+e%f=LT-% zCT`{yZsj&^=ML^*d|@9`5Bn?&kp>vi2xx_oAm+SPX`Y{H0-XE7w z@FdgMyN)ZJvuiZZHhaB4PMbf2+?S`Uf0}2Qq3>C_!dw`(!8=a$p{Gu3?lN`2h6U(0X!mJxfs%jEa` zz>oaI&-}u#{KoJ6!Jqua-~7XN`}jId4rX%7`OlJ_%w`UA>0+Dyd2*=h zF<&lVyRlyLy?4}$Sj-ZZvWy+pFPH6(ze28L6|324-7=qLje0HXSkDG#_$(VeXDeN! zt*+TdW1G4e+bp**+jni3`L?xt+4y<$=N!X51KW&kX9t_Do8tTHtn1RxeBNnn7rU9h z#r>3fS*&M=-hJx*>{K6+2btx%9Fm9GYkaR~^@w_(dK*X8$C&269+xLL$$sAfr{wAG zTHhIYmgzp@SXP{CoEqmFXE{B*iz>r zFSdLML*3^~N|nKzDgrRA&W=^mXjezp1xn9S${n@u*5TcqrB<=QDm20S#)6-K>wPr-QC^Y-OKLoE|d_I4nYY) zPz0nw5kwKBB?VDg@8-i^*L}{!GjZn3piE^N(`mEb3^|io%w`Usy-yytm`By~=(XN_ z`9xp8y1;z4KzkvJSj-ZZvW!^AzFg+JW-H`MO5KxHvc@%CE!XhS`K^`fSWlq+2e3iC zkw@xHax+`lN~wJY>F>%ncWQ6vv38aH_IMXQG-je?yL%PnTI{g=(Fgsm!A|uq3LVRC zxrcV^?v;Jc>kt3+Qe z$tg|~tpAMs2%ytGMX6b-J@6;N4WjO%Sf3ZgIvq!>KEz|=U-{t zM0FA`c||f!jMz%UO2~4+ZN~xv;2#3Q13pcT9!7jjeW;k{#u=5zv(iA zEb~=%zWG+2Ind@U??|wItNmxI-;+ZwA+B|v>~nv<^Ff_Y0Z%P^VY_eU$U^NRiYcL# zSj);}IUo5%m3>sm&r}Yy$@hH_ZQU>GYT^cJbJACJjQWx9sc-5UzLTi0R@U)@dKze? ziDp`8iv!mo_#xRy~jAsI&uHQsCiOEdi-)nQ2oW^u!P~o?pd!}cqXEB>O%w-<) zNil{N$b~FoF)tnK5*cUPrE(d|S;0zHv6?lkWgY9;z(zK)nJsK(8{7FAY2J}L>2d9L z$=&Q>FZ)RL+xz7K4swXY9N{R(c;@_%%M+aB6sI}ES*MwRBg7!sT>ANH^ zbA_v1<2pCE$t`Y^YTY~XF88?410E7*zmH@9k9qDndLjb}BA5^o@{M^yM?49g-t zA(uQp@Y*rt%K{21qL>m&DWjaI&z?{Di3&bbNfi;!>5FXij8@BL<1DDrbLV>e_MR*? zr^K6Y-kCcJE&J~8i?7!EMwQ?1Fm{8j|Ek3EtFO}E79rZ-)wR^|bYOonOomdgelDNU zpl+mzX3FiqMTT3}Dw91gKV=*3bdcs*?V(fMMUZ3YmcQtsm*3R+UaKX=T=Uzz`dg&u zU;ht%f8<~O@z!%)udjiA?b2-5)!##J%)foc|Da3e2HrcjEaRiYZx^{PgY^wzDEYbO z2sxYt&*KO=l2MFi3}YEbh2`Vr1Ri?_#gv*S)FH-Jf!_^wJUqjgH$%T(vP zR^Q`+aT94yQm?1cHXGzd{-}d;%unjgY+)-w*54+#vx8Fa#+`B(y9qWQ?~z4*FVXdD zaE^PmJJQWraz8z;*8$n(ng`gvEz0$`T?5Zt|6QdX}>rZxFN(O4zqSErCmLKDreIJ)62yhMB+>4Xy*do`?Z$9)pfl;o% zv35%TX@d2qyVhm)_t*Z;=!rC!6xzoX^;NEModnn7Z=-D-^9}8r+~PKM_I*d*rOQ3JC-3ushkSDWk7NLkNwKdy z=lDdOXTEr3o9FrNiDQUzy~`bMxATd24T_9`Kxao_ z{BxYoWjGN;5=Ath>^so$#HeFwR>#SB5_mzKWBP2pM0KR)fv$6s`X#SiuUE3d@=V7Q z+pVH8M$;j z=R8^GcR$E{3aHVp^t*-XBED!B%MwZ{Bi^;DG-sBpKT>U-7RUQZUBPE6$ux&o$!fp- zWgz*=H>y0tpNx|(%W7?3qc77n|30vecCLHaZ#>m%zj3T}@(1ffXqb3u;1Pu&$|{*d*S|CJr`pX_JQW%D?LY0*DKw#%V%7}cJu;c^5c`D#4;w7lN@ z@zrsU(pMX0K9^${OLCz(U5;l06Pd(hrqF8psj^9y7<<#yLC$fyoWV?HF`H1=AvxI` zt)5Gv>oZTzX8{Xou%AWpd9gWKR%tJhjdH16#&TAWV(hJy&6agK?gn#nkZZR}-)hqA ze~nzrI@Ys+ZtM55QN4*!+dg*8o7G!rR0n!4wyL+WogM6C7r$&Q!nhWwGO^*AL zeAs0ElU;u6io8nAz;mtr$?rUL4|}{@uIUf=``6_SZgPv;+~F>5wz(%CJHPw#0S|fV zd3huQc+3+5`D6Vc8B7RI2_=kYJg3rmhRZ`o-yrYQb;9@*QAr5r+V{_7&$Bwpvz;lkc*{Goc~1_xWWmsC{=j_AK>V-VxpG8FjAN>R9!AnL{q|&LK~J zaNZweU$9sL>=myl*%~kmC08vu8aI&zaQlb&(Lf8 z`=qYmGnG{Fg=)U?%60fAYlw4-9CzNE843R-*o9 zb&{+#_q3>6d8z$Vw$aY3f%VLv9qLZH=;jwa^zxf3=iVpZ`Ud#eG9cajs)ZU1&PF((*|8Nw=kF?L^{Xr6!VLE7=6B@hRYF*WE7)Gwfz{G z7-1Z!$EwHi#C$kjPGBNQmQ9lX%uADHkFj6xn{|qMD$^({be_&9#k$kAXE2kO+OyRh06i`SJ z#gtG=8RdNB6BT@>k}AGX%~!rr!%x@eyDasaWt0#6&7@t&59(>4ktUicw_b~E<)iwi zY@?kHI_V%^_ptSjO?kGcaC; z8`BfyC)Z)3oWx|NFqLWiwU6mC*?pcNV~q0d@m2kgB;>8Ir@&sckWZI=kusK z)Vt@HJkAT>J}2Z!(yV(*_PB4SWw!Pid6sjW=a>6(L0;q%muYeCS7fO;3n0sMV)(aOPy-jZTUuKaYy~a_^vVT?yBGEyC*BX-wM_D)ek6B zKa?f%vvc}Dh5C`c03P#%K!OM+gevPim7ipvYZ|H!;~CEhCxS?#h$e<|*Du>~7DqfE?6a6s613Z$f4REbbN52~kL?rXXMIWXB@M>ZE166R1(v1CG+La~ zYnje#=bvlY?^4%UyVvz@x9uBsCRx1Y9of7mhcC9tm1(Z|M|Gb11Njv2*!?S%jjlzK zI?p=!M8p~MvdFSZnP8k2t9$IHLo=B~E7kQh&`1-_v`}rGue7Rv(#CJk&U??wZ}+ENyMuOhv2pg(x}Dms zvY9sbrOrvZhmDjL-=Oh8fuA+b&m3lvEC$Gh_JusW#(P$_G%B4!x_OyMlqT(jHTN; z<79;6`lTMPp1?#VF_|e$Wg62-G;U_ddh5@W@t)N-=RHe3n>oy79`jkiLb|NKNG@gx zJ=#m*PFd-G z#Tq-i)Vuj=9PSxd?l|_!eeCA|2RX!Hj&PJ?G<%+o%ip#+Ay0CO)12WfRgUGHtTm?3 z%O2--L0;q%m+5l7uE?vDmznG2b;9ibhWzQ>c~jovHg~v7hI6#2NXn{TdBs5)$*pLApQxeOm|#mQrnf8o76%2Qf0hxnkHY9P6lttB#XDaBb)c+@Yk{YBUhcr2OipA zzAT`SB8n-Yl(K;|w#(&5!W`=-S;1$bY+os>_(C-y`o79<)bP~%`nyb$wX%*->->=Q zG|)&B&9uH$_fm8sU~r zmv0ix0rHvlO!?V2UyM4IcxLIF%^b3{=gN7^X8{XYM5gn4WBFqB5+c+~J_YH6{}gpTGp|i4ZO7e6Yrmm>P;kTZdK(zLhB9kiRvcFJAEy)`e$J?!O` z_4djA9N-{_c&-1iJi<|qahwyJ}o z>eUT2(nK>K^tZ@X(!7U%$~M~Rpp!1T`9-1idt@)a>EjQ7`Nv1g-+K1@)kW$-H$CeN zW(Y%R^LO?zIh+yXT5qHr#c0MbmT`<{0u!0UWP0p>ik!+crZaidGTXcOu=)r`ImU5LaFSD;<_u>!$9XPrkxN|W3Rk(t zb#8EzTioUjce%%X9`KMy1n`(A1QJ9rAv`6NFrM+8a3Y8#ifCepC60I!ctIjbyyO+h zq>xG)uSq9^H)N8IdJ zAJo%8BTY2ZLMuOMqn!>q>7tu>&sd)KaGZHG)w?sG*>k18XJDCcre67*KK}5RfAllx zmS>5<{4oa%kwY2Aa30&&2>C=-_;wqq9>r){y&K2Kv5aFpf!3QKClaK7>Ubup6CC4Y zIfeQJ&zYRYbY?Jv5$;hXB8`S87K@yh)C-M8-# z$GpuxxF_K4u=iKhRK5IXby~gY_ z%d=ghN`24O;Y3j48=^|z7pm#g{wgCa`{o(@rjAzE$j6DsZGmOJ7o+sW@Lhi`bv$+N z-ujlUx7`ozSj+3>^Y`{&W4x&wNi{Dt$!1z;rQ)MGNw)FObM?$v?X;hE?G8GrwoZ+4 z(WOpIbZqw7t^P$1z5FKB`?62|;V;$J%X;ToR=-Fz2IQdI<|$&F&sWPEeV2y6@VowI zD);WLFs=q$K7>^Fbf_H0aOwxng)YZALVF~m7|j@-S%0jI_FRvXjn*A6o8$yJkxv8j zn4HWM{Gi&X?$_+*~WaSlT%qCYUn zxf)ZewA-{l`Tvd8>NWh)?xx7~UaP&1^=u&DdFC1e8`XL4bCG8)&F{v@a`$7C{>^M* zD=%EDU#`bC^>%jf)cuNaEIZYo(#@Z8H+yLHyL;t6{;Gcx>^FO47yI=e;2??m56Qzk za-K)zFY8pQgYEyX>v>dPwevhCj}NR@W)78K{ay9jx+m4A=u`hA#QpD-r}ZT}&oeT8 zV7_rL+VyvER$s47bZ+T>qqEq!)IO*GJk`eG1$mL6@8(~5nLzawd6jE)x?TbLuB$`j z4SADW^teX1+(^4;&+BQNq**!dsyfBtyEW$VvK!}1^TPySEB9nn@o@| zXfP&gw7*kJ9Y4s^UoVTDORV)G2ClozH}5p)PfK!)=JiH(r|}fz*t1-_Fu(uE`DRLeHLTib7OpB-s2s*{Mo^Yvu9n5te``OZ)T0?gmUbFr)fw`cV;H9% z&qvpHg3Q!EQBGnqQ~2#1YkZeYRmUWmyXACRU7r~;*|M2(7PD!#&K#NRI?a_WjwRN- zFi$<71uSF{i&?@_YK{M8ayctlNw9IXO1^hoC9ctHxmx>)d-O)VM!l9g$G=X#)7R^` z)~h#=ti4fgqSiW_fa?_YVVd6#>5`E zmr~32$!yQretCd{s?k~;VRcC)>p!Hb-!_UL)IBbH{~r-jOE+%4tFWE?mc;*2R!5v0X*gjfdmmuzV$=o zQ}WcIGK^T31YS_<9G)7tiRvU?65zRfB?H~lBKuEPr|{NwPL*lA zCY=m^SSQ9kd!x=Ii?_TZoA*>$Cr9Rz$4}4D2boWUWd*X3AI5f(Ear>;5?L)vWf@Oh z$8!0RPgGFpTkrEgdtg6Qs%vGH{A~WHQGZca^CQC?rTta?ReqB-eCKbpc}ZWbx{e>z z^VM_NARB2S$GC5nEwoZ+o1ZewbJivcE&t#d>-8<#uKnHe4%x{s-yB`Cd!Q!Q`|6|R zpXu{ntdc$Y->Wm+hkV&Pu)cSBlzskI_wk3n{G*>icg;l%W(awXd8i!5a7OUczDLSY zjAjgD8OL}g5bk|5QBGnqU$v*msdU?Znw-uIW-^Nq$2eQgVJ^*%yV6|KYW;cI^I5<` z7O|KmEM*zXd7fd8ktf zdvnS~d5OzJn(wa2MCWojXX)sG0^kL@4J zPWeOz5=5VNu>2=O*$>R5iOdueuFaoX`D@Pb5= zc*!f0Ngn!z@{fK7-Sb>Cm>~>h7{eJskZqnaQay^%jA1O}7|#SI zGKtAdVJg#@&J1QUi`mR!F7uer0v57}#Vlbd%UI3|R`StYu}ZFH4QpA)dN#0;P{;a= zP3p~TVJq9%&JMyX-zj&on?3AhANx7LK@M@4BOK)z$2q}C!tLjjJk1%NYoC?pIL`$x za*4}a;VRd-&JAvIi`(4cF88Q5kKdOMh_K&>@(}?%<_UoW5ljeA2_=kYJSWn&;WA>N zCW>fch$W7A5_mx(ZQe6qo274=B<)OdeWAXW>Q^L_LW8-Z)iaf<&Pev`$=9Tl=^d3J zOD!+*t(9zlZwC6w;w@>7oG_G|4p*QUm?HflGKt}nrNM7nvYKgV;euZ32AQfU1)`PO>vvV%^# z=;jwa^zxfN{_vN7)cFo98rZkG!*v*R-*e4ia$Lh9awx+XPI8LpTSmvbX1<@Z{O&jR zc%;4@$M^4*V{wf~X@~eG8ZE~#mT`<{0uyQQjWANg*o!b>z>%DPRUgJ79xXCSUbBDX!<30~~$Orp*B;(!N0Qs0F z1QJA|XFFKdSg*v`&6gqCPYETAXLK4%&t*6f6k0EjNOcs^#89j+R+h*(8BdDePLMB1 zB#D>2BG{NpmMNr?#%n$g{M(Vt;0>9Cx%OG|E$_&t!gYTybI7IC?{@oM%2R(Jp8^VL z_TBc$@*;IHC6rP|IUfgD{z+EwnPl(yN?FAhs`<({%B))>%jI`jOC8^}f5>_oXrzf| zT4?1bFCBZEY^Q@xy6EN?J@oRMEb~I2{KH@V(a&eURqeVAdf+){Fhdy1ForXNk&L3k z`lIC-#xjnd=H~IT(y|G1B9oZR6sD3{;Te|GnZZnEF`GHeWghdXvY!QVA&Xed5|*-z z<*Z;Ot5{7~q~}zwWgY9;z(zK)nJsK(8{65zPIj@IJ?v#4`#HctzBryk@-Rm@$}x^} zf|H!$G}YEUBLmAkpEA{4c21t>0xz392gbxj^(8LTm27F0ul%hd_|1pvM+ESgM14%`@=b;WKf==tC>5o+Z%(JeHCWctrEbk&t9nar)&RM=7 zAj|Q{BwkXUV{F>TD|Ip{bldh9VIMpjsg6-!8a?`6%XBh$LnbM4#=d1)>fiFM?33?g zHhHf6G$k9?wn&s0*y7pnQnH=e)s?0)r}s}tfq!|Lzq zTIy)g{vl(^JlE=<

@K^)=8)6V0^HO1pL1Q(RM7XsrCy*EY~ke5Cs&JL#f(ptfEI zztn#dU9*8@+P(5Oef%N*h2^p!+58~;8T8b=z+d-vu&lIw<|}iAdMLvf&Im@*ZNEK? zQjaFpeMoc9g0ubpz;Bk=m-FjY|K&GhtT&cEbz`bIMcuD{_|5&(9^;Ws~JU zIYmxo8q=AgMA736Ls$;o8DHXdZV@ikR;=NcDsI@Ldn4LOsq>REC&bC^q-F+Wev zX8{Xow7*4iF-!PvyQOj&HR|PZ1uI#_YSvKach|~T_kW#S&o}GGyN9L5!3OQG#$$uN zjp|Kore1rC+)9@^z}VZS-p&qo(x`uztdqOt9`>@2{WR-uBJrJZpnZ_iUS8lLmuRuWy3GsOK_|`7B@|Y3A!iaxs1O`1%R1K6V)+KSkxgtSz;SJnTiM2TcCeFO>}C&p z*~fkkaF9bB<_JeQMxgy2mrvvg86)lh|=K+JB84C>NsbxdtGx?mM>LAx|m>kXs z!u5}oqZmzu_82*qF!eYYBge}LOk@(1nZi`2F`XIAB-Hw|WTc!e=P;Lf%x3`$SwyUL zqKIa(_7aw|jODCgC97D?8rHIo^=x1xn~1lM&2kG{*~WHuu#;WvW)FMW$9@iQkV72i z2uC@_aZYfOIQu^(PjiN|oZ~zfxX2|wxL=oLSett)pUJB-BGX*txlVcO9&3Neb&ur@ zZgPv;+~F>{zULwv-Cy;69x&*+>!t5MnPPwMV%%%>5QZ|0;f!D;(bgR$M>B@8{4lqT zljE7dL?$trDNN;erTZ#lY(HJb${8|F&Xlv5%^b25oZA=kld(QmyDi7Pmhakz0srHD2U4BGo^9t8G_DsN?gDAN5Xl zv6~O(ojr0d``AyH=PIwl^=>uq=NnV{4swXY9N{R(I8L$mWWD=$LVc1`gn7@LmS;H2 zInHx|i^Q}VU$V)uUzS(6${*((+iFayuXBT&+~Tuqa9iHtE^)2Klf2J!=lMVm3OAk@ z%(r%9Ne*Qg_1VUgd{^k(-F+FMu8;kiqt#=mvTUr3bge4Y?dGa+ z+STfu2=~!%kJp~SL?$trFMj8Xb*8ApjqQ5Zq)xk*0N3lQ{6@NEQ>`tBi_Az;!6P)CqzEkqI{7XNlwI3QkXXIJVk(TFusPDWwKwgl)T!%l_uQawU zYG0z=@wGdLNauQ4JJ7mUj${<08N*n@EgL5z<#;)PiA-WL5&Ead=W?o?#&l-z zsKA(%vzW~s<}#1@MA>G6T*xA#wHM1JEM*zXS;0zH@zeWewOm7%xp1v4<0I=>&jwnG zjVGC5olUaXGnj461+^Jh+FPjd9B-A|2yQdBS|U zJKUwy-xK%beJVWX59FXof3MqLy}9W>b-4b)vd-KyL=Gjb)pKp#SYs`(z`SKH$@k0; zv#i&@BMg^Wu2q_AnPWdAv`6yDm>wlZGlutmf2AZhUDoelt9l#T*+HG__r<<%dZJj=DsBdzM+uY$U_qfkL>jXNU2kJrI zFaI%^A%y$BdFYag1jI6Pd(hrjTyG zQ{^V3$xMH%ZI<1}^gGYe7IlZ{3hLxkZ?3Ti0%UsPAx>d)z0%Ggwq;e5ju~-$Cv{$4}!#mK!&N zWxD&{sV~R<3^o4@(KnP~3@6+^M#z!G88@S3yc{jZFqU!r&ar%umEg5^!_U4(Dv z@s>?sB9oZR6kb?os+`6z_a@qQ)73MW$xF+7%`3Ci`31&~4Dnng>Q7>h_BZ`=Wr}tx z^VAt~zFfdU-fAzBnKF-h_iM5CJM|K|lq_{J%hbzh@VhJIN>-8S_*Tm`G&rY1@3l1R zzb2hGthMa7f8SUqAG$~D6*OG4Q|rrdfk$@xx-!Vai0eaay|ZIFr|KHi2Ui<8!CqpYpgso_8Oey zaP1L1H>Zu1#nvAsM>B?|T=(6!W7Q>=6;Z}G?eX+kHbIu_n&m8@8na6x8EL$KKvWUernO~R4rMzJo%UMCU^IIub zv6?To|75(>tJkoWb*v}X?{APB*+ivvGdv%g)mzv~mA-9qJ3H9PE_Snrz3gK@2RO(f z4)eru9+5{mMzwt%mnS&MDNgfM{~1{$&&qR@887GM1+sk0U6hx&%oVP3jRf<`b$NrE ze6x>R@-}z4%RTP%fI;rte+*^_Lm9?*+YOf^7|AF`GlsE@V>}b6v+hJWiOEc1Dz*Bj z$?42sCbO8$9Og2Q`7B@|i&)GOe%OAgT*h)%u##kRV`H=L8TWCO_78KzYT2Z()ts?L zy_R*Xr&<37*H~Fpamb}d!?h@b|_ny4Z0|t37{l{R2FqB~o zr_c5yfw#?H#>IZl+xS7P*yeY-a~M`DPsKlDpYMkL`-g!F$!^eyhbhbD#Qcsj(q@ zEk7WC$%FErdz)$fL+ZmE;V8#A&IwA~+mrGXnZ7Sh%WB)5k!N}M!T6AW?eh=k)ff1! zz9=tonJeV@t*f%w*o|<_uBoqcgPYu<-*&g<9jeTucjZ0al^Q4V0fXWlyY>E)E%rHB z4x!|iF(ZdDoDqy<6r&l#SjI7)2~1=XlX>eMJVj1r8jsqH8TnAokjcjAC(q7b=RZ@s z);*pjXETSn%ws;U&ASWaLKd-@B`jqb%UQun0_=a4T+JHRvW_O#XuaIPMmDjTEo@~Q z+u6ZRcCnj1>}4POIlw^RjW2-R~*X~<^5@YnV{xh8A z93kfN1j~|)`}5kx)_+#w{;OZ;zbF&sC3%@ET;+rHuF31%;IVP_!Tr6dzD1I43XHo5 z`+wy)ZtJ_lT|Vn8aG&m}zc{8>*1fNOz##YIKl=2))IV6AB8SMK3?o@PmEr0UjARs} zNz*?@j%6IwRzv{`;x zUg0V~w6DqQ+~6j+xXm5z(qWx@@;(n3(>~o$O*ad-!MBUb&C`9N-{_ILr|qb{QM;7{@umNlp=9**oLtwE7H>w9m?OoaX`; zxx{6zaFuIZ=LR=Cga_J#{N8^IW(Y$W#&AY3l2JT2{zl6& zjAb0-nZQIQF_|e$Wg63&!Axc`n>oy79`jkiLKd-@B`jqb%UQunR|__a*~4D;v7ZA}nCA}4LmcJ^M>)oE^6WFf zym~@?l6Rh)Q?fM1zZH4EomQXWEcw>`FmMcf8hD@RJ5QnZ1({atIL)UQ)t9);6{;P> zRe6o;B>24>@+L{@BHM>~pWf2G%^mJ?k8d&Vw|qdc^-2h}?jZN^KT5R+%OMPag67i=RGUOyk@-#+MkTGiEgDX6ERr z>S;`81~Zw(Y%1+zj-1Op=Cgo>#CX0J$;B*TDa%;S3Rco!`&Du^vF6D&axLpv&jvQK ziOpmBQMB{ zT;eia-nUoeRj%>DxVh$~2}kgPF`?HglNEJm#~2g)Cw*OIXS>ma~GDtYS55Sj#%rvw@9lVl!LV z$~Lys?VD?d+{rF>vxmLxV?T}V{Q-H9LmcJ^M>)oEPH>V_oaPK?ImdY}aFI(~<_cH2 z#&vFRlUv;84tKf7eI78#v-Tf@8NyJ8F`N;MWE7(r!&sUe`#3qC2~1=XlbJ%Z|!^2 z*vmflbAW>!;xI=z$}x^}f|H!$G-o)=InHx|i(KL|SGdYGu5*K%+~PKOxXV56^MFC- zn*SKg5QZ|0;f!D;qZrK?#xjoaOkg6Dn9LNWGL7lXU?#Je%^c=3kNGTMA&Xed5|*-z z<*Z;Ot60q%*0PTEY+xgs*vuBTvW@NRU?;oS%^vo$kNq5=rpG;yhd9g;juPqJa!elQ z1SdH~i!pXup5ZL#IL`$xa*4}a;VRd-&JAvIi`(4cF88?40|uG9{$nsh7|Jk)GlG$f zVl-nI%Q(g}fr(6FGEEMhTBXfn4hmCIPp3Rbd;)vRGH z>sZeQHnNG$Y+)pB_nm*UIjFzVxqR|1UKa1)7ko=(+9pGN z$g;x(dT$2U?u*}gET0fayzhtx+qT(Xf@R^hEg{IVmI&YXGK9~T|19)3f@6QG-Dz2s zWBY2Z3)Rk4AMrb3>N?*Xy^ig1f%Ub2IIdpXWm`Ae-;B@oh1069Hs5%(-4E}=eBTc_ z&N;%eVA*3?r23fUz3M1+G_PHQ7#T~y;|g=G)#=VfJI&wD?a{`yZ4$I!P~rSieUl}s za~w;ec9QxfuW0mJwYGn4n`G@2LiC-`PF1H7M}C}jwg%nZDJLg&=ODUtAkGykT zKgr}y&#vDn^Sftcq!;I&udeqRxt4XTX9GXj$R;woJbT7)mfWme;aS@vx02{S zZIj!1YxxejlU?j)4}00iJIk}#uYNBN$b%f>Fh}U~_fWrMI;uWKd#!6#+L)1NImdZo+Kn06>bbutzuNYayv!A@a*cZD^3AgA>Ko*^UN_|}ZgYpb z+@sjD@;wIY-`9S?AY-ORyO#gdgQ-&wkwY2AaDM0;A)}176k}(kx?bNXIhrwyWgO#~ zz%yg8#qm#6Phv8m+8>PDDe9NrO94&pjq&!j(fH9fjp@vw(>3Vz+y{6bXKK$P*PJ_B z{;+J0te1aW?*^IS*xnR-ZXMrT%jVIjf4*G6LYlM}$!57&E}=!;%1_#9qr{xO)UstP zX9X)+MTh09WuIePBfGSpJFl!N)FQ-5h$yyp*3= z-+N^r{R}Y35W5*>gi*#AXM#y?dGC|^%|rDxGt4r_Jb&B1AQxF;nH5%9W1S5)*PMZE_ne0(joYQ~hBTMR>q&iwtOFm( zEaM(GN3vxOx#W@03(uR+#_Vx_F3>Kdh+;}8rHpgt>uKZ4)u-e|?GNQ6*6FkIANyZn zTP1(HPO4-z2hY3yozEKeapT_S15R*`*E|bdkhQj7@%`U*zCO|ZoSz)m^Rmvi!|sFi z^1ScXAP@SyM)}3GuP#1{r&Q7`!gU18RC-u-Ex=_Mj2zA2_~6hni*!9;~TG= zmkT`Q`!32;?!VvaUs5l#!q?iX@&(u9np|gtO}2Q*es9YF`@Vxff(Ryr-<{u3`JML( zlh2v^haBtgwZpX|h~!!O@HA2CE4Cf6-v4fYqP1g)<*NQ4*{P0W7x5%;O@E?HBAFE4 zbh$pJlqtAd~Cbw_KB1>VHo;@7mew9DY#e$~^KZ;3fNa!F}ml^)I&n%BQ~H zyY}-p^P*7yO?^eOm=a1U;}8Aia-Z{AAuFk(ny3V+UcN^Ti&NjcJt6r=9>J?oa&W-+tw%h8DNkhb~DTfZ@Z>PW|`wd$KXMq^_l%VXbqXyx4`Gl^`cy2ng6_YMgAjK{DyC8?81A(b>hFa%W{QP z)>vnQO}2Q|m~9zgz1l$_L42wIsI~2ibvao3N$2ECYr!Ains3^ngb~gQpF2j*bA&pQ z{n}4CjxWk6?PxxA9Ao55`eNly;&|h{xhN0n|J|I3SD*7)hqVuopnXI>WGzipCy`7F zNA)chs-)nKe0IyMRJob(~()U!*SPxVl7^@{zhsmh-fIeM7rK z{ib}E_c&v2oswsr+e+IGp79yl7kSkD|4vrv|K2hATwSfM;dS@x3);2nzkP=To_oI4 zK24pzx8yl)Slhocwq9QYjWlt@ac`C_wDPhwt4%)SytK;>KK1%e*~M9Pw>&}*UuyTt zKKdD8kTIwBFW6$#=XBaYWH(#iSa*lq=3w;gKFHS-DMGSrzIP(ROpvb3|wA(uSzDd0KV zKXi-=)kXZ~I~B_kN-5)6bFo}jP{~jB_ZhFNQdd($EeG}0$$EY@=2`6q^�PpOQ_o znHE}Uqn!?3vi${~X0Q8er@k(_>EZF)+wI?z*22B&C+XF{PhNK{UzCqKj)!HR{v+}+ z^Qd1vz{lE08B`Ckn^W4u@@3cOh#cjt`7kE`mg91QMx6 z7g*$dbLmZeOSfzJi1t~zti8f2uV}BybvF3Ox%f!mrh1EQ0?d^ioY8;DcYnvV8>k&b zFd>BUq3tILQ->45TiTH_ifCTej*%ziDeG6P`aShd8OJW-c|+g3j@?oF^Nh9e1MLL; z@5)4(L^3I)lE&+{rOOO5c}M$mYkQVDn;deY zzB9H$R#HVZHPmvUH;?V@r`;zeNk@8FXWcoCcw43gFu1^=7KdSM1~SZIG=gV=X^{9#Oje9xRolu2B2&rFsnq>{#O#-+;)GRY#F9CFDc zp8^UgqL{Beo0P~>PC15U@`m>+mlagrZlAR#>-&`|?P`8f*T`RFt-K=ZWIaE7rf86j zG||j?$LwcgTGXxlpl*}xTvh+(J9Vh9sXJvCC)}I6We>gd(a!(}tXG5b$Wd#Q*9@t5 z^QU@P-jqKwq8??8aVGfLv*4thVw!)9n~}53G0y^vEV0ZAtE}Qq++v#m z&+t14B#2-_2qlbg{_=SdGLk5w`NjE-k^i`^V&zWa_}a1GCF6O~dXXR#Ng|p5yjP0+ zz#5n;(?}~8$fkmD+Zb^P%eOQ(&tg^-nw(aE^*0nddU=D7| zEw%|Thj;LxV{^c`K=t!7NCp!^C}D&X!9Lp~WfalG5X(;D*hM@EB=YDf^T2D8)XAif zN*d{8@T~2bGK*}U)6S7EyDoEO9{KFof6acsBnz|)DWaGXN;za(nLH@VWd)T~QB4iC z9I?Gl*3&>EO*GTOx6Xg7Y@?kHIyrCNUN!f-)ZHBRK0UY7HQFot=x2aIhB#`>ZaK^d zql_`m1Q*5=%&^zJeOAsf&jO1qvCImqtg+4pn{2U7fcM_WoCdp({Nac0!ktWm0Ad@Vz$sw0K@+qK@B8n-Y zlvlh*nS4!_%L*!~qM90NsiU3-8fl`L77km3T4fvUyy3k%WG7v8(?c(P^fSO9L+oal z5k?u~ncsY8&zAeFch5Q3$K<&F37)lWQcf|=472=T{?5sH7Wl$5&Z1mmnU{Zb9_1=) zth2!;TWs^)3qH^L2l%_h^Kyp_^Q zhmFfpXOlxNc^uXMgE^Y7F5rmv0bb>03iZ7ti)1m!)Nk<)CEBGNSHHn)lxde!!Q0xE zvWjYIsO2BeXmzrl23|L=QQmUzxagkPq<&Z5JAMm1=NYM4yM;IPy~jtKqg7uUpO_cz zvV%^}+V;8Z;zys=EqnM_{~3DKee^THZ=MkcEa*PdiU)#S9@eHef0B-v43)npBd0M$PhnjKl-~lr+!!t z%Ml(@kIFG_7&9(E^(-_YCz)cJ8UC?-R?acc9Hzz? zgFu1^CWKJJ2q%I_qKGDjH-C11&MGKEz3TDQ_?T(KKGh@SwJC06jQ>7zC)=jtn7v z*87}m{S91u-s|->s$X+Idg}$}UHzML)hze8m$%5bjA@l^w9~;EYj3CQqMIIidE406 zZhueNr~QGd}b4Q)X2kIo5ObV%dc-_2_>11%z zerL+Box_J6&n$H|Z#sT2xgK)Vx#W>g0dLt>D2q68-Tjhp{O#r=S*)*wGwM=VMmZH! zQbjfAuG@EN)ThjkubrD(bshD5W8M4rC38vL$m#3mk31`zWecsGHl|Is(?KU)bkoCU z*UcT-M?V7$a?acxlK(yDS>w8Sq8?_1QN}ob-SZBgGOj(rBvVZD$#wHY&N9bOj@P_g zV38$`n>SxvH(%5%tg^<--G&Vv;@~ycQ zC8LQUmYu}0i+B=9B#C5FNF|MQGRP#0Y;wpYk9-Pv+qwVU`cSAYqL>m&DdQ{qR4yy1 zq>5^4sHKj28fc`6W?E>ajdnWdq>Hb;XSeL3mp|QW`{Z8w`N#GFImkZO)R5fGFe8jI z#yAs9GQ~7A%reJ33oNq4GApdI#yT5pvc)z5r=2GP2_l#fLJ1?B2qK9hniyi)NgTU~ zCxJwgNG63;(nu$ROtQ%4AAg7Y%>2($ex_uks_g#{DF( z@iV`0%(=|dpHBh*{NdcnB8vG>yF~s^mdbx+nJlM*N-lYiD*50|>-v7@TU|pfbv&fM zUN+Fk!`e-ILUpjx)g|Q%p0% zEOX4Wz#>a5v%)HCth2!;TWk|>#`z|YAc6@YlrX}HAd)Dei6NGq#IcKb5=bP8WKu{a zjdU`|B#Ufvc*L>Gm3ib-Kp{mGQ$i_+Jy(>;aw@2#ifU@8rH*b~@;! zi*9=8rH_6F7-Wdu3^T$gV~jJwBvVW?!z^>mv%n%tEVIJCv(ANFW1S5)*B1t5ZLMmyblR+j~WRpWKdE`?- zAw?8ZLMdgGQ$ZzFR8vDOb=1>9BTY2ZLMv^w(?KU)bkjpGee^THAVchCm=Q)9W1I;l znPQq5W|?E21r}LinH5%9W1S5)*YLoRvb^O}2Wfh?qmVoE5bjB+Zdq>5^4sHKj28fc`6W?E>ajdnWd zq>FBP=w;7M=Rx)}z#v2HW|$F18DpFYCYfTI8D^Pdo&^?JVwn|IS!10IHrZmE0MCFs z2qcJLLI@>{a3Y8#ifCepWhZg$BAx^iNg|mPQb{A73^K_gn;f2X&&ic}&~0{9#{Y8yRUf7i|$!J zcxE^tj~TnFZ=ZYTWq)sZ!nnP>Yul6Zn%@n-c<;|V2d^1-((k2f2i@B}E59lKbetb? zzMnGoX%_A>Yp}*|&n@9U7o3}s5cl_Kl z+b`DRm-YRwenpcGs(#VFe#C3)AN>vUXP^1{?S8)tUO(XXoce=N4(D-pK;6Yh;!Oc+V@Z7pT6^hUUOc3f&bJ8 z?bD~~&v?c2*(c7~=jt!m?{#0wi@fW&2Ap>t6G#xjgb+#?;au}wB4i{{MDvnk_16v8 zwEC8el{@*y?~pjTi+B=9B#C5FcKrCWl<|_}#gF)js5_3n-+B zVoE6GwZo2&dv%$*oC+$bqM8~m_!~m4tfQU=ZrGQ-&-;6UbJ3{XL^Cb4(ndRf7}p^? z`BU8`yXoPS&%UXzSG~{i@00xuFvt+Q8RnL8BXX26{?Z7~w<^Nfgn<5X(;D*hM@EB$7ljDWsA{IvHe=MK(F) zl1DxT6jDSnC6rP|ITch=MKv|lQb#=vG}1&fEws``I~{b=MK?Y4(nmi73^K%Sh8ba$ zF~*r-k}0N{VU{`OSzwVRmRVtyHP+c+lP$IhaDD9{kRXByA(Sw}i6D|FqKP4v{pRD< zv(~yp&V}~#FIjiY&tJ{&6Rw5NtpV@b{)cPg`0X{*di9)Z{($TJYp*?Q{J;9YmJizY zw|l^+SFH!!GVXW%pR51bZ+$XfPZ@Lmu=PRT4WIF)Jm)nRz5hk^m)5&O?hhAjJ8oV2 zO5fL9<`UoVrTfJT_V+F8!nfL2kK0#$CwxYn@34ytmyEa0erNlO)}?rThrHkS+E2-U z-N#OwyC?Y4XC>HvOTOiOp0S3X_WobJU@q#vr0?bpb5fm53TF?Sm-0{jX)>LQ-Zw*L za$Wy(-s6m8cT)c9cxCC&CWl<|$ftlpig?p!7RwTT^BzxWm#WJsr-GNy_*`pirMil0 zYN+Lg*VM^+epffhMw)1*g;v^Vr-M%3cdoi*H$6P!`1Hy?`Wax5A$Bv&2&0TK&IEt> z%t`r;WAUov|C%*tN_(0k>KXZ_oRx3LIeFOpd0joPUSN?|e8;!+EvY|{%W{QP);MWi z{`I2kLH(ZX$JtPS?lU*#7TW}T=6-71JM2&ga!ma`LF%tObG)nm+c^r>4k46}^qnS5 z9Zm$_yH7{T-^}Twww)kKJDP*$Y>bR$Cx1Dfaq^bAy-R**>`6}Xt$F*gjMslwCdfpR zNG63;(s-v3BpKVuo*tP-vgAB2oVZO8Ndq&iwj4{pxle}Wv zl$>UUS>~8$fkl>BW`$MWvd*o^bzb%Q4Y|qNFWO(nV@v&${vX&@f8zWGeC}CBdxyL# z17#4wgb>P)`om;6pYAuu~8$fkl>B zW`$MOSZ9Mxw%8`%3+IqPf(RyrP{If&f=Hr>CWcsc62~s$Ng$CVl1U+zG}6f+lPt2y zA(uSzDWH%diYcL#GRmo-k}9gHp_V%8X`qoNnrWexHrnZ+lPB1t5ZLMmyblR+j~WRpWKFS_>r=eqpKe81(lQJ%hQKbZg4!Jp+hYyUO(%gcvd zhuXh#ov+>3ev`lR2RFFMpM33l`AeSnzPIFuFFVKH_iyz-oYekTKJLEsif5w#)cdSM zXO4I;`|&^R0^=Vv_aEY6{yOOQ<56=&|K;P}^DDn)z5mOe;|`v6k1*y-xktY4dmQyX zMaCZ6Z!P!U#p)7DdEPTqnJlM*O1?AZd#cn|WVNiJmO5T`oUS+y_38#1Y2tNjce8Ba zqSv*`Hrjd5cl*WXcc?pg+;KU7+8k8h^2~JTl)0$>&%XZQIQOV~>7$$nZ6-|(3)Iv#Jz-P*&v)Id54SC3Ge>LAuYJXv$Hub%tZ%dxi zci5V|tq!>880)|6cr!MYH;qY? z>12>e7C(58Ym?))~ZTWFKqE~w(?Tn4w9~?NaZMft);Tj^1#L zj#=ByrOR)dYuf+u4?)Jf^NM*QLkJ~|U(DHX8Num;=7o&n#2M$;S{tp7;h{gwQyw=j z{^$M9S&L%z?<9^#Z2R~%b47jC`Hh!*t*3kRKg@n}^KqG={|R|Q`_P-NbMxwJ@3mK7 zqHRee^QiV?{Q8#pq@79{>16PfZJF}uesf7)^PRKhC)!Wi_6#}Nxje0YmQ%iKo_0P3 z6jDSnC7iN9Pq>*+f=a4*&U-vhwYr8{>ZqrIeYQ2qCSFkQ=S7;eTWF+M?V7$GQ@6%8DW(7Tzg~kjPrlOJ!@S3i}P^)oc;aSwfVZasP9+D zds0p@%?z{5G0y^vEV0+K)v{b+l{MDcV3RGj3Akkb5l9fhgb+#?;Y1Kg6w$;G%TD6h zMLY>4l0-5oq>@HD8Dx@0HaX;yM?M7yM?DQR(nK>Yw9-a9 z9dyz~H$C*yM?V7$GQ@6%8DW$$#+hJ}DW;iWmO18GV38%3Sz(nm*4bc_Ew%~x#_=bR zAc6@YlrX}HAd)Dei6NGq#IcKb5=bP8WKu{ajdU`|B#Ufv$R&?_3MizAVoE5bjB+Zd zq>8^h>s8AdYN?~11{!IinHE}Uqn!>q>7tt+dg-H|0R|ajH}BkZ9^?q4j4{pxlT0zq z471EJ&jO1qvCImqtg+4pn{2U7z-8xwK!OM+gkwHGRE7~w1d&7$O$@Q@B#vFglRzR# zB$GlaX{3`uCRt?juFuJlx#W>g0fiJ%ObMlwQBDPwR8dV0wbW5h1C2D%Obe~F(M|`Q zbkR)@z4Xz~0D}y%n_)&6WsGqqm}H7+W|(D;c@|h?iDgz;WsP+<*kp@s0={(~2qcJL zLI@>{a3Y8#ifCepWhZg$BAx^iNg|mPQb{A73^K_gn;degi*#AXM#zlm}Z7q=9p)J zMV44*g;myAXM;_)IBtKpWx#jN1Azn)ObDTb5l#e=L=jC4vFs#{UBr_>B1t5ZLMmyb zlR+j~WRpWKdF1nfeJYTJ6j4kGrIb-l1(j4$O%1iwQBMPnG|@~8t+dfj2c2}$O%J{F z(a!*b46&PGMi^y`aVD5#ifLw;WsZ3kSY(N1R#;_?bvAh4ciog*Y!mRk^FSa$1QS9i zVf^r?b0H&$B#LNah-D{n>>{275=kPN6jDheoeVO`BAXm?$s?Zv3MrzP5=tqfoC+$b zqM90NsiU3-8fl`L7FubeoenzbqMIIi>7$E!;CP>7~@PZ$rRJfFv}eCEU?HD z%dD`<8tZJZ$rjrLTyYKvB#2-_2qlbgB8Vi4Xkv)vg!8#m#<7cd5=bP8WKu{ajdU`| zB#Ufv$R&?_3MizAVoE5bjB+Zdq>5^4sHKj28fc`6W?E>ajdnh?&mFRpF1qQVmp=L# zV2~kpGt3C1j4{pxlT0zq471EJ&s#tH+Xe6N<5|By4!94hkMSPI*>lV_AwOWjYo7D_ z=H`oztM*A2^?fLp$2_-xA;07zU-30p{f@aLzu~;+q|5UC z+rRDn7JJHTzI`2ik9wb{-!up9`*+&kbA=zc%8&fSitX3r&-}uw_8Pycuk#x>_?>nA zf5@l(ZhQR=$4dPtfAOGWd`rG?(!R)l*f9QI`5zDd;&-8ZNdDnC{cYbKRzJcUetW#? zx5zE~zeoE~9^)^4kIVlY<0s??@3?ln=U(-b?Dt)tl7F8x)^EgT)KA}TJ1>7Z-p{I^ z+ou<+vO&_JH&Bhwl~egE@E7Z*JRO=MCQCG4tnN=kJpF@qzb!Ti-kExIJE; z#mD?+|AY0NR{v?9hN#b||5Bfo z=eX>A{P~Ry zYDyXE2YHFyZj(Qqsq={x)Xr+yII_RW}ZhGjYkA4OiWQg4i zGr}lij5EO`Q%p0%EOX4Wz#>a5v%)HCth2!;TWk|>)jT7RAc6@YlrX}HAd)Dei6NGq z#IcKb5=bP8WKu{ajdU`2`}X|)#{7TJT$P#n&RQ>zyJlW+t^DTtJEs35=lflG*>&-r zJkC3BS~JYybLQ)huIabE=6(G)^?x9EF%akNxfGguV}X%ldm#X50ReeE*bd zLVnC?&TvlOS^1B3=ZN`uPMu@?lj={@=eaw8J^++(gJoqKGDjSauS}F5@HDH+)8h%;YU|EK6py$1%u}xx9MQ+>`mdrhc7M&SQc0A@k@P^QKT; z#AohrZ)-nm4xDh!6zjY3i}@%^dB-((*ztM8d;H^EmFX+zP3;O<$@Le_QCUq5wbW5h z1C2D%%-deqB3o&roenzb;;PSj%$O(aQ@3^xz4Y;f{(d>YAdhPg$=!V8`+wqE99BQ{ zy!j+Y8DpGl)`AIn#rJ*E>n7Dx+;py{6k9bWzPHj6}ie9>uj+1ee+5l^*LK|n}DCpCjto~m=Hnsgi)^Kh zb~@;!i*9iu#>uCm5)$7Nk^u*nwN1YC2@IqBF0${-GUZLka>lrX}HAd&;N zN69bE=V$H4(1?1JF~*r-k}0N{VU{`OSzwVRmRVtyHP+c+lP$Ih_}MumkRXBy zA(Sw}i6D|FqKP4voy4(=coIk?iDXhpC5?14$Rvwwa>yl*dME{$%}r%WuZ#&9w)A^E}~x80x(rQa?T3-yY z>?Dp|#FIcGNhFg(DruyXK_*#blS3|fxG)>12>e7TM&GOCI?YaLPUu$|8y>p_DSpsi2Z7s;Qxt zI_hblktUjHp_Mk;>7bJ?y6K^pKKdD8kRf(6%m}CL*T;;i#~5dVNv4=)hFRvAXMshI zINwY1A=lcnJgWUNukb3b@j5RZ^z8Yu>(BlELvv`)^R7MD?~2#FVf(+XueV$~Z>m@I zt?{n0>+(Ni-_pOKzG>Xs>IfQR*CEd_-(K)6>iq(Z4xG)>12>e7TM&GOCI?YP)HHQlu$|;vnQO}5x3zS>^nCYouXl{VVxpp!1T>7kcC`Wax5A$Bv&2&0TK&IFT8G0hCK%rVab zi!8Cs3ahNK&IX%ou}#45jz56}5ljf7gb_{zkwg(q46*Daj$K@HojvLvea5}^`BQ$c zzTld6pO3fg#eLQZ+rRqGTH^ZqT3+Ied-yl{59&nySLMe(>j$5iq@Bzj_xB(5|MHIK1$m7W{i*z{ep>%8GEMt2&!fMp zuk#x(`M1p9`KH8s@opLu-M-!$Iy`N!UIuakB9kIN5upL*>E8abieBoBY+yvq-@TVyMb zxtF%db~@;!i*9=8rH_6F7-Wdu3^T$gV~jJwBvVW?!z^>mv%n%tEVIHYYpk=uCR=P1 z@Q3qBAVCBZLMUN`6G0?VL=!_SJBec#@g$H)63L{HN*d{8kVzKVgi*#AXM#zlm}Z7q z=9p)JMV44*g;myAXM;_)*e2kn<4+(#1QS9iVT2PwBvC{YLo7RqV;AuxkVq2Aq>xG) z>12>e7TM&GOCI?YP)HHQlu$|;vnQO}5x3z_q%AK!OM+giyi=CxS?# zh$eS>^n zCYouXl{VVxpp!1T>EWBx&VlUXq~p;qUvU5ZNIjq)@uY&*bNfsmGaMk}vdq$#K60rnE1rzv62y@eP;x)$fgO<#&9~6@FmaYp%)} z`J?=aS@kvfGr#aF*ZGa#xxwR}eddh&Lw%D!`HOjd3oNq4GJpHcbj!BC`Gi_Ye`XL_X5%#dgI*;-gkMpx*^n~2YlWefbQ#{RQemgxQx7g-c0{${L2_%SMLI@>{ za3Y8#ifCepWhZg$BAx^iNg|mPQb{A73^K_gn;deuj*e7TW~ea{LJ-h+skpC5&()h$M<=Vu)oYaqJ?V1QJOinG{k*l~ z0tzXjm=a1UqnrvVsiK-1YN?~11{!IinHE}Uqn!>q>7tt+dg-H|0R|ajH^YoD${6EJ zFv%3t%rMIw^DMB)63eWx${Oozu*nwN1pMvz6G#xjgb+#?;Y1Kg6w$;G%TD6hMLY>4 zl0-5oq>@HD8Dx@0HaX;yM?M7yM?DQR(nK>Yw9-a99dyz~ zH$C*yM?V7$GQ@6%8DW$$#+hJ}DW;iWmO18GV38%3Sz(nm*4bc_Ew%~x$MGkSAc6@Y zlrX}HAd)Dei6NGq#IcKb5=bP8WKu{ajdU`&?pgU+f9rYFZ_(%EE&m3VssE6FuRG#* zW|sPS{rh-<{k+Ig+p=x@N#@9d`VR2e8Rt;@W500^X&>e#j&PJb+w%GGkiV;GUpeeN zYrmp?l^@(IUXwo^@S9M+!JE9ri|!3?%XcXBnq%^Y{VYZ_8~ z)KE(u^)%2(6F*!tALLc}BQ5Hqo@H8P8|`$^Nf+Jp&`Tfv4Dhno49ZvJqpp#m+x2;K zLJsrROXh_fWsD=XjmzghH!tKQQ%p0%EWbOJbMjB$WnM0@$P&w}u*w?i{AJvR+~k&e zOKubJpSeLGK?L)U?IH4S87hx?CJU4QYX3*LI)X@|h~|I#V`MBliDMV>B#=lF$)xb3 zzZdNHZ#${#G}6f+lPt2yA(uSzDWH%diYcL#GRmo-k}9gHp_V%8X`qoNnrWexHrnZ+ zlP{nm*T>7Fsz(Ef25{G%%8hAtw8#}@%V~jJwBvVW? z!z^?B?L8kiH?Ej_^V$n6a#i0&*VdAHnH5%9JGqOyxrckXkNbImJLZhzPVVAv?%`hU z<9;6Cj(Ov_le@T^d$^bTxSt2OW5GD?!9`5Bn?&ksSSTv41xr@8GhkLn?`+0yn zmW<<0?&5Cl;a=|JejebCW#hP$ySSTsxR?95p9i>O#W?QdF7Dq8Z}FIu@Jca4DK0UZP{MNe-8y8RDfn7MtX7DViZ( zrem>54ws@C;^jIPo8)jQnjv1HW3fpNm!cWsl{yxiq8Z}VIu@Jc za4DK0UZZ2NNe-8y8RE4%7MtX7DViZ(r(>~64ws@C;`KTfo8)jQnjzkxW3fpNm!cWs zjXD;aO28u}Kb>q8Z}NIu@Jca4DK0-lAi%Ne-8y8RD%v7MtX7DVibPrem>5 z4ws@C;_W&Xo8)jQnjzkyW3fpNm!cWsojMkqO59u}Kb>q8Z}dIu@Jca4DK0 z-lJo&Ne-8y8RES<7MtX7DVibPr(>~64ws@C;{7@no8)jQnjt=*W3fpNm!cWsgE|(Q zq8Z}DIu@Jca4DK0KB8l>Ne-8y8RDZl7MtX7DViZZrem>54ws@C z;^R6No8)jQnjt=+W3fpNm!cWslR6fgq8Z}TIu@Jca4DK0KBHr? zNe-8y8RD}#7MtX7DViZZr(>~64ws@C;`2Hdo8)jQnjyZRW3fpNm!cWsi#isYq8Z}LIu@Jca4DK0zM^BXNe-8y8RDxt7MtX7DVia^rem>54ws@C;_EsV zo8)jQnjyZSW3fpNm!cWsn>rSoq8Z}bIu@Jca4DK0zN2HYNe-8y z8REM-7MtX7DVia^r(>~64ws@C;`=%lo8)jQnjwCmW3fpNm!cWshdLIUq8Z}HIu@Jca4DK0exhTsNe-8y8RDlp7MtX7DViaErem>54ws@C;^#URo8)jQ znjwCnW3fpNm!cWsmpT@kq8Z}XIu@Jca4DK0exqZtNe-8y8REA( z7MtX7DViaEr(>~64ws@C;`cfho8)jQnj!w6W3fpNm!cWsk2)5c zq8Z}PIu@Jca4DK0{-R^CNe-8y8RD-x7MtX7DVibvrem>54ws@C;_o^Zo8)jQnj!w7 zW3fpNm!cWspE?$sq8Z}fIu@Jca4DK0{-a~DNe-8y8REY>7MtX7 zDViZ3bpPi87MtX7DVibvN5^85c-sFz<+mB)!8#V3q8Z|Ubu2c? z;Zih1JXFVGlN>HZGsMGmEH=sEQZz$6T*qRQ94CBoLp)l?Vv`&$MKi=>bSyT>;Zih1JXXhIlN>HZGsNR`EH=sEQZz$6UdLjS z94CBoLp)i>Vv`&$MKi=xbSyT>;Zih1 zJXObHlN>HZGsM$$EH=sEQZz$6UB_aR94CBoLp)o@Vv`&$MKi>6bSyT>;Zih1JXgnJlN>HZGsN?BEH=sEQZz$6U&msT94CBoL%dkWVv`&$MKi=pbSyT>;Zih1yi~_x zlN>HZGsMeuEH=sEQZz%nT*qRQ94CBo zL%dqYVv`&$MKi=}bSyT>;Zih1yjI6zlN>HZGsNq3EH=sEQZz%nUdLjS94CBoL%dnXVv`&$MKi=(bSyT>;Zih1yj90ylN>HZ zGsN3;EH=sEQZz%nUB_aR94Hp$^qG()^o$6}KlE=4oMyL2oz$>CBoL%dtZ zVv`&$MKi>EbSyT>;Zih1yjRC!lN>HZGsOFJEH=sEQZz%nU&msT94CBoLws1rVv`&$MKi=lbSyT>;Zih1d{oC`lN>HZGsMSq zEH=sEQZz$+T*qRQ94CBoLws7tVv`&$ zMKi=_bSyT>;Zih1d{)O|lN>HZGsNd~EH=sEQZz$+UdLjS94CBoLws4sVv`&$MKi=#bSyT>;Zih1d{xI{lN>HZGsM?)EH=sE zQZz$+UB_aR94CBoLwsAuVv`&$MKi>A zbSyT>;Zih1d{@U}lN>HZGsO3FEH=sEQZz$+U&msT94CBoL;P6BVv`&$MKi=tbSyT>;Zih1{8YzclN>HZGsMqyEH=sEQZz&S zT*qRQ94CBoL;PCDVv`&$MKi>2bSyT> z;Zih1{8qHZGsN$7EH=sEQZz&SUdLjS94CBoL;P9CVv`&$MKi=-bSyT>;Zih1{8h(dlN>HZGsNF?EH=sEQZz&SUB_aR z94CBoL;PFEVv`&$MKi>IbSyT>;Zih1 z{8z_flN>HZGsJ_+URU(#t%@F^qW3fpNm!cWsp*j|uq8Z}hIu@Jca4DK09-(8g zNe-8y8RC&T7MtX7DViZ3rDL&44ws@C;?X)5o8)jQnjs#eW3fpNm!cWsu{su;q8Z}xIu@Jca4DK0o}go~Ne-8y8RCgL7MtX7DViakq+_v34ws@C;>kJ| zo8)jQnjxN|W3fpNm!cWssX7*$q8Z}pIu@Jca4DK0o}pv0Ne-8y z8RD5b7MtX7DViakrDL&44ws@C;@LVDo8)jQnjxN}W3fpNm!cWsxjGh`q8Z}(Iu@Jca4DK0UZ7*KNe-8y8RCUH7MtX7DViZ(q+_v34ws@C;>9`^o8)jQ znjv1IW3fpNm!cWsr8*Xyq8Z}lIu@Jca4DK0UZG>LNe-8y8RC^X z7MtX7DViZ(rDL&44ws@C;?+79o8)jQnjv1JW3fpNm!cWswK^7? zq8Z}#Iu@Jca4DK0-k@W#Ne-8y8RCsP7MtX7DVibPq+_v34ws@C;>|i1o8)jQnjzkz zW3fpNm!cWstvVK)O8Au}Kb>q8Z}tIu@Jca4DK0-l1c$Ne-8y8RDHf7MtX7 zDVibPrDL&44ws@C;@vtHo8)jQnjzk!W3fpNm!cWsy*d_~OBBu}Kb>q8Z}- zIu@Jca4DK0KA>Zq8Z}jIu@Jca4DK0KA~f=Ne-8y8RC;V7MtX7DViZZ zrDL&44ws@C;?p`7o8)jQnjt=;W3fpNm!cWsvpN==q8Z}zIu@Jc za4DK0zMx~VNe-8y8RCmN7MtX7DVia^q+_v34ws@C;>$V~o8)jQnjyZTW3fpNm!cWs zt2!2&q8Z}rIu@Jca4DK0zM*5WNe-8y8RDBd7MtX7DVia^rDL&4 z4ws@C;@dhFo8)jQnjyZUW3fpNm!cWsyE+z|q8Z}*Iu@Jca4DK0 zexPHqNe-8y8RCaJ7MtX7DViaEq+_v34ws@C;>S7`o8)jQnjwCoW3fpNm!cWsr#cp! zq8Z}nIu@Jca4DK0exYNrNe-8y8RC~Z7MtX7DViaErDL&44ws@C z;@3JBo8)jQnjwCpW3fpNm!cWsw>lP^q8Z}%Iu@Jca4DK0{-9&A zNe-8y8RCyR7MtX7DVibvq+_v34ws@C;?Fu3o8)jQnj!w8W3fpNm!cWsuR0c+q8Z}vIu@Jca4DK0{-I;BNe-8y8RDNh7MtX7DVibvrDL&44ws@C;@>(J zo8)jQnj!w9W3fpNm!cWszd9D1~;UQ)ajfd9;{=rNe-8y8R8*27MtX7DVibvSI1(L94CBoLp(yqVv`&$MKi=Bbu2c?;Zih1JW9u6lN>HZGsL5HEH=sEQZz$6 zM#o~494@H$>CBoLp(vpVv`&$MKi<`bu2c? z;Zih1JW0o5lN>HZGsKg1EH=sEQZz$6MaN>394CBoLp(#rVv`&$MKi=Rbu2c?;Zih1JWI!7lN>HZGsLrXEH=sEQZz$6N5^85 z94CBoL%cx8Vv`&$MKi<;bu2c?;Zih1 zyhz7llN>HZGsKH^EH=sEQZz%nM8{&294CBoL%c%AVv`&$MKi=Jbu2c?;Zih1yh_JnlN>HZGsLTPEH=sEQZz%nM#o~494vb$P$>CBoL%c!9Vv`&$MKi=3bu2c?;Zih1yh+Dm zlN>HZGsK&9EH=sEQZz%nMaN>394CBo zL%c)BVv`&$MKi=Zbu2c?;Zih1yi3PolN>HZGsL@fEH=sEQZz%nN5^8594CBoLwrETVv`&$MKi<)bu2c?;Zih1d`QP)lN>HZ zGsK5=EH=sEQZz$+M8{&294CBoLwrKV zVv`&$MKi=Fbu2c?;Zih1d`ib+lN>HZGsLHLEH=sEQZz$+M#o~494CBoLwrHUVv`&$MKi<~bu2c?;Zih1d`ZV*lN>HZGsKs5 zEH=sEQZz$+MaN>394CBoLwrNWVv`&$ zMKi=Vbu2c?;Zih1d`rh-lN>HZGsL%bEH=sEQZz$+N5^8594CBoL;OI;Vv`&$MKiHZGsKT|EH=sE zQZz&SM8{&294CBoL;OO=Vv`&$MKi=N zbu2c?;Zih1{7T1SlN>HZGsLfTEH=sEQZz&SM#o~494CBoL;OLHZGsK^DEH=sEQZz&S zMaN>394CBoL;OR>Vv`&$MKi=dbu2c? z;Zih1{7c7TlN>HZGsM4jEH=sEQZz&SN5^8594~&+W8++Z@ z>&9N^%~pzL2y5H}EH;TZYVCFZcdPFImO7mi57x2RB!^4U4Dk>hi%oL46wMI-t7EZA z4ws@C;-NYgo8)jQnjs#hW3fpNm!cWs;W`$Zq8Z|mIu@Jca4DK0 z9;IWkNe-8y8RF487MtX7DViZ3qhqm24ws@C;;}jwo8)jQnjs#iW3fpNm!cWs@j4cp zq8Z|eIu@Jca4DK0o}^>3Ne-8y8RE%07MtX7DViakqGPd14ws@C z;;A|oo8)jQnjxO1W3fpNm!cWs={gphq8Z|uIu@Jca4DK0o~2{4 zNe-8y8RFSG7MtX7DViakqhqm24ws@C;<-8&o8)jQnjxO2W3fpNm!cWs`8pPxq8Z|aIu@Jca4DK0UZi8ONe-8y8REq{7MtX7DViZ(qGPd14ws@C;-xwk zo8)jQnjv1MW3fpNm!cWsq8Z|qIu@Jca4DK0UZrEPNe-8y z8RFGC7MtX7DViZ(qhqm24ws@C;N>4 zu}Kb>q8Z|iIu@Jca4DK0-lSu(Ne-8y8RE@47MtX7DVibPqGPd14ws@C;;lLso8)jQ znjzk%W3fpNm!cWs?K&2lN^5u}Kb>q8Z|yIu@Jca4DK0-lb!)Ne-8y8RFeK z7MtX7DVibPqhqm24ws@C;=MW+o8)jQnjzk&W3fpNm!cWs{W=z# zq8Z|YIu@Jca4DK0KBQx@Ne-8y8REk_7MtX7DViZZqGPd14ws@C;-fkio8)jQnjt=> zW3fpNm!cWs<2n|bq8Z|oIu@Jca4DK0KBZ%^Ne-8y8RFAA7MtX7 zDViZZqhqm24ws@C;q8Z|g zIu@Jca4DK0zNBNZNe-8y8RE-27MtX7DVia^qGPd14ws@C;;T9qo8)jQnjyZXW3fpN zm!cWs>pB*jq8Z|wIu@Jca4DK0zNKTaNe-8y8RFYI7MtX7DVia^ zqhqm24ws@C;=4K)o8)jQnjyZYW3fpNm!cWs`#Khzq8Z|cIu@Jc za4DK0exzfuNe-8y8REw}7MtX7DViaEqGPd14ws@C;-@+mo8)jQnjwCsW3fpNm!cWs z=Qq8Z|sIu@Jca4DK0ex+lvNe-8y8RFME7MtX7DViaEqhqm2 z4ws@C;q8Z|kIu@Jca4DK0 z{-k5ENe-8y8RE}67MtX7DVibvqGPd14ws@C;;%Xuo8)jQnj!wCW3fpNm!cWs?>ZKn zq8Z|!Iu@Jca4DK0{-tBFNe-8y8RFkM7MtX7DVibvqhqm24ws@C z;=ei;o8)jQnjsz(4}O5fCOKS+W(Z5%11vU)f4_UMH)(#t%@7aQvDhSsOVJGR z2px+}a<~-D5RcTc*d&Kb(G2k@9g9tJxD?G0kJho+B!^4U4DlEpi%oL46wMHi)v?$l zhfC26@i-leO>(#t%@B{*vDhSsOVJGR1RaY_a<~-D5Kq*x*d&Kb(G2k<9g9tJxD?G0 zPu8*6B!^4U4Dl2li%oL46wMG%)v?$lhfC26@iZNaO>(#t%@9x5vDhSsOVJGR3>}M2 za<~-D5YN=H*d&Kb(G2k{9g9tJxD?G0&(^WnB!^4U4DlQti%oL46wMIN)v?$lhfC26 z@jM-iO>(#t%@EJmvDhSsOVJGR0v(G@a<~-D5HHlR*d&Kb(G2k-9g9tJxD?G0FV?Zx zB!^4U4Dk{ji%oL46wMGX)v?$lhfC26@iHBYO>(#t%@8lwvDhSsOVJGR3LT40a<~-D z5U(#t%@D8GvDhSsOVJGR1|5q{a<~-D5O376*d&Kb(G2k>9g9tJxD?G0Z`QHcB!^4U z4Dl8ni%oL46wMHC)v?$lhfC26@irZcO>(#t%@A+bvDhSsOVJGR4jqe4a<~-D5bxBn z*d&Kb(G2k}9g9tJxD?G0@7A%{B!^4U4DlWvi%oL46wMIt)v?$lhfC26@je}kO>(#t z%@FU`vDhSsOVJGR0Ue7?a<~-D5FgaB*d&Kb(G2k+9g9tJxD?G0AJ(zhB!^4U4Dk^i zi%oL46wMGH)v?$lhfC26@i85XO>(#t%@7~gvDhSsOVJGR2_1_~a<~-D5TDes*d&Kb z(G2k^9g9tJxD?G0pVqP1B!^4U4DlHqi%oL46wMHy)v?$lhfC26@i`rfO>(#t%@Cj0 zvDhSsOVJGR1s#h`a<~-D5MR`>*d&Kb(G2k=9g9tJxD?G0U)HhMB!^4U4Dl5mi%oL4 z6wMG{)v?$lhfC26@iiTbO>(#t%@AMLvDhSsOVJGR4IPV3a<~-D5Z~0X*d&Kb(G2k| z9g9tJxD?G0-`26%B!^4U4DlTui%oL46wMId)v?$lhfC26@jV@jO>(#t%@E($vDhSs zOVJGR109P^a<~-D5I@wh*d&Kb(G2k;9g9tJxD?G0Ki09>B!^4U4Dk~ki%oL46wMGn z)v?$lhfC26@iQHZO>(#t%@9A=vDhSsOVJGR3muD1a<~-D5Wm#1*d&Kb(G2k`9g9tJ zxD?G0zt*wXB!^4U4DlNsi%oL46wMI7)v?$lhfC26@jD%hO>(#t%@DuWvDhSsOVJGR z2OWz|a<~-D5P#IM*d&Kb(G2k?9g9tJxD?G0f7Y?sB!^4U4DlBoi%oL46wMHS)v?$l zhfC26@i!fdO>(#t%@BXrvDhSsOVJGR4;_n5a<~-D5dYM%*d&Kb(G2k~9g9tJxD?G0 z|JJeCB!^4U4DlZwi%oL46wMI-)v?$lhfC26@t_Cnbr0C<9Ay-tVQeD*q>weJ7UVv`&$MKi=hR4g{h;Zih1{I8D1COKS+W{8LCSZtER zrD%qDn2yCJIb4cnh==P~Y?8yJXoh%%j>RT9T#9ChN9tH?lEbBFhIo{Y#U?piie`vM z>sV}(!=-43c#Mw4COKS+W{Ah?SZtERrD%qDoQ}mNIb4cnh{x+#Y?8yJXoh%#j>RT9 zT#9ChC+b*ilEbBFhIo>W#U?piie`u>>sV}(!=-43c#4k2COKS+W{9WiSZtERrD%qD znvTULIb4cnh^OmVY?8yJXoh%(j>RT9T#9ChXX;pNlEbBFhIp2a#U?piie`vs>sV}( z!=-43c#e+6COKS+W{BtNSZtERrD%qDo{q&PIb4cni0A8AY?8yJXoh%!j>RT9T#9Ch z7wTASlEbBFhIo;V#U?piie`ux>sV}(!=-43c!`e1COKS+W{8*SSZtERrD%qDnU2LK zIb4cnh?nbFY?8yJXoh%&j>RT9T#9ChSL#@7lEbBFhIo~Z#U?piie`vc>sV}(!=-43 zc#V$5COKS+W{B77SZtERrD%qDosPvOIb4cnh}Y{_Y?8yJXoh%$j>RT9T#9ChH|khy zlEbBFhIo^X#U?piie`v6>sV}(!=-43c#Dq3COKS+W{9`ySZtERrD%qDn~udMIb4cn zh_~xlY?8yJXoh%)j>RT9T#9Chcj{PdlEbBFhIp5b#U?piie`v+>sV}(!=-43c#n?7 zCOKS+W{CIdSZtERrD%qDpN_>QIb4cni1+JQY?8yJXomQJj>RT9T#9Ch59(NKlEbBF zhWL<<#U?piie`up>sV}(!=-43_=t|hCOKS+W{8jKSZtERrD%run2yCJIb4cnh>z=7 zY?8yJXomQNj>RT9T#9ChPwH4~lEbBFhWM0@#U?piie`vU>sV}(!=-43_>7LlCOKS+ zW{A(~SZtERrD%ruoQ}mNIb4cnh|lX-Y?8yJXomQLj>RT9T#9ChFX~uqlEbBFhWL_> z#U?piie`u}>sV}(!=-43_==9jCOKS+W{9uqSZtERrD%runvTULIb4cnh_CBdY?8yJ zXomQPj>RT9T#9ChZ|YcVlEbBFhWM6_#U?piie`v!>sV}(!=-43_>PXnCOKS+W{B_V zSZtERrD%ruo{q&PIb4cni0|uIY?8yJXomQKj{nErT`tLWq>CEfmz0z6W#+#*!_3Ug z%pBt}Gc#%=OSVO3MoDI7X0{}Y8R9%=-^GbgR6JFs>bJXE*YyBj^k!=~W$>LZuOO29xxfj!dD_2s(pFdR<4RP-z66!6dz*BU7j}g3e%)-qevP zR2o5NFiCIe$P_A#pfi}Hw{>I+l}6AROwv0#GKESb=nN)lt&U8g(g-?(Nm{2PQ>Zk8 z&R~+(>&O%;ji57_q<3{>3YA9C8BEd!9hpL<5p)KVv{6TY zn{{Lgl}6AROwtw|nL?!zbOw{ORY#^!X#}0YByH1?DO4IkXD~_Ibz};aM$j2d(heP& zLZuOO29vZ?N2X9|1f9Vo?b4AcR2o5NFiE?0WD1o=&>2k99vzuNr4e)nleAYyrch}F zoxvpS(~&7u8bN0;N&9tV3YA9C8BEeacGk!gDvh8sm?THIzK2Yq;_S2b>vTBs)_$Gt ze|PG1E`>@X=nN+55Fd|Bq0$ICgGoA6N2X9|1f9Vo9i}5ws5FAkV3H2kkttLfL1!>Y zN9f2DDvh8sn4}|hWD1o=&>2k9Q93e(N+akDCh2G$nL?!zbOw`jjE+p9(g-?(Njg?X zrch}Foxvm>rz2CSG=k1xl8)DrDO4IkXD~@8=*Sc*ji57_q!V>y3YA9C8BEeiIx>Yy zBj^k!>0}+5LZuOO29tD(j!dD_2s(pFI#oxeP-z66!6cogBU7j}g3e%)PS=qsR2o5N zFiB_V$P_A#pfi}HGj(JNl}6AROww68GKESb=nN+5Y#o_Gr4e)nlXQ-bOrg>UI)h0% zS4XB$X#}0YB%P-tQ>Zk8&R~+x*O4hy8bN0;Nf+qI6e^9NGnk|WIx>YyBj^k!>AyNM zg-Rpn3?^xzj!dD_2s(pFTBIXWs5FAkV3ID>kttLfL1!>Yi*;lQl}6AROwtk^nL?!z zbOw`jk&aBE(g-?(NxE1^rch}Foxvnsq9aqNG=k1xl9uYo6e^9NGnk}hIx>YyBj^k! zX}OL}q0$ICgGpMUBU7j}g3e%)R_e$UDvh8sn50W}WD1o=&>2k9WjZp2N+akDCh2k= znL?!zbOw`jg^o<2(g-?(NxD);rch}Foxvnsr6W_QG=k1xlCIW~DO4IkXD~_E=*Sc* zji57_q-%9#3YA9C8BEf3Ix>YyBj^k!>3SWRLZuOO29tDyj!dD_2s(pFx=}}_P-z66 z!6eZk8&R~+(=*Sc*ji57_q}z353YA9C8BEe0Ix>YyBj^k!=}sM) zLZuOO29tD`j!dD_2s(pFx?4x4P-z66!6eVwr4e)nlk|{|Org>UI)h1iSVyK%X#}0Y zBt4=dQ>Zk8&R~)r)sZPw8bN0;NssBs6e^9NGnk~ubz};aM$j2d(i1u|g-Rpn3?}JG z9hpL<5p)KV^puWFq0$ICgGqW?N2X9|1f9VoJ)Y&*{h% zDvh8sn55@*WD1o=&>2k93pz4|N+akDCh0{TnL?!zbOw|3l8#KF(g-?(NqSjFrch}F zoxvo%q9aqNG=k1xl3vx3DO4IkXD~^x>Btl+ji57_q}O$13YA9C8BEd}Ix>YyBj^k! z=}jG(LZuOO29xxbj!dD_2s(pFdRs@PP-z66!6dz-BU7j}g3e%)*6PRYTXkd#l}6AROwu+TnL?!zbOw{OT}P%+X#}0Y zB<;|VDO4IkXD~@Sbz};aM$j2d(k>mDLZuOO29vZ~N2X9|1f9Vo?a`4bR2o5NFiCrL zWD1o=&>2k9J{_4tr4e)nleAw)rch}Foxvm>6LZuOO29tECj!dD_2s(pFI!s5VP-z66!6Y57BU7j} zg3e%)j?j@QR2o5NFiA)1$P_A#pfi}HqjY2nl}6AROw!RhGKESb=nN+57#*2Hr4e)n zlXR?(Org>UI)h0%PDiFtX#}0YBpt6KQ>Zk8&R~*G(2*%r8bN0;Nhj*a6e^9NGnk~4 zbYu#ZM$j2d(#bk9g-Rpn3?}Im9hpL<5p)KVbgGU_q0$ICgGo9~N2X9|1f9VoovtHO zs5FAkV3N+zkttLfL1!>YXX?llDvh8sn546GWD1o=&>2k9**Y?XN+akDCg~gUI)h2NL`SAjX#}0YBrVmEDO4IkXD~_2bYu#Z zM$j2d(sCV{LZuOO29vZxN2X9|1f9Vot<;ezR2o5NFiDr{$P_A#pfi}H%XDN4l}6AR zOw#2#GKESb=nN+53LTk3r4e)nlXRtyOrg>UI)h2NN=K$pX#}0YBwei|Q>Zk8&R~+R z(UB=s8bN0;N!RMg6e^9NGnl07bYu#ZM$j2d()Btrg-Rpn3?}IY9hpL<5p)KVbfb<; zq0$ICgGstcN2X9|1f9Vo-K-;1s5FAkV3KapkttLfL1!>Yx9Z3gDvh8sn55fuWD1o= z&>2k9Djk_Zr4e)nleAh#rch}Foxvon(UB=s8bN0;Nw@3B6e^9NGnk}1bYu#ZM$j2d z(w#aog-Rpn3?}I=9hpL<5p)KVbhnO7q0$ICgGstaN2X9|1f9Vo-K!&0s5FAkV3O|B zkttLfL1!>Y_v^?MDvh8sn4|}EWD1o=&>2k9gE}&WN+akDCg~v^nL?!zbOw|3u#QZj z(g-?(NqR&_rch}FoxvnMsv}dVG=k1xk{;8MDO4IkXD~^R>&O%;ji57_q$hM_3YA9C z8BEfXIx>YyBj^k!=_wtVLZuOO29xx(j!dD_2s(pFdPYa4P-z66!6ZGaBU7j}g3e%) zp3{*jR2o5NFiFqr$P_A#pfi}H7j$F_l}6AROwx-wGKESb=nN+5B^{YUr4e)nlk~EV zOrg>UI)h1iMMtJkX#}0YB)zI5Q>Zk8&R~*W(~&7u8bN0;Nw4e36e^9NGnk||bYu#Z zM$j2d(wjOmg-Rpn3?}I<9hpL<5p)KV^tO&nq0$ICgGqWvN2X9|1f9Vot<{k!R2o5N zFiGolWD1o=&>2k9dL5ZUr4e)nlk~2ROrg>UI)h2tpd(YLG=k1xk~Zqd6e^9NGnk}J zIx>YyBj^k!X|s+@q0$ICgGt(=BU7j}g3e%)w(7_fDvh8sn51nwGKESb=nN)lyN*nu z(g-?(N!pZk8&R~*u>c|u-ji57_q+L2Pg-Rpn3?^x}j!dD_2s(pF+M^>=s5FAk zV3PLg$P_A#pfi}HeL6CQN+akDCTYKpOrg>UI)h0%$Pue#3YA9C8BCHhN4$qjq0$JP zeb#=R4oBYFuhZdK|M${d2c5wr9ik&ss5FAkV3H2ikttLfL1!>Yhv~=^Dvh8sn54sX zWD1o=&>2k95jrx3N+akDCh15WnL?!zbOw`jl#WcH(g-?(Njh3brch}Foxvm>qa#zO zG=k1xl8)7pDO4IkXD~^}>Btl+ji57_q~mpD3YA9C8BEd%Ix>YyBj^k!=|mlwLZuOO z29tD>j!dD_2s(pFI$1}iP-z66!6cocBU7j}g3e%)PSueqR2o5NFiEHB$P_A#pfi}H z({*GDl}6AROwt)TGKESb=nN+5OdXj*r4e)nlXRAjOrg>UI)h0%TSul)X#}0YB%Pxp zQ>Zk8&R~+x)sZPw8bN0;N$2Uv6e^9NGnl0Fbz};aM$j2d(giv)g-Rpn3?^xTj!dD_ z2s(pF`mc^mq0$ICgGpMbBU7j}g3e%)7U{?oDvh8sn4}AJWD1o=&>2k9VjY=6r4e)n zle9!frch}Foxvnsq$5+PG=k1xk}lSfDO4IkXD~^Z=*Sc*ji57_q@_ACg-Rpn3?^xr zj!dD_2s(pFTCO8gs5FAkV3Jno$P_A#pfi}Hl{zwoN+akDCh1ZgnL?!zbOw`jnT|}M z(g-?(NxED|rch}Foxvnsp(9hMG=k1xlCIQ|DO4IkXD~@u>Btl+ji57_q^osg3YA9C z8BEeOIx>YyBj^k!=~^9`LZuOO29tE1j!dD_2s(pFx?V@7P-z66!6eUI)h1Cr6W_QG=k1xl2+@;6e^9NGnk|`Ix>YyBj^k!>2@8NLZuOO29tD$j!dD_ z2s(pFx>HA{P-z66!6eUI)h1iP)DXvX#}0YBt4`fQ>Zk8&R~)r z){!Yx8bN0;Nss8r6e^9NGnk}Dbz};aM$j2d(qlR@g-Rpn3?}Ju9hpL<5p)KV^n{K~ zq0$ICgGqW)N2X9|1f9VoJ*6X4s5FAkV3MBJkttLfL1!>Y&*;b$Dvh8sn51WQWD1o= z&>2k9b2>7GN+akDCh2({nL?!zbOw|3f{sj~(g-?(NqSL7rch}Foxvo%q$5+PG=k1x zl3v!4DO4IkXD~^x=*Sc*ji57_q*rxh3YA9C8BEe^Ix>YyBj^k!>2)2MLZuOO29xxL zj!dD_2s(pFdQ(THP-z66!6dzUI)h1CuOm~aG=k1xlHS#kDO4IkXD~?{bYu#ZM$j2d(ncMbLZuOO z29vZ&N2X9|1f9VoZPt+~R2o5NFiBf2k9Rvno_r4e)nleA4orch}Foxvn+ z*O4hy8bN0;Njr383YA9C8BEen9hpL<5p)KVv`a^(P-z66!6fb0kttLfL1!>Ydvs(9 zl}6AROwwK*nL?!zbOw{OPe-OuX#}0YB<oSr#o1O-{!Mlr{n)!g3e%)4$+Y*R2o5NFiD5%$P_A#pfi}H!*pZ{l}6AR zOw!>xGKESb=nN+52pyS1r4e)nlXRqxOrg>UI)h0%N=K$pX#}0YBpt0IQ>Zk8&R~*` z(UB=s8bN0;NyqBQ6e^9NGnk~~bYu#ZM$j2d((yVng-Rpn3?}IW9hpL<5p)KVbfS(- zq0$ICgGo9`N2X9|1f9Voovb5Ms5FAkV3JPJkttLfL1!>Yr|QTQDvh8sn55HmWD1o= z&>2k9={honN+akDCg}_vnL?!zbOw`jrjAUZ(g-?(NjghMrch}FoxvoXts_&YG=k1x zlFreQDO4IkXD~_U>c|u-ji57_r1NxS3YA9C8BEgoIx>YyBj^k!=>i>@LZuOO29vZv zN2X9|1f9Vo{Z~h(P-z66!6YrzkttLfL1!>Yi*#fPl}6AROwxrqGKESb=nN)lv5rik z(g-?(Nm`;KQ>Zk8&R~)*(vc}t8bN0;Nf+zL6e^9NGnk}HbYu#ZM$j2d(o!9nLZuOO z29vZ*N2X9|1f9VoE!UALR2o5NFi9(PWD1o=&>2k9N*$R(r4e)nlXR($Org>UI)h2N zOh=|rX#}0YBwel}Q>Zk8&R~+R(2*%r8bN0;NmuH~6e^9NGnk~SbYu#ZM$j2d($zXL zg-Rpn3?}Is9hpL<5p)KVbghm|q0$ICgGsthN2X9|1f9VoU9Tfks5FAkV3KaokttLf zL1!>YH|od~Dvh8sn53I@WD1o=&>2k9%{nrLN+akDCg~O(nL?!zbOw`jtBy>e(g-?( zNxDr(rch}Foxvon(vc}t8bN0;Nvm~a3YA9C8BEd|9hpL<5p)KVbi0mBq0$ICgGstW zN2X9|1f9Vo-Kir}s5FAkV3O|AkttLfL1!>Yck9R$Dvh8sn527jWD1o=&>2k9y*e_5 zN+akDCh0yMnL?!zbOw`jzm80y(g-?(NqRs>rch}FoxvnMs3TLTG=k1xk{;5LDO4Ik zXD~?*>&O%;ji57_q(^jQ3YA9C8BEfnIx>YyBj^k!=`kIdLZuOO29xx-j!dD_2s(pF zdO}C0P-z66!6ZGYBU7j}g3e%)p3;#iR2o5NFiB7A$P_A#pfi}HXLMu=l}6AROwzMD zGKESb=nN+5IUSior4e)nlk~ifOrg>UI)h1iK}V)gX#}0YB)zC3Q>Zk8&R~*W(vc}t z8bN0;NiXZj6e^9NGnk}TbYu#ZM$j2d(yKZ$g-Rpn3?}I{9hpL<5p)KV^tz5rq0$IC zgGqWrN2X9|1f9Voy{RKps5FAkV3OX_kttLfL1!>YZ|leuDvh8sn51`fWD1o=&>2k9 zS{<1}r4e)nleA7prch}Foxvon*O4hy8bN0;N$={&6e^9NGnk|eIx>YyBj^k!X`_xz zq0$ICgGt(?BU7j}g3e%)HtWa~Dvh8sn4~Q_GKESb=nN)ltBy>e(g-?(N!q3(Q>Zk8 z&R~+Z>&O%;ji57_q#Zgkg-Rpn3?^x(j!dD_2s(pF+NC2?s5FAkV3Kz0$P_A#pfi}H zJvuUlN+akDCTXvZOrg>UI)h2trz2CSG=k1xlJ@J!6e^9NGnk}vVY5|GjkAgGo9>N2X9|1f9Vo9jYT!s5FAkV3H2gkttLf zL1!>YhwI1`Dvh8sn4}|gWD1o=&>2k9kvcMkN+akDCg~_0nL?!zbOw`jw2n-n(g-?( zNjgSHrch}Foxvm>t0PmWG=k1xl8)1nDO4IkXD~^}>&O%;ji57_q!V;x3YA9C8BEfN zIx>YyBj^k!=_DPQLZuOO29tEMj!dD_2s(pFIz>mOP-z66!6cokBU7j}g3e%)PScSo zR2o5NFiEHD$P_A#pfi}HGjwDMl}6AROwyS;GKESb=nN+5EFGCbr4e)nlXSL@Org>U zI)h0%M@ObmX#}0YB%P}xQ>Zk8&R~+x(~&7u8bN0;N$2ax6e^9NGnk|cbYu#ZM$j2d z(gGcsLZuOO29xw(9hpL<5p)KVv`|N;P-z66!6YrxkttLfL1!>Y7wX6qDvh8sn54xz zGKESb=nN)liH=O6(g-?(NxDc!rch}FoxvnstRqvXG=k1xk}lDaDO4IkXD~@ibz};a zM$j2d(lQ;HLZuOO29va0N2X9|1f9Vot2k9r8+W&N+akD zCh0OAnL?!zbOw`jxsFVs(g-?(NxDKurch}FoxvnssUuUUG=k1xlCIK`DO4IkXD~@u z>&O%;ji57_q-%6!3YA9C8BEf(Ix>YyBj^k!={g;mLZuOO29tEXj!dD_2s(pFxYyBj^k! z=?)#4LZuOO29tEBj!dD_2s-2c-7b31AqN~-g99^gU;J^$Vn1KT` za9{=w%)o&eI4}bTX5hdK9GHOvGjL!A4$Q!T88|Ql2WH^F3>=t&12b@71`f=?ff+b3 z1OI=|z=BKu=YRgoLKbl$i&?@&T+AgbWf{v^!AdUWGA`!|uH-7N<{GZ$Il%p*L?V?53iJjqi$%`-g9b3D%ryvR$u z%qzUgYrM`IyvbX<%{#1R9qW0Q4Qyl+o7uuvwy~WZ>|__a*~4D;v7ZG?tvd@@#Dy$o z2^VoOm#~y&EN2BPxs=PeoGZAJtGJqLxR&dELd)dc+7A&*wEMyTEvX~`Y#Kl~~QkJot6|Ce^F5_~p z;7YFIYOdj0uH$-c;6`rZW^UnDZetazS;Otz!JXX2-Q2^y+{gVqz=J%*!#u*HJjUZZ z!IM12(>%koJje6Az>B=Z%e=y?yvFOi!JE9r+q}bC*0G*<*}z6Nv6(GwWgFYs!A^Fu zn?3AhANyIb+`6-nMO?^YmT(ala|ugX#&TA$l1sUa%ejIpxr(c~hHJTw>$!m&xrv*( zgU62#@j@kMjgi@)S?=4A1f$&+`H=@)9re z3a|1Suk!|P@)mFN4r^J*dfsIN8`;EWwy>3LY-a~M*~M=5u$O)8XTb{V&O#P(A&XhU zMO@4!EM*zXS;0y!13bt>Jj^3J%40mv6FkXNJk2va%X2)>3%tlnyv!@S%4@vN8@$O|yv;kTWgY8z zmkn%W6Pww>R<^O79qeQmyV=8D_OYJ@E3G>VS;U1bW(gN@F_*BEWh`d}E4h@*xST7v zlB>9yYq*x{xSkuhk(;=gTey|mSjB4Aa65N!CwFl-_i!)waX%06AP?~{kMJmu@ix7qXZoT*Sp(!cvy8oE5C(QZD0iuHZ_p;%ctpTCU@IZs104;%08) zR&HYzt69VC+`*mP#ogS)z1+wBJivoI#KSzoqddmrJi(JZ#nU{)vpmQ1yugdR#LK+G ztGveRyuq8i#oN5YTGp|iciF&3HnEv4Y-JnU*}+bBv70^YWgq)lu*4YzX#cXAhZa}W1& zANTVB5AqNX^9Yaf7?1M=Px2H`^9;}O9MAItFY*#E^9rx>8n5#PZ}Jvz^A2lS$9mpn z0~^`IX11`EZER-;JK4o<_OO?I>}SDl>&`+JaUqLY!bM!nB`jqb%UQunF6A;V=L)Xm zDz4@luH`ze=LT-%CT`{yZsj&sv6?m9&K=yzUEIw*+{=C3&jUQjLp;nQJj!D{&J#Sz zQ#{QxJj-)D&kMZBOT5f0yvl35&KtbRTfEIXtYsbRd6x}rWD}d&!dAAiogM6C7rWWR zUiPt{1$(SJ3t7a4EM^H8aWR*$lw~Yu1uMCf%eb5?xRR^5nrpb0>$sj9xRIN@Fs8ZHt(>Ob*$%IHn5RRY-S5v*~WHuu#;WvW)FMW$9@*fJjBC1!lOLK<2=EWJjK&I!?Qfc^Sr=|yu{1A!mGT->%766yv5tR!&=s{o_E>6 zMmDjTEo@~Q+u6ZRcCnj1>}4POS+LK#vyeqx$YPdo5f^g_OIgNpR zR1KE+|L6%$U{8LBRtAuJkAq5$x}SdGd#<4JkJZf$Vb5JFI0L>v@+AY-AIg*}_(~v7H_4WEZ>H!(R5WpZ6~Kpa1zkypQ+u0Y1ow z_%I*gqkN2y^9er5r}#9V;j?^>&+`So$d~vsU*W5Kjj!_!zR9=vHs9g9e2?$*1AfSl z_%T1>r~Hhc^9z2-ulO~;;kW#b-}49l$e;K#f8nqEjlc5`{>i`iHwW<_4(1RJ(BdmKOf+Oe25S8 z5kAVt_&A^7lYEL#^BF$N=lDEd;EQ~TFY^_?%GdZh-{6~ki*NHCzRUOcK0n}x{D>d( z6Mo9i_&LAem;8!f^BaE4@Ay4`;E()?Kl2y<%HQ}q|KOkei+^(v|KVT`;ZP3aaE{C%t!br zALHYEf=}`(KFw$NET7}^e1R|WCBDp8_$puH>wJT6@-4p2cla*fjng@UGdYX1IfrvOkMp^J_b#&jypQ+u0Y1ow_%I*gqkN2y z^9er5r}#9V;j?^>&+`So$d~vsU*W5Kjj!_!zR9=vHs9g9e2?$*1AfSl_%T1>r~Hhc z^9z2-ulO~;;kW#b-}49l$e;K#f8nqEjlc5`{>i`iHwW<_4(1RJCvh^Ta4M&9I%jYuXK^;?a4zR@J{R!b#nzwq@qRwQ2l)^m<|BNRkMVIn!6*3? zpXM`sme28dzQ7mx5?|&ke3h^9b-uwj`4->iJA9Y#@qK>45BU*4<|q7=pYd~k!7uq0 zzvegmmf!Jv{=gsk6MyC}{FT4)cmBaY`4|7@ApXO_9KxX-#^D^nksQU*9K*33$MKxN ziJZjAoWiM`#_62FnViMhoWr@C$N5~qdzV;$-pBj-03YN-e3*~$Q9j1U`2?TjQ+%4w z@L4{`=lKF(+ukcmA#@G1<-{f0-oA2;lzQ_0Z0YBtN{FtBcQ+~$J`31k^SNxja z@LPVz@A(6NXLAncavtY%0ZaWKyo}|nU?rC_9kczK+YM}FAN$$r->hwHX9qjk z#cuYnmwoJKhwrbQ>|!^2*vmflbDgjM_1wUX+{De?!mT{bGd#<4JkJZf$U4@uh3)KM zC%f3q9`>@2{jBnLUCkP9=ML`VF7D|;Nt zUF2)P8Jx*koXt6$%Xys71$Zs5gVJ4b@NMp|Vl``chqbI@J@2xCjcj5wTiD7rwzGqs z>|!^2*vmfl^OcKzAMj1S#kYBn=gt%=ji57_q`MvCPo{9X_dA0#Ig7J7hjTfP^SOWp z{FjAnWD}d&!dAAiogM6C7rWWRUiPt{-A{Uqz3gK@)#ve9KSOT>LT{df;T5W@hH_r4u`@{#RAsUAtm;M@Pr{RX-2o!}d%TL9!_hmuLL> z*YFWrCW|216oWqizz$s$NL#o;nOZpUO1B%9)J8K1CYvIvq*akz|6 z+A&!K$)-45#;5FLBWe9n%^ zB1ksH;W9pN$7B&Co8oX8U$A4c2$D^4xQs8_F#fOHpSsGzHi555hR=9a2Y?aW3mX6O>wx4AKEcl1j(j2T*i;=m@I;1Qyebi$97B> zL9!_hm+=!jCW|216oW&F&J$s$NL#o;o3ZpUO1B%9)J8NaY&vIvq* zakz|M+A&!K$)-45#;@#{EP`ZH94_P6c1#vQvMCOi@f$lPiy+w)hs*e_9g{_nY>LBW z{LYTaB1ksH;WB=2$7B&Co8oX8f3Rb+2$D^4xQsvAF%aOq{&*P=wPUgfl1*{A zjEC7VSp>#fOHpSsG9%IL35hR=9a2b!aW3mX6O>wx4$JsGi1j(j2T*l+=m@I;1Qyebi33f~t zL9!_hm(g}i7D2Kp4wvy4c1#vQvMCOi@t1Z?7D2Kp4wvy)c1#vQvMCOi@z-`t7D2Kp z4wvyac1#vQvMCOi@wawN7D2Kp4wvzFc1#vQvMCOi@%MI27D2Kp4wvynJ0^=D*%XJ% zc#<8HMUZTY!(}|#j>#fOHpSsGo?^#j5hR=9a2ZdvW3mX6O>wx4r`a)C1j(j2T*lMw zm@I;1Qyebi8Fow-L9!_hm+?$HCW|216o<=rmK~EtkZg*>Wjx!C$s$NL#o;oZW5;9> zB%9)J8PBz2vIvq*akz}<*)drJ$)-45#`Eo%EP`ZH94_Mpc1#vQvMCOi@j^Q$iy+w) zhs$`89g{_nY>LBWyx5M(B1ksH;WA!g$7B&Co8oX8FSTQ`2$D^4xQv(CFLBWyxES)B1ksH z;WFN0$7B&Co8oX8Z?$8x2$D^4xQw^iFLBWeAtf3B1ksH;W9pA$7B&Co8oX8AGKq$2$D^4xQvh4Fvuy zMUZTY!)1Kgj>#fOHpSsGzGBB@5hR=9a2a2wx4uh}tK1j(j2T*lY!m@I;1 zQyebi8+J?WqjL?$s$NL#o;o(W5;9>B%9)J z8Q-;IvIvq*akz}{*)drJ$)-45#`o=*EP`ZH94_Mrc1#vQvMCOi@k2W%iy+w)hs*ep z9g{_nY>LBW{Me4kB1ksH;WB<=$7B&Co8oX8Kec1B2$D^4xQw6KF?U*crWK$e2;}3RB7D2Kp4wvyqJ0^=D*%XJ% z_>&!zMUZTY!(}|^xYr%`y5nAV-0QppHk;yb84tE&vIvq*akvcc$nyY`g?I9Hulw`6 z^!)i!XXoQG9%{#A5hR=9a2XG?W3mX6O>wx4hubk(1j(j2T*f2pm@I;1Qyebik#e&CW|216o<=rv>lU0kZg*>Wjw}?$s$NL#o;m@YsX{}B%9)J8IQALvIvq* zakz}f+c8-L$)-45#uMzAEP`ZH94@2nm@I;1QyebiFYK5sf@D)1F5@rlm@I;1Qyebi zuk4sCf@D)1F5|E5m@I;1QyebiZ|s;Xf@D)1F5_?Qm@I;1Qyebi@9dZ?f@D)1F5~a* zm@I;1QyebiiFQmDL9!_hm+>S!CW|216o<=rvK^B}kZg*>Wjw`>$s$NL#o;oZYR6;| zB%9)J8BeogvIvq*akz}9+c8-L$)-45#xv}gEP`ZH94_OTc1#vQvMCOi@hm$giy+w) zhs$`j9g{_nY>LBWJjag7B1ksH;WD0U$7B&Co8oX8&$DB)2$D^4xQyr9F#fOHpSsGUTeo>5hR=9a2c<&W3mX6O>wx4f3Rb+2$D^4 zxQu_aW3mX6O>wx4*V{2!1j(j2T*e#hm@I;1Qyebijdn~HL9!_hm+?<_Ocp`1DGrzM zCOamJAlVd$%XqULlSPnhio<2R#g54$NH)dcGTv&(WDz8r;&2&nvtzOdl1*{AjJMk{ zSp>#fO zHpSsG-fPEX5hR=9a2fBjW3mX6O>wx4_uDa91j(j2T*e3Nm@I;1QyebigLX_7L9!_h zm+{YbOcp`1DGrzMAv-3EAlVd$%lNPzlSPnhio<1m#E!`#NH)dcGCpd@WDz8r;&2%s zvtzOdl1*{AjE~zfSp>#fOHpSsGK5NHh5hR=9a2cPoW3mX6O>wx4&)YFs1j(j2T*epdm@I;1 zQyebii*`&FL9!_hm+>V#CW|216oWqies$s$NL#o;o(YR6;|B%9)J z8DFzwvIvq*akz}H+c8-L$)-45#y9MkEP`ZH94_OVc1#vQvMCOi@hv+hiy+w)hs*f3 z9g{_nY>LBWe8-N-B1ksH;WEB!$7B&Co8oX8-?L+~2$D^4xQy@HF#fOHpSsGerv~M5hR=9a2da|W3mX6O>wx4-`g=+1j(j2T*e>l zm@I;1Qyebik9JHJL9!_hm+>b%CW|216o<=r&~>l7?seC_?z-1q_d4%@O>wx42iq}O z1j(j2T!w4h156fyck*_x`}6Or`}3vF&c}GD9g{_nY>LBWJj{;CB1ksH;W8d>$7B&C zo8oX8kFaC12$D^4xQs{IFwx4zqDhr2$D^4xQxHDW3mX6O>wx4zqVtt2$D^4xQxHCW3mX6O>wx4zqMns z2$D^4xQxHEW3mX6O>wx4zqezu2$D^4xQr*-F#fOHpSsGo^Quw5hR=9a2YSKW3mX6O>wx47uqpd1j(j2T*iy+m@I;1Qyebi#db^< zL9!_hm+=xiCW|216o<=rsU4F=kZg*>WxULe$s$NL#o;nuZpUO1B%9)J8LzNovIvq* zakz|E+A&!K$)-45#;fd@EP`ZH94_P4c1#vQvMCOi@ftfOiy+w)hs$`a9g{_nY>LBW zyv~lvB1ksH;WGZgj>#fOHpSsG{?U%fB1ksH;WA!t$7B&Co8oX8Z?I#s2$D^4xQsX2 zFWxUOf$s$NL#o;pEZpUO1B%9)J8Sk)TvIvq*akz|k+A&!K$)-45#=Gp8EP`ZH z94_PCc1#vQvMCOi@g6%Siy+w)hs$`c9g{_nY>LBWyw8rwB1ksH;WFND$7B&Co8oX8 zAFyMx2$D^4xQq|lFWqizz$s$NL#o;nOZpUO1B%9)J8K1CYvIvq*akz|6+A&!K z$)-45#;5FLBWe9n%^B1ksH z;W9pN$7B&Co8oX8U$A4c2$D^4xQs8_F#fO zHpSsGzHi555hR=9a2Y?aW3mX6O>wx4AKEcl1j(j2T*i;=m@I;1Qyebi$97B>L9!_h zm+=!jCW|216oW&F&J$s$NL#o;o3ZpUO1B%9)J8NaY&vIvq*akz|M z+A&!K$)-45#;@#{EP`ZH94_P6c1#vQvMCOi@f$lPiy+w)hs*e_9g{_nY>LBW{LYTa zB1ksH;WB=2$7B&Co8oX8f3Rb+2$D^4xQsvAFwx4N7*r11j(j2 zT*jmAm@I;1QyebiF?LKAL9!_hm+@FTCW|216o<=r+<53yea#;5oGgN5Qyebi@qSJw ziy+w)hs$_^9g{_nY>KD(e8=-L+Lp;8NH)dcGXBDj$s$NL#o;pk(vHa@NH)dcGXBbr z$s$NL#o;pk+K$O0NH)dcGXBPn$s$NL#o;pk){e;{NH)dcGXBnv$s$NL#o_6`j@NVi zy)BbPkZg)){Q2wcc^OZ%WwHp8O>wx4C)qJs1j(j2T*i~_m@NJ^uTS%@^KbBP5`OI8 z@=VWv+w#fOHpSsGUS!8)5hR=9a2YSQW3mX6O>wx4m)J2`1j(j2 zT*gc7m@I;1QyebiWp+#!L9!_hm+^8tCW|216o<=rg&mVckZg*>WxUdk$s$NL#o;nu zWyfR@B%9)J8LzfuvIvq*akz}v*fCiI$)-45#%t}EEP`ZH94_N^c1#vQvMCOi@eg)P z7D2Kp4wvzdc1#vQvMCOi@p?NZiy+w)hs$__9g{_nY>LBWywQ%yB1ksH;WGZoj>#fO zHpSsG-ekvQ5hR=9a2ap5W3mX6O>wx4x7aaR1j(j2T*h1Nm@I;1QyebiZFWo+L9!_h zm+^KxCW|216o<=rhaHnekZg*>WxUgl$s$NL#o;pEWyfR@B%9)J8Sl1ZvIvq*akz~4 z*fCiI$)-45#(V9UEP`ZH94_O1c1#vQvMCOi@qRldiy+w)hs*eY9g{_nY>LBWe9(@` zB1ksH;WGZ&j>#fOHpSsGK4iya5hR=9a2X%AW3mX6O>wx4kJvF;1j(j2T*gQ3m@I;1 zQyebiV|GjyL9!_hm+^5sCW|216oWqi_($s$NL#o;nOWyfR@B%9)J z8K1UevIvq*akz}n*fCiI$)-45#%JxAEP`ZH94_N?c1#vQvMCOi@p(HYiy+w)hs*ea z9g{_nY>LBWe9?}{B1ksH;WEBt$7B&Co8oX8U$$ei2$D^4xQwsZF#fOHpSsGeq_gF5hR=9a2Y?gW3mX6O>wx4pV%>31j(j2T*goB zm@I;1QyebiXLd{$L9!_hm+^BuCW|216oW&F~P$s$NL#o;o3WyfR@ zB%9)J8Naq;vIvq*akz}%*fCiI$)-45#&7MIEP`ZH94_N`c1#vQvMCOi@q0Taiy+w) zhs*eb9g{_nY>LBW{LzldB1ksH;WGYY$7B&Co8oX84|>22@Buf#2iyQ3a07h64e$Xs zK(AQG;W8d<$7B&Co8oX8eka}oOcp`n75dx&?QorZs9)W``k4N>2$D^4xQvI{FEUwHnKukclV!cX}cU*|{sm~ZiIzQH&74&UW_e4p#*8V~n*nf#YN z$A86t&40sx%YVne;9v6J^FOd`|3}aNiT|1Zh45qltLOj5|IYux|H=Qw|IPoy|I7c! zgLp6x;i06z_Fwx4 zN82%31j(j2T*hPUm@I;1Qyebiv35)rL9!_hm+?3|CW|216o<=ryd9H8kZg*>Wjw)- z$s$NL#o;pAj>#fOHpSsG{=$yQB1ksH;WGZxj>#fOHpSsG{>qNYB1ksH;WGZ(j>#fO zHpSsG{>F~UB6z0v8+jJb=G)$T=eeHG-h?Ud?NGEwAGr z_(xvP8+arC#G80CZ{e-Hjkog--pRXoH}B!SypQ+u0Y1n-^C3RWNBAfoU-Bz{ z&2RWEzvK7(fj{zMU+46--xP<-_*;K}m@I;1Qyebi@9dZ?f@D)1F5~a*m@I;1Qyebi ziFQmDL9!_hm+>S!CW|216o<=rvK^B}kZg*>Wjw`>$s$NL#o;oZYR6;|B%9)J8Beog zvIvq*akz}9+c8-L$)-45#xv}gEP`ZH94_OTc1#vQvMCOi@hm$gi|_j9;CuY%{@wm3 z|6KeRp3m_Ne=gY+hs$`jzn;k=NH)dcGM;0{WDz8r;&9ObTLWwjurwm5Pwf@)oU+aIZ|F!wm5Pwf@)oU+aIZ|F!wm5Pwf@)oU+aIZ|F!wm5Pwf@)oU+aIZ z|F!wm5Pwf@)oU+aIZ|F!wcZ+ey#hp?$^3s>wc~K zweHutU+aFI=zgvHweHuNUu%A?`L*WPnqO;vt@*X)*P37JeXaMk-q(6x>wT^Fwcgiy zU+aCX_qE>FdSB~(t@pLw*Lq*;eXaMk-q(6x>wT^FwcgiyU+aCX_qD#)+FomVt?9L< z*Lq&-d9CNQp4WO_>v^4McdgyEUe|hE>vgTywO-eHUF&t7=yk2vwO-eHUF&tN*R@{P zdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN z*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{P zdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN z*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+ zb*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lqz)fL_;nT?cwy>vgTywO-eH zUF&tN*R@{PdR+&4UF&tN*R@{PdR^;vt=F|)*LqzCdR^;vt=F|)*Lq#+b*vgTywO-eHT?cwy>vgTywO-eHU60q=FGy4LGjuWP-o^}5#UTCZ!pt^>WU^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Z zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!p zuJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o1HG>Gy4LGjuWP-o^}5#UTCZ!pt^>WU z^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgC zy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGj zuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#Uda}^#TCZ!p zuJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiY zYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#U zTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T z*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o z^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqht ziC))wUF&tN*L9)SwO-eHUF&tN*R@{PdR^;vt=Dy-*R@{PdR^;vt=F|)*Lq#+b*vgTyb)na_Ue|hE>vgTywO-eHUF&tN*L9)SwO-fblXgrN zL9!_h7rn0ay4LGjuWP-o^}5#Uy3p%duWP-o^}5#UTCZ!puJyXs>$=eETCZ!puJyXs z>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Z zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#Uy3p%d zuWP-o^}5#UTCZ!puJyXs>$=eETCZ!puJyXs>sqgCy{`4T*6X^^>sqgCy{`4T*6UiY zYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#U zTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T z*6UiY>&Zf|YrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGj zuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs z>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Z zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!p zuJyXs>sqgCy{`4T*6UiYYrU@Zy4LGjuWP-o^}5#UTCZ!puJyXs>sqgCy{`4T*6UiY zYrU@Zy4LGjuWP-o^}1f@b*sqgCy{`4T*6UiY>y2L5dR^;vt=F|) z*Lq#+b*sqgCy{`4T*6UiYYrU>FdR^;vt=F|)*Lq#+b*>sqht@k=`sqgCy{`4T z-sp9$*R@{PdR^;vt=F|)*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|) z*Lq#+b*vgTywO-eHUF&tN*R@{PdR^;vt=F|)*Lq#+b*vgTy zwO-eHUF&td(d$~TYrU@Zy4LGjuWP-o^}5#UdZX91Ue|hE>vgTywO-eHUF&tN*Y!rP zYrU@Zy4LI5>mG2gd%(T!0r$EG-0L22uk#K>=ymROE-w$ZL$7nMvqP_Qud_q1bFZ`W z$_jd&dz~G6oqL@fdYyZn9eSO6ogI3edz~G6oqL@fdYyZn9eSO6ogI3edz~FRoqL_# z!|l-5-0SSnyWH#S(6`*{>>go|&_c}ZDE%!RR zN7Mg@**)40eapSh4t>kL&JKOcz0U42cIaE~b#~}m?sazPTkdss zkF`VJa<8*P-*T_BL*H_*vwNH!`j&g09r~7gogMm?d!60m?a;T}>+I0C-0SSnx7_RO zo?wT*|& z_c}ZDE%!P*5`D|P&JKOcz0MAO%e~HyMBj3+vqRr+I0C z-0SQ}bQbqIJ9HNJIy-b0_c}WgoyEP*4xPol&JLZ$z0QtAXK}ByLuYZXvqNWbud_pE zaj&yOXK}Byd!ijWi+i0NI*WUq9XgA9o!yh{&{^E;?9f@<>+H~3-0SR~Y=_R`UT25S z;$CNm&f;EY_Y^yH7WX+GIwho0hIXNR8RUT24%;$CO>96R(B_c}ZD z6!$ti^c43xyXV?5Sp>7D2Kp4wvx)J0^=D*%XJ%c%dDW zMUZTY!)3h4j>#fOHpSsGUTnu?5hR=9a2YSLW3mX6O>wx4m)bE|1j(j2T*k}nm@I;1 zQyebi<#tRKL9!_hm+=ZaCW|216o<=rr5%$+kZg*>WxUFc$s$NL#o;nuZO3F0B%9)J z8LzQpvIvq*akz}v+A&!K$)-45#_Q~uEP`ZH94_M@?3gTqWK$e2;~(vqEP`ZH94_Pa zc1#vQvMCOi@di64iy+w)hs$`Q9g{_nY>LBW{F5D%MUZTY!)3h5j>#fOHpSsG-fYKY z5hR=9a2ap0W3mX6O>wx4x7smT1j(j2T*lk%m@I;1Qyebi?RHESL9!_hm+=leCW|21 z6o<=rryY|;kZg*>WxUId$s$NL#o;pEZO3F0B%9)J8Sk-UvIvq*akz~4+A&!K$)-45 z#{2A;EP`ZH94_Pic1#vQvMCOi@c}y~iy+w)hs*e&9g{_nY>LBW{IeaCMUZTY!)1KP zj>#fOHpSsGK5WNi5hR=9a2X%5W3mX6O>wx4kJ>R=1j(j2T*k-jm@I;1Qyebi<919I zL9!_hm+=WZCW|216oWqitx$s$NL#o;nOZO3F0B%9)J8K1FZvIvq* zakz}n+A&!K$)-45#^>yqEP`ZH94_PYc1#vQvMCOi@dZ03iy+w)hs*e)9g{_nY>LBW ze94Zx;}S z){k^-4woP)nqmD|$L4SelA;;bPjqY!mmn#cVf|Fc=5Ps;q8ZlDbZicnASs$*{anZ9 za0!y48P+d!Yz~(oDVkyZQpe_S36i22)~|GI4woP)nqmD~$L4SelA;;bZ**)9mmn#c zVf|Le=5Ps;q8ZljbZicnASs$*{a(lBa0!y48P*?kYz~(oDVkyZQOD+R36i22)}M52 z4woP)nqmD}$L4SelA;;bUvz8^mmn#cVf|Id=5Ps;q8ZlTbZicnASs$*{awfAa0!y4 z8P-2^Yz~(oDVkyZQ^)3T36i22*1vRY4woP)nqmE0$L4SelA;;be{^gPmmn#cVLiyA z!sc)ZlA;;bgLP~Ummn#cVfhu*|6y~u1c?*1>~%W4`ERe&akvCY(G2UMIyQ$(kQB|Z z9;Rb+xCBYj4C~=KHit`)6wR<6p<{En1WC~h>ybJ(hf9zY&9EM&V{^C!Nzn}J(KnHit`)6wR=nrekxs1WC~h>*+c+hf9zY&9I)KV{^C!Nzn}JnL0Ly zOOO=Ju%4x3bGQUa(G2U^IyQ$(kQB|Zo}*)PxCBYj4C}c%Hit`)6wR=nr(<)t1WC~h z>-jo1hf9zY&9GjeV{^C!Nzn}Jg*rBeOOO=JuwJBNbGQUa(G2UwIyQ$(kQB|ZUZP`j zxCBYj4C|#jHit`)6wR<+rekxs1WC~h>*YE&hf9zY&9GjfV{^C!Nzn}Jl{z+uOOO=J zuwJEObGQUa(G2U=IyQ$(kQB|ZUZZ1kxCBYj4C}QzHit`)6wR<+r(<)t1WC~h>-9P| zhf9zY&9L5}V{^C!Nzn}JjXE}mOOO=Ju->F&bGQUa(G2U&IyQ$(kQB|Z-lAi3xCBYj z4C}2rHit`)6wR>Srekxs1WC~h>+L!=hf9zY&9L5~V{^C!Nzn}JojNv$OOO=Ju->I( zbGQUa(G2U|IyQ$(kQB|Z-lJo4xCBYj4C}o*Hit`)6wR>Sr(<)t1WC~h>-{=5hf9zY z&9FY8V{^C!Nzn}JgE}^cOOO=Jus)*G2$hf9zY&9FY9V{^C!Nzn}JlR7qsOOO=Jus)?@bGQUa z(G2U;IyQ$(kQB|ZKBHrExCBYj4C}KxHit`)6wR+?D`hf9zY&9J_p zV{^C!Nzn}Ji#j%kOOO=Ju)d^YbGQUa(G2U$IyQ$(kQB|ZzM^AuxCBYj4C|{pHit`) z6wR={rekxs1WC~h>+3o;hf9zY&9J_qV{^C!Nzn}Jn>sd!OOO=Ju)d{ZbGQUa(G2U` zIyQ$(kQB|ZzN2GvxCBYj4C}i(Hit`)6wR={r(<)t1WC~h>-#!3hf9zY&9Hu;V{^C! zNzn}JhdMTgOOO=JuzsXtbGQUa(G2UyIyQ$(kQB|ZexhS@xCBYj4C|*lHit`)6wR=H zrekxs1WC~h>*qQ)hf9zY&9Hu-Rb~hf9zY&9MHUV{^C!Nzn}J zk2*GoOOO=Ju>PcDbGQUa(G2U)IyQ$(kQB|Z{-R@ZxCBYj4C}8tHit`)6wR>yrekxs z1WC~h>+d=?hf9zY&9MHVV{^C!Nzn}JpE@>&OOO=Ju>PfEbGQUa(G2U~IyQ$(kQB|Z z{-a}axCBYj4C_JOeqwXD1WC~h>%lrUhf9zY&9IzU^gnD4mmn#esAaFy{r6V|bp9SL zK~glsdZ_=$=5Ps;q8Zl1bZicnASs$*JzU4;a0!y48P+3oYz~(oDVkwDQpe_S36i22 z)}wT64woP)nqfU!$L4SelA;;bV{~i|mmn#cVLevI=5Ps;q8ZlXbZicnASs$*JzmG= za0!y48NAhLuha2=*Cj}bW>`-&MB}j^9SWnWiIb4FIXomG<9h<`? zNQ!1yPtmbCT!N%%hV_7s&EXOxMKi3Y>ew7EK~glsdYX>S;SwZ8GpwiU*c>iFQZ&PQ zhK|kQ5+p@4tY_-j94!+MU6&EXOxMKi4D>ew7E zK~glsdY+EW;SwZ8Gpy(9*c>iFQZ&PQfsW1L5+p@4tQYFo94!+MF1&EXOxMKi3I>ew7EK~glsdYO*R;SwZ8Gpv{E*c>iFQZ&PQg^tbP z5+p@4tXJyT94!+MR5&EXOxMKi3|>ew7EK~gls zdYz8V;SwZ8GpyI^*c>iFQZ&PQgO1JN5+p@4tT*b|94!+ML3&EXOxMKi3o>ew7EK~glsdYg{T;SwZ8Gpx7k*c>iFQZ&PQhmOtR5+p@4 ztas|z94!+MX7&EXOxMKi4T>ew7EK~glsdY_KX z;SwZ8GpzUP*c>iFQZ&Q*fR4@K5+p@4tPkqg94 z!}^Gh&EXOxMKi3A>ew7EK~gls`k0Q*;SwZ8Gpvv6*c>iFQZ&Q*gpSSO5+p@4tWWCL z94!}^Sl&EXOxMKi3=>ew7EK~gls`kao<;SwZ8 zGpx_+*c>iFQZ&Q*f{xAM5+p@4tS{==94!}^Mj z&EXOxMKi3g>ew7EK~gls`kIc-;SwZ8Gpw)c*c>iFQZ&Q*hK|kQ5+p@4tZ(Yr94!}^Yn&EXOxMKi4L>ew7EK~gls`ks!>;SwZ8Gpz6H z*c>iFQZ&Q*fsW1L5+p@4tRL#w94!}^Ji&EXOx zMKi3Q>ew7EK~gls`k9W+;SwZ8GpwKM*c>iFQZ&Q*g^tbP5+p@4tY7Nb94!}^Vm&EXOxMKi45>ew7EK~gls`kju=;SwZ8Gpyh1*c>iF zQZ&Q*gO1JN5+p@4tUv1594!}^Pk&EXOxMKi3w z>ew7EK~gls`kRi;;SwZ8GpxVs*c>iFQZ&Q*hmOtR5+p@4tbgj*94!}^bo&EXOxMKi1i`BIV1;SwZ8Gpq;e*c>iFQZ&PIy7>RFIb4FI zXq>2JuhX$PT!N%%hV@V#o5LkYie^|3)3G^Rf~07M^>7`V!zD}BVu{m6Vq-ciq zNFAHQB}j^9SdY@NIb4FIXomG@9h<`?NQ!1ykI}I?T!N%%hV@t-o5LkYie^}k)3G^R zf~07M^>`hd!zD!+N5Q&EXOxMKi1?>DU}D zK~glsda{nq;SwZ8GpwiR*c>iFQZ&PQK*#2A36i22)>CzC4woP)nqfUn$L4SelA;;b z({*ePmmn#cVLd~~=5Ps;q8ZjRb!-loASs$*Jxj;ta0!y48P>CPYz~(oDVkwDN5|%H z36i22)^l}i4woP)nqfUp$L4SelA;;b^L1ve1nmmn#cVZA}e=5Ps;q8Zj3b!-loASs$*y-COB za0!y48P=P1Yz~(oDVkxuMaSlF36i22)?0OK4woP)nqj?7$L4SelA;;b+jVRXmmn#c zVZB4g=5Ps;q8ZjZb!-loASs$*y-UaDa0!y48P>aXYz~(oDVkxuN5|%H36i22)_Zkq z4woP)nqj?9$L4SelA;;b`*my%mmn#cVSPZy=5Ps;q8Zi)b!-loASs$*eMraVa0!y4 z8Pn0G4woP)nqhrS$L4SelA;;b*L7?Tmmn#cVSPi#=5Ps; zq8ZjVb!-loASs$*eM`sYa0!y48P>OTYz~(oDVkw@N5|%H36i22)^~Mm4woP)nqhrU z$L4SelA;;b_jPOzmmn#cVf{eI=5Ps;q8Zi?b!-loASs$*{Yb~=a0!y48P<<=Yz~(o zDVkyZM91cE36i22)=zb84woP)nqmD+$L4SelA;;b&vk4Lmmn#cVf{kK=5Ps;q8ZjN zb!-loASs$*{YuB?a0!y48P>0LYz~(oDVkyZM#tuG36i22)^Bxe4woP)nqmD;$L4Se zlA;;b?{#brmmn#cVf{hJ=5Ps;q8Zj7b!-loASs$*{Yl5>a0!y48P=b5Yz~(oDVkyZ zMaSlF36i22)?amO4woP)nqmD-$L4SelA;;b-*s#bmmn#cVf{nL=5Ps;q8Zjdb!-lo zASs$*{Y%H@a0!y48P>mbYz~(oDVkyZN5|%H36i22)`P-c7xuca*M+?<>~&$U3wvGI z>%v|a_BtJ#!zD^o=u{m6Vq-X}GU)k$)94 z!+N-m&EXOxMKi2N=-3=CK~glsdZdoc;SwZ8GptAH*c>iFQZ&PQw2sZ;5+p@4tjFls z94!+N}q&EXOxMKk!dM0=eMOY#4D`u=;Rd(jN* z2|6~1OOO=Ju%4)6bGQUa(G2TJIyQ$(kQB|Zo~&bYxCBYj4C^U6Hit`)6wR<6(6KpO zf~07M^;8|3!zD`xy^ zB}j^9STE4AIb4FIXomGd9h<`?NQ!1yFVe9&T!N%%hV^0{o5LkYie^|Z(XlyPf~07M z^->+1!zD_!Nu{m6Vq-ciqavht)B}j^9Sg+8rIb4FIXomGl9h<`?NQ!1yuhOwO zT!N%%hV^P4o5LkYie^}^(XlyPf~07M^;#X9!zD~M&u{m6Vq-ciqdL5g?B}j^9 zSZ~m=Ib4FIXomGh9h<`?NQ!1yZ_=?jT!N%%hV^D0o5LkYie^}E(XlyPf~07M^;R95 z!zD|02u{m6Vq-ciqb{(6;B}j^9SntrWIb4FIXomGp9h<`?NQ!1y@6xe3T!N%% zhV^b8o5LkYie^~v(XlyPf~07M^_E7u{m6Vq-ciqaUGk(B}j^9Sf9|bIb4FIXomGk9h<`?NQ!1ypVF~8T!N%%hV^M3 zo5LkYie^}!(XlyPf~07M^;sR8!zD}xou{m6Vq-ciqc^#X>B}j^9SYObwIb4FI zXomGg9h<`?NQ!1yU(&HTT!N%%hV^9~o5LkYie^|}(XlyPf~07M^;I34!zD{a- zu{m6Vq-ciqbsd|-B}j^9Sl`gGIb4FIXomGo9h<`?NQ!1y-_o%;T!N%%hV^Y7o5LkY zie^~f(XlyPf~07M^<5pC!zD`Pdu{m6V zq-ciqa~+$*B}j^9SijJ*Ib4FIXomGm9h<`?NQ!1yztXWeT!N%%hV^S5o5LkYie^~9 z(XlyPf~07M^;;dA!zD~+|u{m6Vq-ciqdmWp@B}j^9Sbxy5Ib4FIXomGi9h<`? zNQ!1yf6}ozT!N%%hV^G1o5LkYie^}U(XlyPf~07M^;aF6!zD|mIu{m6Vq-ciq zcO9F%#oB}j^9SP#*$Ib4FIXa*!+NNW&EXOx zMKi32>DU}DK~glsdbp0w;SwZ8GptAG*c>iFQZ&PQq>jzu5+p@4tVikC94!+NZa&EXOxMKi3&>DU}DK~glsdc2O!;SwZ8GdS7AUZ=xb zo%T8%|92J5u%4h}bGQUa(G2T}IyQ$(kQB|Zo}^=QxCBYj4C~1{Hit`)6wR=nqGNNo z1WC~h>j52`!zD`#Ho5LkYie^|Z*0DKUf~07M z^%5PM!zD_!Pu{m6Vq-ciqG98=4B}j^9STEPHIb4FIXomF)9h<`?NQ!1yuhg+Q zT!N%%hV?2Po5LkYie^}^*0DKUf~07M^%@~M)u{m6Vq-ciqIvtzCB}j^9 zSg+TyIb4FIXomF$9h<`?NQ!1yZ`83lT!N%%hV>>Lo5LkYie^}E*0DKUf~07M^%fnQ z!zD|04u{m6Vq-ciqHXWP8B}j^9SZ~*{Ib4FIXomF;9h<`?NQ!1y@6@q5T!N%% zhV?ETo5LkYie^~v*0DKUf~07M^&TCY!zDyGo5LkYie^|J*0DKUf~07M^${JL!zD_E9u{m6Vq-ciqF&&%3B}j^9SRdE1Ib4FIXomF(9h<`?NQ!1ypVYBAT!N%%hV>~O zo5LkYie^}!*0DKUf~07M^%)(T!zD}xqu{m6Vq-ciqIUSqBB}j^9SfAIiIb4FI zXomF#9h<`?NQ!1yU(~TVT!N%%hV>;Ko5LkYie^|}*0DKUf~07M^%WhP!zD{a< zu{m6Vq-ciqH65G7B}j^9SYOw%Ib4FIXomF-9h<`?NQ!1y-_)@=T!N%%hV?BSo5LkY zie^~f*0DKUf~07M^&K6X!zD&Io5LkYie^|p*0DKUf~07M^%EVN!zD`Pfu{m6V zq-ciqGaZ}5B}j^9SU=aXIb4FIXomF*9h<`?NQ!1yztpigT!N%%hV?5Qo5LkYie^~9 z*0DKUf~07M^&1_V!zD~+~u{m6Vq-ciqI~|+DB}j^9Sije?Ib4FIXomF%9h<`? zNQ!1yf7G!#T!N%%hV>^Mo5LkYie^}U*0DKUf~07M^%otR!zD|mKu{m6Vq-ciq zHyxY9B}j^9Sbx{CIb4FIXomF<9h<`?NQ!1y|J1QLT!N%%hV?HUo5LkYie^~<*0DKU zf~07M^&cIZ!zD^n$S|^*sB}j^9SP#~*Ib4FIXomF=9h<`?NQ!1y|4+x}a0!y4 z8P-E}Yz~(oDVkwDOvmPM36i22*28sd4woP)nqfUc$L4SelA;;bBXw*Jmmn#cVLeL6 z=5Ps;q8Zksb!-loASs$*Jx0goa0!y48P;QUYz~(oDVkwDPRHhO36i22*5h?-4woP) zn!zc=_BtKDz_!=v@bvxnYWHD1LC5BB36i22))RGX4woP)nqfUj$L4SelA;;blXYwk zmmn#cVLe61=5Ps;q8Zi$IyQ$(kQB|Zo~mPWxCBYj4C`q+Hit`)6wR=nu48k!1WC~h z>lr#Whf9zY&9I)SV{^C!Nzn}JSvod{OOO=Ju%4}BbGQUa(G2T3IyQ$(kQB|Zo~vVX zxCBYj4C{G1Hit`)6wR=nuVZt#1WC~h>jgSChf9zY&9GjmV{^C!Nzn}JMLITzOOO=J zuwJZVbGQUa(G2S)IyQ$(kQB|ZUaDhrxCBYj4C`e&Hit`)6wR<+u48k!1WC~h>lHdS zhf9zY&9GjnV{^C!Nzn}JRXR3@OOO=JuwJcWbGQUa(G2S~IyQ$(kQB|ZUaMnsxCBYj z4C{3|Hit`)6wR<+uVZt#1WC~h>kT?Khf9zY&9L66V{^C!Nzn}JO*%G*OOO=Ju->d= zbGQUa(G2S?IyQ$(kQB|Z-l}7BxCBYj4C`$=Hit`)6wR>Su48k!1WC~h>m52ahf9zY z&9L67V{^C!Nzn}JT{g>bGQUa(G2T7IyQ$(kQB|Z-m7DCxCBYj4C{S5 zHit`)6wR>SuVZt#1WC~h>jOGAhf9zY&9FYGV{^C!Nzn}JLpnBxOOO=Jus*C~bGQUa z(G2S&IyQ$(kQB|ZKB{ALxCBYj4C`Y$Hit`)6wRk~RQhf9zY&9FYH zV{^C!Nzn}JQ#v+>OOO=Jus*G0bGQUa(G2S|IyQ$(kQB|ZKC5GMxCBYj4C`|`Hit`) z6wRkB$Ihf9zY&9J_xV{^C!Nzn}JOFA}(OOO=Ju)eHgbGQUa(G2S= zIyQ$(kQB|ZzN%w$xCBYj4C`w;Hit`)6wR={u48k!1WC~h>l->Yhf9zY&9J_yV{^C! zNzn}JTRJv}OOO=Ju)eKhbGQUa(G2T5IyQ$(kQB|ZzN=$%xCBYj4C{M3Hit`)6wR={ zuVZt#1WC~h>jyeEhf9zY&9Hu`V{^C!Nzn}JM>;l#OOO=Juzsv#bGQUa(G2S+IyQ$( zkQB|ZeyU@0xCBYj4C`k)Hit`)6wR=Hu48k!1WC~h>lZpUhf9zY&9Hu{V{^C!Nzn}J zS2{L_OOO=Juzsy$bGQUa(G2T1IyQ$(kQB|Zeyd}1xCBYj4C{9~Hit`)6wR=HuVZt# z1WC~h>km3Mhf9zY&9MHcV{^C!Nzn}JPdYY-OOO=Ju>P!LbGQUa(G2S^IyQ$(kQB|Z z{;FehxCBYj4C`+?Hit`)6wR>yu48k!1WC~h>mNEchf9zY&9MHdV{^C!Nzn}JUph92 zOOO=Ju>P%MbGQUa(G2T9IyQ$(kQB|Z9@O?ar*(3;1WC~h>%lrUhf9zY&9EM#V{^C! zNzn}J|LNEqE!+NNW&EXOxMKi32>DU}DK~glsdbp0w;SwZ8GptAG*c>iFQZ&PQ zq>jzu5+p@4tVikC94!+NZa&EXOxMKi3&>DU}D zK~glsdc2O!;SwZ8Gc0e=Ifd9>r^6T6_BtJ&zW-k1zMi0CbGQUa(G2T}IyQ$(kQB|Z zo}^=QxCBYj4C~1{Hit`)6wR=nqGNNo1WC~h>j52`!zD`#Ho5LkYie^|Z*0DKUf~07M^%5PM!zD_!PvHAZT-Nh0GJC3f=S5jG$ zZ9QIfG50BEW@ct)W@cvQxa)Q})*gMs9R1@;4woTbrDKs4&E{|!;?+79NzrT$mmyxGW04fi=5QI}wK^6_(QFQvAzr6r zkrd75a2ewDIu=RMYz~(p-k@WV6wT&v8RCsP7D>@;4woU`q+^j3&E{|!;>|i1NzrT$ zmm%JwW04fi=5QI}tvVJ-(QFQvA>O8Akrd75a2ew5Iu=RMYz~(p-l1cW6wT&v8RDHf z7D>@;4woU`rDKs4&E{|!;@vtHNzrT$mm%JxW04fi=5QI}y*d_2(QFQvA>OBBkrd75 za2ewLIu=RMYz~(pKA>Zf6wT&v8RCOF7D>@;4woT5q+^j3&E{|!;=?)?NzrT$mmxl) zW04fi=5QI}qdFEz(QFQvAwH&Kkrd75a2ev`Iu=RMYz~(pKA~fg6wT&v8RC;V7D>@; z4woT5rDKs4&E{|!;?p`7NzrT$mmxl*W04fi=5QI}vpN<@(QFQvAwH*Lkrd75a2ewB zIu=RMYz~(pzMx}~6wT&v8RCmN7D>@;4woUmq+^j3&E{|!;>$V~NzrT$mm$8QW04fi z=5QI}t2!1*(QFQvA-<+#krd75a2ew3Iu=RMYz~(pzM*506wT&v8RDBd7D>@;4woUm zrDKs4&E{|!;@dhFNzrT$mm$8RW04fi=5QI}yE+z0(QFQvA-<<$krd75a2ewJIu=RM zYz~(pexPHK6wT&v8RCaJ7D>@;4woT*q+^j3&E{|!;>S7`NzrT$mmz+lW04fi=5QI} zr#co%(QFQvA%3P~krd75a2ev~Iu=RMYz~(pexYNL6wT&v8RC~Z7D>@;4woT*rDKs4 z&E{|!;@3JBNzrT$mmz+mW04fi=5QI}w>lO{(QFQvA%3T0krd75a2ewFIu=RMYz~(p z{-9%#6wT&v8RCyR7D>@;4woVRq+^j3&E{|!;?Fu3NzrT$mm&V5W04fi=5QI}uR0b< z(QFQvA^xUgkrd75a2ew7Iu=RMYz~(p{-I-$6wT&v8RDNh7D>@;4woVRrDKs4&E{|! z;@>(JNzrT$mm&V6W04fi=5QI}zd9C4(QFQvAs#&Ty0O>!S|>%bIb4SLA03ONXf}t- z5D(F@NQ!22xD4@79gC!BHiyd)57V(oie_`T4DoOsi==2ahszL;(6LC0W^=d<@kkwu zq-ZvW%Mg#!u}F$$bGQugXdR2BXf}t-5RcKZNQ!22xD4@F9gC!BHiyd)kJGV8ie_`T z4Dom!i==2ahszL8(6LC0W^=d<;r85v@D*ZvosPz>PJ5k>|9|2E9gC!BHiyd)Pt>tU zie_`T4Dlo#i==2ahszL8*0D&6W^=d<@f014q-ZvW%Mef1u}F$$bGQugG#!hiXf}t- z5Kq^!NQ!22xD4?O9gC!BHiyd)&(yICu}F$$bGQugIvtCoXf}t-5U`3q-ZvW%Md@+u}F$$bGQugGaZYhXf}t-5I@(kNQ!22xD4?N9gC!BHiyd) zztpivie_`T4Dl-+i==2ahszMZ*0D&6W^=d<@f#hBq-ZvW%MicSu}F$$bGQugI~|Lp zXf}t-5Wm;4NQ!22xD4?J9gC!BHiyd)f7G!^ie_`T4Dlx&i==2ahszLu*0D&6W^=d< z@fRJ7q-ZvW%MgFnu}F$$bGQugHyw+lXf}t-5P#RPNQ!22xD4?R9gC!BHiyd)|J1Qa zie_`T4Dl}=i==2ahszNE*0D&6W^=d<@gE(Fq-ZvW%Mkz7u}F$$bGQug;CSFcERv$x z94xWr#=VSR_TWIb4Q#w2nnmG@HX^h{xzyBt^41T!wh8jzv;5 zo5N*@$LUxkMYB0vhIqV=MN%}I!)1sk=vX90vpHObu*5xxMN%~0z<$83&Ic^T4|w_> z`2XiYERv$x94M{ERv$x94bS#ph z*&HrId|byODVojUGQ=lzERv$x94A@ERv$x94Z0ERv$x94wK+~&EYb{|L9mGMYB0vhIojMMN%}I!)1tv>R2R2 zvpHObc$khwQZ$>xWr&CCSR_TWIb4Q#gpNg0G@HX^h)3#JBt^41T!wg*jzv;5o5N*@ zN9$N5MYB0vhIovQMN%}I!)1ua>R2R2vpHObc$|(!QZ$>xWr)Y?SR_TWIb4Q#f{sN} zG@HX^2)E`Q#3Csg|ElxWr!#0SR_TWIb4Q#l8!}E zG@HX^h$rhsTa3vpHOb zc!rKeQZ$>xWr%0$SR_TWIb4Q#mX1YIG@HX^h-d3qBt^41T!wg#jzv;5o5N*@=jvD_ zMYB0vhIpQiMN%}I!)1u)>sTa3vpHObc!7>ZQZ$>xWr!E*SR_TWIb4Q#k&Z=DG@HX^ zh!^WvBt^41T!wgwjzv;5o5N*@m+Dv~MYB0vhIpBdMN%}I!)1t<>sTa3vpHObc!iEd zQZ$>xWr$bmSR_TWIb4Q#m5xPHG@HX^h*#@aBt^41T!wg!jzv;5o5N*@*Xmd#MYB0v zhIpNhMN%}I!)1uq>sTa3vpHObc!Q2bQZ$>xWr#QGSR_TWIb4Q#la57FG@HX^h&St4 zBt^41T!wgyjzv;5o5N*@x9V6VMYB0vhIpHfMN%}I!)1uK>sTa3vpHObc!!QfQZ$>x zWr%m`SR_TWIb4Q#myShJG@HX^hsTa3vpHOb_<)W@QZ$>xWrz>zSR_TWIb4SLkd8%CG@HX^h!5*nBt^41 zT!#3Fjzv;5o5N*@kLp+?MYB0vhWMC{MN%}I!)1t%>sTa3vpHOb_=Ju{QZ$>xWr$De zSR_TWIb4SLl#WGGG@HX^h)?TSBt^41T!#3Jjzv;5o5N*@&+1qtMYB0vhWMP0MN%}I z!)1ui>sTa3vpHOb_=1i_QZ$>xWr#28SR_TWIb4SLl8!}EG@HX^h%f6{Bt^41T!#3H zjzv;5o5N*@uj*JNMYB0vhWMI}MN%}I!)1uC>sTa3vpHOb_=b)}QZ$>xWr%O;SR_TW zIb4SLmX1YIG@HX^h;QpyBt^41T!#3Ljzv;5o5N*@@9J12MYB0vhWMV2MN%}I!)1u? z>sTa3vpHOb_<@c^QZ$>xWr!c@SR_TWIb4SLk&Z=DG@HX^h#%`%Bt^41T!#3Gjzv;5 zo5N*@pXyj7MYB0vhWMF|MN%}I!)1t{>sTa3vpHOb_=S!|QZ$>xWr$zuSR_TWIb4SL zm5xPHG@HX^h+peiBt^41T!#3Kjzv;5o5N*@-|AQ-MYB0vhWMS1MN%}I!)1uy>sTa3 zvpHOb_=Ao`QZ$>xWr#oOSR_TWIb4SLla57FG@HX^h(GICBt^41T!#3Ijzv;5o5N*@ zzv@^dMYB0vhWML~MN%}I!)1uS>sTa3vpHOb_=k=~QZ$>xWr%<3SR_TWIb4SLmyShJ zG@HX^h=1!?Bt^41T!#3Mjzv;5o5N*@|LRyIMYB0vhIp{0ghf&`o5N*@|Ix8Xie_`T z4Dk>hi==2ahszKT)v-v5W^=d<@h}~Wq-ZvW%McIOu}F$$bGQug2px;0Xf}t-5RcTc zNQ!22xD4?q9gC!BHiyd)kJhnBie_`T4DlEpi==2ahszL;)v-v5W^=d<@i-leq-ZvW z%Mg#(u}F$$bGQug1RaZ{Xf}t-5dW)Vkra(DpxEnlxc&KnMfm|w>HnSdTQr-)Wr!#0 zSR_TWIb4Q#l8!}EG@HX^h$rhsTa3vpHObc!rKeQZ$>xWr%0$SR_TWIb4Q#mX1YIG@HX^h-d3qBt^41T!wg# zjzv;5o5N*@=jvD_MYB0vhIpQiMN%}I!)1u)>sTa3vpHObc!7>ZQZ$>xWr!E*SR_TW zIb4Q#k&Z=DG@HX^h!^WvBt^41T!wgwjzv;5o5N*@m+Dv~MYB0vhIpBdMN%}I!)1t< z>sTa3vpHObc!iEdQZ$>xWr$bmSR_TWIb4Q#m5xPHG@HX^h*#@aBt^41T!wg!jzv;5 zo5N*@*Xmd#MYB0vhIpNhMN%}I!)1uq>sTa3vpHObc!Q2bQZ$>xWr#QGSR_TWIb4Q# zla57FG@HX^h&St4Bt^41T!wgyjzv;5o5N*@x9V6VMYB0vhIpHfMN%}I!)1uK>sTa3 zvpHObc!!QfQZ$>xWr%m`SR_TWIb4Q#myShJG@HX^hsTa3vpHOb_<)W@QZ$>xWrz>zSR_TWIb4SLkd8%C zG@HX^h!5*nBt^41T!#3Fjzv;5o5N*@kLp+?MYB0vhWMC{MN%}I!)1t%>sTa3vpHOb z_=Ju{QZ$>xWr$DeSR_TWIb4SLl#WGGG@HX^h)?TSBt^41T!#3Jjzv;5o5N*@&+1qt zMYB0vhWMP0MN%}I!)1ui>sTa3vpHOb_=1i_QZ$>xWr#28SR_TWIb4SLl8!}EG@HX^ zh%f6{Bt^41T!#3Hjzv;5o5N*@uj*JNMYB0vhWMI}MN%}I!)1uC>sTa3vpHOb_=b)} zQZ$>xWr%O;SR_TWIb4SLmX1YIG@HX^h;QpyBt^41T!#3Ljzv;5o5N*@@9J12MYB0v zhWMV2MN%}I!)1u?>sTa3vpHOb_<@c^QZ$>xWr!c@SR_TWIb4SLk&Z=DG@HX^h#%`% zBt^41T!#3Gjzv;5o5N*@pXyj7MYB0vhWMF|MN%}I!)1t{>sTa3vpHOb_=S!|QZ$>x zWr$zuSR_TWIb4SLm5xPHG@HX^h+peiBt^41T!#3Kjzv;5o5N*@-|AQ-MYB0vhWMS1 zMN%}I!)1uy>sTa3vpHOb_=Ao`QZ$>xWr#oOSR_TWIb4SLla57FG@HX^h(GICBt^41 zT!#3Ijzv;5o5N*@zv@^dMYB0vhWML~MN%}I!)1uS>sTa3vpHOb_=k=~QZ$>xWr%<3 zSR_TWIb4SLmyShJG@HX^h=1!?Bt^41T!#3Mjzv;5o5N*@|LRyIMYB0vhIp`BO)Qe4 z*&HrI{Ev=BQZ$>xWr&C9SR_TWIb4Q#sE$QaG@HX^h==J|Bt^41T!whKjzv;5o5N*@ zN9b52MYB0vhIpioMN%}I!)1s^=~yI1vpHObc(jg1QZ$>xWr)YkdqS+iSLp)!{A}N~9;WESvbS#ph z*&HrIyims?DVojUGQ^8?ERv$x94vSxVqS+iSL%d$cA}N~9;WES;_DVojUGQ_)dERv$x94bGQug#Io1vNQ!22xD4?m9gC!BHiyd) zPu8(Wie_`T4Dl2li==2ahszL8)v-v5W^=d<@iZNaq-ZvW%Mef3u}F$$bGQug3>}N4 zXf}t-5YN=HNQ!22xD4?u9gC!BHiyd)&(^U>ie_`T4DlQti==2ahszMp)v-v5W^=d< z@jM-iq-ZvW%Mj1ku}F$$bGQug0v(H_Xf}t-5HHlRNQ!22xD4?k9gC!BHiyd)FV?Y0 zie_`T4Dk{ji==2ahszKz)v-v5W^=d<@iHBYq-ZvW%MdTuu}F$$bGQug3LT52Xf}t- z5UEu}F$$bGQug1|5r}Xf}t-5N|AdosOhvHiyd)Z_=?yie_`T4Dn_ii==2a zhszLe(XmL1W^=d<@m3v+q-ZvW%MfqVu}F$$bGQugb{&hPXf}t-5bw~jNQ!22xD4@5 z9gC!BHiyd)@6xeIie_`T4DoIqi==2ahszM}(XmL1W^=d<@m?K^q-ZvW%MkC=u}F$$ zbGQugejSUXXf}t-5FgO7NQ!22xD4?@9gC!BHiyd)AJVZ%ie_`T4Dn$di==2ahszKj z(XmL1W^=d<@lhR%q-ZvW%Mc&au}F$$bGQugaUF}KXf}t-5TDSoNQ!22xD4@09gC!B zHiyd)pVF~Nie_`T4Do3li==2ahszM3(XmL1W^=d<@mU>`3q-ZvW z%Md@+u}F$$bGQugGaZYh=>NyjT`Wb7COKS+W{6+tSZtERrD%rurH;iWIb4cnh+pYgY?8yJXomQ; zj>RT9T#9Ch-{@FulEbBFhWM?H#U?piie`x4=~!%%!=-43_`QzBCOKS+W{5xNSZtER zrD%ruW7_LRT9T#9ChKkHa*lEbBFhWLw)#U?piie`wv>R4=&!=-43 z_?wQ!COKS+W{AJ*SZtERrD%ruhmOT2Ib4cnh=1x>Y?8yJXomQgj>RT9T#9Chf9qIm zlEbBFhWL+;#U?piie`xa>R4=&!=-43c<`~;`2vwma<~-D5D(F@*d&Kb(G2lW9g9tJ zxD?G057V*OB!^4U4DoOsi%oL46wMHi(6QJghfC26@kkwuO>(#t%@B{$vDhSsOVJGR zXdR19a<~-D5RcKZ*d&Kb(G2le9g9tJxD?G0kJGW(B!^4U4Dom!i%oL46wMG%(6QJg zhfC26@kAYqO>(#t%@9x0vDhSsOX0R+d!6q8>G1Zay-vsfo=edT@qmuSCOKS+W{4;2 zSZtERrD%qDijKu5Ib4cnh^OjUY?8yJXoh&2j>RT9T#9Chr|Vd3lEbBFhIodK#U?pi zie`vs>R4=&!=-43c$SXECOKS+W{79&SZtERrD%qDj*i79Ib4cni0A59Y?8yJXoh&6 zj>RT9T#9Ch=j&K(lEbBFhIoOF#U?piie`ux>R4=&!=-43c#)39COKS+W{4N-SZtER zrD%qDiH^l4Ib4cnh?nYEY?8yJXoh&1j>RT9T#9Chm+M$;lEbBFhIoaJ#U?piie`vc z>R4=&!=-43c$JRDCOKS+W{6koSZtERrD%qDjgG}8Ib4cnh}Y^^Y?8yJXoh&5j>RT9 zT#9Ch*XvkplEbBFhIoUH#U?piie`v6>R4=&!=-43c$1FBCOKS+W{5ZISZtERrD%qD zi;l%6Ib4cni2u>C*d&Kb(G2lc9g9tJxD?G0Z_}~ZB!^4U4Dogyi%oL46wMIt(6QJg zhfC26@lG9!O>(#t%@FU>vDhSsOVJGRZXJtFa<~-D5bx2k*d&Kb(G2lk9g9tJxD?G0 z@6)l^B!^4U4Do&)i%oL46wMGH(6QJghfC26@j)GnO>(#t%@7~bvDhSsOVJGRVI7N2 za<~-D5FgR8*d&Kb(G2lX9g9tJxD?G0AJeheB!^4U4DoRti%oL46wMHy(6QJghfC26 z@kt$vO>(#t%@Ci`vDhSsOVJGRX&sAAa<~-D5TDVp*d&Kb(G2lf9g9tJxD?G0pVP6} zB!^4U4Dop#i%oL46wMG{(6QJghfC26@kJerO>(#t%@AMGvDhSsOVJGRWgUx6a<~-D z5MR-;*d&Kb(G2lb9g9tJxD?G0U(>PJB!^4U4Dodxi%oL46wMId(6QJghfC26@l73z zO>(#t%@E(xvDhSsOVJGRZ5@kEa<~-D5Z}?U*d&Kb(G2lj9g9tJxD?G0-_x(#t%@9A*vDhSsOVJGRV;zf4a<~-D5I@ne z*d&Kb(G2lZ9g9tJxD?G0Khv?;B!^4U4DoXvi%oL46wMI7(6QJghfC26@k(#t z%@DuRvDhSsOVJGRYaNSCa<~-D5Wmr}*d&Kb(G2lh9g9tJxD?G0ztgeUB!^4U4Dov% zi%oL46wMHS(6QJghfC26@kbqtO>(#t%@BXmvDhSsOVJGRXB~@8a<~-D5P#9J*d&Kb z(G2ld9g9tJxD?G0f77wpB!^4U4Dojzi%oL46wMI-(6QJghfC26@lPF#O>(#t%@F_6 zvDhSsOVJGRZyk$Ga<~-D5dYD!*d&Kb(G2ll9g9tJxD?G055D#~{}#q3Ib4cnh==G{ zY?8yJXoh&Gj>RT9T#9Chhv`^slEbBFhIqJ+#U?piie`vM=vZu$!=-43c%+WSCOKS+ zW{5}WSZtERrD%qDw2s9lIb4cnh{xzyY?8yJXoh&Kj>RT9T#9Ch$LUyXlEbBFhIqV= z#U?piie`u>=vZu$!=-43c%qKQCOKS+W{4;0SZtERrD)t%Y_HSdOKp3d4o~U-o$}iZ z@qmuSCOKS+W{4;2SZtERrD%qDijKu5Ib4cnh^OjUY?8yJXoh&2j>RT9T#9Chr|Vd3 zlEbBFhIodK#U?piie`vs>R4=&!=-43c$SXECOKS+W{79&SZtERrD%qDj*i79Ib4cn zi0A59Y?8yJXoh&6j>RT9T#9Ch=j&K(lEbBFhIoOF#U?piie`ux>R4=&!=-43c#)39 zCOKS+W{4N-SZtERrD%qDiH^l4Ib4cnh?nYEY?8yJXoh&1j>RT9T#9Chm+M$;lEbBF zhIoaJ#U?piie`vc>R4=&!=-43c$JRDCOKS+W{6koSZtERrD%qDjgG}8Ib4cnh}Y^^ zY?8yJXoh&5j>RT9T#9Ch*XvkplEbBFhIoUH#U?piie`v6>R4=&!=-43c$1FBCOKS+ zW{5ZISZtERrD%qDi;l%6Ib4cni2u>C*d&Kb(G2lc9g9tJxD?G0Z_}~ZB!^4U4Dogy zi%oL46wMIt(6QJghfC26@lG9!O>(#t%@FU>vDhSsOVJGRZXJtFa<~-D5bx2k*d&Kb z(G2lk9g9tJxD?G0@6)l^B!^4U4Do&)i%oL46wMGH(6QJghfC26@j)GnO>(#t%@7~b zvDhSsOVJGRVI7N2a<~-D5FgR8*d&Kb(G2lX9g9tJxD?G0AJeheB!^4U4DoRti%oL4 z6wMHy(6QJghfC26@kt$vO>(#t%@Ci`vDhSsOVJGRX&sAAa<~-D5TDVp*d&Kb(G2lf z9g9tJxD?G0pVP6}B!^4U4Dop#i%oL46wMG{(6QJghfC26@kJerO>(#t%@AMGvDhSs zOVJGRWgUx6a<~-D5MR-;*d&Kb(G2lb9g9tJxD?G0U(>PJB!^4U4Dodxi%oL46wMId z(6QJghfC26@l73zO>(#t%@E(xvDhSsOVJGRZ5@kEa<~-D5Z}?U*d&Kb(G2lj9g9tJ zxD?G0-_x(#t%@9A*vDhSsOVJGR zV;zf4a<~-D5I@ne*d&Kb(G2lZ9g9tJxD?G0Khv?;B!^4U4DoXvi%oL46wMI7(6QJg zhfC26@k(#t%@DuRvDhSsOVJGRYaNSCa<~-D5Wmr}*d&Kb(G2lh9g9tJxD?G0 zztgeUB!^4U4Dov%i%oL46wMHS(6QJghfC26@kbqtO>(#t%@BXmvDhSsOVJGRXB~@8 za<~-D5P#9J*d&Kb(G2ld9g9tJxD?G0f77wpB!^4U4Dojzi%oL46wMI-(6QJghfC26 z@lPF#O>(#t%@F_6vDhSsOVJGRZyk$Ga<~-D5dYD!*d&Kb(G2ll9g9tJxD?G04=#J1 zfA(jS94CBoLp)r^Vv`&$MKi=BbSyT> z;Zih1JW|JElN>HZGsL5GEH=sEQZz$6TE}9O94CBoLp)x`Vv`&$MKi<`bSyT>;Zih1JWHZGsKg0EH=sEQZ$3xitTke ze5q}()8Q%oztet)ctFQulN>HZGsKg1EH=sEQZz$6MaN>394CBoLp(#rVv`&$MKi=Rbu2c?;Zih1JWI!7lN>HZGsLrXEH=sE zQZz$6N5^8594CBoL%cx8Vv`&$MKi<; zbu2c?;Zih1yhz7llN>HZGsKH^EH=sEQZz%nM8{&294CBoL%c%AVv`&$MKi=Jbu2c?;Zih1yh_JnlN>HZGsLTPEH=sEQZz%n zM#o~494vb$P$>CBoL%c!9Vv`&$MKi=3bu2c? z;Zih1yh+DmlN>HZGsK&9EH=sEQZz%nMaN>394RT9T#9Ch zx9M1HlEbBFhIqS<#U?piie`v+=vZu$!=-43c&CoVCOKS+W{7v`SZtERrD%qDw~oao zIb4cni1+ANY?8yJXoh&Nj>RT9T#9Ch_vu({lEbBFhIqe@#U?piie`up=vZu$!=-43 z_@Iu(COKS+W{3~zSZtERrD%ruu#UwhIb4cnh>z%4Y?8yJXomQxj>RT9T#9ChkLg%! zlEbBFhWNOS#U?piie`vU=vZu$!=-43_@s`-COKS+W{6MeSZtERrD%ruw2s9lIb4cn zh|lO)Y?8yJXomQ#j>RT9T#9Ch&*@lflEbBFhWNaW#U?piie`u}=vZu$!=-43_@a)* zCOKS+W{5B8SZtERrD%ruvW~?jIb4cnh_C2aY?8yJXomQzj>RT9T#9ChujyE9lEbBF zhWNUU#U?piie`v!=vZu$!=-43_@<7RT9T#9Ch@99`RT9T#9ChpXpd^lEbBFhWNRT z#U?piie`vk=vZu$!=-43_@$1;COKS+W{6+uSZtERrD%ruwT{ImIb4cnh~MZ~Y?8yJ zXomQ$j>RT9T#9Ch-|1LvlEbBFhWNdX#U?piie`vE=vZu$!=-43_@j=+COKS+W{5xO zSZtERrD%ruvyR0kIb4cnh`;DqY?8yJXomQ!j>RT9T#9Chzv)RT9T#9Ch2e-Y>Eu3tU!=-43c!-Y0COKS+W{8LCSZtERrD%qDn2yCJIb4cnh==P~ zY?8yJXoh%%j>RT9T#9ChN9tH?lEbBFhIo{Y#U?piie`vM>sV}(!=-43c#Mw4COKS+ zW{Ah?SZtERrD%qDoQ}mNIb4cnh{x+#Y?8yJXoh%#j>RT9T#9ChC+b*ilEbBFhIo>W z#U?piie?CJ(7CPHUZ*4R_NTp0$N!!o9?-GaB!^4U4Dn(#t%@9x1vDhSsOVJGRbRCOLa<~-D5YN!D*d&Kb(G2lS9g9tJxD?G0&(g8j zB!^4U4DoCoi%oL46wMIN(XrShhfC26@mw8?O>(#t%@EJivDhSsOVJGRd>xBTa<~-D z5HHZN*d&Kb(G2lI9g9tJxD?G0FVeBtB!^4U4Dn(ei%oL46wMGX(XrShhfC26@lqX& zO>(#t%@8lsvDhSsOVJGRavh6Ja<~-D5U(#t%@D8CvDhSsOVJGRdL4^Ra<~-D5O2`2 z*d&Kb(G2lM9g9tJxD?G0Z_=^YB!^4U4Dn_ii%oL46wMHC(XrShhfC26@jp5io8)jQ znjzk*W3fpNm!cWsZ8{d4OWIu}Kb>q8Z{HIu@Jca4DK0-l=1;Ne-8y8RA_! z7MtX7DVibPtz)rC4ws@C;ypSRo8)jQnjzk+W3fpNm!cWseL5DKOZJu}Kb> zq8Z`?Iu@Jca4DK0KB!}{Ne-8y8RA1a7MtX7DViZZtYfiB4ws@C;v+g1o8)jQnjt=_ zW3fpNm!cWsV>%X_q8Z{7Iu@Jca4DK0KB;4|Ne-8y8RAnq7MtX7 zDViZZtz)rC4ws@C;xjrHo8)jQnjt=`W3fpNm!cWsb2=8Aq8Z`~ zIu@Jca4DK0zNlldNe-8y8RAPi7MtX7DVia^tYfiB4ws@C;ww59o8)jQnjyZbW3fpN zm!cWsYdRL2q8Z{FIu@Jca4DK0zNureNe-8y8RAq8Z``Iu@Jc za4DK0eyC%yNe-8y8RADe7MtX7DViaEtYfiB4ws@C;wL&5o8)jQnjwCwW3fpNm!cWs zXF3*}q8Z{BIu@Jca4DK0eyL-zNe-8y8RAzu7MtX7DViaEtz)rC z4ws@C;x{@Lo8)jQnjwCxW3fpNm!cWscRCiEq8Z{3Iu@Jca4DK0 z{-|TINe-8y8RAbm7MtX7DVibvtYfiB4ws@C;x9TDo8)jQnj!wGW3fpNm!cWsZ#ov6 zq8Z{JIu@Jca4DK0{;6ZJNe-8y8RB0$7MtX7DVibvtz)rC4ws@C z;y*eTo8)jQnj!wHW3fpNm!cWs!DFu*d!1W2Ne-8y8R8*27MtX7DViZ3s$;Q94ws@C z;$b=#o8)jQnjs#pW3fpNm!cWs5jqx|q8Z{*Iu@Jca4DK09<5`s zNe-8y8R9WI7MtX7DViZ3t7EZA4ws@C;&D0_o8)jQnjs#qW3fpNm!cWs2|5;=q8Z{zIu@Jca4DK0tZ@&*ZN>IF9lq4I*Xi(-{@;lQbSyT>;Zih1JXyzL zlN>HZGsIJLEH=sEQZz$6RmWnJ94CBo zLp)Q*Vv`&$MKi>+bSyT>;Zih1JX^HZGsJUrEH=sEQZz$6SI1(L94CBoL%dMOVv`&$MKi>UbSyT>;Zih1yjaI#lN>HZ zGsH`DEH=sEQZz%nRL5eI94CBoL%dSQ zVv`&$MKi>!bSyT>;Zih1yjsU%lN>HZGsJ6jEH=sEQZz%nR>xwK94CBoL%dPPVv`&$MKi>kbSyT>;Zih1yjjO$lN>HZGsIhT zEH=sEQZz&SkB-GAIb4cnh_~ukY?8yJXoh&3j>RT9T#9Chx9eDJlEbBFhIogL#U?pi zie`v+>R4=&!=-43c$bdFCOKS+W{7v|SZtERrD%qDkB-GAIb4cni1+GPY?8yJXoh&7 zj>RT9T#9Ch_v=_}lEbBFhWLPv#U?piie`up>R4=&!=-43_>hjpCOKS+W{3~#SZtER zrD%ruh>pc3Ib4cnh>z-6Y?8yJXomQhj>RT9T#9ChkLy@$lEbBFhWLbz#U?piie`vU z>R4=&!=-43_>_*tCOKS+W{6MgSZtERrD%rujE==7Ib4cnh|lU+Y?8yJXomQlj>RT9 zT#9Ch&+AxhlEbBFhWLVx#U?piie`u}>R4=&!=-43_>zvrCOKS+W{5BASZtERrD%ru zijKu5Ib4cnh_C8cY?8yJXomQjj>RT9T#9Chuj^QBlEbBFhWLh##U?piie`v!>R4=& z!=-43_?C{vCOKS+W{7X=SZtERrD%ruj*i79Ib4cni0|rHY?8yJXomQnj>RT9T#9Ch z@9S7>lEbBFhWLSw#U?piie`u(>R4=&!=-43_>qpqCOKS+W{4l_SZtERrD%ruiH^l4 zIb4cnh@a|MY?8yJXomQij>RT9T#9ChpX*p`lEbBFhWLe!#U?piie`vk>R4=&!=-43 z_?3>uCOKS+W{6+wSZtERrD%rujgG}8Ib4cnh~Mg1Y?8yJXomQmj>RT9T#9Ch-|JXx zlEbBFhWLYy#U?piie`vE>R4=&!=-43_>+#sCOKS+W{5xQSZtERrD%rui;l%6Ib4cn zh`;JsY?8yJXomQkj>RT9T#9Chzw20RlEbBFhWLk$#U?piie`v^>R4=&!=-43_?M2w zCOKS+W{7|5SZtERrD%rukB-GAIb4cni2v$XY?8yJXoh%jJn$eEo8)jQnjs#dW3fpN zm!cWsp*j|uq8Z}hIu@Jca4DK09-(8gNe-8y8RC&T7MtX7DViZ3 zrDL&44ws@C;?X)5o8)jQnjs#eW3fpNm!cWsu{su;q8Z}xIu@Jc za4DK0o}go~Ne-8y8RCgL7MtX7DViakq+_v34ws@C;{WMbxUKks#J?&&;7jcXy#4ur zMfm|w=>z|J9>ijk94CBoLp)8#Vv`&$ zMKi?Hbu2c?;Zih1JVVD~lN>HZGsH7>EH=sEQZz$6OUGi994$>CBoLp)E%Vv`&$MKi?nbu2c?;Zih1ygHZGsFvZEH=sE zQZz%nNXKH694CBoL%dAKVv`&$MKi?9 zbu2c?;Zih1yh6uflN>HZGsG)(EH=sEQZz%nO2=Z894CBoL%dGMVv`&$MKi?fbu2c?;Zih1yg|oelN>HZGsGKpEH=sEQZz%n zNylQ794RT9T#9Ch z_vlz`lEbBFhIp@z#U?piie`xS=~!%%!=-43c)yOtCOKS+W{3~ySZtERrD%ruppL~R zIb4cnh!5#lY?8yJXomQ(j>RT9T#9ChkLXxzlEbBFhWMzC#U?piie`w9=~!%%!=-43 z__&V6COKS+W{6MdSZtERrD%ruq>jZVIb4cnh)?NQY?8yJXomQ-j>RT9T#9Ch&*)fe zlEbBFhWMRT9T#9Chujp88lEbBFhWM(E#U?piie`wf=~!%%!=-43__~h8 zCOKS+W{7X-SZtERrD%rurjErXIb4cnh;QjwY?8yJXomQRT9T#9Ch@90=;lEbBF zhWM_I#U?piie`xK=~!%%!=-43_`Z(CCOKS+W{4l?SZtERrD%rup^n8SIb4cnh#%=# zY?8yJXomQ)j>RT9T#9ChpXgX@lEbBFhWM$D#U?piie`wP=~!%%!=-43__>b7COKS+ zW{6+tSZtERrD%rurH;iWIb4cnh+pYgY?8yJXomQ;j>RT9T#9Ch-{@FulEbBFhWM?H z#U?piie`x4=~!%%!=-43_`QzBCOKS+W{5xNSZtERrD%ruqmIQUIb4cnh(GCAY?8yJ zXomQ+j>RT9T#9Chzvx(OlEbBFhWM+F#U?piie`wv=~!%%!=-43_`8n9COKS+W{7|2 zSZtERrD%rur;f!YIb4cnh=1u=Y?8yJXomQ=j>RT9T#9Ch|L9n3lEbBFhWM|J#U?pi zie`uhKgeG9AbZ_|>~#;a*SUq0OVJGR5FLw6a<~-D5D(R{*d&Kb(G2l09g9tJxD?G0 z57)8SB!^4U4DkpZi%oL46wMHi)UntkhfC26@hBaOO>(#t%@B{)vDhSsOVJGR7#)jE za<~-D5RcWd*d&Kb(G2l89g9tJxD?G0kJqu-B!^4U4DkdVi%oL46wMG%)UntkhfC26 z@gyCKO>(#t%@E$2dk~9F;-(aPoepn_+Us=Iy8k_kO>(#t%@9vkvDhSsOVJGR6dj9A za<~-D5Kq;y*d&Kb(G2l49g9tJxD?G0PuH>7B!^4U4Dk#di%oL46wMIN)UntkhfC26 z@hlySO>(#t%@EJlvDhSsOVJGR936{Ia<~-D5YN@I*d&Kb(G2lC9g9tJxD?G0&)2co zB!^4U4DkXTi%oL46wMGX)UntkhfC26@gg0IO>(#t%@8lvvDhSsOVJGR5*>?8a<~-D z5HHoS*d&Kb(G2l29g9tJxD?G0FW0fyB!^4U4Dkvbi%oL46wMH?)UntkhfC26@hTmQ z|Ig7qEdk7|ZM!|CUfqxS@TRSI+O}=mwr!iW#{X4nWb4|@)?G>Z5F|x2T-K{~Yz{$E zG{a@RM#tt5Btve1nK~glsWxYYi<`5)BGhEgi zb!-knQZ&P5y-COB5F|x2T-KX)Yz{$EG{a@RMaSk4Btn0G4na~h!)1L<$L0_uMKfI1*L7?T zK~glsWqm`(<`5)BGhEg;b!-knQZ&P5eM`sY5F|x2T-LXBYz{$EG{a?mN5|$6Bt$L0_uMKfI1_jPOzK~glsW&J?M<`5)BGhEgWb!-knQZ&P5{Yb~= z5F|x2T-J|uYz{$EG{a^6M91b3Bt5F|x2 zT-Kj;Yz{$EG{a^6MaSk4Bt*Qpe^HBt* zQOD*GBtiYKQ@QJsm2dDDdmC27u^qdOVnPclr#Whaf4M;j*5oV{-_S zq8TphSvod{ASs&RvYxGDa|n{687}KNIyQ$ODVpK3o~vVX2$G^1F6((ZHisZ7n&GmZ zuVZrvlA;+d>jgSChaf4M;j&(+V{-_Sq8TphMLITzASs&RvRlHdShaf4M;j&(-V{-_Sq8Tph zRXR3@ASs&RvRkT?Khaf4M;j-SSV{-_Sq8TphO*%G*ASs&Rvfiv?a|n{687}KBIyQ$ODVpK3 z-l}7B2$G^1F6(VNHisZ7n&GnEu48iulA;+d>m52ahaf4M;j-STV{-_Sq8TphT{jOGAhaf4M;j%ucV{-_Sq8TphLpnBxASs&RvOcV1a|n{687}K1IyQ$ODVpK3KB{AL z2$G^1F6(1DHisZ7n&GlOu48iulA;+d>k~RQhaf4M;j%udV{-_Sq8TphQ#v+>ASs&R zvOcY2a|n{687}KHIyQ$ODVpK3KC5GM2$G^1F6(nTHisZ7n&GlOuVZrvlA;+d>kB$I zhaf4M;j+G{V{-_Sq8TphOFA}(ASs&Rvc9Zia|n{687}K9IyQ$ODVpK3zN%w$2$G^1 zF6(PLHisZ7n&Gm(u48iulA;+d>l->Yhaf4M;j+G|V{-_Sq8TphTRJv}ASs&Rvc9cj za|n{687}KPIyQ$ODVpK3zN=$%2$G^1F6(jyeEhaf4M z;j(_HV{-_Sq8TphM>;l#ASs&RvVN>%a|n{687}K5IyQ$ODVpK3eyU@02$G^1F6(DH zHisZ7n&Gm3u48iulA;+d>lZpUhaf4M;j(_IV{-_Sq8TphS2{L_ASs&RvVN^&a|n{6 z87}KLIyQ$ODVpK3eyd}12$G^1F6(zXHisZ7n&Gm3uVZrvlA;+d>km3Mhaf4M;j;dy zV{-_Sq8TphPdYY-ASs&Rvi_`Na|n{687}KDIyQ$ODVpK3{;Feh2$G^1F6(bPHisZ7 zn&Gnku48iulA;+d>mNEchaf4M;j;dzV{-_Sq8TphUph92ASs&Rvi_}Oa|n{687}KT zIyQ$ODVpK3{;Oki2$G^1F6)0fHisZ7n&Gk@rpy3haf4M;j$jBV{-_Sq8TphF*-JfASs&RvL35ra|n{687}K_IyQ$ODVpK39olA;+d>q$B`hahpPvAs@*FS;M_mgobP=LbB^|96FZ zQZ&P5Jz2-*5F|x2T-H-`Yz{$EG{a>*RmbKKBt*SI6cM zBt$TLBtK~glsWqnY`<`5)BGhEh(bZibmQZ&P5eOSll5F|x2 zT-HZ)Yz{$EG{a?mRLABJBtg4na~h!)1M3$L0_uMKfI1Cv$TLBtbZibmQZ&P5{aDB55F|x2T-Hx?Yz{$E zG{a^6RLABJBt$TLBt*T*u}RBt*UdQGTBtM;OIRr`3443r-9h*at6wPp1Kh&`~1WC~hm-QnZn?sNk&2U*i*0DJR zNzn|K^%EVNLy#2Ba9Kaqu{i`u(F~XMGaZ{lkQB{uSwGjYIRr`3443r_9h*at6wPp1 zztpig1WC~hm-Q9h*at6wPp1f7G!#1WC~hm-Qzdn?sNk&2U+N*0DJRNzn|K z^%otRLy#2Ba9MxVu{i`u(F~XMHyxWpkQB{uS%25DIRr`3443r}9h*at6wPp1|J1QL z1WC~hm-R0ln?sNk&2U-&*0DJRNzn|K^&cIZLy#2Ba9RJ=u{i`u(F~XMKOLJxkQB{u zSr76TFgAxEDVpK39;{tQ-Jhaf4M;j$jC zV{-_Sq8Tph5jr-9ASs&RvL2~pa|n{687}KlIyQ$ODVpK39<5_@2$G^1F6%KmHisZ7 zn&Gk@t7CHrlA;+d>v1|Zhaf4M;j$jDV{-_Sq8Tph2|6~1ASs&RvYx18a|n{687}Kd zIyQ$ODH^95+v{`>=)0HEq-ciAdWMe8AxMg5xU6UD*c^hSXokyrmX6IKNQ!2-tY_=k z9D<~1hRb@6j?E!Rie|X1=jzxTf~07M%X*%U%^^sNX1J{9>)0HEq-ciAdV!A3AxMg5 zxU3iI*c^hSXokyrk&ewFNQ!2-tQYIp9D<~1hRb@1j?E!Rie|X1m+IIYf~07M%X*oP z%^^sNX1J`E>)0HEq-ciAdWDY7AxMg5xU5&|*c^hSXokyrm5$9JNQ!2-tXJ#U9D<~1 zhRb@5j?E!Rie|X1*Xr0Df~07M%X*!T%^^sNX1J`^>)0HEq-ciAdV`M5AxMg5xU4to z*c^hSXokyrla9?HNQ!2-tT*e}9D<~1hRb@3j?E!Rie|X1x9Zp&f~07M%X*uR%^^sN zX1J`k>)0HEq-ciAdWVk9AxMg5xU6^T*c^hSXokyrmyXRLNQ!2-tat0!9D<~1hRb@7 zj?E!Rie|X1_v+Xjf~07M%X*)V%^^sNX1J{P>)0HEq-ciA`hbqjAxMg5xU3KA*c^hS zXok!BkdDnENQ!2-tPkth9D<~1hRgbhj?E!Rie|X1kLuVQf~07M%lep(%^^sNX1J`6 z>)0HEq-ciA`h)0HEq-ciA`ht$lAxMg5xU4Vg*c^hSXok!B zl8((GNQ!2-tS{@>9D<~1hRgbjj?E!Rie|X1uj<$wf~07M%lev*%^^sNX1J`c>)0HE zq-ciA`i73pAxMg5xU6sL*c^hSXok!BmX6IKNQ!2-tZ(bs9D<~1hRgbnj?E!Rie|X1 z@9Nkbf~07M%le*<%^^sNX1J{H>)0HEq-ciA`hkwkAxMg5xU3)Q*c^hSXok!Bk&ewF zNQ!2-tRL&x9D<~1hRgbij?E!Rie|X1pX%5gf~07M%les)%^^sNX1J`M>)0HEq-ciA z`h||oAxMg5xU665*c^hSXok!Bm5$9JNQ!2-tY7Qc9D<~1hRgbmj?E!Rie|X1-|E;L zf~07M%le&;%^^sNX1J{1>)0HEq-ciA`h$+mAxMg5xU4_w*c^hSXok!Bla9?HNQ!2- ztUv469D<~1hRgbkj?E!Rie|X1zv|c=f~07M%ley+%^^sNX1J`s>)0HEq-ciA`iG9q zAxMg5xU7Hb*c^hSXok!BmyXRLNQ!2-tbgm+9D<~1hRgboj?E!Rie|X1|LWKrf~07M z%le;=%^^sNX1J^e`C~tuLy#2Ba9I!5u{i`u(F~XM5FMLCkQB{uSr65*IRr`3443sV z9h*at6wPp157)6d1WC~hm-Pr8n?sNk&2U+d)Ui1PNzn|K^(Y;iLy#2Ba9NMmu{i`u z(F~XM7#*8KkQB{uS&!ARIRr`3443sd9h*at6wPp1kJqs|1WC~hm-Pf4n?sNk&2U*y z)Ui1PNzn|K^&}meLy#2B;8bIKoep1g+v{|An*Z-=_u;ahtYdQslA;+d>nS=mhaf4M z;j*5pV{-_Sq8TphX*xECASs&RvYxJEa|n{687}J?IyQ$ODVpK3o~dJV2$G^1F6&u3 zHisZ7n&GmZtz&ZtlA;+d>p40$haf4M;j*5qV{-_Sq8Tphc{(m@oihaf4M;j&(; zV{-_Sq8TphWjZ#8ASs&RvRoqzyhaf4M;j&(n%Dqhaf4M;j-SUV{-_S zq8TphZ8|oGASs&Rvfi#^a|n{687}J`IyQ$ODVpK3-l=1A2$G^1F6&)7HisZ7n&GnE ztz&ZtlA;+d>peO)haf4M;j-SVV{-_Sq8TpheL6OWASs&Rvfi&_a|n{687}JsIyQ$O zDVpK3KB!}J2$G^1F6%=&HisZ7n&GlOtYdQslA;+d>mxcghaf4M;j%ueV{-_Sq8Tph zV>&j6ASs&RvOcb3a|n{687}J+IyQ$ODVpK3KB;4K2$G^1F6&b|HisZ7n&GlOtz&Zt zlA;+d>oYnwhaf4M;j%ufV{-_Sq8Tphb2>JMASs&RvOce4a|n{687}J!IyQ$ODVpK3 zzNlk!2$G^1F6&D=HisZ7n&Gm(tYdQslA;+d>nl1ohaf4M;j+G}V{-_Sq8TphYdSWE zASs&Rvc9fka|n{687}J^IyQ$ODVpK3zNuq#2$G^1F6&!5HisZ7n&Gm(tz&ZtlA;+d z>pMC&haf4M;j+G~V{-_Sq8Tphdpb6UASs&Rvc9ila|n{687}JwIyQ$ODVpK3eyC$} z2$G^1F6&1+HisZ7n&Gm3tYdQslA;+d>nA!khaf4M;j(_JV{-_Sq8TphXF4{AASs&R zvVN{(a|n{687}J=IyQ$ODVpK3eyL+~2$G^1F6&o1HisZ7n&Gm3tz&ZtlA;+d>o+n}Pshaf4M;j;d!V{-_Sq8TphZ#p)IASs&Rvi`1P za|n{687}J|IyQ$ODVpK3{;6Yg2$G^1F6&=9HisZ7n&Gnktz&ZtlA;+d>pwa+haf4M z;j;d#V{-_Sq8Tphe>ygYASs&RvL4j-y0+J~y{_$bZLe#4UEAy0Uf1@zw%6&{9D<~1 zhRb@0j?E!Rie|X1hw9iIf~07M%X*lO%^^sNX1J_}>)0HEq-ciAdW4S6AxMg5xU5I& z*c^hSXokyrl#b0INQ!2-tViqE9D<~1hRb@4j?E!Rie|X1$LiP|f~07M%X*xS%^^sN zX1J`!>)0HEq-ciAdV-G4AxMg5xU47Y*c^hSXokyrl8((GNQ!2-IMvu*r^6TB_BtJ& z=Ks6K{j#2{V{-_Sq8TphDLOWXASs&RvYx7Aa|n{687}K-IyQ$ODVpK3o~~na2$G^1 zF6$XOHisZ7n&GmZsbg~plA;+d>sdNBhaf4M;j*5sV{-_Sq8TphIXX6nASs&RvYxAB za|n{687}L2IyQ$ODVpK3p08tb2$G^1F6#w4HisZ7n&GlusAF>olA;+d>qR;?haf4M z;j&(=V{-_Sq8TphB|0{TASs&RvRs2~7haf4M;j&(>V{-_Sq8TphH99tjASs&RvRolA;+d>rFZ~haf4M;j-SW zV{-_Sq8TphEjl)bASs&Rvfip=a|n{687}K>IyQ$ODVpK3-mYVF2$G^1F6$jSHisZ7 zn&GnEsbg~plA;+d>s>lFhaf4M;j-SXV{-_Sq8TphJvugrASs&Rvfis>a|n{687}L6 zIyQ$ODVpK3-mhbG2$G^1F6#q2HisZ7n&GlOsAF>olA;+d>q9y=haf4M;j%ugV{-_S zq8TphBRV#RASs&RvOcO~a|n{687}K%IyQ$ODVpK3KCWYP2$G^1F6$FIHisZ7n&GlO zsbg~plA;+d>r*;5haf4M;j%uhV{-_Sq8TphGdebhASs&RvOcS0a|n{687}K{IyQ$O zDVpK3KCfeQ2$G^1F6#?AHisZ7n&Gm(sAF>olA;+d>q|N|haf4M;j+H0V{-_Sq8Tph zD>^oZASs&Rvc9Tga|n{687}KsvZDhaf4M;j+H1V{-_Sq8TphJ32OpASs&Rvc9Wha|n{687}L4IyQ$ODVpK3 zzOQ3*2$G^1F6#$6HisZ7n&Gm3sAF>olA;+d>qj~^haf4M;j(_LV{-_Sq8TphCptEV zASs&RvVN*#a|n{687}K*IyQ$ODVpK3ey(G42$G^1F6$RMHisZ7n&Gm3sbg~plA;+d z>sLB9haf4M`Tse(iyew~oZ+^wYe!OC)dy1KvnVFfHnVCs<{GXz+TT{E0mX)k9 z#IJQMHix8WE<^lA$6|9xismxJZ*?p-hoopOL;Oz1Vsl7}<}$?Zbu2cAq-ZWf{6WWJ zb4ZHjGQ=NsEH;OvXf8wiNylPyNQ&k%#GiF6Hix8WE<^l9$6|9xismxJUv(@thoopO zL;Ow0Vsl7}<}$?Jbu2cAq-ZWf{6oiLb4ZHjGQ>Z1EH;OvXf8wiOUGh!NQ&k%#J_bc zHix8WE<^lB$6|9xismxJe|0Q2hoopOL;O$2Vsl7}<}$>CuX)`yuk*!z4oT5mhIojM z#paL{&1Hy(>R4YDX6wPIbN9$N@4oT5mhIovQ#paL{&1Hzk>R4YDX6wPIbC+k>j4oT5mhH!$;tH$Pa zI^5_suhU^S|KA$F@qmuS=8zQ4Wr(NfSZoeS(Oiajs*c6xkQB{jh^OgTYz|4$T!whM zj>YDX6wPIbXXsdL4oT5mhIpoq#paL{&1HyZ=~!$INzq(}c(#tk=8zQ4Wr*kKSZoeS z(Oiaju8zg#kQB{ji0A28Yz|4$T!whQj>YDX6wPIb7wA}Q4oT5mhIpZl#paL{&1Hxe z=~!$INzq(}c(IPf=8zQ4Wr&yPSZoeS(OiajsgA|wkQB{jh?nVDYz|4$T!whLj>YDX z6wPIbSLj%54oT5mhIplp#paL{&1HyJ=~!$INzq(}c(snj=8zQ4Wr)}4SZoeS(Oiaj zt&YX!kQB{jh}Y>@Yz|4$T!whPj>YDX6wPIbH|SVw4oT5mhIpfn#paL{&1Hx;=~!$I zNzq(}c(abh=8zQ4Wr(-vSZoeS(OiajtB%FykQB{jh_~rjYz|4$T!whNj>YDX6wPIb zcj#Db4oT5mhIprr#paL{&1Hyp=~!$INzq(}c(;zl=8zQ4Wr+9aSZoeS(Oiajua3p$ zkQB{ji1+DOYz|4$T!whRj>YDX6wPIb59nBI4oT5mhWMb4#paL{&1HxW=~!$INzq(} z_^^(}=8zQ4Wr&aHSZoeS(Oic3sE)z)5Yz|4$T!#3#j>YDX6wPIbPv}@| z4oT5mhWMn8#paL{&1HyB=~!$INzq(}__U72=8zQ4Wr)w{SZoeS(Oic3td7OzkQB{j zh|lR*Yz|4$T!#3(j>YDX6wPIbFX&io4oT5mhWMh6#paL{&1Hx$=~!$INzq(}__B`0 z=8zQ4Wr(lnSZoeS(Oic3s*c6xkQB{jh_C5bYz|4$T!#3%j>YDX6wPIbZ|GQT4oT5m zhWMtA#paL{&1Hyh=~!$INzq(}__mJ4=8zQ4Wr*+SSZoeS(Oic3u8zg#kQB{ji0|oG zYz|4$T!#3*j>YDX6wPIbALv+Y4oT5mhWMe5#paL{&1Hxm=~!$INzq(}__2<~=8zQ4 zWr&~XSZoeS(Oic3sgA|wkQB{jh@a_LYz|4$T!#3$j>YDX6wPIbU+7qD4oT5mhWMq9 z#paL{&1HyR=~!$INzq(}__dD3=8zQ4Wr*MCSZoeS(Oic3t&YX!kQB{jh~Md0Yz|4$ zT!#3)j>YDX6wPIbKj>I&4oT5mhWMk7#paL{&1Hx`=~!$INzq(}__L11=8zQ4Wr)A% zSZoeS(Oic3tB%FykQB{jh`;GrYz|4$T!#3&j>YDX6wPIbf9P0j4oT5mhWMwB#paL{ z&1Hyx=~!$INzq(}__vP5=8zQ4Wr+XiSZoeS(Oic3ua3p$kQB{ji2vzWYz|4$T!wh? znAeSYo!2!vBt>%>;vqT~n?q7GmmwaiW3f3TMROVAVLBF@LsB%CAs(({u{k6~a~a|h zIu@HlQZ$z#9;suoIV44M8RAho7Mnv-G?yVBtz)q{Bt>%>;xRfFn?q7GmmwajW3f3T zMROVAaXJ>8LsB%CAs(+|u{k6~a~a|ZIu@HlQZ$z#o~UE7IV44M8RAJg7Mnv-G?yWs ztYfh`Bt>%>!s)pO;Z%>;+Z-Yn?q7Gmm!{|W3f3TMROVA z**X@RLsB%CA)cdSu{k6~a~a~fIu@HlQZ$z#o~L86IV44M8RGdm7Mnv-G?yV>pkuK) zBt>%>;)OaEn?q7GmmyxHW3f3TMROVA#X1(7LsB%CAzq?mu{k6~a~a~LIu@HlQZ$z# zUZ!KQIV44M8RF$S7Mnv-G?yV>p<}T*Bt>%>;*~lUn?q7GmmyxIW3f3TMROVA)jAfN zLsB%CAzq_nu{k6~a~a~bIu@HlQZ$z#UZ-QRIV44M8RGRi7Mnv-G?yXXpkuK)Bt>%> z;*B~Mn?q7Gmm%JyW3f3TMROVA%{msFLsB%CA>N{6u{k6~a~a~TIu@HlQZ$z#-lk)* zIV44M8RG3a7Mnv-G?yXXp<}T*Bt>%>;+;Acn?q7Gmm%JzW3f3TMROVA-8vSVLsB%C zA>N~7u{k6~a~a~jIu@HlQZ$z#-lt=+IV44M8RGpq7Mnv-G?yVhpkuK)Bt>%>;)6OC zn?q7Gmmxl+W3f3TMROVA!#Wn5LsB%CAwHsGu{k6~a~a~JIu@HlQZ$z#KBi-_IV44M z8RFwQ7Mnv-G?yVhp<}T*Bt>%>;*&ZSn?q7Gmmxl-W3f3TMROVA(>fNLLsB%CAwHvH zu{k6~a~a~ZIu@HlQZ$z#KBr@`IV44M8RGLg7Mnv-G?yX1pkuK)Bt>%>;)^;Kn?q7G zmm$8SW3f3TMROVA%Q_aDLsB%CA-%>;+r}an?q7Gmm$8TW3f3TMROVA+d3ATLsB%CA-%>;)gmGn?q7Gmmz+n zW3f3TMROVA$2u09LsB%CA%3D`u{k6~a~a~NIu@HlQZ$z#ex_rwIV44M8RF+U7Mnv- zG?yWMp<}T*Bt>%>;+HxWn?q7Gmmz+oW3f3TMROVA*E$xPLsB%CA%3G{u{k6~a~a~d zIu@HlQZ$z#ey3xxIV44M8RGXk7Mnv-G?yX%pkuK)Bt>%>;*UBOn?q7Gmm&V7W3f3T zMROVA&pH;HLsB%CA^xIcu{k6~a~a~VIu@HlQZ$z#{-$HGIV44M8RG9c7Mnv-G?yX% zp<}T*Bt>%>;-5Men?q7Gmm&V8W3f3TMROVA-#QkXLsB%CA^xLdu{k6~a~a~lIu@Hl zQZ$z#{-R4YDX6wPIbN9$N@4oT5mhIovQ z#paL{&1Hzk>R4YDX6wPIbC+k>j4oT5mhWP(}NjAt{>6 z5YN=H*c_6gxeW0v9gEE&DVoa=&(^Wn9Fn5B4DlQti_IY^n#&N+)v?$dlA^f`@jM-i z%^@k8%Mj1kvDh4vqPYz50v(IZAt{>65HHlR*c_6gxeW0l9gEE&DVoa=FV?Zx9Fn5B z4Dk{ji_IY^n#&L`)v?$dlA^f`@iHBY%^@k8%MdTuvDh4vqPYz53LT5hAt{>65UEvDh4vqPYz51|5sdAt{>65O376*c_6gxeW0p9gEE&DVoa=Z`QHc9Fn5B4Dl8n zi_IY^n#&Mx)v?$dlA^f`@irZc%^@k8%MfqZvDh4vqPYz54jqflAt{>65bxBn*c_6g zxeW0x9gEE&DVoa=@7A%{9Fn5B4DlWvi_IY^n#&OH)v?$dlA^f`@je}k%^@k8%MkC^ zvDh4vqPYz50Ue9YAt{>65FgaB*c_6gxeW0k9gEE&DVoa=AJ(zh9Fn5B4Dk^ii_IY^ zn#&L$)v?$dlA^f`@i85X%^@k8%Mc&evDh4vqPYz52_1{gAt{>65TDes*c_6gxeW0s z9gEE&DVoa=pVqP19Fn5B4DlHqi_IY^n#&NM)v?$dlA^f`@i`rf%^@k8%MhQ}vDh4v zqPYz51s#jcAt{>65MR`>*c_6gxeW0o9gEE&DVoa=U)HhM9Fn5B4Dl5mi_IY^n#&Mh z)v?$dlA^f`@iiTb%^@k8%Mf4JvDh4vqPYz54IPWkAt{>65Z~0X*c_6gxeW0w9gEE& zDVoa=-`26%9Fn5B4DlTui_IY^n#&O1)v?$dlA^f`@jV@j%^@k8%Mjn!vDh4vqPYz5 z109RaAt{>65I@wh*c_6gxeW0m9gEE&DVoa=Ki09>9Fn5B4Dk~ki_IY^n#&MB)v?$d zlA^f`@iQHZ%^@k8%Md@;vDh4vqPYz53muEiAt{>65Wm#1*c_6gxeW0u9gEE&DVoa= zzt*wX9Fn5B4DlNsi_IY^n#&Ns)v?$dlA^f`@jD%h%^@k8%MicUvDh4vqPYz52OW#e zAt{>65P#IM*c_6gxeW0q9gEE&DVoa=f7Y?s9Fn5B4DlBoi_IY^n#&M>)v?$dlA^f` z@i!fd%^@k8%MgFpvDh4vqPYz54;_omAt{>65dYM%*c_6gxeW0y9gEE&DVoa=|JJeC z9Fn5B4DlZwi_IY^n#&OX)v?$dlA^f`@jo4l%^@k8%McHKka^vM%%>;-NYgn?q7GmmwaeW3f3TMROVA;W`$ZLsB%CAs(S)u{k6~a~a~1 zIu@HlQZ$z#9;IWkIV44M8RF487Mnv-G?yVBqhql-Bt>%>;;}jwn?q7GmmwafW3f3T zMROVA@j4cpLsB%CA)cUPu{k6~a~a}^Iu@HlQZ$z#o}^>3IV44M8RE%07Mnv-G?yWq zntKq7jn|LO>vS|ulbYA*OzZyNT5JwU(Oiajii*YNkQB{jh^OjUYz|4$T!wg>j>YDX z6wPIbr|Vd34oT5mhIodK#paL{&1HyZ>R4YDX6wPIb=j&K(4oT5mhIoOF#paL{&1Hxe>R4YDX6wPIb zm+M$;4oT5mhIoaJ#paL{&1HyJ>R4YDX6wPIb*Xvkp4oT5mhIoUH#paL{&1Hx;>R4YDX6wPIbx9eDJ z4oT5mhIogL#paL{&1Hyp>R4YDX6wPIb_v=_}4oT5mhWLPv#paL{&1HxW>R4hjp z=8zQ4Wrz>!SZoeS(Oic3h>pePkQB{jh>z-6Yz|4$T!#3Vj>YDX6wPIbkLy@$4oT5m zhWLbz#paL{&1HyB>R4_*t=8zQ4Wr$DfSZoeS(Oic3jE=?TkQB{jh|lU+ zYz|4$T!#3Zj>YDX6wPIb&+Axh4oT5mhWLVx#paL{&1Hx$>R4zvr=8zQ4 zWr#29SZoeS(Oic3ijKwRkQB{jh_C8cYz|4$T!#3Xj>YDX6wPIbuj^QB4oT5mhWLh# z#paL{&1Hyh>R4YDX6wPIb@9S7>4oT5mhWLSw#paL{&1Hxm>R4qpq=8zQ4Wr!c^ zSZoeS(Oic3iH^nQkQB{jh@a|MYz|4$T!#3Wj>YDX6wPIbpX*p`4oT5mhWLe!#paL{ z&1HyR>R4u=8zQ4Wr$zvSZoeS(Oic3jgH0UkQB{jh~Mg1Yz|4$T!#3a zj>YDX6wPIb-|JXx4oT5mhWLYy#paL{&1Hx`>R4+#s=8zQ4Wr#oPSZoeS z(Oic3i;l(SkQB{jh`;JsYz|4$T!#3Yj>YDX6wPIbzw20R4oT5mhWLk$#paL{&1Hyx z>R4YDX z6wPIb2b*lL*c_6gxeW0T9gEE&DVoa=57n{Q9Fn5B4Dm1>i_IY^n#&Lm*Rj|flA^f` z@dzD@%^@k8%Mg#$vDh4vqPYz5C>@K65RcZe*c_6gxeW0b9gEE&DVoa=kJYi* z9Fn5B4DmP}i_IY^n#&N6*Rj|flA^f`@dO=<%^@k8%Mef0vDh4vqPYz5Bpr**At{>6 z5Kq>z*c_6gxeVck>w{Qq4oT6t`E6dO`@cz@&e|N3qPYz56#vI!b4ZHjGQ?ALEH;Ov zXf8uMO~+z$NQ&k%#M5;wHix8WE<-#+$6|9xismxJGj%LBhoopOLp)2zVsl7}<}$>y zbu2cAq-ZWfJV(c3b4ZHjGQ@LrEH;OvXf8uMPsd_&NQ&k%#PfA5Hix8WEKbu2cAq-ZWfyhO)hb4ZHjGQ>-DEH;OvXf8v% zOvhq#NQ&k%#LIOoHix8WEqbu2cA zq-ZWfyhg`jb4ZHjGQ?|jEH;OvXf8v%PRC+%NQ&k%#Ork|Hix8WEabu2cAq-ZWfyhX=ib4ZHjGQ?YTEH;OvXf8v%O~+z$ zNQ&k%#M^Z&Hix8WE)bu2cAq-ZWf zyhq1kb4ZHjGQ@jzEH;OvXf8v%Psd_&NQ&k%#QSwDHix8WE<=1k$6|9xismxJ2X!nq zhoopOLwrcbVsl7}<}$>Gbu2cAq-ZWfd_>1$b4ZHjGQ>x9EH;OvXf8v1Ovhq#NQ&k% z#K(0kHix8WE<=1m$6|9xismxJCv_|~hoopOLwridVsl7}<}$>mbu2cAq-ZWfd`8D& zb4ZHjGQ?+fEH;OvXf8v1PRC+%NQ&k%#OHM^Hix8WE<=1l$6|9xismxJ7j-N)hoopO zLwrfcVsl7}<}$>Wbu2cAq-ZWfd_~7%b4ZHjGQ?MPEH;OvXf8v1O~+z$NQ&k%#MgB! zHix8WE<=1n$6|9xismxJH+3vFhoopOLwrleVsl7}<}$>$bu2cAq-ZWfd`HJ(b4ZHj zGQ@XvEH;OvXf8v1Psd_&NQ&k%#P@Y9Hix8WE<^l4$6|9xismxJ4|OayhoopOL;Og` zVsl7}<}$>Obu2cAq-ZWf{6xoMb4ZHjGQ>}HEH;OvXf8wiOvhq#NQ&k%#LsmsHix8W zE<^l6$6|9xismxJFLf+7hoopOL;Om|Vsl7}<}$>ubu2cAq-ZWf{6@!Ob4ZHjGQ@9n zEH;OvXf8wiPRC+%NQ&k%#P4-1Hix8WE<^l5$6|9xismxJA9XA?hoopOL;Oj{Vsl7} z<}$>ebu2cAq-ZWf{6)uNb4ZHjGQ?kXEH;OvXf8wiO~+z$NQ&k%#NTx+Hix8WE<^l7 z$6|9xismxJKXoiNhoopOL;Op}Vsl7}<}$>;bu2cAq-ZWf{71)Pb4ZHjGQ@v%EH;Ov zXf8wiPsd_&NQ&k%#DkqeVzD_SMROVAAvzYDLsB%CAs(t@u{k6~a~a}cIu@HlQZ$z# z9%>;!!#ln?q7GmmwalW3f3TMROVAF*+8T zLsB%CAs(w^u{k6~a~a}sIu@HlQZ$z#9%> z;z>Fdn?q7Gmm!|4W3f3TMROU#*XSO^Vsl7}##b62aP!-|PKRCpf9v>7ismxJQ*~bSyT9q-ZWfyj;g(b4ZHjGQ=x%EH;OvXf8v%QpaL*NQ&k%#H(~H zHix8WEM{EH;OvXf8v%Q^#U+NQ&k%#JhAXHix8W zE`bSyT9q-ZWfd|bz3b4ZHjGQ=lzEH;OvXf8v1QpaL*NQ&k%#HVyDHix8WE<=1; z$6|9xismxJXLKw!hoopOLwr`pVsl7}<}$?RbSyT9q-ZWfd|t<5b4ZHjGQ<~jEH;Ov zXf8v1QO9C)NQ&k%#Fum|Hix8WE<=1-$6|9xismxJS9B~khoopOLwr@oVsl7}<}$?B zbSyT9q-ZWfd|k(4b4ZHjGQ>A@EH;OvXf8v1Q^#U+NQ&k%#J6-THix8WE<=1<$6|9x zismxJcXTW^hoopOLwr}qVsl7}<}$?hbSyT9q-ZWfd|$_6b4ZHjGQZ0EH;OvXf8wiQ^#U+NQ&k%#J_YbHix8WE<^lV$6|9xismxJe{?K1 zhoopOL;P3AVsl7}<}$?pbSyT9q-ZWfJlKsv7Mnv-G?yVBqGPc+Bt>%>;-NYgn?q7G zmmwaeW3f3TMROVA;W`$ZLsB%CAs(S)u{k6~a~a~1Iu@HlQZ$z#9;IWkIV44M8RF48 z7Mnv-G?yVBqhql-Bt>%>;;}jwn?q7GmmwafW3f3TMROVA@j4cpLsB%CA)cUPu{k6~ za~a}^Iu@HlQZ$z#o}^>3IV44M8RE%07Mnv-G?yX%KOKwBAt@R!s+ia59?)Sz{eWHn ze=GeK&1HzE=vZtHNzq(}c&d)Y=8zQ4Wr(NgSZoeS(Oiajx{k%>kQB{jh-c_nYz|4$ zT!wh2j>YDX6wPIbXX#jM4oT5mhIqD)#paL{&1Hz^=vZtHNzq(}c&?7c=8zQ4Wr*kL zSZoeS(OiajzK+G_kQB{jh!^NsYz|4$T!wg|j>YDX6wPIb7wK4R4oT5mhIp}##paL{ z&1Hy}=vZtHNzq(}c&U!X=8zQ4Wr&yQSZoeS(OiajxsJu=kQB{jh*#)XYz|4$T!wh1 zj>YDX6wPIbSLs-64oT5mhIqA(#paL{&1Hz!=vZtHNzq(}c&(1b=KtsD9+m*uwseiY z(yWDv$2&IfKDKS!wr$%++)))7BU@iHTYqHcI$V;X8RE4%7MsH*DViZ(r(>}>T#}+0 z;`KTfo5Lk3njzkxW3f40lA;;njXD;a!zC%2A>O28u{m6lq8Z}NIu@J5B`KOA-lAi% zIb4#W8RD%v7MsH*DVibPrem==T#}+0;_W&Xo5Lk3njzkyW3f40lA;;nojMkq!zC%2 zA>O59u{m6lq8Z}dIu@J5B`KOA-lJo&Ib4#W8RES<7MsH*DVibPr(>}>T#}+0;{7@n zo5Lk3njt=*W3f40lA;;ngE|(Q!zC%2AwHyIu{m6lq8Z}DIu@J5B`KOAKB8l>Ib4#W z8RDZl7MsH*DViZZrem==T#}+0;^R6No5Lk3njt=+W3f40lA;;nlR6fg!zC%2AwH#J zu{m6lq8Z}TIu@J5B`KOAKBHr?Ib4#W8RD}#7MsH*DViZZr(>}>T#}+0;`2Hdo5Lk3 znjyZRW3f40lA;;ni#isY!zC%2A-<$zu{m6lq8Z}LIu@J5B`KOAzM^BXIb4#W8RDxt z7MsH*DVia^rem==T#}+0;_EsVo5Lk3njyZSW3f40lA;;nn>rSo!zC%2A-<(!u{m6l zq8Z}bIu@J5B`KOAzN2HYIb4#W8REM-7MsH*DVia^r(>}>T#}+0;`=%lo5Lk3njwCm zW3f40lA;;nhdLIU!zC%2A%3J|u{m6lq8Z}HIu@J5B`KOAexhTsIb4#W8RDlp7MsH* zDViaErem==T#}+0;^#URo5Lk3njwCnW3f40lA;;nmpT@k!zC%2A%3M}u{m6lq8Z}X zIu@J5B`KOAexqZtIb4#W8REA(7MsH*DViaEr(>}>T#}+0;`cfho5Lk3nj!w6W3f40 zlA;;nk2)5c!zC%2A^xOeu{m6lq8Z}PIu@J5B`KOA{-R^CIb4#W8RD-x7MsH*DVibv zrem==T#}+0;_o^Zo5Lk3nj!w7W3f40lA;;npE?$s!zC%2A^xRfu{m6lq8Z}fIu@J5 zB`KOA{-a~DIb4#W8REY>7MsH*DViZ39`^o5Lk3njv1IW3f40lA;;nr8*Xy!zC%2Azr3qu{m6lq8Z}lIu@J5B`KOAUZG>L zIb4#W8RC^X7MsH*DViZ(rDL%|i1 zo5Lk3njzkzW3f40lA;;ntvVK)!zC%2A>O8Au{m6lq8Z}tIu@J5B`KOA-l1c$Ib4#W z8RDHf7MsH*DVibPrDL%OBB zu{m6lq8Z}-Iu@J5B`KOAKA>Z$V~o5Lk3njyZT zW3f40lA;;nt2!2&!zC%2A-<+#u{m6lq8Z}rIu@J5B`KOAzM*5WIb4#W8RDBd7MsH* zDVia^rDL%S7`o5Lk3njwCoW3f40 zlA;;nr#cp!!zC%2A%3P~u{m6lq8Z}nIu@J5B`KOAexYNrIb4#W8RC~Z7MsH*DViaE zrDL%lP^!zC%2A%3T0u{m6lq8Z}%Iu@J5 zB`KOA{-9&AIb4#W8RCyR7MsH*DVibvq+_u;T#}+0;?Fu3o5Lk3nj!w8W3f40lA;;n zuR0c+!zC%2A^xUgu{m6lq8Z}vIu@J5B`KOA{-I;BIb4#W8RDNh7MsH*DVibvrDL%< zT#}+0;@>(Jo5Lk3nj!w9W3f40lA;;nzd9D1!zC%2As&?Wy0q7&y)Nx_X|GFrUE1r? zUYGW|wAblaYz~*CXoh%*j>YD1Ns4BOhw4~t4ws~8hIp8c#pZBHie`w1>sV|Km!xQh zc!Z9{=5R@hW{5}XSZofLq-chCl#a#ba7l`0h)3&KYz~*CXoh%YD1Ns4BO$Ld&Y z4ws~8hIpKg#pZBHie`w%>sV|Km!xQhc!G|_=5R@hW{4;1SZofLq-chCl8(jZa7l`0 zh$rhYD1 zNs4BOr|DR14ws~8hIqP;#pZBHie`vs=vZtHm!xQhc&3iU=5R@hW{79$SZofLq-chC zwvNT-a7l`0i09~7Yz~*CXoh&Mj>YD1Ns4BO=jm8%4ws~8hIqb?#pZBHie`ux=vZtH zm!xQhc%hEP=5R@hW{4N*SZofLq-chCv5v*&a7l`0h?nSCYz~*CXoh&Hj>YD1Ns4BO zm+4q+4ws~8hIqM-#pZBHie`vc=vZtHm!xQhc%_cT=5R@hW{6kmSZofLq-chCwT{K+ za7l`0h}Y;?Yz~*CXoh&Lj>YD1Ns4BO*XdYn4ws~8hIqY>#pZBHie`v6=vZtHm!xQh zc%zQR=5R@hW{5ZGSZofLq-chCvyR2)a7l`0h_~oiYz~*CXoh&Jj>YD1Ns4BOx9M1H z4ws~8hIqS<#pZBHie`v+=vZtHm!xQhc&CoV=5R@hW{7v`SZofLq-chCw~oc;a7l`0 zi1+ANYz~*CXoh&Nj>YD1Ns4BO_vu({4ws~8hIqe@#pZBHie`up=vZtHm!xQh_@Iu( z=5R@hW{3~zSZofLq-citu#Uy%a7l`0h>z%4Yz~*CXomQxj>YD1Ns4BOkLg%!4ws~8 zhWNOS#pZBHie`vU=vZtHm!xQh_@s`-=5R@hW{6MeSZofLq-citw2sB*a7l`0h|lO) zYz~*CXomQ#j>YD1Ns4BO&*@lf4ws~8hWNaW#pZBHie`u}=vZtHm!xQh_@a)*=5R@h zW{5B8SZofLq-citvW~^(a7l`0h_C2aYz~*CXomQzj>YD1Ns4BOujyE94ws~8hWNUU z#pZBHie`v!=vZtHm!xQh_@<7<=5R@hW{7X;SZofLq-citwvNT-a7l`0i0|lFYz~*C zXomQ%j>YD1Ns4BO@99`<4ws~8hWNgY#pZBHie`u(=vZtHm!xQh_@R!)=5R@hW{4l@ zSZofLq-citv5v*&a7l`0h@a?KYz~*CXomQyj>YD1Ns4BOpXpd^4ws~8hWNRT#pZBH zie`vk=vZtHm!xQh_@$1;=5R@hW{6+uSZofLq-citwT{K+a7l`0h~MZ~Yz~*CXomQ$ zj>YD1Ns4BO-|1Lv4ws~8hWNdX#pZBHie`vE=vZtHm!xQh_@j=+=5R@hW{5xOSZofL zq-citvyR2)a7l`0h`;DqYz~*CXomQ!j>YD1Ns4BOzv)YD1 zNs4BO2RSv9#pZBHie`uh>sV|Km!xQhc!-Y0=5R@hW{8LCSZofLq-chCn2yEfa7l`0 zh==P~Yz~*CXoh%%j>YD1Ns4BON9tH?4ws~8hIo{Y#pZBHie`vM>sV|Km!xQhc#Mw4 z=5R@hW{Ah?SZofLq-chCoQ}oja7l`0h{x+#Yz~*CXoh%#j>YD1Ns4BOC+b*i4ws~8 zhIo>W#pZBHie`u>>sV|Km!xP0rytwvbolbyUZ=xT|9@Az5AlGG#pZBHie`wX=vZtH zm!xQhc&d)Y=5R@hW{9WhSZofLq-chCx{k%>a7l`0h-c_nYz~*CXoh&Ej>YD1Ns4BO zXX#jM4ws~8hIqD)#pZBHie`xC=vZtHm!xQhc&?7c=5R@hW{BtMSZofLq-chCzK+G_ za7l`0h!^NsYz~*CXoh&9j>YD1Ns4BO7wK4R4ws~8hIp}##pZBHie`wH=vZtHm!xQh zc&U!X=5R@hW{8*RSZofLq-chCxsJu=a7l`0h*#)XYz~*CXoh&Dj>YD1Ns4BOSLs-6 z4ws~8hIqA(#pZBHie`w{=vZtHm!xQhc&(1b=5R@hW{B76SZofLq-chCy^h7^a7l`0 zh&Sk1Yz~*CXoh&Bj>YD1Ns4BOH|bbx4ws~8hIq4%#pZBHie`wn=vZtHm!xQhc&m=Z z=5R@hW{9`xSZofLq-chCyN<=?a7l`0hYD1Ns4BOcj;Jc4ws~8 zhIqG*#pZBHie`xS=vZtHm!xQhc(0Dd=5R@hW{CIcSZofLq-chCzmCP`a7l`0h!5yk zYz~*CXomQpj>YD1Ns4BO59wHJ4ws~8hWN0K#pZBHie`w9=vZtHm!xQh_^6J>=5R@h zW{8jJSZofLq-citxQ@lYD1Ns4BOPw7}}4ws~8hWNCO z#pZBHie`w<=vZtHm!xQh_^gh_=5R@hW{A(}SZofLq-citypF}@a7l`0h%e|^Yz~*C zXomQrj>YD1Ns4BOFX>op4ws~8hWN6M#pZBHie`wf=vZtHm!xQh_^OV@=5R@hW{9up zSZofLq-citx{k%>a7l`0h;QgvYz~*CXomQvj>YD1Ns4BOZ|PWU4ws~8hWNIQ#pZBH zie`xK=vZtHm!xQh_^yt{=5R@hW{B_USZofLq-citzK+G_a7l`0h#%-!Yz~*CXomQq zj>YD1Ns4BOAL&?Z4ws~8hWN3L#pZBHie`wP=vZtHm!xQh_^FP?=5R@hW{98ZSZofL zq-citxsJu=a7l`0h+pVfYz~*CXomQuj>YD1Ns4BOU+GwE4ws~8hWNFP#pZBHie`x4 z=vZtHm!xQh_^pn`=5R@hW{BVESZofLq-city^h7^a7l`0h(G99Yz~*CXomQsj>YD1 zNs4BOKj~O(4ws~8hWN9N#pZBHie`wv=vZtHm!xQh_^Xb^=5R@hW{AJ(SZofLq-cit zyN<=?a7l`0h=1rYD1Ns4BOf9Y6k4ws~8hWNLR#pZBHie`xa=vZtH zm!xQh_^*z|=5R@hW{3y1z0RqbYz~*CXoh&Oj>YD1Ns4BOhv-;r4ws~8hIpus#pZBH zie`w1=~!$Im!xQhc({(m=5R@hW{5}VSZofLq-chCq>jbra7l`0h)3yIYz~*CXoh&S zj>YD1Ns4BO$LLsW4ws~8hIp)w#pZBHie`w%=~!$Im!xQhc)X6q=5R@hW{4-~SZofL zq-chCqK?Jpa7l`0h$rb-Yz~*CXoh&Qj>YD1Ns49&Z_qjY*j}f@m*4g}9iICCyT&~p z(6QJYE=kc0@f014&Eb+1%@9x3vDh3gNzn}PG#!i0;gS^15Kq^!*c>iN(G2kn9gEH3 zk`&Dl&(yKl94<-G4Dl=-i_PJZ6wMIN*0IiN(G2kd9gEH3k`&DlFVwNv94<-G4Dlizi_PJZ6wMGX*0IiN(G2kl9gEH3k`&Dl zuhg;F94<-G4Dl)*i_PJZ6wMH?*0IiN(G2kh9gEH3k`&DlZ`85a94<-G4Dlu%i_PJZ6wMHC*0IiN(G2kp9gEH3k`&Dl@6@r_ z94<-G4Dl`iN(G2kc9gEH3k`&DlAJnnf94<-G4Dlfyi_PJZ6wMGH*0IiN(G2kk9gEH3k`&DlpVYC~94<-G z4Dl%)i_PJZ6wMHy*0IiN(G2kg9gEH3k`&DlU(~VK94<-G4Dlr$i_PJZ6wMG{*0IiN(G2ko9gEH3k`&Dl-_)_#94<-G4Dl@; zi_PJZ6wMId*0IiN z(G2ke9gEH3k`&DlKh&|<94<-G4Dll!i_PJZ6wMGn*0I`3&Eb+1%@9A; zvDh3gNzn}PGaZY~;gS^15I@(k*c>iN(G2km9gEH3k`&DlztpkV94<-G4Dl-+i_PJZ z6wMI7*0IiN(G2ki z9gEH3k`&Dlf7G$q94<-G4Dlx&i_PJZ6wMHS*0IiN(G2kq9gEH3k`&Dl|J1SA94<-G4Dl}=i_PJZ6wMI- z*0I9Gv{>0BEDViZ3tYfh`T#}+0 z;vqT~o5Lk3njs#lW3f40lA;;nVLBF@!zC%2As(({u{m6lq8Z{5Iu@J5B`KOA9;suo zIb4#W8RAho7MsH*DViZ3tz)q{T#}+0;xRfFo5Lk3njs#mW3f40lA;;naXJ>8!zC%2 zAs(+|u{m6lq8Z`|Iu@J5B`KOAo~UE7Ib4#W8RAJg7MsH*DViaktYfh`T#}+0!rOEI zgVT@gbvk_cZLibessFz#9?-Ga94<-G4Dl2li_PJZ6wMG%)v?$dE=kc0@iZNa&Eb+1 z%@9x5vDh3gNzn}P3>}Nj;gS^15YN=H*c>iN(G2k{9gEH3k`&Dl&(^Wn94<-G4DlQt zi_PJZ6wMIN)v?$dE=kc0@jM-i&Eb+1%@EJmvDh3gNzn}P0v(IZ;gS^15HHlR*c>iN z(G2k-9gEH3k`&DlFV?Zx94<-G4Dk{ji_PJZ6wMGX)v?$dE=kc0@iHBY&Eb+1%@8lw zvDh3gNzn}P3LT5h;gS^15UiN(G2k_9gEH3k`&Dluhy~H94<-G4DlKri_PJZ z6wMH?)v?$dE=kc0@j4xg&Eb+1%@D8GvDh3gNzn}P1|5sd;gS^15O376*c>iN(G2k> z9gEH3k`&DlZ`QHc94<-G4Dl8ni_PJZ6wMHC)v?$dE=kc0@irZc&Eb+1%@A+bvDh3g zNzn}P4jqfl;gS^15bxBn*c>iN(G2k}9gEH3k`&Dl@7A%{94<-G4DlWvi_PJZ6wMIt z)v?$dE=kc0@je}k&Eb+1%@FU`vDh3gNzn}P0Ue9Y;gS^15FgaB*c>iN(G2k+9gEH3 zk`&DlAJ(zh94<-G4Dk^ii_PJZ6wMGH)v?$dE=kc0@i85X&Eb+1%@7~gvDh3gNzn}P z2_1{g;gS^15TDes*c>iN(G2k^9gEH3k`&DlpVqP194<-G4DlHqi_PJZ6wMHy)v?$d zE=kc0@i`rf&Eb+1%@Cj0vDh3gNzn}P1s#jc;gS^15MR`>*c>iN(G2k=9gEH3k`&Dl zU)HhM94<-G4Dl5mi_PJZ6wMG{)v?$dE=kc0@iiTb&Eb+1%@AMLvDh3gNzn}P4IPWk z;gS^15Z~0X*c>iN(G2k|9gEH3k`&Dl-`26%94<-G4DlTui_PJZ6wMId)v?$dE=kc0 z@jV@j&Eb+1%@E($vDh3gNzn}P109Ra;gS^15I@wh*c>iN(G2k;9gEH3k`&DlKi09> z94<-G4Dk~ki_PJZ6wMGn)v?$dE=kc0@iQHZ&Eb+1%@9A=vDh3gNzn}P3muEi;gS^1 z5Wm#1*c>iN(G2k`9gEH3k`&Dlzt*wX94<-G4DlNsi_PJZ6wMI7)v?$dE=kc0@jD%h z&Eb+1%@DuWvDh3gNzn}P2OW#e;gS^15P#IM*c>iN(G2k?9gEH3k`&Dlf7Y?s94<-G z4DlBoi_PJZ6wMHS)v?$dE=kc0@i!fd&Eb+1%@BXrvDh3gNzn}P4;_om;gS^15dYM% z*c>iN(G2k~9gEH3k`&Dl|JJeC94<-G4DlZwi_PJZ6wMI-)v?$dE=kc0@t}C%e^_h| zm!xQhc(9Je=5R@hW{8LASZofLq-chCsE)YD1Ns4BO zN9b5=4ws~8hIpio#pZBHie`vM=~!$Im!xQhc(jhi=5R@hW{Ah=SZofLq-chCtd7Oz za7l`0h{x$zYz~*CXoh&aj>YD1Ns4BOC+Jvg4ws~8hIpcm#pZBHie`u>=~!$Im!xQh zc(RVg=5R@hW{Cf%W8w7U2b`$#fWI_8ka(N)0Som5p85y=_xc|eo5Lk3njxN|W3f40 zlA;;nsX7*$!zC%2A)cmVu{m6lq8Z}pIu@J5B`KOAo}pv0Ib4#W8RD5b7MsH*DViak zrDL%9`^o5Lk3njv1IW3f40lA;;n zr8*Xy!zC%2Azr3qu{m6lq8Z}lIu@J5B`KOAUZG>LIb4#W8RC^X7MsH*DViZ(rDL%< zT#}+0;?+79o5Lk3njv1JW3f40lA;;nwK^7?!zC%2Azr6ru{m6lq8Z}#Iu@J5B`KOA z-k@W#Ib4#W8RCsP7MsH*DVibPq+_u;T#}+0;>|i1o5Lk3njzkzW3f40lA;;ntvVK) z!zC%2A>O8Au{m6lq8Z}tIu@J5B`KOA-l1c$Ib4#W8RDHf7MsH*DVibPrDL%OBBu{m6lq8Z}-Iu@J5B`KOAKA>Z< zIb4#W8RCOF7MsH*DViZZq+_u;T#}+0;=?)?o5Lk3njt=-W3f40lA;;nqdFFw!zC%2 zAwH&Ku{m6lq8Z}jIu@J5B`KOAKA~f=Ib4#W8RC;V7MsH*DViZZrDL%$V~o5Lk3njyZTW3f40lA;;nt2!2&!zC%2A-<+# zu{m6lq8Z}rIu@J5B`KOAzM*5WIb4#W8RDBd7MsH*DVia^rDL%S7`o5Lk3njwCoW3f40lA;;nr#cp!!zC%2A%3P~u{m6l zq8Z}nIu@J5B`KOAexYNrIb4#W8RC~Z7MsH*DViaErDL%evLyp=gH7`kjtVkQ|C;xUApn*aXR;Xok!BgN{v*9ExVRtUv151j(UjhRgbsj!lpp zie|X1KkL{8$)RY5%leCsO^_UlX1J`s>evLyp=gH7`kRhTkQ|C;xU9eH*aXR;Xok!B zhmK8<9ExVRtbgj*1j(UjhRgbwj!lppie|X1f9u!;$)RY5%leOwO^_UlX1J{X>evLy zp=gH7de8&*x(Doa57_G-u-83cuY15=_kg|b0ejs8_PPh`bviadawwYNvL2#i6C{VC z87}LgIyOOaD4OB29;RaxB!{9IF6-esHbHVIn&Gk@p<@#yhoTuS>ybJ(L2@XX;j$j3 zV-qBYq8Tph(KxnuxL2@XX;j*5jV-qBYq8Tph$vQScawwYNvb;6-0Gq%m$@V%O zz7V(9>F{*?-?iO?*Q^zJq4n;Fu*0XeMg5*#%!(}~N$0kS)MKfI1b98KievLyp=gH7dYg_-kQ|C;xU9G9*aXR;XokyrhmK8< z9ExVRtas|z1j(UjhRb@Fj!lppie|X1ck9>$$)RY5%X*KFO^_UlX1J{P>evLyp=gH7 zdY_I>kQ|C;xUBc<*aXR;Xok!BfR0U&9ExVRtPkqg1j(UjhRgbpj!lppie|X159`evLyp=gH7`k0PQkQ|C;xU7%s*aXR;Xok!BgpN&+9ExVR ztWWCL1j(UjhRgbtj!lppie|X1PwUtO$)RY5%leFtO^_UlX1J`+>evLyp=gH7`kanU zkQ|C;xUA3X*aXR;Xok!Bf{sm)9ExVRtS{==1j(UjhRgbrj!lppie|X1FYDL@$)RY5 z%le9rO^_UlX1J`c>evLyp=gH7`kIbSkQ|C;xU8@1*aXR;Xok!BhK@~;9ExVRtZ(Yr z1j(UjhRgbvj!lppie|X1Z|m3u$)RY5%leLvO^_UlX1J{H>evLyp=gH7`kszWkQ|C; zxUBE%*aXR;Xok!BfsRd(9ExVRtRL#w1j(UjhRgbqj!lppie|X1AM4lz$)RY5%le6q zO^_UlX1J`M>evLyp=gH7`k9VRkQ|C;xU8S+*aXR;Xok!Bg^o>-9ExVRtY7Nb1j(Uj zhRgbuj!lppie|X1U+dTe$)RY5%leIuO^_UlX1J{1>evLyp=gH7`kjtVkQ|C;xUApn z*aXR;Xok!BgN{v*9ExVRtUv151j(UjhRgbsj!lppie|X1KkL{8$)RY5%leCsO^_Ul zX1J`s>evLyp=gH7`kRhTkQ|C;xU9eH*aXR;Xok!BhmK8<9ExVRtbgj*1j(UjhRgbw zj!lppie|X1f9u!;$)RY5%leOwO^_UlX1J{X>evLyp=gH7dXU9}O^_UlX1J^e>(~Uz zp=gH7dWeoqkQ|C;xU7fj*aXR;Xokyrn2t@59ExVRtcUB^1j(UjhRb?{j!lppie|X1 zN9x!F$)RY5%X*ZKO^_UlX1J_J>(~Uzp=gH7dW?=ukQ|C;xU9$O*aXR;XokyroQ_S9 z9ExVRtjFuv1j(UjhRb?_j!lppie|X1C+gS)$)RY5%X*TIO^_UlX1J^;>(~Uzp=gH7 z@`dXIY=Xoo$@V%Oz7V(9>7JtF|6f6JD4OB2o~mOLB!{9IF6(JJHbHVIn&GmZu45A< zhoTuS>lr#WL2@XX;j*5oV-qBYq8TphSvodBawwYNvYxGD6C{VC87}KNIyOOaD4OB2 zo~vUMB!{9IF6((ZHbHVIn&GmZuVWJ=hoTuS>jgSCL2@XX;j&(+V-qBYq8TphMLIS? zawwYNvRlHdSL2@XX;j&(-V-qBYq8TphRXR37awwYNvRkT?KL2@XX;j-SSV-qBYq8TphO*%F~awwYN zvfiv?6C{VC87}KBIyOOaD4OB2{#VB)NDf6aT-IB4Y=Y!aG{a@RO~)ok4n;Fu*4uS# zg5*#%!)3ig$0kS)MKfI1J9TV=vvvg5*#%!)1Lz$0kS)MKfI17jvCP)rNGhEiUb!>v zb!>vvv< zP&C73{YA$nNDf6aT-IN8Y=Y!aG{a^6O~)ok4n;Fu*57q(g5*#%!)5(L$0kS)MKfI1 zKXq(^v*$lFD1 zg5*#%!(}~K$0kS)MKfI1Lv(C{*QpYAp4n;Fu)}wT6g5*#%!(}~M$0kS)MKfI1V{~kS*QO71o4n;Fu){}H>g5*#% z!(}~L$0kS)MKfHMztKIwCP)s2lUM9@I=ppiuha4WujEiP!(}~H$0kS)MKfI1({yZt z*TgN6y4n;Fu z)^l`hg5*#%!(}~J$0kS)MKfI1^K@*2#{ zNDf6aT-J+pY=Y!aG{a@RSjQ$v4n;Fu)=PA3g5*#%!)3ix$0kS)MKfI1%XDml}NDf6aT-K{}Y=Y!aG{a@RTE`|x4n;Fu)@yWZ zg5*#%!)3iz$0kS)MKfI1>vU{_(~Uzp=gH7dWVipkQ|C;xU6^T*aXR;XokyrmyS)49ExVRtat0!1j(Uj zhRb@7j!lppie|X1_v+XL$)RY5%X*)VO^_UlX1J{P>(~Uzp=gH7`hbp2kQ|C;xU3KA z*aXR;Xok!Bkd94|9ExVRtPkth1j(UjhRgbhj!lppie|X1kLuV2$)RY5%lep(O^_Ul zX1J`6>(~Uzp=gH7`h<>6kQ|C;xU5g=*aXR;Xok!Bl#Wf19ExVRtWWFM1j(UjhRgbl zj!lppie|X1&+6C&$)RY5%le#-O^_UlX1J`+>(~Uzp=gH7`ht#4kQ|C;xU4Vg*aXR; zXok!Bl8#M~9ExVRtS{@>1j(UjhRgbjj!lppie|X1uj<$Y$)RY5%lev*O^_UlX1J`c z>(~Uzp=gH7`i728kQ|C;xU6sL*aXR;Xok!BmX1x39ExVRtZ(bs1j(UjhRgbnj!lpp zie|X1@9NkD$)RY5%le*(~Uzp=gH7`hkv3kQ|C;xU3)Q*aXR;Xok!B zk&aD}9ExVRtRL&x1j(UjhRgbij!lppie|X1pX%5I$)RY5%les)O^_UlX1J`M>(~Uz zp=gH7`h|{7kQ|C;xU665*aXR;Xok!Bm5xo29ExVRtY7Qc1j(UjhRgbmj!lppie|X1 z-|E-|$)RY5%le&;O^_UlX1J{1>(~Uzp=gH7`h$*5kQ|C;xU4_w*aXR;Xok!Bla5W0 z9ExVRtUv461j(UjhRgbkj!lppie|X1zv|co$)RY5%ley+O^_UlX1J`s>(~Uzp=gH7 z`iG89kQ|C;xU7Hb*aXR;Xok!BmyS)49ExVRtbgm+1j(UjhRgboj!lppie|X1|LWKT z$)RY5%X*M60oeq}p=gH7da#a7kQ|C;xU7fh*aXR;XokyrsE$pL9ExVRtcU5?1j(Uj zhRb@mj!lppie|X1N9foD$)RY5%X*}aO^_UlX1J_J>DUCxp=gH7dbEyBkQ|C;xU9$M z*aXR;Xokyrtd32P9ExVRtjFot1j(UjhRb@qj!lppie|X1C+OG&$)RY5%X*@YO^_Ul zX1J^;>DUCxp=gH7da{m9kQ|C;xUB!tu?dnx;gsa3IC*TgN6y4n;Fu)^l`hg5*#%!(}~J$0kS)MKfI1^K@*2#{NDf6aT-J+pY=Y!aG{a@RSjQ$v4n;Fu)=PA3g5*#%!)3ix z$0kS)MKfI1%XDml}NDf6aT-K{}Y=Y!a zG{a@RTE`|x4n;Fu)@yWZg5*#%!)3iz$0kS)MKfI1>vU{_(~Uzp=gH7dWVipkQ|C;xU6^T*aXR;Xokyr zmyS)49ExVRtat0!1j(UjhRb@7j!lppie|X1_v+XL$)RY5%X*)VO^_UlX1J{P>(~Uz zp=gH7`hbp2kQ|C;xU3KA*aXR;Xok!Bkd94|9ExVRtPkth1j(UjhRgbhj!lppie|X1 zkLuV2$)RY5%lep(O^_UlX1J`6>(~Uzp=gH7`h<>6kQ|C;xU5g=*aXR;Xok!Bl#Wf1 z9ExVRtWWFM1j(UjhRgblj!lppie|X1&+6C&$)RY5%le#-O^_UlX1J`+>(~Uzp=gH7 z`ht#4kQ|C;xU4Vg*aXR;Xok!Bl8#M~9ExVRtS{@>1j(UjhRgbjj!lppie|X1uj<$Y z$)RY5%lev*O^_UlX1J`c>(~Uzp=gH7`i728kQ|C;xU6sL*aXR;Xok!BmX1x39ExVR ztZ(bs1j(UjhRgbnj!lppie|X1@9NkD$)RY5%le*(~Uzp=gH7`hkv3 zkQ|C;xU3)Q*aXR;Xok!Bk&aD}9ExVRtRL&x1j(UjhRgbij!lppie|X1pX%5I$)RY5 z%les)O^_UlX1J`M>(~Uzp=gH7`h|{7kQ|C;xU665*aXR;Xok!Bm5xo29ExVRtY7Qc z1j(UjhRgbmj!lppie|X1-|E-|$)RY5%le&;O^_UlX1J{1>(~Uzp=gH7`h$*5kQ|C; zxU4_w*aXR;Xok!Bla5W09ExVRtUv461j(UjhRgbkj!lppie|X1zv|co$)RY5%ley+ zO^_UlX1J`s>(~Uzp=gH7`iG89kQ|C;xU7Hb*aXR;Xok!BmyS)49ExVRtbgm+1j(Uj zhRgboj!lppie|X1|LWKT$)RY5%X*N%cCiVPL(vSE^;n;!~_6L2@XX;j*5lV-qBYq8Tph={hz+awwYNvYw%16C{VC z87}LYIyOOaD4OB2o~2_GB!{9IF6-GkHbHVIn&GmZqhk{!hoTuS>$y5ML2@XX;j*5m zV-qBYq8Tph`8qa1awwYNvR!mt2L2@XX;j&()V-qBYq8Tph$N&IL2@XX;j&(*V-qBY zq8Tph^*S~|awwYNvfiL$6C{VC87}LMIyOOaD4OB2-lSs_B!{9IF6+%YHbHVIn&GnE zqGJ;zhoTuS>wk4@g5*#%!)3iy$0kS)MKfI1+jMM#Ch zm|Fg5*#%!)1L{$0kS)MKfI1*K}-xoCP)rNGhEg$bZmm;P&C73{Zhv!NDf6a zT-L92Y=Y!aG{a^6TE`|x4n;Fu)^Budg5*#%!)5(e$0kS)MKfI1?{sW}(~Uz zp=gH7dWeoqkQ|C;xU7fj*aXR;Xokyrn2t@59ExVRtcUB^1j(UjhRb?{j!lppie|X1 zN9x!F$)RY5%X*ZKO^_UlX1J_J>(~Uzp=gH7dW?=ukQ|C;xU9$O*aXR;XokyroQ_S9 z9ExVRtjFuv1j(UjhRb?_j!lppie|X1C+gS)$)RY5%X*TIO^_UlX1J^;>(~Uzp=gH7 z`X3#eAUPDx;FM&0oep1!+v{|AI{xo!_u;ahs$&x*hoTuS>uEYRL2@XX;j*5tV-qBY zq8Tph89FvWawwYNvYx496C{VC87}KtIyOOaD4OB2o~>gOB!{9IF6%iuHbHVIn&GmZ zt78)+hoTuS>v=jhL2@XX;j*5uV-qBYq8Tph1v)lCawwYNvRt#ANL2@XX;j&(?V-qBYq8Tph z6*@LSawwYNvRvcLdL2@XX;j&(@V-qBYq8Tph4LUYKawwYNvfij;6C{VC87}KhIyOOaD4OB2 z-mGI2B!{9IF6%8iHbHVIn&GnkSH~tu4n;Fu)?0OKg5*#%!)3iq$0kS)MKfI1+jVS$ zv{e4n;Fu z)_Zkqg5*#%!)3is$0kS)MKfI1`*m!Bvvvn0Gg5*#%!)1L<$0kS)MKfI1*L7@yv{e4n;Fu)^~Mmg5*#% z!)1L>$0kS)MKfI1_jPQ7vvvv{e4n;Fu)_-+ug5*#%!(~0lX_#z+ z*T*oFz4n;Fu z)+2Omg5*#%!(}~E$0kS)MKfI1qjYS7*UdJX#4n;Fu))RDWg5*#%!(}~D$0kS)MKfI1lXPr?*+c+L2@XX;j*5gV-qBYq8TphnL0K>awwYNvYw@56C{VC87}MDIyOOaD4OB2 zo}*(EB!{9IF6+5EHbHVIn&GmZr(+W&hoTuS>-jo1L2@XX;j&(!V-qBYq8Tphg*rAt zawwYNvR*YE&L2@XX;j&(#V-qBYq8Tphl{z*-awwYNvR-9P|L2@XX;j-SKV-qBYq8a`lM|ZJA!LDoD z_LsCQ*_J+UGxOWb%*@Qp%*@OT@!GkO(PpVvvoaz*J;WPzERte#xHLn&Nyj27Hit_y z#G7?2l45hXG()^a$08{{oGsHV}ERte#xHLn&OUEK9Hit_y#JhDYl45hXG()^c$08{{oGsFjVERte#xHLn2NXH^6Hit_y#D{e( zl45hXG(&tu$08{{o zGsGu#ERte#xHLn2O2;B8Hit_y#HV#El45hXG(&tw$08{{oGsG8lERte#xHLn2Nyj27Hit_y#Fup}l45hX zG(&tv$08{{oGsHJ_ zERte#xHLn2OUEK9Hit_y#J6=Ul45hXG(&tx$08{{oGsF*dERte#xHLojNXH^6Hit_y#E*3>l45hXG(-GE z$08{{oGsG`-ERte# zxHLojO2;B8Hit_y#IJQMl45hXG(-GG$08{{oGsGWtERte#xHLojNyj27Hit_y#GiF6l45hXG(-GF$08{< zhf6cWUv(^!Vsp4OL;Ow0A}Kb9OEbjZbu5x%bGS4^{6ohgDK>{oGsHi2ERte#xHLoj zOUEK9Hit_y#J_bcl45hXG(-GH$08{{oGsL5GERte#xHLmNTE`+OHit_y#A9?Ul45hXG($XA z$08{{oGsKg0ERte# zxHLmNS;rzNHit_y#8Y%El45hXG(-4;?g8AqVz1NTt5bWOj{kdxc&d&?Qfv;FW{9Wh zSR}>faA}5kx{gIsYz~)Zh-c_nB*o@%X@+>Fjzv;z4wq(#XX#iZ#pZBnhIqD)MN(`I zmu86P=vXAh=5T3-c&?5`Qfv;FW{BtMSR}>faA}5kzK%swYz~)Zh!^NsB*o@%X@+>A zjzv;z4wq(#7wK3e#pZBnhIp}#MN(`Imu85U=vXAh=5T3-c&Uy>Qfv;FW{8*RSR}>f zaA}5kxsF9rYz~)Zh*#)XB*o@%X@+>Ejzv;z4wq(#SLs+J#pZBnhIqA(MN(`Imu869 z=vXAh=5T3-c&&~_Qfv;FW{B76SR}>faA}5ky^cjvYz~)Zh&Sk1B*o@%X@+>Cjzv;z z4wq(#H|ba;#pZBnhIq4%MN(`Imu85!=vXAh=5T3-c&m;@Qfv;FW{9`xSR}>faA}5k zyN*RtYz~)ZhGjzv;z4wq(#cj;Ip#pZBnhIqG*MN(`Imu86f=vXAh z=5T3-c(0B{Qfv;FW{CIcSR}>faA}5kzm7#xYz~)Zh!5ykB*o@%X@>Zqjzv;z4wq(# z59wGW#pZBnhWN0KMN(`Imu85M=vXAh=5T3-_^6IWQfv;FW{8jJSR}>faA}74xQ<0q zYz~)Zh)?KPB*o@%X@>Zujzv;z4wq(#Pw7}B#pZBnhWNCOMN(`Imu861=vXAh=5T3- z_^ggaQfv;FW{A(}SR}>faA}74ypBauYz~)Zh%e|^B*o@%X@>Zsjzv;z4wq(#FX>n$ z#pZBnhWN6MMN(`Imu85s=vXAh=5T3-_^OUYQfv;FW{9upSR}>faA}74x{gIsYz~)Z zh;QgvB*o@%X@>Zwjzv;z4wq(#Z|PVh#pZBnhWNIQMN(`Imu86X=vXAh=5T3-_^ysc zQfv;FW{B_USR}>faA}74zK%swYz~)Zh#%-!B*o@%X@>Zrjzv;z4wq(#AL&>m#pZBn zhWN3LMN(`Imu85c=vXAh=5T3-_^FOXQfv;FW{98ZSR}>faA}74xsF9rYz~)Zh+pVf zB*o@%X@>Zvjzv;z4wq(#U+GvR#pZBnhWNFPMN(`Imu86H=vXAh=5T3-_^pmbQfv;F zW{BVESR}>faA}74y^cjvYz~)Zh(G99B*o@%X@>Ztjzv;z4wq(#Kj~N`#pZBnhWN9N zMN(`Imu85+=vXAh=5T3-_^XaZQfv;FW{AJ(SR}>faA}74yN*RtYz~)Zh=1rZxjzv;z4wq(#f9Y5x#pZBnhWNLRMN(`Imu86n=vXAh=5T3-_^*ydQfv;FW{Cgk zSR}>faA}5k(Aew7UgtJUip}BD4Dnzci=@~bF3k`R(XmL1&Ee7v@lYL$q}UuT%@7aM zu}F%|;nEE8a2<=J*c>j+5RcHYNQ%wj(hTuP9gC#c94^fekJ7P7ip}BD4Do0ki=@~b zF3k{+(XmL1&Ee7v@mL*;q}UuT%@B{%u}F%|;nEE8cpZzR*c>j+5KqvtNQ%wj(hTuL z9gC#c94^fePtvhSip}BD4Dn{oGsJUrERte#xHLmNSH~hLHit_y#Pf74l45hXG($XJ$08{< zhf6cW3v?`!Vsp4OL%dMOA}Kb9OEbiabS#o$bGS4^yjaH~DK>{oGsH`DERte#xHLn& zRL3GIHit_y#LILnl45hXG()^x$08{{oGsJ6jERte#xHLn&R>vYKHit_y#Orh{l45hXG()^z$08{{oGsIhTERte#xHLn&RmUPJ zHit_y#M^W%l45hXG()^y$08{{oGsJszERte#xHLn&SH~hLHit_y#QStCl45hXG()^!$08{{oGsH)9ERte#xHLn2RL3GIHit_y z#K&|jl45hXG(&t`$08{{oGsI_fERte#xHLn2R>vYKHit_y#OHJ@l45hXG(&t|$08{{oGsIVPERte#xHLn2RmUPJHit_y#Mg8z zl45hXG(&t{$08{{o zGsJgvERte#xHLn2SH~hLHit_y#P@V8l45hXG(&t}$08{{oGsI7HERte#xHLojRL3GIHit_y#Lsjrl45hX zG(-Gc$08{{oGsJIn zERte#xHLojR>vYKHit_y#P4)0l45hXG(-Ge$08{{oGsItXERte#xHLojRmUPJHit_y#NTu*l45hXG(-Gd z$08{{oGsJ&%ERte# zxHLojSH~hLHit_y#Q$_Gl45hXG($Wnp85cbq}UuT%@7aPu}F%|;nEE85FLx8*c>j+ z5D(R{NQ%wj(hTu19gC#c94^fe57)6sip}BD4DkpZi=@~bF3k{+)Uim4&Ee7v@hBaO zq}UuT%@B{)u}F%|;nEE87#)kG*c>j+5RcWdNQ%wj(hTu99gC#c94^fekJqtCip}BD z4DkdVi=@~bF3k{6)Uim4&Ee7v@gyCKq}UuT%@9x4u}F%|;nEE86djAC*c>j+5dWW! zggJWF`Zvd?IwAg4U!6YHlKoU~$5a3Bd4NSyYz~)Zh^OgTB*o@%X@+>Zjzv;z z4wq(#XXscY#pZBnhIpoqMN(`Imu84(=~yJi=5T3-c(#s3Qfv;FW{BtLSR}>faA}5k zu8u`gYz~)Zi0A28B*o@%X@+>djzv;z4wq(#7wA|d#pZBnhIpZlMN(`Imu83;=~yJi z=5T3-c(IN}Qfv;FW{8*QSR}>faA}5ksg6ZbYz~)Zh?nVDB*o@%X@+>Yjzv;z4wq(# zSLj$I#pZBnhIplpMN(`Imu84p=~yJi=5T3-c(sm2Qfv;FW{B75SR}>faA}5kt&T-f zYz~)Zh}Y>@B*o@%X@+>cjzv;z4wq(#H|SU-#pZBnhIpfnMN(`Imu84J=~yJi=5T3- zc(aa0Qfv;FW{9`wSR}>faA}5ktByrdYz~)Zh_~rjB*o@%X@+>ajzv;z4wq(#cj#Co z#pZBnhIprrMN(`Imu84}=~yJi=5T3-c(;y4Qfv;FW{CIbSR}>faA}5kuZ~4hYz~)Z zi1+DOB*o@%X@+>ejzv;z4wq(#59nAV#pZBnhWMb4MN(`Imu83$=~yJi=5T3-_^^&e zQfv;FW{8jISR}>faA}74sE$QaYz~)Zh>z)5B*o@%X@>Z?jzv;z4wq(#Pv}@A#pZBn zhWMn8MN(`Imu84h=~yJi=5T3-__U5iQfv;FW{A(|SR}>faA}74td2!eYz~)Zh|lR* zB*o@%X@>Z`jzv;z4wq(#FX&h##pZBnhWMh6MN(`Imu84B=~yJi=5T3-__B^gQfv;F zW{9uoSR}>faA}74s*XicYz~)Zh_C5bB*o@%X@>Z^jzv;z4wq(#Z|GPg#pZBnhWMtA zMN(`Imu84>=~yJi=5T3-__mHkQfv;FW{B_TSR}>faA}74u8u`gYz~)Zi0|oGB*o@% zX@>Z|jzv;z4wq(#ALv*l#pZBnhWMe5MN(`Imu83`=~yJi=5T3-__2;fQfv;FW{98Y zSR}>faA}74sg6ZbYz~)Zh@a_LB*o@%X@>Z@jzv;z4wq(#U+7pQ#pZBnhWMq9MN(`I zmu84x=~yJi=5T3-__dBjQfv;FW{BVDSR}>faA}74t&T-fYz~)Zh~Md0B*o@%X@>Z{ zjzv;z4wq(#Kj>H_#pZBnhWMk7MN(`Imu84R=~yJi=5T3-__K~hQfv;FW{AJ&SR}>f zaA}74tByrdYz~)Zh`;GrB*o@%X@>Z_jzv;z4wq(#f9O~w#pZBnhWMwBMN(`Imu856 z=~yJi=5T3-__vNlQfv;FW{CgjSR}>faA}74uZ~4hYz~)Zi2vzWB*o@%X@+>v1NOQH z>~#;=>mIPzJz%eUz+U%&z3u^f-2?VIi^YR=ERte#xHLmNM8_g2Hit_y#6xu~l45hX zG($X0$08{{oGsL5H zERte#xHLmNM#my4Hit_y#A9_Vl45hXG($X2$08{^OVsp4OLp(vpA}Kb9 zOEbh1bu5x%bGS4^JW0nQDK>{oGsKg1ERte#xHLmNMaLp3Hit_ygsj+5Kq&wNQ%wj(hTu*9gC#c94^fe&(N_*ip}BD4Dn1Ii=@~b zF3k|n(y>U2&Ee7v@oXK7q}UuT%@EJgu}F%|;nEE8Tpf#~*c>j+5YN-GNQ%wj(hTu@ z9gC#c94^feFVL|_ip}BD4Dmu8i=@~bF3k`x(y>U2&Ee7v@nRi|q}UuT%@8lqu}F%| z;nEE8QXPw=*c>j+5HHiQNQ%wj(hTu(9gC#c94^feuh6kbip}BD4Dm`Gi=@~bF3k|H z(y>U2&Ee7v@oF85q}UuT%@D8Au}F%|;nEE8S{;j|*c>j+5U9gC#c z94^feZ_u$wip}BD4Dm)Ci=@~bF3k{c(y>U2&Ee7v@n#*1q}UuT%@A+Vu}F%|;nEE8 zRvn9^*c>j+5O345NQ%wj(hTu-9gC#c94^fe@6fSGip}BD4Dn7Ki=@~bF3k|{(y>U2 z&Ee7v@opW9q}UuT%@FU=u}F%|;nEE8ULA|1*c>j+5bx8mNQ%wj(hTu_9gC#c94^fe zAJDN#ip}BD4Dmr7i=@~bF3k`h(y>U2&Ee7v@nIc{q}UuT%@7~au}F%|;nEE8Q5}n< z*c>j+5FgXANQ%wj(hTu&9gC#c94^fepU|;Lip}BD4Dm@Fi=@~bF3k|1(y>U2&Ee7v z@o624q}UuT%@Ci_u}F%|;nEE8Ssja{*c>j+5TDbrNQ%wj(hTu=9gC#c94^feU(m5g zip}BD4Dm%Bi=@~bF3k{M(y>U2&Ee7v@ns#0q}UuT%@AMFu}F%|;nEE8RUM0@*c>j+ z5MR@=NQ%wj(hTu+9gC#c94^fe-_Ws0ip}BD4Dn4Ji=@~bF3k|%(y>U2&Ee7v@ogQ8 zq}UuT%@E(wu}F%|;nEE8T^)<0*c>j+5Z}|WNQ%wj(hTu^9gC#c94^feKhUvAip}BD z4Dmx9i=@~bF3k`>(y>U2&Ee7v@nao}q}UuT%@9A)u}F%|;nEE8Qyq(>*c>j+5I@tg zNQ%wj(hTu)9gC#c94^feztFKrip}BD4Dm}Hi=@~bF3k|X(y>U2&Ee7v@oOE6q}UuT z%@DuQu}F%|;nEE8TOEs}*c>j+5Wmy0NQ%wj(hTu?9gC#c94^fef6%c=ip}BD4Dm-D zi=@~bF3k{s(y>U2&Ee7v@n;>2q}UuT%@BXlu}F%|;nEE8R~?I_*c>j+5P#FLNQ%wj z(hTu;9gC#c94^fe|Io2Wip}BD4DnALi=@~bF3k}C(y>U2&Ee7v@oycAq}UuT%@F_5 zu}F%|;nEE8Umc62*c>j+5dYJ$NQ%wj(hTt+O9YFg*c>j+5D(U|NQ%wj(hTts9gC#c z94^fe57n_qip}BD4Dm1>i=@~bF3k`R*Re>7&Ee7v@dzD@q}UuT%@B{&u}F%|;nEE8 zC>@KW*c>j+5RcZeNQ%wj(hTt!9gC#c94^fekJYhAip}BD4DmP}i=@~bF3k{+*Re>7 z&Ee7v@dO=j+5Kq>zNQ%wj(hTtw9gC#c94^fe zPPjh6A}QRaY_HSdB)Pp#_f#GK_aw#UaA}5knvO+MYz~)Zh^OmVB*o@%X@+=)jzv;z z4wq(#XX;oa#pZBnhIp2aMN(`Imu84(>sTbk=5T3-c#e)mQfv;FW{BtNSR}>faA}5k zo{mLQYz~)Zi0A8AB*o@%X@+=#jzv;z4wq(#7wT9f#pZBnhIo;VMN(`Imu83;>sTbk z=5T3-c!`chQfv;FW{8*SSR}>faA}5knT|zLYz~)Zh?nbFB*o@%X@+=(jzv;z4wq(# zSL#?K#pZBnhIo~ZMN(`Imu84p>sTbk=5T3-c#V!lQfv;FW{B77SR}>faA}5kosLCP zYz~)Zh}Y{_B*o@%X@+=%jzv;z4wq(#H|kg<#pZBnhIo^XMN(`Imu84J>sTbk=5T3- zc#DojQfv;FW{9`ySR}>faA}5kn~p_NYz~)Zh_~xlB*o@%X@+=*jzv;z4wq(#cj{Oq z#pZBnhIp5bMN(`Imu84}>sTbk=5T3-c#n=nQfv;FW{CIdSR}>faA}5kpN>URYz~)Z zi1+JQB*o@%X@>ZKjzv;z4wq(#59(MX#pZBnhWL<sTbk=5T3-_=t{0 zQfv;FW{8jKSR}>faA}74n2tqKYz~)Zh>z=7B*o@%X@>ZOjzv;z4wq(#PwH4C#pZBn zhWM0@MN(`Imu84h>sTbk=5T3-_>7K4Qfv;FW{A(~SR}>faA}74oQ_3OYz~)Zh|lX- zB*o@%X@>ZMjzv;z4wq(#FX~t%#pZBnhWL_>MN(`Imu84B>sTbk=5T3-_==82Qfv;F zW{9uqSR}>faA}74nvO+MYz~)Zh_CBdB*o@%X@>ZQjzv;z4wq(#Z|Ybi#pZBnhWM6_ zMN(`Imu84>>sTbk=5T3-_>PW6Qfv;FW{B_VSR}>faA}74o{mLQYz~)Zi0|uIB*o@% zX@>ZLjzv;z4wq(#AL>{n#pZBnhWL?=MN(`Imu83`>sTbk=5T3-_=%21Qfv;FW{98a zSR}>faA}74nT|zLYz~)Zh@b0NB*o@%X@>ZPjzv;z4wq(#U+P#S#pZBnhWM3^MN(`I zmu84x>sTbk=5T3-_>GQ5Qfv;FW{BVFSR}>faA}74osLCPYz~)Zh~Mj2B*o@%X@>ZN zjzv;z4wq(#Kk8T{#pZBnhWL|?MN(`Imu84R>sTbk=5T3-_=}E3Qfv;FW{AJ)SR}>f zaA}74n~p_NYz~)Zh`;MtB*o@%X@>ZRjzv;z4wq(#f9hBy#pZBnhWM9`MN(`Imu856 z>sTbk=5T3-_>Yc7Qfv;FW{CglSR}>faA}74pN>URYz~)ZhzI#R2Sj=5T3-c$khwQfv;FW{8LDSR}>faA}5kgpNg0Yz~)Z zh)3#JB*o@%X@+=|jzv;z4wq(#N9$N5#pZBnhIovQMN(`Imu85^>R2Sj=5T3-c$|(! zQfv;FW{Ah@SR}>faA}5kf{sN}Yz~)Zh$re;B*o@%X@+=`jzv;z4wq(#C+k=w#pZBn zhIopOMN(`Imu3k6M)v@Vq}aGk*sTbk=5T3-c#e)mQfv;F zW{BtNSR}>faA}5ko{mLQYz~)Zi0A8AB*o@%X@+=#jzv;z4wq(#7wT9f#pZBnhIo;V zMN(`Imu83;>sTbk=5T3-c!`chQfv;FW{8*SSR}>faA}5knT|zLYz~)Zh?nbFB*o@% zX@+=(jzv;z4wq(#SL#?K#pZBnhIo~ZMN(`Imu84p>sTbk=5T3-c#V!lQfv;FW{B77 zSR}>faA}5kosLCPYz~)Zh}Y{_B*o@%X@+=%jzv;z4wq(#H|kg<#pZBnhIo^XMN(`I zmu84J>sTbk=5T3-c#DojQfv;FW{9`ySR}>faA}5kn~p_NYz~)Zh_~xlB*o@%X@+=* zjzv;z4wq(#cj{Oq#pZBnhIp5bMN(`Imu84}>sTbk=5T3-c#n=nQfv;FW{CIdSR}>f zaA}5kpN>URYz~)Zi1+JQB*o@%X@>ZKjzv;z4wq(#59(MX#pZBnhWL<sTbk=5T3-_=t{0Qfv;FW{8jKSR}>faA}74n2tqKYz~)Zh>z=7B*o@%X@>ZOjzv;z z4wq(#PwH4C#pZBnhWM0@MN(`Imu84h>sTbk=5T3-_>7K4Qfv;FW{A(~SR}>faA}74 zoQ_3OYz~)Zh|lX-B*o@%X@>ZMjzv;z4wq(#FX~t%#pZBnhWL_>MN(`Imu84B>sTbk z=5T3-_==82Qfv;FW{9uqSR}>faA}74nvO+MYz~)Zh_CBdB*o@%X@>ZQjzv;z4wq(# zZ|Ybi#pZBnhWM6_MN(`Imu84>>sTbk=5T3-_>PW6Qfv;FW{B_VSR}>faA}74o{mLQ zYz~)Zi0|uIB*o@%X@>ZLjzv;z4wq(#AL>{n#pZBnhWL?=MN(`Imu83`>sTbk=5T3- z_=%21Qfv;FW{98aSR}>faA}74nT|zLYz~)Zh@b0NB*o@%X@>ZPjzv;z4wq(#U+P#S z#pZBnhWM3^MN(`Imu84x>sTbk=5T3-_>GQ5Qfv;FW{BVFSR}>faA}74osLCPYz~)Z zh~Mj2B*o@%X@>ZNjzv;z4wq(#Kk8T{|363fv;}PatevZYunv_+cu|d+qP{x z&N>qnYhQi0b(2xG>u^bmW{5xPSZofLq-citla9saa7l`0h(GICYz~*CXomQUj>YD1 zNs4BOzv@_Q4ws~8hWML~#pZBHie`wv>sV|Km!xQh_=k?g=5R@hW{7|4SZofLq-cit zmyX5ea7l`0h=1!?Yz~*CXomQYj>YD1Ns4BO|LRz54ws~8hIo)0ek?YJOHwpLJXptK zbGRf$GsHu5EH;NrQZz$6RL5d-xFkh0#KUwfHit`6G($XG$6|B1BtsbSyT9OHwpLJX*(MbGRf$GsI(bEH;NrQZz$6R>xvcbSyT9OHwpLJXyzLbGRf$ zGsIJLEH;NrQZz$&IpTjYD1Ns4BOXX{vO4ws~8hIo#S#pZBH zie`xC>R4YD1Ns4BO7wcGT4ws~8hIomN#pZBHie`wH>R4YD1Ns4BOSL;}84ws~8hIoyR#pZBHie`w{ z>R4L=5R@hW{B78SZofLq-chCgO0`Ka7l`0h&Sq3Yz~*CXoh%`j>YD1 zNs4BOH|tnz4ws~8hIosP#pZBHie`xa)v?$dE=kc0@m3v+&Eb+1%@A+XvDh3gNzn}P zb{&h&;gS^15bw~j*c>iN(G2lU9gEH3k`&Dl@6xf@94<-G4DoIqi_PJZ6wMIt(XrSZ zE=kc0@m?K^&Eb+1%@FU?vDh3gNzn}PejSU=;gS^15FgO7*c>iN(G2lH9gEH3k`&Dl zAJVbd94<-G4Dn$di_PJZ6wMGH(XrSZE=kc0@lhR%&Eb+1%@7~cvDh3gNzn}PaUF}z z;gS^15TDSo*c>iN(G2lP9gEH3k`&DlpVG0|94<-G4Do3li_PJZ6wMHy(XrSZE=kc0 z@mU><&Eb+1%@Ci{vDh3gNzn}Pc^!+*;gS^15MR)-*c>iN(G2lL9gEH3k`&DlU(&JI z94<-G4Dn?hi_PJZ6wMG{(XrSZE=kc0@l_p*&Eb+1%@AMHvDh3gNzn}PbsdY%;gS^1 z5Z}iN(G2lT9gEH3k`&Dl-_o(z94<-G4DoFpi_PJZ6wMId(XrSZE=kc0@m(E@ z&Eb+1%@E(yvDh3gNzn}PeI1L<;gS^15I@kd*c>iN(G2lJ9gEH3k`&DlKhm+-94<-G z4Dn+fi_PJZ6wMGn(XrSZE=kc0@lzd(&Eb+1%@9A+vDh3gNzn}Pa~+G#;gS^15Wmo| z*c>iN(G2lR9gEH3k`&DlztXYT94<-G4Do9ni_PJZ6wMI7(XrSZE=kc0@mn2>&Eb+1 z%@DuSvDh3gNzn}PdmW3-;gS^15P#6I*c>iN(G2lN9gEH3k`&Dlf6}qo94<-G4Dn|j zi_PJZ6wMHS(XrSZE=kc0@mC#-&Eb+1%@BXnvDh3gNzn}PcO8q(;gS^15dYAz*c>iN z(G2lV9gEH3k`&Dl|I)G894<-G4DoLri_PJZ6wMI-(XrSZE=kc0@n0Q_&Eb+1%@7ar zH!c>N!zC%2As(z_u{m6lq8Z{LIu@J5B`KOA9;#!pIb4#W8RB6&7MsH*DViZ3u4Az| zT#}+0;t@I)o5Lk3njs#kW3f40lA;;nQ92fz!zC%2As($`u{m6lq8Z{bIu@J5B`KOA z9;;)qIb4#W8RBs|7MsH*DViZ3uVb+}T#}+0;t4tyo5Lk3njxO3W3f40lA;;nNjesr z!zC%2A)c&bu{m6lq8Z{TIu@J5B`KOAo~mQ9Ib4#W8RBU=oK7{b)A9dTQZz$6pkuK) zT#}+0;^{gTo5Lk3njxN{W3f40lA;;nnK~Am!zC%2A)cjUu{m6lq8Z}ZIu@J5B`KOA zo}**2Ib4#W8REG*7MsH*DViakr(>}>T#}+0;`urjo5Lk3njv1GW3f40lA;;ng*q0S z!zC%2Azq|ou{m6lq8Z}FIu@J5B`KOAUZP{MIb4#W8RDfn7MsH*DViZ(rem==T#}+0 z;^jIPo5Lk3njv1HW3f40lA;;nl{yxi!zC%2Azr0pu{m6lq8Z}VIu@J5B`KOAUZZ2N zIb4#W8RE4%7MsH*DViZ(r(>}>T#}+0;`KTfo5Lk3njzkxW3f40lA;;njXD;a!zC%2 zA>O28u{m6lq8Z}NIu@J5B`KOA-lAi%Ib4#W8RCC+EH;NrQZz%nRmWm;xFkh0#M^W% zHit`6G()^y$6|B1Bt^bSyT9OHwpLyj#a&bGRf$ zGsJszEH;NrQZz%nSI1&=xFkh0#QStCHit`6G()^!$6|B1BtQbSyT9OHwpLd|1a~bGRf$GsH)9EH;NrQZz$+RL5d-xFkh0#K&|jHit`6 zG(&t`$6|B1BtwbSyT9OHwpLd|Jn1bGRf$GsI_f zEH;NrQZz$+R>xvgbSyT9OHwpLd|Ah0bGRf$GsIVPEH;NrQZz$+RmWm;xFkh0#Mg8zHit`6G(&t{ z$6|B1Bt=bSyT9OHwpLd|St2bGRf$GsJgvEH;Nr zQZz$+SI1&=xFkh0#P@V8Hit`6G(&t}$6|B1BtY zbSyT9OHwpL{8-0gbGRf$GsI7HEH;NrQZz&SRL5d-xFkh0#LsjrHit`6G(-Gc$6|B1 zBt&bSyT9OHwpL{94CibGRf$GsJInEH;NrQZz&S zR>xvhf7j4L;O+4Vsp48MKi>obSyT9 zOHwpL{8`6hbGRf$GsItXEH;NrQZz&SRmWm;xFkh0#NTu*Hit`6G(-Gd$6|B1Bt|bSyT9OHwpL{9DIjbGRf$GsJ&%EH;NrQZz&SSI1&= zxFkh0#Dn}fpT*{INs4BO2kTgD4ws~8hIojM#pZBHie`w1>R4YD1Ns4BON9$N@4ws~8hIovQ z#pZBHie`w%>R4YD1Ns4BOC+k>j4ws~8hIopO#pZBHie`wX>R4jWhf7j4Lp)!{Vsp48 zMKi<;bSyT9OHwpLyimttbGRf$GsKH@EH;NrQZz%nSjS>>xFkh0#7lH6Hit`6G()^p z$6|B1BtvSwOhf7j4L%d$cVsp48MKi=3 zbSyT9OHwpLyivzubGRf$GsK&8EH;NrQZz%nS;t~?xFkh0#9MSMHit`6G(-Haj>YD1 zNs4BOx9V7I4ws~8hIpHf#pZBHie`wn>sV|Km!xQhc!!R~=5R@hW{7v{SZofLq-chC zmyX5ea7l`0hYD1Ns4BO_v%<|4ws~8hIpTj#pZBHie`xS>sV|K zm!xQh_<)YZ=5R@hW{3~!SZofLq-citkdDRXa7l`0h!5*nYz~*CXomQRj>YD1Ns4BO zkLp-#4ws~8hWMC{#pZBHie`w9>sV|Km!xQh_=Jwd=5R@hW{6MfSZofLq-citl#a#b za7l`0h)?TSYz~*CXomQVj>YD1Ns4BO&+1rg4ws~8hWMP0#pZBHie`w<>sV|Km!xQh z_=1kb=5R@hW{5B9SZofLq-citl8(jZa7l`0h%f6{Yz~*CXomQTj>YD1Ns4BOuj*KA z4ws~8hWMI}#pZBHie`wf>sV|Km!xQh_=b+f=5R@hW{7XYD1Ns4BO@9J1=4ws~8hWMV2#pZBHie`xK>sV|Km!xQh_<@ea z=5R@hW{4l^SZofLq-citk&eaYa7l`0h#%`%Yz~*CXomQSj>YD1Ns4BOpXyj_4ws~8 zhWMF|#pZBHie`wP>sV|Km!xQh_=S$e=5R@hW{6+vSZofLq-citm5#;ca7l`0h+pei zYz~*CXomQWj>YD1Ns4BO-|ARw4ws~8hWMS1#pZBHie`x4>sV|Km!xQh_=Aqc=5R@h zW{5xPSZofLq-citla9saa7l`0h(GICYz~*CXomQUj>YD1Ns4BOzv@_Q4ws~8hWML~ z#pZBHie`wv>sV|Km!xQh_=k?g=5R@hW{7|4SZofLq-citmyX5ea7l`0h=1!?Yz~*C zXomQYj>YD1Ns4BO|LRz54ws~8hIo)yE?I02m!xQhc(9Je=5R@hW{8LASZofLq-chC zsE)YD1Ns4BON9b5=4ws~8hIpio#pZBHie`vM=~!$I zm!xQhc(jhi=5R@hW{Ah=SZofLq-chCtd7Oza7l`0h{x$zYz~*CXoh&aj>YD1Ns4BO zC+Jvg4ws~8hIpcm#pZBHie`u>=~!$Im!xQhc(RVg=5R@hW{9WgSZofLq-chCs*c6x za7l`0h^OiB*GKa@9VXsSvy1+3weJuQ=vZtHm!xQhc)E_o=5R@hW{79#SZofLq-chC zrjEtta7l`0h-c|oYz~*CXoh&Uj>YD1Ns4BO=jd2$4ws~8hIp=y#pZBHie`xC=~!$I zm!xQhc)pIs=5R@hW{4N)SZofLq-chCp^nAoa7l`0h!^QtYz~*CXoh&Pj>YD1Ns4BO zm*`k*4ws~8hIpxt#pZBHie`wH=~!$Im!xQhc)5YD1Ns4BO*XUSm4ws~8hIp-x#pZBHie`w{=~!$Im!xQh zc)gCr=5R@hW{5ZFSZofLq-chCqmISqa7l`0h&Sn2Yz~*CXoh&Rj>YD1Ns4BOx9C`G z4ws~8hWK9{i_PJZ6wMHC)v?$dE=kc0@irZc&Eb+1%@A+bvDh3gNzn}P4jqfl;gS^1 z5bxBn*c>iN(G2k}9gEH3k`&Dl@7A%{94<-G4DlWvi_PJZ6wMIt)v?$dE=kc0@je}k z&Eb+1%@FU`vDh3gNzn}P0Ue9Y;gS^15FgaB*c>iN(G2k+9gEH3k`&DlAJ(zh94<-G z4Dk^ii_PJZ6wMGH)v?$dE=kc0@i85X&Eb+1%@7~gvDh3gNzn}P2_1{g;gS^15TDes z*c>iN(G2k^9gEH3k`&DlpVqP194<-G4DlHqi_PJZ6wMHy)v?$dE=kc0@i`rf&Eb+1 z%@Cj0vDh3gNzn}P1s#jc;gS^15MR`>*c>iN(G2k=9gEH3k`&DlU)HhM94<-G4Dl5m zi_PJZ6wMG{)v?$dE=kc0@iiTb&Eb+1%@AMLvDh3gNzn}P4IPWk;gS^15Z~0X*c>iN z(G2k|9gEH3k`&Dl-`26%94<-G4DlTui_PJZ6wMId)v?$dE=kc0@jV@j&Eb+1%@E($ zvDh3gNzn}P109Ra;gS^15I@wh*c>iN(G2k;9gEH3k`&DlKi09>94<-G4Dk~ki_PJZ z6wMGn)v?$dE=kc0@iQHZ&Eb+1%@9A=vDh3gNzn}P3muEi;gS^15Wm#1*c>iN(G2k` z9gEH3k`&Dlzt*wX94<-G4DlNsi_PJZ6wMI7)v?$dE=kc0@jD%h&Eb+1%@DuWvDh3g zNzn}P2OW#e;gS^15P#IM*c>iN(G2k?9gEH3k`&Dlf7Y?s94<-G4DlBoi_PJZ6wMHS z)v?$dE=kc0@i!fd&Eb+1%@BXrvDh3gNzn}P4;_om;gS^15dYM%*c>iN(G2k~9gEH3 zk`&Dl|JJeC94<-G4DlZwi_PJZ6wMI-)v?$dE=kc0@t`)Z^U5Wg!zC%2As(z_u{m6l zq8Z{LIu@J5B`KOA9;#!pIb4#W8RB6&7MsH*DViZ3u4Az|T#}+0;t@I)o5Lk3njs#k zW3f40lA;;nQ92fz!zC%2As($`u{m6lq8Z{bIu@J5B`KOA9;;)qIb4#W8RBs|7MsH* zDViZ3uVb+}T#}+0;t4tyo5Lk3njxO3W3f40lA;;nNjesr!zC%2A)c&bu{m6lq8Z{T zIu@J5B`KOAo~mQ9Ib4#W8NvxVuPK|?>2Q}Nj;gS^15YN=H*c>iN(G2k{9gEH3k`&Dl&(^Wn94<-G4DlQti_PJZ6wMIN z)v?$dE=kc0@jM-i&Eb+1%@EJmvDh3gNzn}P0v(IZ;gS^15HHlR*c>iN(G2k-9gEH3 zk`&DlFV?Zx94<-G4Dk{ji_PJZ6wMGX)v?$dE=kc0@iHBY&Eb+1%@8lwvDh3gNzn}P z3LT5h;gS^15UiN(G2k_9gEH3k`&Dluhy~H94<-G4DlKri_PJZ6wMH?)v?$d zE=kc0@j4xg&Eb+1%@D8GvDh3gNzn}P1|5sd;gS^15O376*c>iN(G2k>9gEH3k`&Dl zZ`QHc94<-G4Dl8ni_PJZ6wMI-t7EY_T#}+0;;lLso5Lk3njzk%W3f40lA;;n?K&2l z!zC%2A>N^5u{m6lq8Z|yIu@J5B`KOA-lb!)Ib4#W8RFeK7MsH*DVibPqhql-T#}+0 z;=MW+o5Lk3njzk&W3f40lA;;n{W=z#!zC%2AwHmEu{m6lq8Z|YIu@J5B`KOAKBQx@ zIb4#W8REk_7MsH*DViZZqGPc+T#}+0;-fkio5Lk3njt=>W3f40lA;;n<2n|b!zC%2 zAwHpFu{m6lq8Z|oIu@J5B`KOAKBZ%^Ib4#W8RFAA7MsH*DViZZqhql-T#}+0;pB*j!zC%2A-ZKn!zC%2A^xFbu{m6lq8Z|! zIu@J5B`KOA{-tBFIb4#W8RFkM7MsH*DVibvqhql-T#}+0;=ei;o5Lk3njs!E=5=FU z=aowim!xQhc(9Je=5R@hW{8LASZofLq-chCsE)YD1 zNs4BON9b5=4ws~8hIpio#pZBHie`vM=~!$Im!xQhc(jhi=5R@hW{Ah=SZofLq-chC ztd7Oza7l`0h{x$zYz~*CXoh&aj>YD1Ns4BOC+Jvg4ws~8hIpcm#pZBHie`u>=~!$I zm!xQhc(RVg=5R@hW{9WgSZofLq-chCs*c6xa7l`02&d=%2d^oc*XeMR+`LYQUG#q| z9?-Ga94<-G4Doawi_PJZ6wMIN(6QJYE=kc0@k||y&Eb+1%@EJhvDh3gNzn}PY#ocu z;gS^15YN%E*c>iN(G2li9gEH3k`&Dl&(pEk94<-G4Doy&i_PJZ6wMGX(6QJYE=kc0 z@j@Mo&Eb+1%@8lrvDh3gNzn}PVjYXk;gS^15HHcO*c>iN(G2lY9gEH3k`&DlFVnHu z94<-G4DoUui_PJZ6wMH?(6QJYE=kc0@k$+w&Eb+1%@D8BvDh3gNzn}PY8{Ks;gS^1 z5UiN(G2lg9gEH3k`&DluhX&E94<-G4Dos$i_PJZ6wMHC(6QJYE=kc0@kSks z&Eb+1%@A+WvDh3gNzn}PW*v*o;gS^15O2}3*c>iN(G2mwIu@J5B`KOA-l}7OTH zu{m6lq8Z{nIu@J5B`KOA-m7D=Ib4#W8RC697MsH*DVibPuVb+}T#}+0;sZJso5Lk3 znjt=@W3f40lA;;nLpm0l!zC%2AwH~Qu{m6lq8Z{NIu@J5B`KOAKB{A}Ib4#W8RBC) z7MsH*DViZZu4Az|T#}+0;uAU+o5Lk3njt=^W3f40lA;;nQ#ux#!zC%2AwI2Ru{m6l zq8Z{dIu@J5B`KOAKC5G~Ib4#W8RBy~7MsH*DViZZuVb+}T#}+0;tM(!o5Lk3njyZZ zW3f40lA;;nOF9;t!zC%2A-=3*u{m6lq8Z{VIu@J5B`KOAzN%xfIb4#W8RBa?7MsH* zDVia^u4Az|T#}+0;u|^^o5Lk3njyZaW3f40lA;;nTRIk-!zC%2A-=6+u{m6lq8Z{l zIu@J5B`KOAzN=%gIb4#W8RC077MsH*DVia^uVb+}T#}+0;s-hwo5Lk3njwCuW3f40 zlA;;nM>-ap!zC%2A%3i5u{m6lq8Z{RIu@J5B`KOAeyU@!Ib4#W8RBO;7MsH*DViaE zu4Az|T#}+0;uks=o5Lk3njwCvW3f40lA;;nS2`A(!zC%2A%3l6u{m6lq8Z{hIu@J5 zB`KOAeyd}#Ib4#W8RB<37MsH*DViaEuVb+}T#}+0;tx6&o5Lk3nj!wEW3f40lA;;n zPdXNx!zC%2A^xmmu{m6lq8Z{ZIu@J5B`KOA{;FfKIb4#W8RBm`7MsH*DVibvu4Az| zT#}+0;vYH|o5Lk3nj!wFW3f40lA;;nUpf|>!zC%2A^xpnu{m6lq8Z{pIu@J5B`KOA z{;OlLIb4#W8R9|l!2ht=94<-G4Dnzci_PJZ6wMG1(XrSZE=kc0@lYL$&Eb+1%@7aM zvDh3gNzn}Pa2<=y;gS^15RcHY*c>iN(G2lO9gEH3k`&DlkJ7Q&94<-G4Do0ki_PJZ z6wMHi(XrSZE=kc0@mL*;&Eb+1%@B{%vDh3gNzn}PcpZz);gS^15Kqvt*c>iN(G2lK z9gEH3k`&DlPtvj294<-G4Dn}> zT#}+0;`urjo5Lk3njv1GW3f40lA;;ng*q0S!zC%2Azq|ou{m6lq8Z}FIu@J5B`KOA zUZP{MIb4#W8RDfn7MsH*DViZ(rem==T#}+0;^jIPo5Lk3njv1HW3f40lA;;nl{yxi z!zC%2Azr0pu{m6lq8Z}VIu@J5B`KOAUZZ2NIb4#W8RE4%7MsH*DViZ(r(>}>T#}+0 z;`KTfo5Lk3njzkxW3f40lA;;njXD;a!zC%2A>O28u{m6lq8Z}NIu@J5C8__%(OoQ2 z5Zl}ueI-Y-W$E$4%(-D^W@ct)W@hH3?)p<*t4H6oC%cZ1X@>P?9YL}=6qjaLZ_yDX zn?rGFhV@n*L9#g%mu6UR(-9<_Lvd+_^>!UWvN;r&W?1jg5hR;KacPG2P8~tAITV*> zSntviB%4EVX@>P~9YL}=6qjaL@6iz?n?rGFhV@<@L9#g%mu6V+(-9<_Lvd+_^?n^e zvN;r&W>_E45hR;KacPG2K^;M|ITV*>SRc|6B%4EVX@>P-9YL}=6qjaLAJGvcn?rGF zhV@Y$L9#g%mu6TW(-9<_Lvd+_^>H0RvN;r&W>}xl5hR;KacPG2NgYA5ITV*>SfA1n zB%4EVX@>P_9YL}=6qjaLpV1K{n?rGFhV@w;L9#g%mu6U>(-9<_Lvd+_^?4mZvN;r& zW>{a)5hR;KacPG2MIAx1ITV*>SYOf+B%4EVX@>P>9YL}=6qjaLU(pdHn?rGFhV@k) zL9#g%mu6UB(-9<_Lvd+_^>rOVvN;r&W?0|Q5hR;KacPG2O&vk9ITV*>Sl`kSB%4EV zX@>P}9YL}=6qjaL-_a2yn?rGFhV@+?L9#g%mu6Vs(-9<_Lvd+_^?e;dvN;r&W>`Pa z5hR;KacPG2Lmfe~ITV*>SU=JcB%4EVX@>P<9YL}=6qjaLKhY5+n?rGFhV@e&L9#g% zmu6T$(-9<_Lvd+_^>ZCTvN;r&W>~+_5hR;KacPG2OC3S7ITV*>SijN{B%4EVX@>P{ z9YL}=6qjaLztIsSn?rGFhV@$=L9#g%mu6VM(-9<_Lvd+_^?MybvN;r&W>|mF5hR;K zacPG2M;$@3ITV*>Sbx$HB%4EVX@>P@9YL}=6qjaLf6);nn?rGFhV@q+L9#g%mu6Uh z(-9<_Lvd+_^>-aXvN;r&W?28w5hR;KacPG2PaQ$BITV*>SpU)yB%4EVX@>Q09YL}= z6qjaL|Ira7n?rGFhV@?^L9#g%mu6TGe1N^~0rt8F*y|o(uXD>K#ibe6gLDMR=1^Rk zVLez!kZcacr5V;kbOg!fP+Xc}Jyb`KY!1bx8P>ye1j*)5T$*7$Tt|>>4#lMz)+2NT z$>va8nqfUsN04j|#ibe6qjUtx=1^RkVLe($kZcacr5V;^bOg!fP+Xc}Jyu7MY!1bx z8P?-;1j*)5T$*7$UPq8@4#lMz))RCD$>va8nqfUrN04j|#ibe6lXL{h=1^RkVLe$# zkZcacr5V;!bOg!fP+Xc}`PJM52okq0+v{{Vac-~E;cNTf6W+<@P+Xc}JxxcDY!1bx z8P?Nv1j*)5T$*7$Lr0Ko4#lMz)-!bk$>va8nqfUlN04j|#ibe6vvmZ?=1^RkVLeAj zkZcacr5V<9bp*-gP+Xc}Jx@oFY!1bx8P@Z41j*)5T$*9MKu3^l4#lMz)(dq6$>va8 znqj?2N04j|#ibe6i**Fa=1^RkVZB60kZcacr5V;sbp*-gP+Xc}y-Y`tY!1bx8P>~n z1j*)5T$*9MLPwBn4#lMz)+==c$>va8nqj?4N04j|#ibe6t91m)=1^RkVZBC2kZcac zr5V<1bp*-gP+Xc}y-r7vY!1bx8P@A{1j*)5T$*9MK}V2m4#lMz)*E#M$>va8nqj?3 zN04j|#ibe6n{@=q=1^RkVZB91kZcacr5V;+bp*-gP+Xc}y-i1uY!1bx8P?l%1j*)5 zT$*9MLr0Ko4#lMz);o0s$>va8nqj?5N04j|#ibe6yLAM~=1^RkVZBF3kZcacr5Vva8nqhrNN04j| z#ibe6hjj$W=1^RkVSPkLkZcacr5V;obp*-gP+Xc}eN0D?Y!1bx8P>;j1j*)5T$*8h zLPwBn4#lMz)+coY$>va8nqhrPN04j|#ibe6r*#C$=1^RkVSPqNkZcacr5V;|bp*-g zP+Xc}eNIP^Y!1bx8P?}@1j*)5T$*8hK}V2m4#lMz))#dI$>va8nqhrON04j|#ibe6 zmvscm=1^RkVSPnMkZcacr5V;&bp*-gP+Xc}eN9J@Y!1bx8P?Zz1j*)5T$*8hLr0Ko z4#lMz);Dzo$>va8nqhrQN04j|#ibe6w{--`=1^RkVSPtOkZcacr5V?A$>va8nqmD&N04j|#ibe6k97pe z=1^RkVf{o$kZcacr5V;wbp*-gP+Xc}{Y*!YY!1bx8P?Br1j*)5T$*A1LPwBn4#lMz z)-QDg$>va8nqmD)N04j|#ibe6uXO~;=1^RkVf{u&kZcacr5V<5bp*-gP+Xc}{Z2=a zY!1bx8P@N01j*)5T$*A1K}V2m4#lMz)*p2Q$>va8nqmD(N04j|#ibe6pLGPu=1^Rk zVf{r%kZcacr5V;=bp*-gP+Xc}{Y^)ZY!1bx8P?x*1j*)5T$*A1Lr0Ko4#lMz)<1Ow z$>va8nqmD*N04j|#ibe6zjXx3=1^RkVf{x(kZcacr5Vva8nqfU$ zN04j|#ibe6BXk7G=1^RkVLehukZcacr5Vva8nqfU&N04j|#ibe66LbX0=1^RkVLeetkZcacr5VC)pf| zOEave=?Id|p|~`|db*Av*&K>XGpuLm2$IdAxHQ9hrj8)l9EwXbtY_&6lFgyGG{btf zjv(0_ic2%B=jaHM&7rt7!+NfcAlV#>OEawJ=?Id|p|~`|dcKYz*&K>XGprZr2$IdA zxHQ9hp^hNg9EwXbtQYABlFgyGG{btajv(0_ic2%Bm*@zR&7rt7!+NQXAlV#>OEavO z=?Id|p|~`|dby4u*&K>XGptwW2$IdAxHQ9hrH&xk9EwXbtXJs>lFgyGG{btejv(0_ zic2%B*XRh6&7rt7!+NcbAlV#>OEaw3=?Id|p|~`|dcBSy*&K>XGpsl02$IdAxHQ9h zqmCfi9EwXbtT*WhlFgyGG{btcjv(0_ic2%Bx9A9x&7rt7!+NWZAlV#>OEavu=?Id| zp|~`|db^Gw*&K>XGpu*$2$IdAxHQ9hr;Z@m9EwXbtas@MlFgyGG{btgjv(0_ic2%B z_vi?c&7rt7!+NidAlV#>OEawZ=?Id|p|~`|dcTe!*&K>XGprBj2$IdAxHQB1ppGEf z9EwXbtPkl3lFgyGG{gF^jv(0_ic2%BkLU=J&7rt7!}_R>AlV#>OEavG=?Id|p|~`| z`nZlD*&K>XGptYO2$IdAxHQB1q>doj9EwXbtWW6(lFgyGG{gF|jv(0_ic2%B&*%t} z&7rt7!}_d_AlV#>OEav`=?Id|p|~`|`n--H*&K>XGpsM@2$IdAxHQB1qK+Wh9EwXb ztS{*ZlFgyGG{gF`jv(0_ic2%BujmMp&7rt7!}_X@AlV#>OEavm=?Id|p|~`|`nrxF z*&K>XGpuju2$IdAxHQB1rj8)l9EwXbtZ(TElFgyGG{gF~jv(0_ic2%B@8}4U&7rt7 z!}_j{AlV#>OEawR=?Id|p|~`|`o4}J*&K>XGprxz2$IdAxHQB1p^hNg9EwXbtRLwJ zlFgyGG{gF_jv(0_ic2%BpXdmZ&7rt7!}_U?AlV#>OEavW=?Id|p|~`|`nirE*&K>X zGpt|e2$IdAxHQB1rH&xk9EwXbtY7H}lFgyGG{gF}jv(0_ic2%B-{=UE&7rt7!}_g` zAlV#>OEawB=?Id|p|~`|`n`@I*&K>XGps-82$IdAxHQB1qmCfi9EwXbtUu`plFgyG zG{gF{jv(0_ic2%Bzvu{(&7rt7!}_a^AlV#>OEav$=?Id|p|~`|`n!%G*&K>XGpv8; z2$IdAxHQB1r;Z@m9EwXbtbgeUlFgyGG{gG0jv(0_ic2%B|L6#k&7rt7!}_m|AlV#> zOEatoroArhb!o3ldtKV=(q5PLy0q7&y)Nx_I)Y?#C@#&g9;_osHizQU4C^5}f@E_j zF3qqWsv}4?hvL!<>tQ;AWOFDk&9EM>BSv1}QWOFDk&9EM?BS`SkKTAB%4EV zX@>Po9YL}=6qjaL&(aYjn?rGFhV^V6L9#g%mu6Vc(Get@Lvd+_^;{i6vN;r&W?0YD z5hR;KacPG2d>uiuITV*>STE2KB%4EVX@>Pe9YL}=6qjaLFVYbtn?rGFhV^0{L9#g% zmu6Tm(Get@Lvd+_^->){vN;r&W>_!N5hR;KacPG2avedkITV*>Sg+6#B%4EVX@>Pm z9YL}=6qjaLuhJ1Dn?rGFhV^P4L9#g%mu6V6(Get@Lvd+_^;#W4vN;r&W>~M&5hR;K zacPG2dL2QsITV*>SZ~k~B%4EVX@>Pi9YL}=6qjaLZ_*JYn?rGFhV^D0L9#g%mu6UR z(Get@Lvd+_^;R80vN;r&W>|025hR;KacPG2b{#>oITV*>SntpgB%4EVX@>Pq9YL}= z6qjaL@6r(@n?rGFhV^b8L9#g%mu6V+(Get@Lvd+_^SRc?4B%4EVX@>Pd9YL}=6qjaLAJP#dn?rGFhV@|`L9#g%mu6TW(Get@ zLvd+_^-&!`vN;r&W>_E75hR;KacPG2aUDUjITV*>Sf9`lB%4EVX@>Pl9YL}=6qjaL zpVAQ|n?rGFhV^M3L9#g%mu6U>(Get@Lvd+_^;sQ3vN;r&W>}xo5hR;KacPG2c^yHr zITV*>SYOZ)B%4EVX@>Ph9YL}=6qjaLU(yjIn?rGFhV^9~L9#g%mu6UB(Get@Lvd+_ z^;I1~vN;r&W>{a-5hR;KacPG2bsa&nITV*>Sl`eQB%4EVX@>Pp9YL}=6qjaL-_j8z zn?rGFhV^Y7L9#g%mu6Vs(Get@Lvd+_^<5o7vN;r&W?0|T5hR;KacPG2eH}rvITV*> zSU=DaB%4EVX@>Pf9YL}=6qjaLKhhB-n?rGFhV^3|L9#g%mu6T$(Get@Lvd+_^-~=| zvN;r&W>`Pd5hR;KacPG2a~(mlITV*>SijH_B%4EVX@>Pn9YL}=6qjaLztRyTn?rGF zhV^S5L9#g%mu6VM(Get@Lvd+_^;;c5vN;r&W>~+|5hR;KacPG2dmTZtITV*>SbxwF zB%4EVX@>Pj9YL}=6qjaLf6@^on?rGFhV^G1L9#g%mu6Uh(Get@Lvd+_^;aE1vN;r& zW>|mI5hR;KacPG2cO5~pITV*>SpU!wB%4EVX@>Pr9YL}=6qjaL|I!g8n?rGFhV^e9 zL9#g%mu6W1(Get@Lvd+_^^n&a*rU{9EwXbtOw}`lFgyGG{btZjv(0_ zic2%Bhv*2B&7rt7!+NNWAlV#>OEav8=?Id|p|~`|dbo}t*&K>XGptAG2$IdAxHQ9h zq>doj9EwXbtVihxlFgyGG{btdjv(0_ic2%B$LI)>&7rt7!+NZaAlV#>OEav;=?Id| zp|~`|dc2Mx*&K>XGpr}*2$IdAxHQ9hqK+Wh9EwXbtS9LRlFgyGG{btbjv(0_ic2%B zr|1Zh&7rt7!*X-P0|=7Mp>XT6y-tS{=k_`szPA58$Gf;R!+M&IAlV#>OEave>j;v~ zp|~`|dWMc5*&K>XGpuLo2$IdAxHQ9hmX09V9EwXbtY_;8lFgyGG{bt1jv(0_ic2%B z=jsTO&7rt7!+M^MAlV#>OEawJ>j;v~p|~`|dV!80*&K>XGprZt2$IdAxHQ9hk&YnQ z9EwXbtQYGDlFgyGG{bs{jv(0_ic2%Bm+AOEavO>j;v~p|~`| zdWDW4*&K>XGptwY2$IdAxHQ9hm5w0U9EwXbtXJy@lFgyGG{bt0jv(0_ic2%B*Xjt8 z&7rt7!+M>LAlV#>OEaw3>j;v~p|~`|dV`K2*&K>XGpsl22$IdAxHQ9hla3(S9EwXb ztT*cjlFgyGG{bs}jv(0_ic2%Bx9SLz&7rt7!+M*JAlV#>OEavu>j;v~p|~`|dWVi6 z*&K>XGpu*&2$IdAxHQ9hmyRIW9EwXbtas}OlFgyGG{bt2jv(0_ic2%B_v#3e&7rt7 z!+M{NAlV#>OEawZ>j;v~p|~`|`hbog*&K>XGprBl2$IdAxHQB1kd7eP9EwXbtPkr5 zlFgyGG{gFcjv(0_ic2%BkLn1L&7rt7!}^$xAlV#>OEavG>j;v~p|~`|`h<=k*&K>X zGptYQ2$IdAxHQB1l#U?T9EwXbtWWC*lFgyGG{gFgjv(0_ic2%B&*})0&7rt7!}^?# zAlV#>OEav`>j;v~p|~`|`ht!i*&K>XGpsM_2$IdAxHQB1l8zwR9EwXbtS{>blFgyG zG{gFejv(0_ic2%Buj&Yr&7rt7!}^+zAlV#>OEavm>j;v~p|~`|`i71m*&K>XGpujw z2$IdAxHQB1mX09V9EwXbtZ(ZGlFgyGG{gFijv(0_ic2%B@9GGW&7rt7!}^|%AlV#> zOEawR>j;v~p|~`|`hkuh*&K>XGprx#2$IdAxHQB1k&YnQ9EwXbtRL$LlFgyGG{gFd zjv(0_ic2%BpXvyb&7rt7!}^(yAlV#>OEavW>j;v~p|~`|`h|`l*&K>XGpt|g2$IdA zxHQB1m5w0U9EwXbtY7O0lFgyGG{gFhjv(0_ic2%B-|7gG&7rt7!}^_$AlV#>OEawB z>j;v~p|~`|`h$)j*&K>XGps-A2$IdAxHQB1la3(S9EwXbtUv1rlFgyGG{gFfjv(0_ zic2%Bzv>8*&7rt7!}^OEav$>j;v~p|~`|`iG7n*&K>XGpv8=2$IdAxHQB1 zmyRIW9EwXbtbgkWlFgyGG{gFjjv(0_ic2%B|LO>m&7rt7!+M~9*&;|bhvL!<>p?n# zWOFDk&9EMhvL!<>rpy_WOFDk&9EM=BSs3S-=hvL!<>q$C-WOFDk z&9I)VBS82X?R7f-?r6Wi-hvL!<>)ASjWOFDk z&9I)MBS%}^PWOFDk&9GjgBS(x4fWOFDk&9Gjh zBS8$HizQU4C{?Lf@E_j zF3qssq$5Z+hvL!<>&-fXWOFDk&9L60BSL4NH&M!(hTeE zI)Y?#C@#&g-k~E%HizQU4C|dbf@E_jF3qssr6Wi-hvL!<>)kqnWOFDk&9L61BSO5NH&M!(hTeUI)Y?#C@#&gKA%%&NWOFDk&9FYABSHizQU4C|9Rf@E_jF3qq$r6Wi-hvL!<>(e@dWOFDk&9FYBBS&rTVWOFDk&9J_rBS)SelWOFDk&9J_sBS&H5RWOFDk&9Hu=BS(@GhWOFDk&9Hu>BSpAkb0{v& zuzsf_NH&M!(hTeOI)Y?#C@#&g{-7gBHizQU4C{|Nf@E_jF3qt1q$5Z+hvL!<>(4rZ zWOFDk&9MHWBSPhaNH&M!(hTeGI)Y?#C@#&g{-GmCHizQU z4C|jdf@E_jF3qt1r6Wi-hvL!<>)$$pWOFDk&9MHXBSXGpq;e2$IdAxHQ9hh>jrH9EwXbtcU6dlFgyGG{btBjv(0_ zic2%BhwBKE&7rt7!+L~{AlV#>OEauT>Ijm}p|~`|dX$bJ*&K>XGptAJ2$IdAxHQ9h zjE*4L9EwXbtjFpIlFgyGG{btFjv(0_ic2%B$Lk1^&7rt7!+L^_AlV#>OEat|>Ijm} zp|~`|dXkPH*&K>XGpr};2$IdAxHQ9hijE-J9EwXbtpBGYNH&M!(hTdVI)cP9{#0Mv z|DNmJ4C`q+f@E_jF3qr>t|Le`hvL!<>lr$NWOFDk&9I)SBSuOmn{hvL!<>jgT3 zWOFDk&9GjmBSlHeJWOFDk&9GjnBSkT@BWOFDk z&9L66BSPb0{v&u->dANH&M!(hTb@I)Y?#C@#&g-l`)=HizQU4C`$= zf@E_jF3qsst|Le`hvL!<>m53RWOFDk&9L67BSgBNH&M! z(hTc8I)Y?#C@#&g-m4=>HizQU4C{S5f@E_jF3qssuOmn{hvL!<>jOH1WOFDk&9FYG zBSk~SHWOFDk&9FYHBSkB%9WOFDk&9J_xBSI)Y?#C@#&gzN#ZgHizQU4C`w;f@E_jF3qsM zt|Le`hvL!<>l-?PWOFDk&9J_yBSjyf5WOFDk&9Hu`BS>LJb0{v&uzsu~NH&M!(hTb-I)Y?#C@#&geySr#HizQU4C`k)f@E_jF3qrht|Le` zhvL!<>lZqLWOFDk&9Hu{BSkm4DWOFDk&9MHcBSPzgNd7-Z_q0Souykwmm2zhmG9Pc-wr$(CZQC~EjPpmuSXbX|-^}Pj+5P#Q^6pPK_(hTtr9Z9j+94^fe|J0Ebi_PKE4Dl}= zNwL@*F3k}C){zv8&Ee7v@gE&YvDh3g%@F_9kra!~;nEE8KOIT2*c>j+5D#>FB}uW^ z94^fe57Lnoi_PKE4DnzcNwL@*F3k`R(UBC3&Ee7v@lYK}vDh3g%@7aMkra!~;nEE8 za2-jp*c>j+5RcH26pPK_(hTuP9Z9j+94^fekJ6D8i_PKE4Do0kNwL@*F3k{+(UBC3 z&Ee7v@mL*6vDh3g%@B{%kra!~;nEE8cpXWx*c>j+5KqvN6pPK_(hTuL9Z9j+94^fe zPtuVTi_PKE4DnN=PDHfZN@QDHfZBPkY}!=)MG z<2sUJu{m6tAwHoaDHfZpGHR zu{m6tA-drVu{m6tA^xEw zDHfZ{hf6cW!*wLZVsp4OLp(x9QY{hf6cW<8>s(Vsp4O zLp(u8QYj+5YN_;6pPK_(hTt&9Z9j+94^fe&()C>i_PKE4Dmc2NwL@*F3k|n*O3&9 z&Ee7v@d6!5vDh3g%@8ltkra!~;nEE8A{|Mw*c>j+5HHq|6pPK_(hTtu9Z9j+94^fe zFV&G0i_PKE4Dm7@NwL@*F3k`x*O3&9&Ee7v@d_PDvDh3g%@D8Dkra!~;nEE8Dji9& z*c>j+5Uj+5O3Cz6pPK_(hTty9Z9j+94^feZ`F|$ zi_PKE4DmJ{NwL@*F3k{c*O3&9&Ee7v@eUnHvDh3g%@FU@kra!~;nEE8E*(j+*c>j+ z5bxHJ6pPK_(hTt)9Z9j+94^fe@70kMi_PKE4Dmi4NwL@*F3k|{*O3&9&Ee7v@c|u4 zvDh3g%@7~dkra!~;nEE8AstDv*c>j+5Fgf&6pPK_(hTtt9Z9j+94^feAJvf*i_PKE z4Dm4?NwL@*F3k`h*O3&9&Ee7v@d+JCvDh3g%@Ci|kra!~;nEE8DIH0%*c>j+5TDkO z6pPK_(hTt#9Z9j+94^fepVg5Ri_PKE4DmS~NwL@*F3k|1*O3&9&Ee7v@dX`8vDh3g z%@AMIkra!~;nEE8B^^nz*c>j+5MS1j6pPK_(hTtx9Z9j+94^feU)7Nmi_PKE4DmG` zNwL@*F3k{M*O3&9&Ee7v@eLhGvDh3g%@E(zkra!~;nEE8Egea**c>j+5Z~636pPK_ z(hTt(9Z9j+94^fe-_?;6i_PKE4Dmf3NwL@*F3k|%*O3&9&Ee7v@dF)6vDh3g%@9A- zkra!~;nEE8BOOVx*c>j+5I@$D6pPK_(hTtv9Z9j+94^feKh=>Gi_PKE4DmA^NwL@* zF3k`>*O3&9&Ee7v@e3VEvDh3g%@DuTkra!~;nEE8D;-I(*c>j+5Wm)u6pPK_(hTt% z9Z9j+94^feztxcxi_PKE4DmZ1NwL@*F3k|X*O3&9&Ee7v@dq7AvDh3g%@BXokra!~ z;nEE8Cml(#*c>j+5P#N@6pPK_(hTtz9Z9j+94^fef7Ou`i_PKE4DmM|NwL@*F3k{s z*O3&9&Ee7v@edtIvDh3g%@F_8kra!~;nEE8FC9s-*c>j+5dYSZ6pPK_(hTt*9Z9j+ z94^fe|J9Kci_PKE4Dml5NwL@*F3k`R9DCi^>)c++Vsp4OLp(@FQYM^Y>{hf6cW zBXuOjVsp4OLp(}HQY{hf6cW6LloTVsp4OLp(`GQY`_a z*c>j+5YN<+6pPK_(hTt|9Z9j+94^fe&(@I?i_PKE4DlQtNwL@*F3k|n)sYm7&Ee7v z@jM+#vDh3g%@EJmkra!~;nEE80v$=Q*c>j+5HHk`6pPK_(hTt;9Z9j+94^feFV>M1 zi_PKE4Dk{jNwL@*F3k`x)sYm7&Ee7v@iHArvDh3g%@8lwkra!~;nEE83LQzY*c>j+ z5Uj+5O36x6pPK_(hTt?9Z9j+94^feZ`P3%i_PKE z4Dl8nNwL@*F3k{c)sYm7&Ee7v@irYvvDh3g%@A+bkra!~;nEE84joCc*c>j+5bxBH z6pPK_(hTt~9Z9j+94^fe@79qNi_PKE4DlWvNwL@*F3k|{)sYm7&Ee7v@je|%vDh3g z%@FU`kra!~;nEE80Ub%P*c>j+5FgZ$6pPK_(hTt-9Z9j+94^feAJ&l+i_PKE4Dk^i zNwL@*F3k`h)sYm7&Ee7v@i84qvDh3g%@7~gkra!~;nEE82^~qX*c>j+5TDeM6pPK_ z(hTt_9Z9j+94^fepVpBSi_PKE4DlHqNwL@*F3k|1)sYm7&Ee7v@i`qyvDh3g%@Cj0 zkra!~;nEE81szGT*c>j+5MR`h6pPK_(hTt>9Z9j+94^feU)GTni_PKE4Dl5mNwL@* zF3k{M)sYm7&Ee7v@iiSuvDh3g%@AMLkra!~;nEE84IN3b*c>j+5Z~016pPK_(hTt} z9Z9j+94^fe-`0^7i_PKE4DlTuNwL@*F3k|%)sYm7&Ee7v@jV?$vDh3g%@E($kra!~ z;nEE8106}R*c>j+5I@wB6pPK_(hTt<9Z9j+94^feKh}{Hi_PKE4Dk~kNwL@*F3k`> z)sYm7&Ee7v@iQGsvDh3g%@9A=kra!~;nEE83mr+Z*c>j+5Wm!s6pPK_(hTt{9Z9j+ z94^fezt)iyi_PKE4DlNsNwL@*F3k|X)sYm7&Ee7v@jD$!vDh3g%@DuWkra!~;nEE8 z2OUYV*c>j+5P#H>6pPK_(hTt@9Z9j+94^fef7X!{i_PKE4DlBoNwL@*F3k{s)sYm7 z&Ee7v@i!ewvDh3g%@BXrkra!~;nEE84;@Ld*c>j+5dYMX6pPK_(hTu09Z9j+94^fe z|JIQdi_PKE4DlZwNwL@*F3k}C)sYm7&Ee7v@jo3&vDh3g%@7Zar$2zCSZofLW{3yr zNQ%YgaA}5ku#TiyYz~)Zh==G%ipAz|X@+>Hj-*&@4wq(#hv`U)#pZBnhIqJ+q*!bY zmu84Z=tzpi=5T3-c%+V`SZofLW{5}WNQ%YgaA}5kw2q`$Yz~)Zh{xziipAz|X@+>L zj-*&@4wq(#$LUCl#pZBnhIqV=q*!bYmu843=tzpi=5T3-c%qJ^SZofLW{4;0NQ%Yg zaA}5kvW}!!Yz~)Zh^OdCipAz|X@+>Jj-*&@4wq(#r|C!vH@Q6Bze7IV7w1p+7VFb3 z<4^arJ^lZm2aptt&Ee7v@eCbFvDh3g%@EJjkra!~;nEE8EFDR)*c>j+5YN_;6pPK_ z(hTt&9Z9j+94^fe&()C>i_PKE4Dmc2NwL@*F3k|n*O3&9&Ee7v@d6!5vDh3g%@8lt zkra!~;nEE8A{|Mw*c>j+5HHq|6pPK_(hTtu9Z9j+94^feFV&G0i_PKE4Dm7@NwL@* zF3k`x*O3&9&Ee7v@d_PDvDh3g%@D8Dkra!~;nEE8Dji9&*c>j+5Uj+5O3Cz6pPK_(hTty9Z9j+94^feZ`F|$i_PKE4DmJ{NwL@*F3k{c z*O3&9&Ee7v@eUnHvDh3g%@FU@kra!~;nEE8E*(j+*c>j+5bxHJ6pPK_(hTt)9Z9j+ z94^fe@70kMi_PKE4Dmi4NwL@*F3k|{*O3&9&Ee7v@c|u4vDh3g%@7~dkra!~;nEE8 zAstDv*c>j+5Fgf&6pPK_(hTtt9Z9j+94^feAJvf*i_PKE4Dm4?NwL@*F3k`h*O3&9 z&Ee7v@d+JCvDh3g%@Ci|kra!~;nEE8DIH0%*c>j+5TDkO6pPK_(hTt#9Z9j+94^fe zpVg5Ri_PKE4DmS~NwL@*F3k|1*O3&9&Ee7v@dX`8vDh3g%@AMIkra!~;nEE8B^^nz z*c>j+5MS1j6pPK_(hTtx9Z9j+94^feU)7Nmi_PKE4DmG`NwL@*F3k{M*O3&9&Ee7v z@eLhGvDh3g%@E(zkra!~;nEE8Egea**c>j+5Z~636pPK_(hTt(9Z9j+94^fe-_?;6 zi_PKE4Dmf3NwL@*F3k|%*O3&9&Ee7v@dF)6vDh3g%@9A-kra!~;nEE8BOOVx*c>j+ z5I@$D6pPK_(hTtv9Z9j+94^feKh=>Gi_PKE4DmA^NwL@*F3k`>*O3&9&Ee7v@e3VE zvDh3g%@DuTkra!~;nEE8D;-I(*c>j+5Wm)u6pPK_(hTt%9Z9j+94^feztxcxi_PKE z4DmZ1NwL@*F3k|X*O3&9&Ee7v@dq7AvDh3g%@BXokra!~;nEE8Cml(#*c>j+5P#N@ z6pPK_(hTtz9Z9j+94^fef7Ou`i_PKE4DmM|NwL@*F3k{s*O3&9&Ee7v@edtIvDh3g z%@F_8kra!~;nEE8FC9s-*c>j+5dYSZ6pPK_(hTt*9Z9j+94^fe|J9Kci_PKE4Dml5 zNwL@*F3k`Re1N^~0rt8F*y|o(uXB4Phf6cWgLEXtVsp4OLp)eVQY{hf6cW zqjV(2Vsp4OLp)kXQY{hf6cWlXN7-Vsp4OLp)hWQYVj-*&@4wq(#=jcd^#pZBnhIp=yq*!bYmu86P=}3yj=5T3- zc)pILSZofLW{4N)NQ%YgaA}5kp^l_jYz~)Zh!^QdipAz|X@+>Qj-*&@4wq(#m*_}} z#pZBnhIpxtq*!bYmu85U=}3yj=5T3-c)5Uj-*&@4wq(#*XT%!#pZBnhIp-xq*!bYmu869=}3yj=5T3-c)gCK zSZofLW{5ZFNQ%YgaA}5kqmHClYz~)Zh&Sm-ipAz|X@+>Sj-*&@4wq(#x9CWU#pZBn zhIp%vq*!bYmu85!=}3yj=5T3-c)O0ISZofLW{7v_NQ%YgaA}5kr;empYz~)ZhWj-*&@4wq(#_vlE9#pZBnhIp@zq*!bYmu86f=}3yj=5T3-c)yOMSZofL zW{3~yNQ%YgaA}74ppK+iYz~)Zh!5#VipAz|X@>Z)j-*&@4wq(#kLXB>#pZBnhWMzC zq*!bYmu85M=}3yj=5T3-__&UwSZofLW{6MdNQ%YgaA}74q>iLmYz~)Zh)?NAipAz| zX@>Z;j-*&@4wq(#&*(^s#pZBnhWM3kYz~)Zh%f0#ipAz|X@>Z+j-*&@4wq(#ujojM#pZBnhWM(Eq*!bY zmu85s=}3yj=5T3-__~gySZofLW{7X-NQ%YgaA}74rjDdoYz~)Zh;QjgipAz|X@>Z= zj-*&@4wq(#@90R1#pZBnhWM_Iq*!bYmu86X=}3yj=5T3-_`Z&$SZofLW{4l?NQ%Yg zaA}74p^l_jYz~)Zh#%=lipAz|X@>Z*j-*&@4wq(#pXf-6#pZBnhWM$Dq*!bYmu85c z=}3yj=5T3-__>axSZofLW{6+tNQ%YgaA}74rH-UnYz~)Zh+pYQipAz|X@>ZZ-j-*&@4wq(#zvxJc#pZBnhWM+Fq*!bYmu85+=}3yj z=5T3-_`8mzSZofLW{7|2NQ%YgaA}74r;empYz~)Zh=1uwipAz|X@>Z>j-*&@4wq(# z|L91H#pZBnhWM|Jq*!bYmu86n=}3yj=5T3-cwpM=(q5PLy0q7&y)Nx_X|GFrUE1r? zUZ*1|7MsJR8REe@l47wrT$&*sq9Z95o5Q6U;-NZ{VzD_~njs#hBPkY}!=)MG;X0CH zu{m6tAs(S4DHfZPvDh3g%@EJfkra!~;nEE8OdUzF*c>j+5YN()6pPK_(hTuz9Z9j+94^fe&(V<- zi_PKE4DnnYNwL@*F3k|n(~%U5&Ee7v@q8UgvDh3g%@8lpkra!~;nEE8LLEu5*c>j+ z5HHe^6pPK_(hTup9Z9j+94^feFVT?{i_PKE4DnJONwL@*F3k`x(~%U5&Ee7v@p2tW zvDh3g%@D89kra!~;nEE8N*zhD*c>j+5UIevDh3g%@A+Ukra!~;nEE8Mjc79*c>j+5O30v z6pPK_(hTut9Z9j+94^feZ_$wyi_PKE4DnVSNwL@*F3k{c(~%U5&Ee7v@pc_avDh3g z%@FUj+5bx5F6pPK_(hTu#9Z9j+94^fe@6nMIi_PKE4Dnta zNwL@*F3k|{(~%U5&Ee7v@qQgivDh3g%@7~Zkra!~;nEE8K^;l4*c>j+5FgT!6pPK_ z(hTuo9Z9j+94^feAJLH%i_PKE4DnGNNwL@*F3k`h(~%U5&Ee7v@o^nVvDh3g%@Ci^ zkra!~;nEE8NgYYC*c>j+5TDYK6pPK_(hTuw9Z9j+94^fepV5&Ni_PKE4DneVNwL@* zF3k|1(~%U5&Ee7v@p&CdvDh3g%@AMEkra!~;nEE8MIA}8*c>j+5MR=f6pPK_(hTus z9Z9j+94^feU(t~ii_PKE4DnSRNwL@*F3k{M(~%U5&Ee7v@pTj+5Z}^~6pPK_(hTu!9Z9j+94^fe-_em2i_PKE4DnqZNwL@*F3k|% z(~%U5&Ee7v@qHahvDh3g%@9A(kra!~;nEE8Lmf%6*c>j+5I@q96pPK_(hTuq9Z9j+ z94^feKhcpCi_PKE4DnMPNwL@*F3k`>(~%U5&Ee7v@pBzXvDh3g%@DuPkra!~;nEE8 zOC3qE*c>j+5Wmuq6pPK_(hTuy9Z9j+94^feztNEti_PKE4DnkXNwL@*F3k|X(~%U5 z&Ee7v@p~OfvDh3g%@BXkkra!~;nEE8M;%GA*c>j+5P#B<6pPK_(hTuu9Z9j+94^fe zf6j+5dYGV6pPK_(hTu$9Z9j+94^fe|Iv{Yi_PKE4DnwbNwL@*F3k}C(~%U5&Ee7v z@j!3+kQ9r};nEE8ARS4u*c>j+5D(Uo6pPK_(hTts9Z9j+94^fe57m(ri_PKE4Dm1> zNwL@*F3k`R*O3&9&Ee7v@dzDBvDh3g%@B{&kra!~;nEE8C>=?$*c>j+5RcZ86pPK_ z(hTt!9Z9j+94^fekJXVBi_PKE4DmP}NwL@*F3k{+*O3&9&Ee7v@dO=7vDh3g%@9x2 zkra!~;nEE8Bppey*c>j+5Kq>T6pPK_(hTtw9Z9j+94^fePt}nWi_PKE4B_AC9zaqo zHg0FO*Xi(Oy1h<^r}F>K^1C@)njxN{BPkY}!=)MGnL3hUu{m6tA)cipDHfZO1TDHfZ`=5BUtp8G_oyApI6LW)vuVDnVFfHnVC7}bcf^Q>TYwRNT=d$I+Dfa zP+XcJ-mW8AY!1bx8R8u}lEvmwT$&-?sUulz4#lMz;$1qD#pY04njzk;BUx+?#ibeI zJvx%b=1^RkA>OMaS!@o)r5WOVI+DfaP+XcJ-mfEBY!1bx8R7#vlEvmwT$&+1s3Tcy z4#lMz;zK%;#pY04njt={BUx+?#ibeIBRZ1B=1^RkAwH@jS!@o)r5WO5I+DfaP+XcJ zKCUBKY!1bx8R8Q{zlEvmwT$&+%s3Tcy4#lMz;zv4? z#pY04njwCyBUx+?#ibeICpwbF=1^RkA%3bOS!@o)r5WO9I+DfaP+XcJey$@~Y!1bx z8R8c@lEvmwT$&+%sUulz4#lMz;#WG7#pY04njwCzBUx+?#ibeIH#(BV=1^RkA%3eP zS!@o)r5WOPI+DfaP+XcJey<~0Y!1bx8R8E*lEvmwT$&;Ns3Tcy4#lMz;!iq~#pY04 znj!wIBUx+?#ibeIFFKON=1^RkA^xf(S!@o)r5WOHI+DfaP+XcJ{;nfgY!1bx8R8#0 zlEvmwT$&;NsUulz4#lMz;$J$F#pY04nj!wJBUx+?#ibeIKRS}d=1^RkA^xi)S!@o) zr5WNuZsd_HHizQU4Dnzc$zpRTF3k`R(UB}RhvL!<@lYMfVsj`i%@7aMkt{Zc;?fN9 za2?5Fb0{v&5RcH2EH;PY(hTuP9m!&IC@#$qkJ6DWHizQU4Do0k$zpRTF3k{+(UB}R zhvL!<@mL+nVsj`i%@B{%kt{Zc;?fN9cpb@Nb0{v&5KqvNEH;PY(hTuL9m!&IC@#$q zPtuVrHizQU4DnQ9EwXb#B+5di_M|9G($X3N3z%)ic2%Z^K~SP z&7rt7L%cvove+DoOEbg^btH?;p|~_dyhul~*c^&WGsKH^B#X_VxHLn&L`SmN9EwXb z#7lJ~i_M|9G()^hN3z%)ic2%Z%XK7+&7rt7L%c#qve+DoOEbhPbtH?;p|~_dyh=y1 z*c^&WGsLTPB#X_VxHLn&Mn|&P9EwXb#A|gVi_M|9G()^jN3z%)ic2%Z>vbfH&7rt7 zL%cypve+DoOEbh9btH?;p|~_dyh%s0*c^&WGsK&9B#X_VxHLn&MMtvO9EwXb#9MVF zi_M|9G()^iN3z%)ic2%Z+jS(1&7rt7L%c&rve+DoOEbhfbtH?;p|~_dyh}&2*c^&W zGsL@fB#X_VxHLn&M@O>Q9EwXb#Cvrli_M|9G()^kN3z%)ic2%Z`*kFX&7rt7LwrC- zve+DoOEbg=btH?;p|~_dd`L&K*c^&WGsK5=B#X_VxHLn2L`SmN9EwXb#7A``i_M|9 zG(&t$N3z%)ic2%Z$8{u&&7rt7LwrIQ9EwXb#CLThi_M|9G(&t(N3z%)ic2%Z_jM$T&7rt7L;OHTve+DoOEbg| zbtH?;p|~_d{76T#*c^&WGsKT|B#X_VxHLojL`SmN9EwXb#7}i3i_M|9G(-GMN3z%) zic2%Z&vhh=&7rt7L;ONVve+DoOEbhTbtH?;p|~_d{7Of%*c^&WGsLfTB#X_VxHLoj zMn|&P9EwXb#BX&Zi_M|9G(-GON3z%)ic2%Z?{y@L&7rt7L;OKUve+DoOEbhDbtH?; zp|~_d{7FZ$*c^&WGsK^DB#X_VxHLojMMtvO9EwXb#9wtJi_M|9G(-GNN3z%)ic2%Z z-*qI5&7rt7L;OQWve+DoOEbhjbtH?;p|~_d{7Xl&*c^&WGsM4jB#X_VxHLojM@O>Q z9EwXb#D8@pi_M|9G($Yd-?K;-n?rGFhIp`!WU)CEmu85E=tvfuLvd+_c&LtKu{ji% zW{8LBNEVwzacPElxQ=A8ITV*>h)3v17MnwHX@+>Dj%2Yp6qja*N9jlwn?rGFhIq7& zWU)CEmu85^=tvfuLvd+_c&v_Ou{ji%W{Ah>NEVwzacPElypCkCITV*>h$rYs7MnwH zX@+>Bj%2Yp6qja*C+SEQn?rGFhIq1$WU)CEmu85k=tvfuLvd+_c&d(Mu{ji%W{9Wh zNEVwzacPFI<@NuOEH;PYVmq^Wo$di0i3$1x-pcITV*>h-c|Y7MnwHX@+>Vj%2Yp6qja*=jccln?rGFhIp=yWU)CEmu86P z=|~ovLvd+_c)pHgu{ji%W{4N)NEVwzacPElp^jv+ITV*>h!^Qd7MnwHX@+>Qj%2Yp z6qja*m*_|qn?rGFhIpxtWU)CEmu85U=|~ovLvd+_c)5;bu{ji%W{6klNEVwzacPEl zrH*8=ITV*>h*#-I7MnwHX@+>Uj%2Yp6qja**XT$Vn?rGFhIp-xWU)CEmu869=|~ov zLvd+_c)gBfu{ji%W{5ZFNEVwzacPElqmE>;ITV*>h&Sm-7MnwHX@+>Sj%2Yp6qja* zx9CU~n?rGFhIp%vWU)CEmu85!=|~ovLvd+_c)N~du{ji%W{7v_NEVwzacPElr;cQ? zITV*>hWj%2Yp6qja*_vlC#n?rGFhIp@zWU)CEmu86f=|~ovLvd+_ zc)yNhu{ji%W{3~yNEVwzacPG5ppIm*ITV*>h!5#V7MnwHX@>Z)j%2Yp6qja*kLXAi zn?rGFhWMzCWU)CEmu85M=|~ovLvd+___&T_u{ji%W{6MdNEVwzacPG5q>f~ zh)?NA7MnwHX@>Z;j%2Yp6qja*&*(@Nn?rGFhWMh%f0#7MnwHX@>Z+j%2Yp6qja*ujoh?n?rGF zhWM(EWU)CEmu85s=|~ovLvd+___~f{u{ji%W{7X-NEVwzacPG5rjBH>ITV*>h;Qjg z7MnwHX@>Z=j%2Yp6qja*@90Ptn?rGFhWM_IWU)CEmu86X=|~ovLvd+__`Z&0u{ji% zW{4l?NEVwzacPG5p^jv+ITV*>h#%=l7MnwHX@>Z*j%2Yp6qja*pXf*yn?rGFhWM$D zWU)CEmu85c=|~ovLvd+___>Z`u{ji%W{6+tNEVwzacPG5rH*8=ITV*>h+pYQ7MnwH zX@>Z;ITV*>h(GB_7MnwHX@>Z-j%2Yp6qja*zvxI7n?rGFhWM+FWU)CE zmu85+=|~ovLvd+__`8l|u{ji%W{7|2NEVwzacPG5r;cQ?ITV*>h=1uw7MnwHX@>Z> zj%2Yp6qja*|L8~-n?rGFhWM|JWU)CEmu83u`O`hgVsj`i%@7aPkt{Zc;?fN95FN>4 zb0{v&5D(RnEH;PY(hTu19m!&IC@#$q57&__HizQU4DkpZ$zpRTF3k{+)R8PUhvL!< z@hBb1Vsj`i%@B{)kt{Zc;?fN97#+!Cb0{v&5RcW7EH;PY(hTu99m!&IC@#$qkJphb zHizQU4DkdV$zpRTF3k{6)R8PUhvL!<@gyC|Vsj`i%@9x4kt{Zc;?fN96dlQ8b0{v& z5Kq;SEH;PY(hTu59m!&IC@#$q|Dz*WY!1bxv7OnxPDkQvSMxd@|9dXY5Kq^UEH;PY z(hTto9m!&IC@#$q&(x7DHizQU4Dl=-$zpRTF3k|n){!hWhvL!<@f;n=Vsj`i%@EJk zkt{Zc;?fN9JRQkmb0{v&5YN|Vsj`i%@E(!kt{Zc;?fN9Jsrtnb0{v& z5Z~94EH;PY(hTtf9m!&IC@#$qKh%*dHizQU4Dll!$zpRTF3k`>){!hWhvL!<@e>`% zVsj`i%@9A;kt{Zc;?fN9Gabodb0{v&5I@(EEH;PY(hTtn9m!&IC@#$qztoW|HizQU z4Dl-+$zpRTF3k|X){!hWhvL!<@f#hPj%2Yp z6qja*hv-Nan?rGFhIpusWU)CEmu85E=|~ovLvd+_c({&au{ji%W{5}VNEVwzacPEl zq>f~h)3y27MnwHX@+>Tj%2Yp6qja*$LL5Fn?rGFhIp)wWU)CEmu85^=|~ov zLvd+_c)X5eu{ji%W{4-~NEVwzacPElqK;&-ITV*>h$rbt7MnwHX@+>Rj%2Yp6qja* zr|3u)n?rGFhIp!uWU)CEmu85k=|~ovLvd+__#Yj~Vsj`i%@7ahNZd?+z}K!1n4mx4 zt^B{!o(-p|~_dJX=Sy*c^&W zGsJUrB#X_VxHLmNS4Xng9EwXb#Pf6{i_M|9G($XJN3z%)ic2%Z3v?ul&7rt7L%dK& zve+DoOEbiabR>(-p|~_dyjVxF*c^&WGsH`DB#X_VxHLn&R7bMd9EwXb#LILfi_M|9 zG()^xN3z%)ic2%ZD|94_&7rt7L%dQ)ve+DoOEbi)bR>(-p|~_dyjn-H*c^&WGsJ6j zB#X_VxHLn&R!6ef9EwXb#Orh(-p|~_dyje%G*c^&WGsIhTB#X_VxHLn&RY$Ve9EwXb#M^Wvi_M|9G()^y zN3z%)ic2%ZJ9H$A&7rt7L%dT*ve+DoOEbi~bR>(-p|~_dyjw@I*c^&WGsJszB#X_V zxHLn&S4Xng9EwXb#QSt4i_M|9G()^!N3z%)ic2%Z2XrKh&7rt7Lwrz2ve+DoOEbiW zbR>(-p|~_dd{{@a*c^&WGsH)9B#X_VxHLn2R7bMd9EwXb#K&|bi_M|9G(&t`N3z%) zic2%ZCv+r>&7rt7Lwr(4ve+DoOEbi$bR>(-p|~_dd|F4c*c^&WGsI_fB#X_VxHLn2 zR!6ef9EwXb#OHJ*i_M|9G(&t|N3z%)ic2%Z7jz_x&7rt7Lwr$3ve+DoOEbimbR>(- zp|~_dd|5}b*c^&WGsIVPB#X_VxHLn2RY$Ve9EwXb#Mg8ri_M|9G(&t{N3z%)ic2%Z zH*_S6&7rt7Lwr+5ve+DoOEbi`bR>(-p|~_dd|OAd*c^&WGsJgvB#X_VxHLn2S4Xng z9EwXb#P@V0i_M|9G(&t}N3z%)ic2%Z4|F7p&7rt7L;O%jve+DoOEbiebR>(-p|~_d z{8&e_*c^&WGsI7HB#X_VxHLojR7bMd9EwXb#Lsjji_M|9G(-GcN3z%)ic2%ZFLWe} z&7rt7L;O-lve+DoOEbi;bR>(-p|~_d{8~q{*c^&WGsJInB#X_VxHLojR!6ef9EwXb z#P4(@i_M|9G(-GeN3z%)ic2%ZA9N&(&7rt7L;O)kve+DoOEbiubR>(-p|~_d{8>k` z*c^&WGsItXB#X_VxHLojRY$Ve9EwXb#NTuzi_M|9G(-GdN3z%)ic2%ZKXfFE&7rt7 zL;O=mve+DoOEbj3bR>(-p|~_d{98w|*c^&WGsJ&%B#X_VxHLojS4Xng9EwXb#Dm(r z&Q?kmn?rGFhIp`!WU)CEmu85E=tvfuLvd+_c&LtKu{ji%W{8LBNEVwzacPElxQ=A8 zITV*>h)3v17MnwHX@+>Dj%2Yp6qja*N9jlwn?rGFhIq7&WU)CEmu85^=tvfuLvd+_ zc&v_Ou{ji%W{Ah>NEVwzacPElypCkCITV*>h$rYs7MnwHX@+>Bj%2Yp6qja*C+SEQ zn?rGFhIq1$WU)CEmu85k=tvfuLvd+_c&d(Mu{ji%W{9WhNEVwzacPG5A05eJb0{v& z5D(}`{6+EsH`5>Rwd(^W=nr@+|L=@vJY7e!*c^&WGsH7=B#X_VxHLmNQ%ADc9EwXb z#ItlHi_M|9G($XFN3z%)ic2%Zb95w&&7rt7Lp)bUve+DoOEbjtbR>(-p|~_dJYPq$ z*c^&WGsFvYB#X_VxHLn&P)D-Z9EwXb#EWz!i_M|9G()^tN3z%)ic2%ZOLQcQ&7rt7 zL%dW+ve+DoOEbjFbR>(-p|~_dyj(}J*c^&WGsG)&B#X_VxHLn&Qb)4b9EwXb#H(~9 zi_M|9G()^vN3z%)ic2%ZYjh-w&7rt7L%dc;ve+DoOEbjlbR>(-p|~_dyk1AL*c^&W zGsGKoB#X_VxHLn&QAe`a9EwXb#G7;^i_M|9G()^uN3z%)ic2%ZTXZCg&7rt7L%dZ- zve+DoOEbjVbR>(-p|~_dyj@4K*c^&WGsHV|B#X_VxHLn&Q%ADc9EwXb#JhAPi_M|9 zG()^wN3z%)ic2%Zdvqj=&7rt7L%df(-p|~_dykAGM*c^&WGsFjU zB#X_VxHLn2P)D-Z9EwXb#D{bwi_M|9G(&t?N3z%)ic2%ZM|32M&7rt7Lwr<6ve+Do zOEbjBbR>(-p|~_dd|XGe*c^&WGsGu!B#X_VxHLn2Qb)4b9EwXb#HVy5i_M|9G(&t^ zN3z%)ic2%ZXLKZs&7rt7Lwr_8ve+DoOEbjhbR>(-p|~_dd|pSg*c^&WGsG8kB#X_V zxHLn2QAe`a9EwXb#Fum=i_M|9G(&t@N3z%)ic2%ZS9Bzc&7rt7Lwr?7ve+DoOEbjR zbR>(-p|~_dd|gMf*c^&WGsHJ^B#X_VxHLn2Q%ADc9EwXb#J6-Li_M|9G(&t_N3z%) zic2%ZcXT9+&7rt7Lwr|9ve+DoOEbjxbR>(-p|~_dd|yYh*c^&WGsF*cB#X_VxHLoj zP)D-Z9EwXb#E*0&i_M|9G(-GYN3z%)ic2%ZPjn=U&7rt7L;O@nve+DoOEbjJbR>(- zp|~_d{9H$}*c^&WGsG`+B#X_VxHLojQb)4b9EwXb#IJNDi_M|9G(-GaN3z%)ic2%Z zZ*(M!&7rt7L;O}pve+DoOEbjpbR>(-p|~_d{9Z@0*c^&WGsGWsB#X_VxHLojQAe`a z9EwXb#GiB|i_M|9G(-GZN3z%)ic2%ZUvwmk&7rt7L;O`ove+DoOEbjZbR>(-p|~_d z{9Q+~*c^&WGsHi1B#X_VxHLojQ%ADc9EwXb#J_YTi_M|9G(-GbN3z%)ic2%Ze{>{^ z&7rt7L;P1qve+DoOEbiS#=LIK>ujZDb0{v&5D(UoEH;PY(hTts9m!&IC@#$q57m(@ zHizQU4Dm1>$zpRTF3k`R*O4qXhvL!<@dzEsVsj`i%@B{&kt{Zc;?fN9C>_aSb0{v& z5RcZ8EH;PY(hTt!9m!&IC@#$qkJXVZHizQU4DmP}$zpRTF3k{+*O4qXhvL!<@dO>o zVsj`i%@9x2kt{Zc;?fN9Bpu0Ob0{v&5Kq>TEH;PY(hTtw9m!&IC@#$qPt}nuHizQU z4DmD_$zpRTF3k}Cqa#^t4#lMz;sG6rjW6bPI(+SFUZ>-KPdr^mve+DoOEbhXbR>(- zp|~_dJX1%q*c^&WGsLrWB#X_VxHLmNTSv0k9EwXb#B+2ci_M|9G($XBN3z%)ic2%Z z^K>MO&7rt7Lp)zcve+DoOEbg^bR>(-p|~_dyiiB7*c^&WGsKH@B#X_VxHLn&SVywh z9EwXb#7lG}i_M|9G()^pN3z%)ic2%Z%XB1*&7rt7L%du^ve+DoOEbhPbR>(-p|~_d zyi!N9*c^&WGsLTOB#X_VxHLn&T1T?j9EwXb#A|dUi_M|9G()^rN3z%)ic2%Z>vSZG z&7rt7L%d!`ve+DoOEbh9bR>(-p|~_dyirH8*c^&WGsK&8B#X_VxHLn&Sx2(i9EwXb z#9MSEi_M|9G()^qN3z%)ic2%Z+jJz0&7rt7L%dx_ve+DoOEbhfbR>(-p|~_dyi-TA z*c^&WGsL@eB#X_VxHLn&TSv0k9EwXb#Cvoki_M|9G()^sN3z%)ic2%Z`*b9W&7rt7 zL%d%{ve+DoOEbg=bR>(-p|~_dd{9TS*c^&WGsK5(-p|~_dd{RfU*c^&W zGsLHKB#X_VxHLn2T1T?j9EwXb#AkFQi_M|9G(&t=N3z%)ic2%Z=X4~C&7rt7LwsIG zve+DoOEbh5bR>(-p|~_dd{IZT*c^&WGsKs4B#X_VxHLn2Sx2(i9EwXb#8-4Ai_M|9 zG(&t(-p|~_dd{alV*c^&WGsL%a zB#X_VxHLn2TSv0k9EwXb#CLQgi_M|9G(&t>N3z%)ic2%Z_jDwS&7rt7LwsLHve+Do zOEbg|bR>(-p|~_d{7^@-*c^&WGsKT{B#X_VxHLojSVywh9EwXb#7}f2i_M|9G(-GU zN3z%)ic2%Z&vYb<&7rt7L;PGvve+DoOEbhTbR>(-p|~_d{8C4<*c^&WGsLfSB#X_V zxHLojT1T?j9EwXb#BX#Yi_M|9G(-GWN3z%)ic2%Z?{p-K&7rt7L;PMxve+DoOEbhD zbR>(-p|~_d{82};*c^&WGsK^CB#X_VxHLojSx2(i9EwXb#9wqIi_M|9G(-GVN3z%) zic2%Z-*hDF|8sN?O8_)W!)|XW->OQ~d`apNk&&EhooqR zOZ-E}Vsl7}X1K&Zbu2cAq-cgq{7c7Tb4ZG2xWvD8EH;OvXogGtN5^7wNQ!2-#D8@x zHix8WhD-cU$6|9xie|XPgW?$vu-F`uq8TpnU>%FiAt{>S5)aX_*c_6g87}cq9gEE& zDVpID57V*O9Fn3LF7a?3i_IY^n&A?U(6QJYlA;+d@kkwu%^@k8;S!J1vDh4vq8Tpn zXdR2qAt{>S5|7cb*c_6g87}cy9gEE&DVpIDkJGW(9Fn3LF7bFBi_IY^n&A>p(6QJY zlA;+d@kAYq%^@k8;Sx{MvDh4vq8TpnWF3pmAt{>S5>L^w*c_6g87}cu9gEE&DVpID zPt&p39Fn3LF7b37i_IY^n&A>AaSyPto%tCyzC6QUB%k4C`ZIj(`V15FXLu{0@&C>P zEH;OvXogEXQ^#U+NQ!2-#ItlPHix8WhD$tK$6|9xie|XPb95{=hooqROFUP{Vsl7} zX1K)jbSyT9q-cgqJYUCRb4ZG2xWo%|EH;OvXogF?P{(3(NQ!2-#EWz+Hix8WhD*Fy z$6|9xie|XPOLQzYhooqROT1LaVsl7}X1K)5bSyT9q-cgqyj;g(b4ZG2xWp@TEH;Ov zXogF?QpaL*NQ!2-#H(~HHix8WhD*F!$6|9xie|XPYji9&hooqROT1RcVsl7}X1K)b zbSyT9q-cgqyk5s*b4ZG2xWpTDEH;OvXogF?QO9C)NQ!2-#G7<1Hix8WhD*Fz$6|9x zie|XPTXZZohooqROT1ObVsl7}X1K)LbSyT9q-cgqyj{m)b4ZG2xWqejEH;OvXogF? zQ^#U+NQ!2-#JhAXHix8WhD*F#$6|9xie|XPdvq)|hooqROT1UdVsl7}X1K)rbSyT9 zq-cgqykEy+b4ZG2xWor^EH;OvXogFCP{(3(NQ!2-#D{b&Hix8WhD&@{$6|9xie|XP zM|3PUhooqROMFzvVsl7}X1K)1bSyT9q-cgqd|bz3b4ZG2xWp%PEH;OvXogFCQpaL* zNQ!2-#HVyDHix8WhD&@}$6|9xie|XPXLKw!hooqROMF(xVsl7}X1K)XbSyT9q-cgq zd|t<5b4ZG2xWpH9EH;OvXogFCQO9C)NQ!2-#Fum|Hix8WhD&@|$6|9xie|XPS9B~k zhooqROMF$wVsl7}X1K)HbSyT9q-cgqd|k(4b4ZG2xWqSfEH;OvXogFCQ^#U+NQ!2- z#J6-THix8WhD&@~$6|9xie|XPcXTW^hooqROMF+yVsl7}X1K)nbSyT9q-cgqd|$_6 zb4ZG2xWo^1EH;OvXogGtP{(3(NQ!2-#E*0=Hix8WhD-cd$6|9xie|XPPjoCchooqR zOZ-&FVsl7}X1K)9bSyT9q-cgq{9MOkb4ZG2xWq4XEH;OvXogGtQpaL*NQ!2-#IJNL zHix8WhD-cf$6|9xie|XPZ*(j+hooqROZ-;HVsl7}X1K)fbSyT9q-cgq{9eamb4ZG2 zxWpfHEH;OvXogGtQO9C)NQ!2-#GiC5Hix8WhD-ce$6|9xie|XPUvw-shooqROZ-*G zVsl7}X1K)PbSyT9q-cgq{9VUlb4ZG2xWqqnEH;OvXogGtQ^#U+NQ!2-#J_YbHix8W zhD-cg$6|9xie|XPe{?K1hooqROZ->IVsl7}X1K)vbSyT9q-cgqJm>-Qx(Ceb9x$(a zz`V{@N{VK<#DjG#Hix8WhD$s|$6|9xie|XPLv<`RhooqROFT@+Vsl7}X1K(|bu2cA zq-cgqJVM7}b4ZG2xWprMEH;OvXogEXO2=YzNQ!2-#G`dAHix8WhD$s~$6|9xie|XP zV|6SxhooqROFT};Vsl7}X1K)Tbu2cAq-cgqJVD1|b4ZG2xWp56EH;OvXogEXNylPy zNQ!2-#FKR_Hix8WhD$s}$6|9xie|XPQ*|shhooqROFT`-Vsl7}X1K)Dbu2cAq-cgq z_-gI}78_ff&Fgfy!ERos!`u6RXL)W8Nzn|Kc&3iU=8zQ4aEWK>SZoeS(F~V(wvNT- zkQB{uiRb88Yz|4$43~JWj>YDX6wPpn=jm8%4oT4rmw3L8#paL{&2Whq=vZtHNzn|K zc%hEP=8zQ4aETY`SZoeS(F~V(v5v*&kQB{uiI?bDYz|4$43~JRj>YDX6wPpnm+4q+ z4oT4rmw363#paL{&2WiV=vZtHNzn|Kc%_cT=8zQ4aEVvxSZoeS(F~V(wT{K+kQB{u ziPz{@Yz|4$43~JVj>YDX6wPpn*XdYn4oT4rmw3I7#paL{&2Wh~=vZtHNzn|Kc%zQR z=8zQ4aEUkRSZoeS(F~V(vyR2)kQB{uiMQxjYz|4$43~JTj>YDX6wPpnx9M1H4oT4r zmw3C5#paL{&2Wi#=vZtHNzn|Kc&CoV=8zQ4aEW*6SZoeS(F~V(w~oc;kQB{uiTCJO zYz|4$43~JXj>YDX6wPpn_vu({4oT4rmw3O9#paL{&2Whi=vZtHNzn|K_@Iu(=8zQ4 zaETA;SZoeS(F~XPu#Uy%kQB{uiI3=5Yz|4$443$*j>YDX6wPpnkLg%!4oT4rm-x7j z#paL{&2WiN=vZtHNzn|K_@s`-=8zQ4aEVXpSZoeS(F~XPw2sB*kQB{uiO=X*Yz|4$ z443$YDX6wPpn&*@lf4oT4rm-xJn#paL{&2Wh?=vZtHNzn|K_@a)*=8zQ4aEUMJ zSZoeS(F~XPvW~^(kQB{uiLdBbYz|4$443$-j>YDX6wPpnujyE94oT4rm-xDl#paL{ z&2Wit=vZtHNzn|K_@<7<=8zQ4aEWi}SZoeS(F~XPwvNT-kQB{uiSOuGYz|4$443$> zj>YDX6wPpn@99`<4oT4rm-xPp#paL{&2Why=vZtHNzn|K_@R!)=8zQ4aETx3SZoeS z(F~XPv5v*&kQB{uiJ$0LYz|4$443$+j>YDX6wPpnpXpd^4oT4rm-xAk#paL{&2Wid z=vZtHNzn|K_@$1;=8zQ4aEV{(SZoeS(F~XPwT{K+kQB{uiQnj0Yz|4$443$=j>YDX z6wPpn-|1Lv4oT4rm-xMo#paL{&2Wi7=vZtHNzn|K_@j=+=8zQ4aEU+ZSZoeS(F~XP zvyR2)kQB{uiNEMrYz|4$443$;j>YDX6wPpnzv)YDX6wPpn z|LIt44oT4rmw1qg0E^8bDVpID57x2R9Fn3LF7Xf@i_IY^n&A=;)v?$dlA;+d@h}~W z%^@k8;SvwmvDh4vq8Tpn2px;fAt{>S5|7le*c_6g87}cC9gEE&DVpIDkJho+9Fn3L zF7X&0i_IY^n&A?U)v?$dlA;+d@i-le%^@k8;S!J6vDh4vq8Tpn1RaabAt{>S5>M2z z*c_6g87}c89gEE&DVpIDPu8*69Fn3LF7Xr{i_IY^n&A>p)v?$dlA;+d@iZNa%^@k8 z;Sx{RvDh4vq8TpXhU)_?HV0dr&Fgfy!ERosdxnnxcQ%KlXogEXQ^#U+NQ!2-#ItlP zHix8WhD$tK$6|9xie|XPb95{=hooqROFUP{Vsl7}X1K)jbSyT9q-cgqJYUCRb4ZG2 zxWo%|EH;OvXogF?P{(3(NQ!2-#EWz+Hix8WhD*Fy$6|9xie|XPOLQzYhooqROT1La zVsl7}X1K)5bSyT9q-cgqyj;g(b4ZG2xWp@TEH;OvXogF?QpaL*NQ!2-#H(~HHix8W zhD*F!$6|9xie|XPYji9&hooqROT1RcVsl7}X1K)bbSyT9q-cgqyk5s*b4ZG2xWpTD zEH;OvXogF?QO9C)NQ!2-#G7<1Hix8WhD*Fz$6|9xie|XPTXZZohooqROT1ObVsl7} zX1K)LbSyT9q-cgqyj{m)b4ZG2xWqejEH;OvXogF?Q^#U+NQ!2-#JhAXHix8WhD*F# z$6|9xie|XPdvq)|hooqROT1UdVsl7}X1K)rbSyT9q-cgqykEy+b4ZG2xWor^EH;Ov zXogFCP{(3(NQ!2-#D{b&Hix8WhD&@{$6|9xie|XPM|3PUhooqROMFzvVsl7}X1K)1 zbSyT9q-cgqd|bz3b4ZG2xWp%PEH;OvXogFCQpaL*NQ!2-#HVyDHix8WhD&@}$6|9x zie|XPXLKw!hooqROMF(xVsl7}X1K)XbSyT9q-cgqd|t<5b4ZG2xWpH9EH;OvXogFC zQO9C)NQ!2-#Fum|Hix8WhD&@|$6|9xie|XPS9B~khooqROMF$wVsl7}X1K)HbSyT9 zq-cgqd|k(4b4ZG2xWqSfEH;OvXogFCQ^#U+NQ!2-#J6-THix8WhD&@~$6|9xie|XP zcXTW^hooqROMF+yVsl7}X1K)nbSyT9q-cgqd|$_6b4ZG2xWo^1EH;OvXogGtP{(3( zNQ!2-#E*0=Hix8WhD-cd$6|9xie|XPPjoCchooqROZ-&FVsl7}X1K)9bSyT9q-cgq z{9MOkb4ZG2xWq4XEH;OvXogGtQpaL*NQ!2-#IJNLHix8WhD-cf$6|9xie|XPZ*(j+ zhooqROZ-;HVsl7}X1K)fbSyT9q-cgq{9eamb4ZG2xWpfHEH;OvXogGtQO9C)NQ!2- z#GiC5Hix8WhD-ce$6|9xie|XPUvw-shooqROZ-*GVsl7}X1K)PbSyT9q-cgq{9VUl zb4ZG2xWqqnEH;OvXogGtQ^#U+NQ!2-#J_YbHix8WhD-cg$6|9xie|XPe{?K1hooqR zOZ->IVsl7}X1K)vbSyT9q-cgqJjmBOEH;OvXogEXSjS>>NQ!2-#6xr}Hix8WhD$tD z$6|9xie|XP!*nb*hooqROFUf1Vsl7}X1K&7bSyT9q-cgqJW|JEb4ZG2xWuD$EH;Ov zXogEXTE}8@NQ!2-#A9?UHix8WhD$tF$6|9xie|XP<8&-GhooqROFUl3Vsl7}X1K%? zbSyT9q-cgqJWR4YDX z6wPpn=j&K(4oT4rmw17W#paL{&2Whq>R4YDX6wPpnm+M$;4oT4rmw1Ja#paL{&2WiV>R4YDX6wPpn z*Xvkp4oT4rmw1DY#paL{&2Wh~>R4YDX6wPpnx9eDJ4oT4rmw1Pc#paL{&2Wi#>R4YDX6wPpn_v=_} z4oT4rm-v8=#paL{&2Whi>R4hjp=8zQ4aETA=SZoeS(F~XPh>pePkQB{u ziI3`7Yz|4$443$rj>YDX6wPpnkLy@$4oT4rm-vK^#paL{&2WiN>R4_*t z=8zQ4aEVXrSZoeS(F~XPjE=?TkQB{uiO=d-Yz|4$443$vj>YDX6wPpn&+Axh4oT4r zm-vE?#paL{&2Wh?>R4zvr=8zQ4aEUMLSZoeS(F~XPijKwRkQB{uiLdHd zYz|4$443$tj>YDX6wPpnuj^QB4oT4rm-vQ`#paL{&2Wit>R4YDX6wPpn@9S7>4oT4rm-vB> z#paL{&2Why>R4qpq=8zQ4aETx5SZoeS(F~XPiH^nQkQB{uiJ$6NYz|4$ z443$sj>YDX6wPpnpX*p`4oT4rm-vN_#paL{&2Wid>R4u=8zQ4aEV{* zSZoeS(F~XPjgH0UkQB{uiQnp2Yz|4$443$wj>YDX6wPpn-|JXx4oT4rm-vH@#paL{ z&2Wi7>R4+#s=8zQ4aEU+bSZoeS(F~XPi;l(SkQB{uiNEStYz|4$443$u zj>YDX6wPpnzw20R4oT4rm-vT{#paL{&2Wi->R4YDX6wPpn2f1m-Vsl7}X1K(Ibu2cAq-cgq zJVeK0b4ZG2xWq$sEH;OvXogEXOvhq#NQ!2-#KUzgHix8WhD$s`$6|9xie|XPBXuk` zhooqROFT-)Vsl7}X1K(obu2cAq-cgqJVwW2b4ZG2xWr?1EH;OvXogEXPRC+%NQ!2- z#N%}=Hix8WhD$s_$6|9xie|XP6Ll;$hooqROFT)(Vsl7}X1K(Ybu2cAq-cgqJVnQ1 zb4ZG2xWrR+EH;OvXogEXO~+z$NQ!2-#M5;wHix8WhD+ES@c@g>At`KeHm}p+2D^Ek z4sY-Oo%Af4;S$f(vDh4vq8TpnEFFu@At{>S63^DL*c_6g87}c09gEE&DVpID&(*Qm z9Fn3LF7Z4ai_IY^n&A@9*Rj|flA;+d@d6!-%^@k8;Sw*@vDh4vq8TpnA{~p(At{>S z5---V*c_6g87}b>9gEE&DVpIDFV(Tw9Fn3LF7YxQi_IY^n&A>J*Rj|flA;+d@d_P_ z%^@k8;S#UZvDh4vq8TpnDjkc>At{>S60g>=*c_6g87}b}9gEE&DVpIDuhp^G9Fn3L zF7Y}Yi_IY^n&A?!*Rj|flA;+d@dh1>%^@k8;Sz7uvDh4vq8TpnCLN2-At{>S5^vVA z*c_6g87}b_9gEE&DVpIDZ`HBb9Fn3LF7Y-Ui_IY^n&A>}*Rj|flA;+d@eUn}%^@k8 z;S%rEvDh4vq8TpnE**=_At{>S67SZr*c_6g87}c29gEE&DVpID@71x`9Fn3LF7ZAc zi_IY^n&A@f*Rj|flA;+d@c|u+%^@k8;SwLzvDh4vq8TpnAsvg&At{>S5+ByF*c_6g z87}b=9gEE&DVpIDAJwtg9Fn3LF7YuPi_IY^n&A>3*Rj|flA;+d@d+J^%^@k8;S!(J zvDh4vq8TpnDIJT=At{>S5}($w*c_6g87}b|9gEE&DVpIDpVhJ09Fn3LF7Y`Xi_IY^ zn&A?k*Rj|flA;+d@dX`=%^@k8;SyievDh4vq8TpnB^`^+At{>S5?|J_*c_6g87}b^ z9gEE&DVpIDU)8bL9Fn3LF7Y)Ti_IY^n&A>(*Rj|flA;+d@eLh|%^@k8;S%4}vDh4v zq8TpnEgg%^At{>S65rOb*c_6g87}c19gEE&DVpID-_^0$9Fn3LF7Z7bi_IY^n&A@P z*Rj|flA;+d@dF);%^@k8;SxX8vDh4vq8TpnBOQy)At{>S5Z*Rj|flA;+d@e3V`%^@k8;S#^pvDh4vq8Tpn zD;S62I25*c_6g87}b~9gEE&DVpIDztyqW9Fn3LF7Z1Zi_IY^n&A?^*Rj|f zlA;+d@dq7?%^@k8;Szt;vDh4vq8TpnCmoB;At{>S5`WgQ*c_6g87}b`9gEE&DVpID zf7P+r9Fn3LF7Y=Vi_IY^n&A?E*Rj|flA;+d@edt~%^@k8;S&GUvDh4vq8TpnFCB}` zAt{>S693k**c_6g87}c39gEE&DVpID|JAYB9Fn3LF7ZDdi_IY^n&A=;@>eVtn?q7G z!zCW9W3f3TMKfIDAvzYDLsB%uB_66{u{k6~GhE_fIu@HlQZ&OQ9Fdn?q7G!zG@q zW3f3TMKfIDDLNLLLsB%uC7!Bdu{k6~GhE_nIu@HlQZ&OQo~~oDIV43hT*8*u2Uu(l zNzvHiY+k2(h7MoFn%C+0f2U}MOFUD@Vsl7}X1K(&bSyT9q-cgqJX^xvxv< zNQ!2-#OHJ@Hix8WhD&^2$6|9xie|XP7j!H(hooqROMFqsVsl7}X1K(cbSyT9q-cgq zd|Ah0b4ZG2xWrdxvhooqROZ-vCVsl7}X1K(kbSyT9q-cgq{8`6hb4ZG2 zxWr#{EH;OvXogGtRmWm;NQ!2-#NTu*Hix8WhD-ci$6|9xie|XPKXfcMhooqROZ-#E zVsl7}X1K(^bSyT9q-cgq{9DIjb4ZG2xWs>SEH;OvXogGtSI1&=NQ!2-#Q$_GHix8W zhD$uiAM9Cd4oT4rmw2#_#paL{&2Wi_=vZtHNzn|Kc&LuW=8zQ4aEXWMSZoeS(F~V( zxQ@lYDX6wPpnN9kB>4oT4rmw2>}#paL{&2Wjw=vZtH zNzn|Kc&v`a=8zQ4aEZt1SZoeS(F~V(ypF}@kQB{ui6`h-Yz|4$43~JKj>YDX6wPpn zC+S#h4oT4rmw2*{#paL{&2WjQ=vZtHNzn|Kc&d)Y=8zQ4aEYhsSZoeS(F~V(x{k%> zkQB{uiT_W>Vsl7}X0XNCyiSK3?B;bkyuJT-+H<(XGj%LBhooqROFT=*Vsl7}X1K(& zbu2cAq-cgqJV(c3b4ZG2xWsdHEH;OvXogEXPsd_&NQ!2-#PfA5Hix8WhD*Fa$6|9x zie|XP3w10uhooqROT0+OVsl7}X1K(Qbu2cAq-cgqyhO)hb4ZG2xWr3!EH;OvXogF? zOvhq#NQ!2-#LIOoHix8WhD*Fc$6|9xie|XPD|IY3hooqROT0?QVsl7}X1K(wbu2cA zq-cgqyhg`jb4ZG2xWsF9EH;OvXogF?PRC+%NQ!2-#Ork|Hix8WhD*Fb$6|9xie|XP z8+9x;hooqROT0|8sN~OBC$5qHTXkWy!Ym zdBx21b}=(EGcz+YGgG{APdG-lW;Yv4kzQhv6r01P8RFeK7D=%=T$&-?qhpa2o5Q6U z;=MW+NwGOxnjzk&W04e_!=)MG{W=y&u{m6tAwHmEkrbQ5r5WObIu=Q>Ib50{KBQxj z6r01P8REk_7D=%=T$&+1qGOR1o5Q6U;-fkiNwGOxnjt=>W04e_!=)MG<2n{eu{m6t zAwHpFkrbQ5r5WOrIu=Q>Ib50{KBZ%k6r01P8RFAA7D=%=T$&+1qhpa2o5Q6U;Ib50{zNBN36r01P z8RE-27D=%=T$&-iqGOR1o5Q6U;;T9qNwGOxnjyZXW04e_!=)MG>pB)mu{m6tA-Ib50{zNKT46r01P8RFYI7D=%=T$&-iqhpa2o5Q6U;=4K)NwGOx znjyZYW04e_!=)MG`#Kg$u{m6tA%37^krbQ5r5WOfIu=Q>Ib50{exzfO6r01P8REw} z7D=%=T$&+%qGOR1o5Q6U;-@+mNwGOxnjwCsW04e_!=)MG=QIb50{ex+lP6r01P8RFME7D=%=T$&+%qhpa2o5Q6U;Ib50{{-k4(6r01P8RE}67D=%= zT$&;NqGOR1o5Q6U;;%XuNwGOxnj!wCW04e_!=)MG?>ZJqu{m6tA^xFbkrbQ5r5WO% zIu=Q>Ib50{{-tA)6r01P8RFkM7D=%=T$&;Nqhpa2o5Q6U;=ei;NwGOxnj!wDW04e_ z!=)MG!M07ZNQ%wj(hTts9gC#c94^fe57n_qip}BD4Dm1>i=@~bF3k`R*Re>7&Ee7v z@dzD@q}UuT%@B{&u}F%|;nEE8C>@KW*c>j+5RcZeNQ%wj(hTt!9gC#c94^fekJYhA zip}BD4DmP}i=@~bF3k{+*Re>7&Ee7v@dO=j+ z5Kq>zNQ%wj(hTtw9gC#c94^fePt~zVip}BD4DmD_i=@~bF3k{6*Re>7&Ee7v@eCb{ zq}UuT%@EJju}F%|;nEDYIGfk$aD&~vPKUSm|4w@j@qms+Qfv;FW{79$SR}>faA}5k zwvI(oYz~)Zi09~7B*o@%X@+>Njzv;z4wq(#=jm7^#pZBnhIqb?MN(`Imu83;=vXAh z=5T3-c%hC(Qfv;FW{4N*SR}>faA}5kv5rMjYz~)Zh?nSCB*o@%X@+>Ijzv;z4wq(# zm+4p}#pZBnhIqM-MN(`Imu84p=vXAh=5T3-c%_a-Qfv;FW{6kmSR}>faA}5kwT?wn zYz~)Zh}Y;?B*o@%X@+>Mjzv;z4wq(#*XdX!#pZBnhIqY>MN(`Imu84J=vXAh=5T3- zc%zO*Qfv;FW{5ZGSR}>faA}5kvyMelYz~)Zh_~oiB*o@%X@+>Kjzv;z4wq(#x9M0U z#pZBnhIqSfaA}5kw~j?pYz~)Z zi1+ANB*o@%X@+>Ojzv;z4wq(#_vu(9#pZBnhIqe@MN(`Imu83$=vXAh=5T3-_@ItO zQfv;FW{3~zSR}>faA}74u#QDiYz~)Zh>z%4B*o@%X@>Zyjzv;z4wq(#kLg$>#pZBn zhWNOSMN(`Imu84h=vXAh=5T3-_@s_SQfv;FW{6MeSR}>faA}74w2nnmYz~)Zh|lO) zB*o@%X@>Z$jzv;z4wq(#&*@ks#pZBnhWNaWMN(`Imu84B=vXAh=5T3-_@a(QQfv;F zW{5B8SR}>faA}74vW`VkYz~)Zh_C2aB*o@%X@>Z!jzv;z4wq(#ujyDM#pZBnhWNUU zMN(`Imu84>=vXAh=5T3-_@<6UQfv;FW{7X;SR}>faA}74wvI(oYz~)Zi0|lFB*o@% zX@>Z&jzv;z4wq(#@99`1#pZBnhWNgYMN(`Imu83`=vXAh=5T3-_@RzPQfv;FW{4l@ zSR}>faA}74v5rMjYz~)Zh@a?KB*o@%X@>Zzjzv;z4wq(#pXpd6#pZBnhWNRTMN(`I zmu84x=vXAh=5T3-_@$0TQfv;FW{6+uSR}>faA}74wT?wnYz~)Zh~MZ~B*o@%X@>Z% zjzv;z4wq(#-|1K+#pZBnhWNdXMN(`Imu84R=vXAh=5T3-_@jf zaA}74vyMelYz~)Zh`;DqB*o@%X@>Z#jzv;z4wq(#zv);c#pZBnhWNXVMN(`Imu856 z=vXAh=5T3-_@|CVQfv;FW{7|3SR}>faA}74w~j?pYz~)Zi2vwVB*o@%X@>Z(jzv;z z4wq(#|LIsH#pZBnhInwB*V#5nQfv;FW{8LASR}>faA}5ksE$QaYz~)Zh==J|B*o@% zX@+>Xjzv;z4wq(#N9b52#pZBnhIpioMN(`Imu84Z=~yJi=5T3-c(jg1Qfv;FW{Ah= zSR}>faA}5ktd2!eYz~)Zh{x$zB*o@%X@+>bjzv;z4wq(#C+Jut#pZBnhIpcmMN(`I zmu843=~yJi=5T3-c(RT~Qfv;FW{9WgSR}>faA}5ks*XicYz~)Zh^OgTB*o@%X@+>Z zjzv;z4wq(#XXscY#pZBnhIpoqMN(`Imu3iG(AnZ_UZ=wicJn$N-roN^;~5X=SR}>f zaA}5kmX1YIYz~)Zh-d3qB*o@%X@+=?jzv;z4wq(#=jvD_#pZBnhIpQiMN(`Imu86P z>sTbk=5T3-c!7>ZQfv;FW{4N+SR}>faA}5kk&Z=DYz~)Zh!^WvB*o@%X@+=-jzv;z z4wq(#m+Dv~#pZBnhIpBdMN(`Imu85U>sTbk=5T3-c!iEdQfv;FW{6knSR}>faA}5k zm5xPHYz~)Zh*#@aB*o@%X@+=>jzv;z4wq(#*Xmd##pZBnhIpNhMN(`Imu869>sTbk z=5T3-c!Q2bQfv;FW{5ZHSR}>faA}5kla57FYz~)Zh&St4B*o@%X@+=sTbk=5T3-c!!QfQfv;FW{7v{SR}>faA}5kmyShJ zYz~)ZhsTbk=5T3- z_<)W@Qfv;FW{3~!SR}>faA}74kd8%CYz~)Zh!5*nB*o@%X@>ZSjzv;z4wq(#kLp+? z#pZBnhWMC{MN(`Imu85M>sTbk=5T3-_=Ju{Qfv;FW{6MfSR}>faA}74l#WGGYz~)Z zh)?TSB*o@%X@>ZWjzv;z4wq(#&+1qt#pZBnhWMP0MN(`Imu861>sTbk=5T3-_=1i_ zQfv;FW{5B9SR}>faA}74l8!}EYz~)Zh%f6{B*o@%X@>ZUjzv;z4wq(#uj*JN#pZBn zhWMI}MN(`Imu85s>sTbk=5T3-_=b)}Qfv;FW{7XfaA}74mX1YIYz~)Zh;Qpy zB*o@%X@>ZYjzv;z4wq(#@9J12#pZBnhWMV2MN(`Imu86X>sTbk=5T3-_<@c^Qfv;F zW{4l^SR}>faA}74k&Z=DYz~)Zh#%`%B*o@%X@>ZTjzv;z4wq(#pXyj7#pZBnhWMF| zMN(`Imu85c>sTbk=5T3-_=S!|Qfv;FW{6+vSR}>faA}74m5xPHYz~)Zh+peiB*o@% zX@>ZXjzv;z4wq(#-|AQ-#pZBnhWMS1MN(`Imu86H>sTbk=5T3-_=Ao`Qfv;FW{5xP zSR}>faA}74la57FYz~)Zh(GICB*o@%X@>ZVjzv;z4wq(#zv@^d#pZBnhWML~MN(`I zmu85+>sTbk=5T3-_=k=~Qfv;FW{7|4SR}>faA}74myShJYz~)Zh=1!?B*o@%X@>ZZ zjzv;z4wq(#|LRyI#pZBnhWMY3MN(`Imu83uk9pmg*V#5nu{m6tAs(V*krbQ5r5WO( zIu=Q>Ib50{9;RcF6r01P8RFqO7D=%=T$&*sp<|I0o5Q6U;*mNQNwGOxnjs#gW04e_ z!=)MG(K;4Mu{m6tAs(Y+krbQ5r5WO}Iu=Q>Ib50{9;aiG6r01P8RGFe7D=%=T$&-C zpkt8~o5Q6U;)yyINwGOxnjxN~W04e_!=)MG$vPHEu{m6tA)caRkrbQ5r5WO>Iu=Q> zIb50{o~C1w6r01P8RF?W7D=%=T$&-Cp<|I0o5Q6U;+Z-YNwGOxnjw5W_aJO>Hm}p+ z2D^Ek4sY-Oop?aUA}Kb9OEbi?bS#o$bGS4^JX^;iDK>{oGsJUrERte#xHLmNSH~hL zHit_y#Pf74l45hXG($XJ$08{{oGsH`DERte#xHLn&RL3GIHit_y#LILnl45hXG()^x$08{{oGsJ6jERte#xHLn&R>vYKHit_y z#Orh{l45hXG()^z$08{{oGsIhTERte#xHLn&RmUPJHit_y#M^W%l45hXG()^y$08{{oGsJszERte#xHLn&SH~hLHit_y#QStC zl45hXG()^!$08{{o zGsH)9ERte#xHLn2RL3GIHit_y#K&|jl45hXG(&t`$08{{oGsI_fERte#xHLn2R>vYKHit_y#OHJ@l45hX zG(&t|$08{{oGsIVP zERte#xHLn2RmUPJHit_y#Mg8zl45hXG(&t{$08{{oGsJgvERte#xHLn2SH~hLHit_y#P@V8l45hXG(&t} z$08{{oGsI7HERte# zxHLojRL3GIHit_y#Lsjrl45hXG(-Gc$08{{oGsJInERte#xHLojR>vYKHit_y#P4)0l45hXG(-Ge$08{< zhf6cWA9O5|Vsp4OL;O+4A}Kb9OEbiubS#o$bGS4^{8`5$DK>{oGsItXERte#xHLoj zRmUPJHit_y#NTu*l45hXG(-Gd$08{{oGsJ&%ERte#xHLojSH~hLHit_y#Q$_Gl45hXG($W%9(WLoq}UuT z%@7aKu}F%|;nEE8P#ue;*c>j+5D(L_NQ%wj(hTu%9gC#c94^fekI=D5ip}BD4Dm=E zi=@~bF3k{+(y>U2&Ee7v@n{{3q}UuT%@B{#u}F%|;nEE8SRIR`*c>j+5RcQbNQ%wj z(hTu<9gC#c94^fePtdVQip}BD4Dm!Ai=@~bF3k{6(y>U2&Ee7v@nju~q}UuT%@9w~ zu}F%|;nEE8R2_??*c>j+5Kq&wNQ%wj(hTu*9gC#c94^fe&(N_*ip}BD4Dn1Ii=@~b zF3k}CpN@qs&JWlO^MHSwe83I%2YeO#fJyrU-rfiP-+2&=q}UuT%@EJhu}F%|;nEE8 zY#ocF*c>j+5YN%ENQ%wj(hTuj9gC#c94^fe&(pC;ip}BD4Doy&i=@~bF3k`x(6LC0 z&Ee7v@j@Moq}UuT%@8lru}F%|;nEE8VjYX5*c>j+5HHcONQ%wj(hTuZ9gC#c94^fe zFVnF|ip}BD4DoUui=@~bF3k|H(6LC0&Ee7v@k$+wq}UuT%@D8Bu}F%|;nEE8Y8{KD z*c>j+5Uj+5O2}3NQ%wj(hTud9gC#c94^feZ_}|z zip}BD4Dogyi=@~bF3k|{(6LC0&Ee7v@lG9!q}UuT%@FU>u}F%|;nEE8ZXJuH*c>j+ z5bx2kNQ%wj(hTul9gC#c94^fe@6)kJip}BD4Do&)i=@~bF3k`h(6LC0&Ee7v@j)Gn zq}UuT%@7~bu}F%|;nEE8VI7O4*c>j+5FgR8NQ%wj(hTuY9gC#c94^feAJef&ip}BD z4DoRti=@~bF3k|1(6LC0&Ee7v@kt$vq}UuT%@Ci`u}F%|;nEE8X&sBC*c>j+5TDVp zNQ%wj(hTug9gC#c94^fepVP5Oip}BD4Dop#i=@~bF3k{M(6LC0&Ee7v@kJerq}UuT z%@AMGu}F%|;nEE8WgUy8*c>j+5MR-;NQ%wj(hTuc9gC#c94^feU(>Njip}BD4Dodx zi=@~bF3k|%(6LC0&Ee7v@l73zq}UuT%@E(xu}F%|;nEE8Z5@lG*c>j+5Z}?UNQ%wj z(hTuk9gC#c94^fe-_x;3ip}BD4Do#(i=@~bF3k`>(6LC0&Ee7v@k1Spq}UuT%@9A* zu}F%|;nEE8V;zg6*c>j+5I@neNQ%wj(hTua9gC#c94^feKhv>Dip}BD4DoXvi=@~b zF3k|X(6LC0&Ee7v@kj+5Wmr}NQ%wj(hTui z9gC#c94^feztgcuip}BD4Dov%i=@~bF3k{s(6LC0&Ee7v@kbqtq}UuT%@BXmu}F%| z;nEE8XB~^A*c>j+5P#9JNQ%wj(hTue9gC#c94^fef77u@ip}BD4Dojzi=@~bF3k}C z(6LC0&Ee7v@lPF#q}UuT%@F_6u}F%|;nEE8Zyk%I*c>j+5dYD!NQ%wj(hTum9gC#c z94^fe|I@KZip}BD4DsLxnb$qYyzW8fbq_MHvu%>Yr5WNOIu=Q>Ib50{9;#!J6r01P z8RB6&7D=%=T$&*su49oDo5Q6U;t@I)NwGOxnjs#kW04e_!=)MGQ92e$u{m6tAs($` zkrbQ5r5WNeIu=Q>Ib50{9;;)K6r01P8RBs|7D=%=T$&*suVaxEo5Q6U;t4tyNwGOx znjxO3W04e_!=)MGNjeruu{m6tA)c&bkrbQ5r5WNWIu=Q>Ib50{o~mP!6r01P8RBU= z7D=%=T$&-Cu49oDo5Q6U;u$&?NwGOxnjxO4W04e_!=)L*S91?yk=XWZUZ=xNck?{oGsN?B zERte#xHLmNU&kUTHit_y#0zvRl45hXG()^l$08{{oGsMeuERte#xHLn&T*o3QHit_y#4B_xl45hXG()^n z$08{{oGsNq3ERte# zxHLn&UdJLSHit_y#2a)hl45hXG()^m$08{{oGsN3;ERte#xHLn&UB@CRHit_y#5;5>l45hXG()^o$08{< zhf6cWyL2p)Vsp4OL%dtZA}Kb9OEbiKbS#o$bGS4^yjRB}DK>{oGsOFJERte#xHLn& zU&kUTHit_y#0PXNl45hXG(&t)$08{{oGsMSqERte#xHLn2T*o3QHit_y#3yttl45hXG(&t+$08{{oGsNd~ERte#xHLn2UdJLS zHit_y#20idl45hXG(&t*$08{{oGsM?)ERte#xHLn2UB@CRHit_y#5Z&-l45hXG(&t-$08{{oGsO3FERte#xHLn2U&kUTHit_y z#1C{Vl45hXG(-GQ$08{{oGsMqyERte#xHLojT*o3QHit_y#4mI#l45hXG(-GS$08{{oGsN$7ERte#xHLojUdJLSHit_y#2<7l zl45hXG(-GR$08{{o zGsNF?ERte#xHLojUB@CRHit_y#6NT_l45hXG(-GT$08{{oGsORNERte#xHLmN*e`t+NwGOxnjs#dW04e_ z!=)MGp*j{xu{m6tAs(hIb50{9-(8A6r01P8RC&T7D=%=T$&*s zrDKs4o5Q6U;?X)5NwGOxnjs#eW04e_!=)MGu{st>u{m6tAs(k=krbQ5r5WP!Iu=Q> zIb50{o}goq6r01P8RCgL7D=%=T$&-Cq+^j3o5Q6U;>kJ|NwGOxnjxN|W04e_!=)MG zsX7)(u{m6tA)cmVkrbQ5r5WPsIu=Q>Ib50{o}pur6r01P8RD5b7D=%=T$&-=aD5Pq zq_FMTyiSLk?&fv62Xy?ulN6i7r5WN`Iu=Q>Ib50{o~>h%6r01P8R9uQ7D=%=T$&-C zt7DNAo5Q6U;(0n2NwGOxnjxOAW04e_!=)MG1v(Z zIb50{UaVu06r01P8R8{67D=%=T$&+Xs$-E9o5Q6U;$=D(NwGOxnjv1UW04e_!=)MG z6*?A4u{m6tAzrCtkrbQ5r5WN?Iu=Q>Ib50{Uae!16r01P8R9iM7D=%=T$&+Xt7DNA zo5Q6U;&nO}NwGOxnjv1VW04e_!=)MG4LTM{u{m6tA>OECkrbQ5r5WN)Iu=Q>Ib50{ z-mGJh6r01P8R9KE7D=%=T$&-?s$-E9o5Q6U;%zz>NwGOxnjzkOHDkrbQ5r5WN~Iu=Q>Ib50{-mPPi6r01P8R9)U7D=%=T$&-?t7DNAo5Q6U z;(a<6NwGOxnjzk=W04e_!=)MG13DH-u{m6tAwH;MkrbQ5r5WNwIu=Q>Ib50{KCEMr z6r01P8R8>47D=%=T$&+1s$-E9o5Q6U;$u1%NwGOxnjt=}W04e_!=)MG6FL@2u{m6t zAwH>NkrbQ5r5WN=Iu=Q>Ib50{KCNSs6r01P8R9cK7D=%=T$&+1t7DNAo5Q6U;&VC{ zNwGOxnjt=~W04e_!=)MG3py4_u{m6tA-Ib50{zN}-B6r01P z8R9EC7D=%=T$&-is$-E9o5Q6U;%hnIb50{zO7@C6r01P8R9!S7D=%=T$&-it7DNAo5Q6U;(Iz4NwGOx znjyZgW04e_!=)MG2Rar>u{m6tA%3W1krbQ5r5WN!Iu=Q>Ib50{eyn4W6r01P8R928 z7D=%=T$&+%s$-E9o5Q6U;%7P*NwGOxnjwC!W04e_!=)MG7djS6u{m6tA%3Z2krbQ5 zr5WN^Iu=Q>Ib50{eywAX6r01P8R9oO7D=%=T$&+%t7DNAo5Q6U;&(b0NwGOxnjwC# zW04e_!=)MG4>}e}u{m6tA^xaikrbQ5r5WN+Iu=Q>Ib50{{;Xq>6r01P8R9QG7D=%= zT$&;Ns$-E9o5Q6U;%_<@NwGOxnj!wKW04e_!=)MGA37FEu{m6tA^xdjkrbQ5r5WO1 zIu=Q>IsE?|-9-`rF|J_2E2(YEl8)ERjML1_%*@Qp%*+%&r^Au8dfVD4%B7+i;$J!z zn?rIbnj!wJW3f3Tm!cWsKROnhLvksaA^xjlu{k7{q8Z|WzRF>-IV6{&8R9`Y7MnwI zDViZ3tYfh`B$uKY;vqT~n?rIbnjs#lW3f3Tm!cWsVLBF@LvksaAs(({u{k7{q8Z{5 zIu@Hlaw(c29;suoIV6{&8RAho7MnwIDViZ3tz)q{B$uKY;xRfFn?rIbnjs#mW3f3T zm!cWsaXJ>8LvksaAs(+|u{k7{q8Z`|Iu@Hlaw(c2o~UE7IV6{&8RAJg7MnwIDViak ztYfh`B$uKY;wd^7n?rIbnjxO5W3f3Tm!cWsX*w30LvksaA)c;du{k7{q8Y;9=pMjg zb4YA^Hm}p+rn`Ba4sZGY&hbnxMKi=Rbu2cAvb$PhvZT;L%c!9Vsl6?MKi=3bu2cAVsl6?MKi=d zbu2cA}>B$uKY;_*5bn?rIbnjxN`W3f3Tm!cWsi8>aWLvksa zA)cgTu{k7{q8Z}JIu@Hlaw(c2o}y#1IV6{&8RDrr7MnwIDViakrem==B$uKY;^{gT zn?rIbnjvhCcmRvdA-UN0Y+k3sO?UG;9p3W)o%FmE%@EJjvDh4vOVJGREFFu@A-NRI z5YN`J*c_5e(G2k%9gEE&xfIP1&(*Qm9Fj}X4Dmc2i_Iaq6wMIN*Rj|fl1tGH@d6!- z%^|rI%@8ltvDh4vOVJGRA{~p(A-NRI5HHrT*c_5e(G2kt9gEE&xfIP1FV(Tw9Fj}X z4Dm7@i_Iaq6wMGX*Rj|fl1tGH@d_P_%^|rI%@D8DvDh4vOVJGRDjkc>A-NRI5U%^|rI z%@A+YvDh4vOVJGRCLN2-A-NRI5O3D8*c_5e(G2kx9gEE&xfIP1Z`HBb9Fj}X4DmJ{ zi_Iaq6wMHC*Rj|fl1tGH@eUn}%^|rI%@FU@vDh4vOVJGRE**=_A-NRI5bxHp*c_5e z(G2k(9gEE&xfIP1@71x`9Fj}X4Dmi4i_Iaq6wMIt*Rj|fl1tGH@c|u+%^|rI%@7~d zvDh4vOVJGRAsvg&A-NRI5FggD*c_5e(G2ks9gEE&xfIP1AJwtg9Fj}X4Dm4?i_Iaq z6wMGH*Rj|fl1tGH@d+J^%^|rI%@Ci|vDh4vOVJGRDIJT=A-NRI5TDku*c_5e(G2k! z9gEE&xfIP1pVhJ09Fj}X4DmS~i_Iaq6wMHy*Rj|fl1tGH@dX`=%^|rI%@AMIvDh4v zOVJGRB^`^+A-NRI5MS1@*c_5e(G2kw9gEE&xfIP1U)8bL9Fj}X4DmG`i_Iaq6wMG{ z*Rj|fl1tGH@eLh|%^|rI%@E(zvDh4vOVJGREgg%^A-NRI5Z~6Z*c_5e(G2k&9gEE& zxfIP1-_^0$9Fj}X4Dmf3i_Iaq6wMId*Rj|fl1tGH@dF);%^|rI%@9A-vDh4vOVJGR zBOQy)A-NRI5I@$j*c_5e(G2ku9gEE&xfIP1Kh?3=9Fj}X4DmA^i_Iaq6wMGn*Rj|f zl1tGH@e3V`%^|rI%@DuTvDh4vOVJGRD;Fdn?rIbnjxO7W3f3Tm!cWsDLNLLLvksaA)cyZu{k7{q8Z|8 zIu@Hlaw(c2o~~oDIV6{&8N!y=2e8;2l1pLRvw5BF|LO4cta+V||9>t;GsH7>EH;Pa zQZz$6OUGh!NG?S)#ItoQHizU=G($W`$6|9xE=4oMb9F2>hvZT;Lp)E%Vsl6?MKi?n zbu2cAHizU=G(-GE$6|9xE=4oMPjxIdhvZT;L;Os~ zVsl6?MKi?Dbu2cApeP zkX(vph==M}Y!1n#Xoh&0j>YDXT#9ChhwE5u4#}lxhIoXI#paM)ie`vM>R4YDXT#9Ch$Lm;Z z4#}lxhIoRG#paM)ie`u>>R4YDXT#9Chr|Vd34#}lxhIodK#paM)ipI8Q^Ew@Fx|`SO@RtAY zlxH)+bu2cAUbu2cA z!bu2cAkbu2cA^bu2cAQbu2cA1$ zb4V^lGsH)AEH;PaQZz$+Ovhq#NG?S)#K(0kHizU=G(&ts$6|9xE=4oMCv_|~hvZT; zLwridVsl6?MKi>wbu2cAgbu2cA=bu2cAYbu2cA&bu2cAobu2cA| zbu2cA z9Fj}X4Dn7Ki_Iaq6wMIt(y`bal1tGH@opW9%^|rI%@FU=vDh4vOVJGRULA|gA-NRI z5bx8m*c_5e(G2l^9gEE&xfIP1AJDPb9Fj}X4Dmr7i_Iaq6wMGH(y`bal1tGH@nIc{ z%^|rI%@7~avDh4vOVJGRQ5}oTA-NRI5FgXA*c_5e(G2l%9gEE&xfIP1pU|<`9Fj}X z4Dm@Fi_Iaq6wMHy(y`bal1tGH@o624%^|rI%@Ci_vDh4vOVJGRSsjbbA-NRI5TDbr z*c_5e(G2l<9gEE&xfIP1U(m7G9Fj}X4Dm%Bi_Iaq6wMG{(y`bal1tGH@ns#0%^|rI z%@AMFvDh4vOVJGRRUM1XA-NRI5MR@=*c_5e(G2l*9gEE&xfIP1-_Wtx9Fj}X4Dn4J zi_Iaq6wMId(y`bal1tGH@ogQ8%^|rI%@E(wvDh4vOVJGRT^) z9gEE&xfIP1f6%em9Fj}X4Dm-Di_Iaq6wMHS(y`bal1tGH@n;>2%^|rI%@BXlvDh4v zOVJGRR~?JZA-NRI5P#FL*c_5e(G2l-9gEE&xfIP1|Io469Fj}X4DnALi_Iaq6wMI- z(y`bal1tGH@oycA%^|rI%@F_5vDh4vOVJGRUmc6hA-NRI5D#qgI$I>!9Fj}X4Dlcx zi_Iaq6wMG1*0Iv49Fj}X4Dlo#i_Iaq z6wMG%*0I@pA-NRI5HHoS*c_5e(G2l29gEE& zxfIP1FW0fy9Fj}X4Dkvbi_Iaq6wMH?)Untcl1tGH@hTmQ%^|rI%@D8FvDh4vOVJGR z8Xb$xA-NRI5UFdn?rIbnjxO7W3f3Tm!cWsDLNLLLvksaA)cyZu{k7{q8Z|8Iu@Hl zaw(c2o~~oDIV6{&8R8i_7MnwIDViaCJ@)`?dp57r;ikKJoeppL|4uwp$6|9xE=4oM zvve#rhvZT;Lp)o@Vsl6?MKi>6bSyT9HizU=G()^o$6|9xE=4oMyL2ozhvZT; zL%dtZVsl6?MKi>EbSyT9{&2YHH2X!RHV$%$VOMFO2 zQY<#jaJa;WbtJ`N(+r18d_+f5EH=$>xWq?wB*kLW42Mg6Oh-~IHqCIj#K(0c#bVP8 zhf91yM^Y>{&2YHHCv_ynV$%$VOMFU4QY<#jaJa;$btJ`N(+r18d`3r7EH=$>xWs35 zB*kLW42Mg6PDfHKHqCIj#OHM+#bVP8hf91xM^Y>{&2YHH7j-1XV$%$VOMFR3QY<#j zaJa;mbtJ`N(+r18d__l6EH=$>xWrd=B*kLW42Mg6O-E8JHqCIj#MgBs#bVP8hf91z zM^Y>{&2YHHH+3Y%V$%$VOMFX5QY<#jaJa;`btJ`N(+r18d`Cx8EH=$>xWspLB*kLW z42Mg6Pe)QLHqCIj#P@Y1#bVP8hfDlGM^Y>{&2YHH4|OEPV$%$VOZ-SjQY<#jaJa;e zbtJ`N(+r18{6t4mEH=$>xWrF&B*kLW42MhnOh-~IHqCIj#Lsmk#bVP8hfDlIM^Y>{ z&2YHHFLflvV$%$VOZ-YlQY<#jaJa;;btJ`N(+r18{6xWsRDB*kLW42Mhn zPDfHKHqCIj#P4+^#bVP8hfDlHM^Y>{&2YHHA9WxWr#|B*kLW42MhnO-E8JHqCIj#NTx!#bVP8hfDlJM^Y>{&2YHH zKXoLxWs>TB*kLW42MhnPe)QL zHqCIj#Dn5l50Dg#O*0%W@n9WEvDh@j;SvwgkrazfGaN4QP#sCJ*fhi85)adn6pKwW z94_&29Z9j+G{fN%kI<16i%l~eF7ZemNwL^8!{HK-(vcL4O*0%W@n{`MvDh@j;S!J0 zkrazfGaN4QSRF~R*fhi85|7i76pKwW94_&A9Z9j+G{fN%PtcJRi%l~eF7ZSiNwL^8 z!{HK7(vcL4O*0%W@njuIvDh@j;Sx{LkrazfGaN4QR2@mN*fhi85>L~S6pKwW94_&6 z9Z9j+G{fN%&(M(+i%l~eF7ZqqNwL^8!{HMDpN_<~=V#d<^DJMbe3qN;&+_){vrOcl z<*)o%|92iBDHfY%I9%e{I+9|sX@DHfY%I9%ezI+9|sX@I+9|sX@;37Mo@`T;i)bl47xG zhQlSkrXwj9n`Ss%;_Et+VzFt4!zI3vzWv1x|GCBCI2DHfY%I9%e} zI+9|sX@xWvPBB*kLW42MfRTt`wYHqCIj#3OVh#bVP8 zhf6$CM^Y>{&2YHHqjV(2V$%$VOFUXfQY<#jaJa-{bR@-M(+r18JXS|iEH=$>xWwah zB*kLW42MfRUPn?aHqCIj#1nKR#bVP8hf6$BM^Y>{&2YHHlXN7-V$%$VOFUUeQY<#j zaJa-%bR@-M(+r18JXJ?hEH=$>xWv{&2YGcx8@!oDQtx{uhZd1ym_4tPlNw=(r>ZYG{fN%&(@I?i%l~eF7X^4NwL^8 z!{HLo)sYm7O*0%W@jM+#vDh@j;S$f+krazfGaN4Q0v$=Q*fhi85--$|6pKwW94_%9 z9Z9j+G{fN%FV>M1i%l~eF7Xl_NwL^8!{HJy)sYm7O*0%W@iHArvDh@j;Sw*`krazf zGaN4Q3LQzY*fhi860g*e6pKwW94_%H9Z9j+G{fN%uhx+ii%l~eF7X;2NwL^8!{HLI z)sYm7O*0%W@j4wzvDh@j;S#UckrazfGaN4Q1|3PU*fhi85^vOz6pKwW94_%D9Z9j+ zG{fN%Z`P3%i%l~eF7Xx}NwL^8!{HKd)sYm7O*0%W@irYvvDh@j;Sz7xkrazfGaN4Q z4joCc*fhi867STJ6pKwW94_%L9Z9j+G{fN%@79qNi%l~eF7X~6NwL^8!{HL|)sYm7 zO*0%W@je|%vDh@j;S%rHkrazfGaN4Q0Ub%P*fhi85+Br&6pKwW94_%89Z9j+G{fN% zAJ&l+i%l~eF7Xi^NwL^8!{HJi)sYm7O*0%W@i84qvDh@j;SwL$krazfGaN4Q2^~qX z*fhi85}(wO6pKwW94_%G9Z9j+G{fN%pVpBSi%l~eF7X*1NwL^8!{HL2)sYm7O*0%W z@i`qyvDh@j;S!(MkrazfGaN4Q1szGT*fhi85?|Dj6pKwW94_%C9Z9j+G{fN%U)GTn zi%l~eF7Xu|NwL^8!{HKN)sYm7O*0%W@iiSuvDh@j;SyihkrazfGaN4Q4IN3b*fhi8 z65rI36pKwW94_%K9Z9j+G{fN%-`0^7i%l~eF7X{5NwL^8!{HL&)sYm7O*0%W@jV?$ zvDh@j;S%51krazfGaN4Q106}R*fhi853NwL^8!{HLY)sYm7O*0%W@jD$!vDh@j z;S#^skrazfGaN4Q2OUYV*fhi85`WZ@6pKwW94_%E9Z9j+G{fN%f7X!{i%l~eF7X!~ zNwL^8!{HKt)sYm7O*0%W@i!ewvDh@j;Szt>krazfGaN4Q4;@Ld*fhi8693eZ6pKwW z94_%M9Z9j+G{fN%|JIQdi%l~eF7Y27NwL^8!{HMD)sYm7O*0%W@jo3&vDh@j;Svw> zA3RC1*fhi85)amq6pKwW94_$?9Z9j+G{fN%57m(ri%l~eF7YrONwL^8!{HJS*O3&9 zO*0%W@dzDBvDh@j;S!J3krazfGaN4QC>=?$*fhi85|7rA6pKwW94_$~9Z9j+G{fN% zkJXVBi%l~eF7Y@WNwL^8!{HK-*O3&9O*0%W@dO=7vDh@j;Sx{OkrazfGaN4QBppey z*fhi85>M8V6pKwW94_$`9Z9j+G{fN%Pt}nWi%l~eF7Y%SNwL^8!{HK7*O3&9O*0%W z@eCbFvDh@j;S$f(krazfGaN4AhU)_)#llu-^Ew@F#GBXYo~7gePO;cD!{HLo){zv8 zO*0%W@f;mVvDh@j;S$f)krazfGaN4QJRM1~*fhi863^F>6pKwW94_$!9Z9j+G{fN% zFVv9~i%l~eF7YBANwL^8!{HJy){zv8O*0%W@e&_MvDh@j;SxX9krazfGaN4QGaX5>*fhi859Z9j+ zG{fN%|J0Ebi%l~eF7YoNNwL^8!{HMD){zv8O*0%W@gE&YvDh@j;S&GVkrazfGaN4Q zKOIT2*fhi85)bmW4N0-sG{fN%57vM2T z6pKwW94_%B9Z9j+G{fN%Pu7tXi%l~eF7Xr{NwL^8!{HK7)sYm7O*0%W@iZMtvDh@j z;Sx{RkrazfGaN4Q3>`_a*fhi863^6;6pKwW94_H&bPtdei;b<&=5;#Uh&Qj(;c4*y z&hooyhQlSEts^NGn`Ss%;yF5!VzFt4!zG@pBPkY}W;k5pc{-9}v1x|GC7!P%DHfY% zI9%cdI+9|sX@*&zv1x|GB|ferDHfY%I9%crI+9|sX@ zDHfY%I9%c%I+9|sX@#$4v1x|GB_8Bv97(a*G{fN%57vM2T6pKwW94_%B9Z9j+G{fN%Pu7tXi%l~eF7Xr{NwL^8!{HK7)sYm7 zO*0%W@iZMtvDh@j;Sx{RkrazfGaN4Q3>`_a*fhi863^6;6pKwW94=vV!~-P7V$;|P zZCxWsdHB*kLW42MfRPe)QL zHqCIj#Pf9|#bVP8hfBObM^Y>{&2YHH3w0#LV$%$VOT0)&QY<#jaJa;abtJ`N(+r18 zyhKM*EH=$>xWr3!B*kLW42Mg+Oh-~IHqCIj#LIOg#bVP8hfBOdM^Y>{&2YHHD|IBr zV$%$VOT0=)QY<#jaJa;)btJ`N(+r18yhcY-EH=$>xWsF9B*kLW42Mg+PDfHKHqCIj z#Ork=#bVP8hfBOcM^Y>{&2YHH8+9bbV$%$VOT0-(QY<#jaJa;qbtJ`N(+r18yhTS+ zEH=$>xWrp^B*kLW42Mg+O-E8JHqCIj#M^Zw#bVP8hfBOeM^Y>{&2YHHJ9Q+*V$%$V zOT0@*QY<#jaJa;~btJ`N(+r18yhle;EH=$>xWs#PB*kLW42Mg+Pe)QLHqCIj#QSw5 z#bVP8hf91wM^Y>{&2YHH2X!RHV$%$VOMFO2QY<#jaJa;WbtJ`N(+r18d_+f5EH=$> zxWq?wB*kLW42Mg6Oh-~IHqCIj#K(0c#bVP8hf91yM^Y>{&2YHHCv_ynV$%$VOMFU4 zQY<#jaJa;$btJ`N(+r18d`3r7EH=$>xWs35B*kLW42Mg6PDfHKHqCIj#OHM+#bVP8 zhf91xM^Y>{&2YHH7j-1XV$%$VOMFR3QY<#jaJa;mbtJ`N(+r18d__l6EH=$>xWrd= zB*kLW42Mg6O-E8JHqCIj#MgBs#bVP8hf91zM^Y>{&2YHHH+3Y%V$%$VOMFX5QY<#j zaJa;`btJ`N(+r18d`Cx8EH=$>xWspLB*kLW42Mg6Pe)QLHqCIj#P@Y1#bVP8hfDlG zM^Y>{&2YHH4|OEPV$%$VOZ-SjQY<#jaJa;ebtJ`N(+r18{6t4mEH=$>xWrF&B*kLW z42MhnOh-~IHqCIj#Lsmk#bVP8hfDlIM^Y>{&2YHHFLflvV$%$VOZ-YlQY<#jaJa;; zbtJ`N(+r18{6xWsRDB*kLW42MhnPDfHKHqCIj#P4+^#bVP8hfDlHM^Y>{ z&2YHHA9WxWr#|B*kLW42Mhn zO-E8JHqCIj#NTx!#bVP8hfDlJM^Y>{&2YHHKXoLxWs>TB*kLW42MhnPe)QLHqCIj#DjdrilkUPU*krWp>Gc$ki)SZtc%aEXWONQ%X#84j0tgpQPU*krWp>Gc$|);SZtc% zaEZt3NQ%X#84j0tf{vtEY?|S4i6`nvip8cG4wrb6j-*&@n&EJXC+kRx#ikh!mw1Yf zq*!d4;c$tk>PU*krWp>Gc$$u+SZtc%aEYhuNQ%X#84j0thK{6IY?|S4iD&9aip8cG z4wtay^#PJ%v1tZdq0Q@b&(h&7Tk|>{|96_PU*krWp>Gc#)2zSZtc% zaETY|NQ%X#84j0tiH@XLY?|S4iI?g~ip8cG4wrbDj-*&@n&EJXm+MH1#ikh!mw1Ja zq*!d4;c$sp>PU*krWp>Gc$JQ%SZtc%aEVvzNQ%X#84j0tjgF*PY?|S4iP!2#ip8cG z4wrbHj-*&@n&EJX*Xu}%#ikh!mw1DYq*!d4;c$sJ>PU*krWp>Gc$1E#SZtc%aEUkT zNQ%X#84j0ti;kpNY?|S4iMQ%Vip8cG4wrbFj-*&@n&EJXx9doX#ikh!mw1Pcq*!d4 z;c$s}>PU*krWp>Gc$bc(SZtc%aEW*8NQ%X#84j0tkB+2RY?|S4iTCPAip8cG4wrbJ zj-*&@n&EJX_v=WC#ikh!m-v8=q*!d4;c$r$>PU*krWp>G_>hjISZtc%aETA=NQ%X# z84j2Dh>oOKY?|S4iI3_?ip8cG4wv|tj-*&@n&EJXkLyT^#ikh!m-vK^q*!d4;c$sh z>PU*krWp>G_>_*MSZtc%aEVXrNQ%X#84j2DjEPU*krWp>G_>zvKSZtc%aEUMLNQ%X#84j2D zijJgMY?|S4iLdHNip8cG4wv|vj-*&@n&EJXuj@#P#ikh!m-vQ`q*!d4;c$s>>PU*k zrWp>G_?C{OSZtc%aEWj0NQ%X#84j2Dj*g^QY?|S4iSO!2ip8cG4wv|zj-*&@n&EJX z@9Rj4#ikh!m-vB>q*!d4;c$r`>PU*krWp>G_>qpJSZtc%aETx5NQ%X#84j2DiH@XL zY?|S4iJ$67ip8cG4wv|uj-*&@n&EJXpX*49#ikh!m-vN_q*!d4;c$sx>PU*krWp>G z_?3>NSZtc%aEV{*NQ%X#84j2DjgF*PY?|S4iQno-ip8cG4wv|yj-*&@n&EJX-|I+< z#ikh!m-vH@q*!d4;c$sR>PU*krWp>G_>+#LSZtc%aEU+bNQ%X#84j2Di;kpNY?|S4 ziNESdip8cG4wv|wj-*&@n&EJXzw1bf#ikh!m-vT{q*!d4;c$t6>PU*krWp>G_?M2P zSZtc%aEX8GNQ%X#84j2DkB+2RY?|S4iT~eiIl8MI3VNK;wy)$) zoY;Q6W@bKLGcz+YGcz+Yck7J(D;jk*uS;51WjQ%qie`uh`^R|}o8)jQnjs#dW3fpN zm!cWsp*j|uq8Z}hIu@Jca4DK09-(8gNe-8y8RC&T7MtX7DViZ3 zrDL&44ws@C;?X)5o8)jQnjs#eW3fpNm!cWsu{su;q8Z}xIu@Jc za4DK0o}go~Ne-8y8RCgL7MtX7DViakq+_v34ws@C;>kJ|o8)jQnjxN|W3fpNm!cWs zsX7*$q8Z}pIu@Jca4DK0o}pv0Ne-8y8RD5b7MtX7DViakrDL&4 z4ws@C;@LVDo8)jQ8e5^w>vXsgZ(gUv+u;9Bc{W2lpkuK~4ws@C;yF4No8)jQnjxO6 zW3fpNm!cWsc{&!Geu}Kb>q8Z`^Iu@Jca4DK0UZ`WSNe-8y8RA7c7MtX7 zDViZ(tYfiB4ws@C;w3s3o8)jQnjv1QW3fpNm!cWsWjYp{q8Z{9 zIu@Jca4DK0Ua4cTNe-8y8RAts7MtX7DViZ(tz)rC4ws@C;x#%Jo8)jQnjv1RW3fpN zm!cWsbvhQCq8Z{1Iu@Jca4DK0-l$`-Ne-8y8RAVk7MtX7DVibP ztYfiB4ws@C;w?HBo8)jQnjzk*W3fpNm!cWsZ8{d4OWIu}Kb>q8Z{HIu@Jc za4DK0-l=1;Ne-8y8RA_!7MtX7DVibPtz)rC4ws@C;ypSRo8)jQnjzk+W3fpNm!cWs zeL5DKOZJu}Kb>q8Z`?Iu@Jca4DK0KB!}{Ne-8y8RA1a7MtX7DViZZtYfiB z4ws@C;v+g1o8)jQnjt=_W3fpNm!cWsV>%X_q8Z{7Iu@Jca4DK0 zKB;4|Ne-8y8RAnq7MtX7DViZZtz)rC4ws@C;xjrHo8)jQnjt=`W3fpNm!cWsb2=8A zq8Z`~Iu@Jca4DK0zNlldNe-8y8RAPi7MtX7DVia^tYfiB4ws@C z;ww59o8)jQnjyZbW3fpNm!cWsYdRL2q8Z{FIu@Jca4DK0zNure zNe-8y8RAq8Z``Iu@Jca4DK0eyC%yNe-8y8RADe7MtX7DViaEtYfiB4ws@C;wL&5 zo8)jQnjwCwW3fpNm!cWsXF3*}q8Z{BIu@Jca4DK0eyL-zNe-8y z8RAzu7MtX7DViaEtz)rC4ws@C;x{@Lo8)jQnjwCxW3fpNm!cWscRCiEq8Z{3Iu@Jca4DK0{-|TINe-8y8RAbm7MtX7DVibvtYfiB4ws@C;x9TDo8)jQ znj!wGW3fpNm!cWsZ#ov6q8Z{JIu@Jca4DK0{;6ZJNe-8y8RB0$ z7MtX7DVibvtz)rC4ws@C;y*eTo8)jQnj!wHW3fpNm!cWse>xVM(#t%@B{!vDhSsOVJGR zNF9q!a<~-D5RcNa*d&Kb(G2lu9g9tJxD?G0kI}K%B!^4U4DnbUi%oL46wMHi)3Mkj zhfC26@pv7JO>(#t%@9w}vDhSsOVJGRL>-Gwa<~-D5Kq#v*d&Kb(G2lq9g9tJxD?G0 zPtmd1B!^4U4DnPQi%oL46wMG%)3MkjhfC26@pK)FO>(#t%@EJfvDhSsOVJGROdX3& za<~-D5YN)F*d&Kb(G2ly9g9tJxD?G`E3|o?4maY>>vVV<{NHKMAs*1N*d&Kb(G2k% z9g9tJxD?G0&(*QmB!^4U4Dmc2i%oL46wMIN*Rj|nhfC26@d6!-O>(#t%@8ltvDhSs zOVJGRA{~oOa<~-D5HHrT*d&Kb(G2kt9g9tJxD?G0FV(TwB!^4U4Dm7@i%oL46wMGX z*Rj|nhfC26@d_P_O>(#t%@D8DvDhSsOVJGRDjkbWa<~-D5UO>(#t%@A+YvDhSsOVJGR zCLN1Sa<~-D5O3D8*d&Kb(G2kx9g9tJxD?G0Z`HBbB!^4U4DmJ{i%oL46wMHC*Rj|n zhfC26@eUn}O>(#t%@FU@vDhSsOVJGRE**(#t%@7~dvDhSsOVJGRAsvfN za<~-D5FggD*d&Kb(G2ks9g9tJxD?G0AJwtgB!^4U4Dm4?i%oL46wMGH*Rj|nhfC26 z@d+J^O>(#t%@Ci|vDhSsOVJGRDIJSVa<~-D5TDku*d&Kb(G2k!9g9tJxD?G0pVhJ0 zB!^4U4DmS~i%oL46wMHy*Rj|nhfC26@dX`=O>(#t%@AMIvDhSsOVJGRB^`@Ra<~-D z5MS1@*d&Kb(G2kw9g9tJxD?G0U)8bLB!^4U4DmG`i%oL46wMG{*Rj|nhfC26@eLh| zO>(#t%@E(zvDhSsOVJGREgg$Za<~-D5Z~6Z*d&Kb(G2k&9g9tJxD?G0-_^0$B!^4U z4Dmf3i%oL46wMId*Rj|nhfC26@dF);O>(#t%@9A-vDhSsOVJGRBOQxPa<~-D5I@$j z*d&Kb(G2ku9g9tJxD?G0Kh?3=B!^4U4DmA^i%oL46wMGn*Rj|nhfC26@e3V`O>(#t z%@DuTvDhSsOVJGRD;(#t%@BXovDhSsOVJGRCmoATa<~-D5P#OO*d&Kb z(G2ky9g9tJxD?G0f7P+rB!^4U4DmM|i%oL46wMHS*Rj|nhfC26@edt~O>(#t%@F_8 zvDhSsOVJGRFCB|ba<~-D5dYS(*d&Kb(G2k)9g9tJxD?G0|JAYBB!^4U4Dml5i%oL4 z6wMG1Zu2_ZA=xB{OVJGR5FLw6a<~-D5D(R{*d&Kb(G2l09g9tJxD?G057)8SB!^4U z4DkpZi%oL46wMHi)UntkhfC26@hBaOO>(#t%@B{)vDhSsOVJGR7#)jEa<~-D5RcWd z*d&Kb(G2l89g9tJxD?G0kJqu-B!^4U4DkdVi%oL46wMG%)UntkhfC26@gyCKO>(#t z%@9x4vDhSsOVJGR6dj9Aa<~-D5Kq;y*d&Kb(G2l49g9tJxD?G0PuH>7B!^4U4Dk#d zi%oL46wMIN)UntkhfC26@hlySO>(#t%@EJlvDhSsOVJGB3p!h&&Fgfy5pQ0n!`tBh z&UnTHIu@Jca4DK0o}**2Ne-8y8REG*7MtX7DViakr(>~64ws@C;`urjo8)jQnjv1G zW3fpNm!cWsg*q0Sq8Z}FIu@Jca4DK0UZP{MNe-8y8RDfn7MtX7 zDViZ(rem>54ws@C;^jIPo8)jQnjv1HW3fpNm!cWsl{yxiq8Z}V zIu@Jca4DK0UZZ2NNe-8y8RE4%7MtX7DViZ(r(>~64ws@C;`KTfo8)jQnjzkxW3fpN zm!cWsjXD;aO28u}Kb>q8Z}NIu@Jca4DK0-lAi%Ne-8y8RD%v7MtX7DVibP zrem>54ws@C;_W&Xo8)jQnjzkyW3fpNm!cWsojMkqO59u}Kb>q8Z}dIu@Jc za4DK0-lJo&Ne-8y8RES<7MtX7DVibPr(>~64ws@C;{7@no8)jQnjt=*W3fpNm!cWs zgE|(Qq8Z}DIu@Jca4DK0KB8l>Ne-8y8RDZl7MtX7DViZZrem>5 z4ws@C;^R6No8)jQnjt=+W3fpNm!cWslR6fgq8Z}TIu@Jca4DK0 zKBHr?Ne-8y8RD}#7MtX7DViZZr(>~64ws@C;`2Hdo8)jQnjyZRW3fpNm!cWsi#isY zq8Z}LIu@Jca4DK0zM^BXNe-8y8RDxt7MtX7DVia^rem>54ws@C z;_EsVo8)jQnjyZSW3fpNm!cWsn>rSoq8Z}bIu@Jca4DK0zN2HY zNe-8y8REM-7MtX7DVia^r(>~64ws@C;`=%lo8)jQnjwCmW3fpNm!cWshdLIUq8Z}HIu@Jca4DK0exhTsNe-8y8RDlp7MtX7DViaErem>54ws@C;^#UR zo8)jQnjwCnW3fpNm!cWsmpT@kq8Z}XIu@Jca4DK0exqZtNe-8y z8REA(7MtX7DViaEr(>~64ws@C;`cfho8)jQnj!w6W3fpNm!cWsk2)5cq8Z}PIu@Jca4DK0{-R^CNe-8y8RD-x7MtX7DVibvrem>54ws@C;_o^Zo8)jQ znj!w7W3fpNm!cWspE?$sq8Z}fIu@Jca4DK0{-a~DNe-8y8REY> z7MtX7DVibvr(>~64ws@C;=yBHH|BM=Ly{aWMKi=hbSyT>;Zih1JXFVGlN>HZGsMGm zEH=sEQZz$6T*qRQ94CBoLp)l?Vv`&$ zMKi=>bSyT>;Zih1JXXhIlN>HZGsNR`EH=sEQZz$6UdLjS94CBoLp)i>Vv`&$MKi=xbSyT>;Zih1JXObHlN>HZGsM$$EH=sE zQZz$6UB_aR94CBoLp)o@Vv`&$MKgr2 z=N^Qu(B^eI+=w@?)8TFKe(#t%@8lvvDhSsOVJGR z5*>?8a<~-D5HHoS*d&Kb(G2l29g9tJxD?G0FW0fyB!^4U4Dkvbi%oL46wMH?)Untk zhfC26@hTmQO>(#t%@D8FvDhSsOVJGR8Xb#Ga<~-D5U(#t%@A+avDhSsOVJGR79ERC za<~-D5O3A7*d&Kb(G2l69g9tJxD?G0Z`ZNdB!^4U4Dk*fi%oL46wMIt)UntkhfC26 z@h%;UO>(#t%@FU_vDhSsOVJGR9vzEKa<~-D5bxEo*d&Kb(G2lE9g9tJxD?G0@7J-| zB!^4U4DkUSi%oL46wMGH)UntkhfC26@gW_HO>(#t%@7~fvDhSsOVJGR5gm(7a<~-D z5FgdC*d&Kb(G2l19g9tJxD?G0AJ?(iB!^4U4Dksai%oL46wMHy)UntkhfC26@hKgP zO>(#t%@Ci~vDhSsOVJGR86AsFa<~-D5TDht*d&Kb(G2l99g9tJxD?G0pVzV2B!^4U z4DkgWi%oL46wMG{)UntkhfC26@g*ILO>(#t%@AMKvDhSsOVJGR6&;IBa<~-D5MR}? z*d&Kb(G2l59g9tJxD?G0U)QnNB!^4U4Dk&ei%oL46wMId)UntkhfC26@hu&TO>(#t z%@E(#vDhSsOVJGR9UY5Ja<~-D5Z~3Y*d&Kb(G2lD9g9tJxD?G0-`BC&B!^4U4DkaU zi%oL46wMGn)UntkhfC26@gp6JO>(#t%@9A(#t%@DuV zvDhSsOVJGR8y$;Ha<~-D5Wm&2*d&Kb(G2lB9g9tJxD?G0zt^$YB!^4U4DkmYi%oL4 z6wMHS)UntkhfC26@h2UNO>(#t%@BXqvDhSsOVJGR7afaDa<~-D5P#LN*d&Kb(G2l7 z9g9tJxD?G0f7h|tB!^4U4Dk;gi%oL46wMI-)UntkhfC26@h=^VO>(#t%@F_AvDhSs zOVJGRA03NLa<~-D5dYP&*d&Kb(G2lF9g9tJxD?G04~_>O#A1^iE=4oMLv$=Q$>CBo zLp)T+Vv`&$MKi?1bSyT>;Zih1JY2_OlN>HZGsGiwEH=sEQZz$6QpaMG94CBoLp)Z;Vv`&$MKi?XbSyT>;Zih1JYL6QlN>HZ zGsF{gEH=sEQZz$6QO9DF94CBoLp)W- zVv`&$MKi?HbSyT>;Zih1JYC0PlN>HZGsH7=EH=sEQZz$6Q^#VH94RT9 zT#9Ch7wK4RlEbBFhIp}##U?piie`wH=vZu$!=-43c&U!XCOKS+W{8*RSZtERrD%qD zxsJsqIb4cnh*#)XY?8yJXoh&Dj>RT9T#9ChSLs-6lEbBFhIqA(#U?piie`w{=vZu$ z!=-43c&(1bCOKS+W{B76SZtERrD%qDy^h5uIb4cnh&Sk1Y?8yJXoh&Bj>RT9T#9Ch zH|bbxlEbBFhIq4%#U?piie`wn=vZu$!=-43c&m=ZCOKS+W{9`xSZtERrD%qDyN<;s zIb4cnhRT9T#9Chcj;JclEbBFhIqG*#U?piie`xS=vZu$!=-43 zc(0DdCOKS+W{CIcSZtERrD%qDzmCNwIb4cnh!5ykY?8yJXomQpj>RT9T#9Ch59wHJ zlEbBFhWN0K#U?piie`w9=vZu$!=-43_^6J>COKS+W{8jJSZtERrD%ruxQ@jpIb4cn zh)?KPY?8yJXomQtj>RT9T#9ChPw7}}lEbBFhWNCO#U?piie`w<=vZu$!=-43_^gh_ zCOKS+W{A(}SZtERrD%ruypF{tIb4cnh%e|^Y?8yJXomQrj>RT9T#9ChFX>oplEbBF zhWN6M#U?piie`wf=vZu$!=-43_^OV@COKS+W{9upSZtERrD%rux{k#rIb4cnh;Qgv zY?8yJXomQvj>RT9T#9ChZ|PWUlEbBFhWNIQ#U?piie`xK=vZu$!=-43_^yt{COKS+ zW{B_USZtERrD%ruzK+EvIb4cnh#%-!Y?8yJXomQqj>RT9T#9ChAL&?ZlEbBFhWN3L z#U?piie`wP=vZu$!=-43_^FP?COKS+W{98ZSZtERrD%ruxsJsqIb4cnh+pVfY?8yJ zXomQuj>RT9T#9ChU+GwElEbBFhWNFP#U?piie`x4=vZu$!=-43_^pn`COKS+W{BVE zSZtERrD%ruy^h5uIb4cnh(G99Y?8yJXomQsj>RT9T#9ChKj~O(lEbBFhWN9N#U?pi zie`wv=vZu$!=-43_^Xb^COKS+W{AJ(SZtERrD%ruyN<;sIb4cnh=1rRT9T#9Chf9Y6klEbBFhWNLR#U?piie`xa=vZu$!=-43_^*z|COKS+W{CgkSZtER zrD%qD@Po|j9%NqkAoIEhnb+A4$)#w9c!-Y0COKS+W{8LCSZtERrD%qDn2yCJIb4cn zh==P~Y?8yJXoh%%j>RT9T#9ChN9tH?lEbBFhIo{Y#U?piie`vM>sV}(!=-43c#Mw4 zCOKS+W{Ah?SZtERrD%qDoQ}mNIb4cnh{x+#Y?8yJXoh%#j>RT9T#9ChC+b*ilEbBF zhIo>W#U?piie`u>>sV}(!=-43c#4k2COKS+W{9WiSZtERrD%qDnvTULIb4cnh^OmV zY?8yJXoh%(j>RT9T#9ChXX;pNlEbBFhIp2a#U?piie`vs>sV}(!=-43@YURdSZr*M zHm}p+=Dc~G4sVVBJIiyE94jW$>CBoLp)!{ zVv`&$MKi<;bSyT>;Zih1yimttlN>HZGsKH@EH=sEQZz%nSjS?M94CBoL%dwaVv`&$MKi=JbSyT>;Zih1yi&(vlN>HZGsLTO zEH=sEQZz%nTE}9O94vSwO$>CBoL%d$cVv`&$ zMKi=3bSyT>;Zih1yivzulN>HZGsK&8EH=sEQZz%nS;u0N94CBoL%dzbVv`&$MKi=ZbSyT>;Zih1yi>HZGsL@eEH=sE zQZz%nTgPIP94CBoL%d(dVv`&$MKi<) zbSyT>;Zih1d{DHZGsK5CBoLwsDvVv`&$MKi=FbSyT>;Zih1d{W0^lN>HZGsLHKEH=sEQZz$+ zTE}9O94CBoLwsJxVv`&$MKi<~bSyT> z;Zih1d{M_@lN>HZGsKs4EH=sEQZz$+S;u0N94CBoLwsGwVv`&$MKi=VbSyT>;Zih1d{f6_lN>HZGsL%aEH=sEQZz$+TgPIP z94$6}KlE=4oM_jD{a$>CBoLwsMyVv`&$MKi;Zih1 z{7}bYlN>HZGsKT{EH=sEQZz&SSjS?M94CBoL;PIFVv`&$MKi=NbSyT>;Zih1{8GnalN>HZGsLfSEH=sEQZz&STE}9O94CBoL;POHVv`&$MKi=7bSyT>;Zih1{87hZ zlN>HZGsK^CEH=sEQZz&SS;u0N94CBo zL;PLGVv`&$MKi=dbSyT>;Zih1{8PtblN>HZGsM4iEH=sEQZz&STgPIP94CBoLp<0oa~7NAa4DK09-?EhNe-8y8RDTj7MtX7 zDViZ3rem>54ws@C;^8_Lo8)jQnjs#cW3fpNm!cWskvbNeq8Z}R zIu@Jca4DK09;0KiNe-8y8RD@z7MtX7DViZ3r(>~64ws@C;_*5bo8)jQnjxN`W3fpN zm!cWsi8>aWq8Z}JIu@Jca4DK0o}y#1Ne-8y8RDrr7MtX7DViak zrem>54ws@C;^{gTo8)jQnjxN{W3fpNm!cWsnK~Amq8Z}ZIu@Jc za4DK0+;Dvmi%nvCw0WHlH|NdkbPwqGe`k{%E=4oMb95{=$>CBoLp)c;Zih1JYUCRlN>HZGsFvYEH=sEQZz%nP{(4E94CBoL%dYSVv`&$MKi?9bSyT>;Zih1yj;g(lN>HZGsG)&EH=sEQZz%n zQpaMG94CBoL%deUVv`&$MKi?fbSyT> z;Zih1yk5s*lN>HZGsGKoEH=sEQZz%nQO9DF94CBoL%dbTVv`&$MKi?PbSyT>;Zih1yj{m)lN>HZGsHV|EH=sEQZz%nQ^#VH z94CBoL%dhVVv`&$MKi?vbSyT>;Zih1 zykEy+lN>HZGsFjUEH=sEQZz$+P{;cJIl7A_0Cpq6qQ9h;l=OLKX6`XFGcz+Yv!9t6 zqt7@Lr&f1ei;Pkwhf9zY&9FYGV{^C!Nzn}JLpnBxOOO=Jus*C~bGQUa(G2S&IyQ$( zkQB|ZKB{ALxCBYj4C`Y$Hit`)6wRk~RQhf9zY&9FYHV{^C!Nzn}J zQ#v+>OOO=Jus*G0bGQUa(G2S|IyQ$(kQB|ZKC5GMxCBYj4C`|`Hit`)6wRkB$Ihf9zY&9J_xV{^C!Nzn}JOFA}(OOO=Ju)eHgbGQUa(G2S=IyQ$(kQB|Z zzN%w$xCBYj4C`w;Hit`)6wR={u48k!1WC~h>l->Yhf9zY&9J_yV{^C!Nzn}JTRJv} zOOO=Ju)eKhbGQUa(G2T5IyQ$(kQB|ZzN=$%xCBYj4C{M3Hit`)6wR={uVZt#1WC~h z>jyeEhf9zY&9Hu`V{^C!Nzn}JM>;l#OOO=Juzsv#bGQUa(G2S+IyQ$(kQB|Z9?-El zT!N%%hV@e&o5LkYie^|p)3G^Rf~07M^>ZDY!zD~+_u{m6Vq-ciqOC6iTB}j^9 zSijP-Ib4FIXomG`9h<`?NQ!1yztOQdT!N%%hV@$=o5LkYie^~9)3G^Rf~07M^?Mzg z!zD|mFu{m6Vq-ciqM;)8PB}j^9Sbx&7Ib4FIXomG?9h<`?NQ!1yf6=iyT!N%% zhV@q+o5LkYie^}U)3G^Rf~07M^>-bc!zDv{(XcsOf~07M^^o=u{m6V zq-ciqP#v4YB}j^9SP#>&Ib4FIXomH09h<`?NQ!1ykI=C>T!N%%hV@7to5LkYie^}k z(y=*Qf~07M^=KWN!zD}BWu{m6Vq-ciqSRI?gB}j^9SdY`OIb4FIXomH89h<`? zNQ!1yPtdVBT!N%%hV?`po5LkYie^|((y=*Qf~07M^<*8J!zD`zgt)8Xd4d7Tb#jsKqO86-tBtY_=k94!+M^M&EXOxMKi4D>)0GFK~glsdV!A3;SwZ8GprZt*c>iFQZ&PQk&eyb z5+p@4tQYIp94!+M#H&EXOxMKi3I>)0GFK~gls zdWDY7;SwZ8GptwY*c>iFQZ&PQm5$Bf5+p@4tXJ#U94!+M>L&EXOxMKi3|>)0GFK~glsdV`M5;SwZ8Gpsl2*c>iFQZ&PQla9^d5+p@4 ztT*e}94!+M*J&EXOxMKi3o>)0GFK~glsdWVk9 z;SwZ8Gpu*&*c>iFQZ&PQmyXTh5+p@4tat0!94 z!+M{N&EXOxMKi4T>)0GFK~gls`hbqj;SwZ8GprBl*c>iFQZ&Q*kdDpa5+p@4tPkth z94!}^$x&EXOxMKi3A>)0GFK~gls`hiFQZ&Q*l#b2e5+p@4tWWFM94!}^?# z&EXOxMKi3=>)0GFK~gls`ht$l;SwZ8GpsM_*c>iFQZ&Q*l8(*c5+p@4tS{@>94!}^+z&EXOxMKi3g>)0GFK~gls`i73p;SwZ8Gpujw z*c>iFQZ&Q*mX6Kg5+p@4tZ(bs94!}^|%&EXOx zMKi4L>)0GFK~gls`hkwk;SwZ8Gprx#*c>iFQZ&Q*k&eyb5+p@4tRL&x94mmn#cVf|Fc=5Ps;q8ZlDbZicnASs$*{anZ9a0!y48P+d!Yz~(o zDVkyZQpe_S36i22)~|GI4woP)nqmD~$L4SelA;;bZ**)9mmn#cVf|Le=5Ps;q8Zlj zbZicnASs$*{a(lBa0!y48P*?kYz~(oDVkyZQOD+R36i22)}M524woP)nqmD}$L4Se zlA;;bUvz8^mmn#cVf|Id=5Ps;q8ZlTbZicnASs$*{awfAa0!y48P-2^Yz~(oDVkyZ zQ^)3T36i22*1vRY4woP)nqmE0$L4SelA;;be{^gPmmn#cVLix=H#Ub$kQB|Z9;{tQ-Jhf9zY&9EM>V{^C!Nzn}J5jr-9OOO=J zupX&nbGQUa(G2TRIyQ$(kQB|Z9<5_@xCBYj4C^sEHit`)6wR<6t7CJx1WC~h>v1|Z zhf9zY&9EM?V{^C!Nzn}J2|6~1OOO=Ju%4)6bGQUa(G2TJIyQ$(kQB|Zo~&bYxCBYj z4C^U6Hit`)6wR=ns$+Aw1WC~h>uEYRhf9zY&9I)XV{^C!Nzn}J89FwHOOO=Ju%4-7 zbGQUa(G2TZIyQ$(kQB|ZY>xOJHit`)*dA?Or^C&8^Ew^g8vi}vnH0^io~>hZxCBYj z4C^^MHit`)6wR=nt7CJx1WC~h>v=jhhf9zY&9I)YV{^C!Nzn}J1v)l|OOO=JuwJNR zbGQUa(G2TFIyQ$(kQB|ZUaVttxCBYj4C^I2Hit`)6wR<+s$+Aw1WC~h>t#ANhf9zY z&9GjsV{^C!Nzn}J6*@MDOOO=JuwJQSbGQUa(G2TVIyQ$(kQB|ZUaezuxCBYj4C^&I zHit`)6wR<+t7CJx1WC~h>vcLdhf9zY&9GjtV{^C!Nzn}J4LUZ5OOO=Ju->R+bGQUa z(G2TNIyQ$(kQB|Z-mGJDxCBYj4C^gAHit`)6wR>Ss$+Aw1WC~h>uowVhf9zY&9L6C zV{^C!Nzn}J9Xd9LOOO=Ju->U-bGQUa(G2TdIyQ$(kQB|Z-mPPExCBYj4C_5QHit`) z6wR>St7CJx1WC~h>wP*lhf9zY&9L6DV{^C!Nzn}J13ET`OOO=Jus*0`bGQUa(G2TD zIyQ$(kQB|ZKCEMNxCBYj4C^C0Hit`)6wRti}Lhf9zY&9FYMV{^C! zNzn}J6FN4BOOO=Jus*3{bGQUa(G2TTIyQ$(kQB|ZKCNSOxCBYj4C^yGHit`)6wRvK9bhf9zY&9FYNV{^C!Nzn}J3pzH3OOO=Ju)e5cbGQUa(G2TLIyQ$( zkQB|ZzN}+&xCBYj4C^a8Hit`)6wR={s$+Aw1WC~h>uWkThf9zY&9J_%V{^C!Nzn}J z8#*?JOOO=Ju)e8dbGQUa(G2TbIyQ$(kQB|ZzO7?(xCBYj4C^~OHit`)6wR={t7CJx z1WC~h>w7vjhf9zY&9J_&V{^C!Nzn}J2Rb%~OOO=JuzsjxbGQUa(G2THIyQ$(kQB|Z zeyn42xCBYj4C^O4Hit`)6wR<6(6KpOf~07M^-~?2!zD`Pdu{m6Vq-ciqa~+$* zB}j^9SijJ*Ib4FIXomGm9h<`?NQ!1yztXWeT!N%%hV^S5o5LkYie^~9(XlyPf~07M z^;;dA!zD~+|u{m6Vq-ciqdmWp@B}j^9Sbxy5Ib4FIXomGi9h<`?NQ!1yf6}oz zT!N%%hV^G1o5LkYie^}U(XlyPf~07M^;aF6!zD|mIu{m6Vq-ciqcO9FybJ(hf9zY&9EM&V{^C!Nzn}J(Kxnuxhf9zY&9I)NV{^C! zNzn}J$vQTNOOO=Ju%4o0bGQUa(G2UUIyQ$(kQB|Zo~C1SxCBYj4D0DSHit`)6wR=n zp<{En1WC~h>zO(>hf9zY&9I)OV{^C!Nzn|;me>DbbGQUaVSBWBo$mkX@HMV^osR#1 zlA;;bvvq6^mmn#cVLeC3=5Ps;q8Zk6b!-loASs$*Jx|Bxa0!y48P@Z4Yz~(oDVkxu zK*#2A36i22)(drP4woP)nqj?2$L4SelA;;bi*;-cmmn#cVZB7h=5Ps;q8Zjpb!-lo zASs$*y-dgEa0!y48P>~nYz~(oDVkxuLdWKC36i22)+=>v4woP)nqj?4$L4SelA;;b zt95J+mmn#cVZBDj=5Ps;q8Zj}b!-loASs$*y-vsGa0!y48P@A{Yz~(oDVkxuLC5BB z36i22)*E$f4woP)nqj?3$L4SelA;;bn{{jsmmn#cVZBAi=5Ps;q8Zj(b!-loASs$* zy-mmFa0!y48P?l%Yz~(oDVkxuL&xTD36i22);o1<4woP)nqj?5$L4SelA;;byLD_1 zmmn#cVZBGk=5Ps;q8ZkEb!-loASs$*y-&yHa0!y48P@xCYz~(oDVkw@K*#2A36i22 z)(3TL4woP)nqhrN$L4SelA;;bhjnZYmmn#cVSPl$=5Ps;q8Zjlb!-loASs$*eN4yZ za0!y48P>;jYz~(oDVkw@LdWKC36i22)+cpr4woP)nqhrP$L4SelA;;br*&)&mmn#c zVSPr&=5Ps;q8Zj_b!-loASs$*eNM;ba0!y48P?}@Yz~(oDVkw@LC5BB36i22))#eb z4woP)nqhrO$L4SelA;;bmvw9ommn#cVSPo%=5Ps;q8Zj#b!-loASs$*eND&aa0!y4 z8P?ZzYz~(oDVkw@L&xTD36i22);D!*4woP)nqhrQ$L4SelA;;bw{>g|mmn#cVSPu( z=5Ps;q8ZkAb!-loASs$*eNV^ca0!y48P@l8Yz~(oDVkyZK*#2A36i22)(>@T4woP) znqmD&$L4SelA;;bk9BMgmmn#cVf{qM=5Ps;q8Zi$IyQ$(kQB|ZeyU@0xCBYj4C`k) zHit`)6wR=Hu48k!1WC~h>lZpUhf9zY&9Hu{V{^C!Nzn}JS2{L_OOO=Juzsy$bGQUa z(G2T1IyQ$(kQB|Zeyd}1xCBYj4C{9~Hit`)6wR=HuVZt#1WC~h>km3Mhf9zY&9MHc zV{^C!Nzn}JPdYY-OOO=Ju>P!LbGQUa(G2S^IyQ$(kQB|Z{;FehxCBYj4C`+?Hit`) z6wR>yu48k!1WC~h>mNEchf9zY&9MHdV{^C!Nzn}JUph92OOO=Ju>P%MbGQUa(G2T9 zIyQ$(kQB|Z9^_B*Yz~(oDVkwDSjXmY36i22)O=5Ps;q8ZjBbZicnASs$*JyOT!a0!y48P=n8Yz~(oDVkwDTF2&a36i22 z)?;*R4woP)nqfUw$L4SelA;;b<8*8emmn#cVLe{Q=5Ps;q8Zi`bZicnASs$*JyFNz za0!y48P=0@Yz~(oDVkwDS;yvZ36i22)>CwB4woP)nqfUv$L4SelA;;b({yYOmmn#c zVLe^P=5Ps;q8ZjRbZicnASs$*JyXZ#a0!y48P>COYz~(oDVkyZua3>(5+p@qd$f6- z4man`>vVW){P&b+GpuLp*c>iFQZ&PQj*iXY5+p@4tmo?394!+L>^&EXOxMKi1y>ew7EK~glsdXbLJ;SwZ8GprZu*c>iFQZ&PQiH^!+M2|&EXOxMKi2d>ew7EK~gls zdXiFQZ&PQjgHOX5+p@4tk>$;94!+L{`&EXOxMKi27>ew7EK~glsdXtXL;SwZ8Gpsl3*c>iFQZ&PQi;m6V5+p@4 zthege94!+M8~&EXOxMKi2->ew7EK~glsdY6vP z;SwZ8Gpu*(*c>iFQZ&PQkB-gZ5+p@4toQ2J94 z!}@@Z&EXOxMKi1q>ew7EK~gls`jC#z;SwZ8GprBm*c>iFQZ&Q*h>p$S5+p@4tdHv0 z94!}^4d&EXOxMKi2V>ew7EK~gls`jn2%;SwZ8 zGptYR*c>iFQZ&Q*jE>FW5+p@4tk3G$94!}@}b z&EXOxMKi1~>ew7EK~gls`jU>#;SwZ8GpsM`*c>iFQZ&Q*ijK|U5+p@4tgq_W94!}^Af&EXOxMKi2#>ew7EK~gls`j(E(;SwZ8Gpujx z*c>iFQZ&Q*j*iXY5+p@4tncdB94!}@`a&EXOx zMKi1)>ew7EK~gls`jL*!;SwZ8Gprx$*c>iFQZ&Q*iH^0KYz~(o zDVkyZTF2&a36i22)^Bud4woP)nqmD`$L4SelA;;b?{sVqmmn#cVf|jm=5Ps;q8Zj7 zbZicnASs$*{ZYr}a0!y48P=b4Yz~(oDVkyZS;yvZ36i22)?ajN4woP)nqmD_$L4Se zlA;;b-*jvammn#cVf|gl=5Ps;q8ZjdbZicnASs$*{Zq&0a0!y48P>maYz~(oDVkyZ zTgT>b36i22)_-(t4woP)nqfW2)<-snOOO=JupX>qbGQUa(G2S$IyQ$(kQB|Z9;#z= zxCBYj4C`S!Hit`)6wR<6u48k!1WC~h>k&FOhf9zY&9EM+V{^C!Nzn}JQ93qxCBYj4C`?^Hit`)6wR<6uVZt#1WC~h>j^qG zhf9zY&9I)RV{^C!Nzn}JNjf%%OOO=Ju%4`AbGQUa(G2S;IyQ$(kQB|Zo~mPWxCBYj z4C`q+Hit`)6wR=nu48k!1WC~h>lr#Whf9zY&9I)SV{^C!Nzn}JSvod{OOO=Ju>M!a z=5Ps;q8V(DHm}p+=Dc~G4sVVBp7tEpvvq6^mmn#cVLeC3=5Ps;q8Zk6b!-loASs$* zJx|Bxa0!y48P@Z4Yz~(oDVkxuK*#2A36i22)(drP4woP)nqj?2$L4SelA;;bi*;-c zmmn#cVZB7h=5Ps;q8Zjpb!-loASs$*y-dgEa0!y48P>~nYz~(oDVkxuLdWKC36i22 z)+=>v4woP)nqj?4$L4SelA;;bt95J+mmn#cVZBDj=5Ps;q8Zj}b!-loASs$*y-vsG za0!y48P@A{Yz~(oDVkxuLC5BB36i22)*E$f4woP)nqj?3$L4SelA;;bn{{jsmmn#c zVZBAi=5Ps;q8Zj(b!-loASs$*y-mmFa0!y48P?l%Yz~(oDVkxuL&xTD36i22);o1< z4woP)nqj?5$L4SelA;;byLD_1mmn#cVZBGk=5Ps;q8ZkEb!-loASs$*y-&yHa0!y4 z8P@xCYz~(oDVkw@K*#2A36i22)(3TL4woP)nqhrN$L4SelA;;bhjnZYmmn#cVSPl$ z=5Ps;q8Zjlb!-loASs$*eN4yZa0!y48P>;jYz~(oDVkw@LdWKC36i22)+cpr4woP) znqhrP$L4SelA;;br*&)&mmn#cVSPr&=5Ps;q8Zj_b!-loASs$*eNM;ba0!y48P?}@ zYz~(oDVkw@LC5BB36i22))#eb4woP)nqhrO$L4SelA;;bmvw9ommn#cVSPo%=5Ps; zq8Zj#b!-loASs$*eND&aa0!y48P?ZzYz~(oDVkw@L&xTD36i22);D!*4woP)nqhrQ z$L4SelA;;bw{>g|mmn#cVSPu(=5Ps;q8ZkAb!-loASs$*eNV^ca0!y48P@l8Yz~(o zDVkyZK*#2A36i22)(>@T4woP)nqmD&$L4SelA;;bk9BMgmmn#cVf{qM=5Ps;q8Zi$ zIyQ$(kQB|ZeyU@0xCBYj4C`k)Hit`)6wR=Hu48k!1WC~h>lZpUhf9zY&9Hu{V{^C! zNzn}JS2{L_OOO=Juzsy$bGQUa(G2T1IyQ$(kQB|Zeyd}1xCBYj4C{9~Hit`)6wR=H zuVZt#1WC~h>km3Mhf9zY&9MHcV{^C!Nzn}JPdYY-OOO=Ju>P!LbGQUa(G2S^IyQ$( zkQB|Z{;FehxCBYj4C`+?Hit`)6wR>yu48k!1WC~h>mNEchf9zY&9MHdV{^C!Nzn}J zUph92OOO=Ju>P%MbGQUa(G2T9IyQ$(kQB|Z9@OS_wmx#W1WC~h>%lrUhf9zY&9EM# zV{^C!Nzn}Jp*l8)OOO=JupXvkbGQUa(G2V1IyQ$(kQB|Z9-(7%xCBYj4C|3PHit`) z6wR<6rDJor1WC~h>(M$khf9zY&9EM$V{^C!Nzn}Ju{t(~OOO=JupXylbGQUa(G2VH zIyQ$(kQB|Zo}goMxCBYj4C{$HHit`)6wR=nq+@fq1WC~h>&ZGchf9zY&9I)LV{^C! zNzn}JsX8`?OOO=Ju%4!4bGQUa(G2V9IyQ$(kQB|Zo}puNxCBYj4C|RXHit`)6wR=n zrDJor1WC~h>wk4@4woP)nqm2Z&h}{YIvsA#o7d^^*7)xk&-H8_o5LkYie^~P(XlyP zf~07M^;{jB!zDxy^B}j^9STE4AIb4FIXomGd9h<`?NQ!1y zFVe9&T!N%%hV^0{o5LkYie^|Z(XlyPf~07M^->+1!zD_!Nu{m6Vq-ciqavht) zB}j^9Sg+8rIb4FIXomGl9h<`?NQ!1yuhOwOT!N%%hV^P4o5LkYie^}^(XlyPf~07M z^;#X9!zD~M&u{m6Vq-ciqdL5g?B}j^9SZ~m=Ib4FIXomGh9h<`?NQ!1yZ_=?j zT!N%%hV^D0o5LkYie^}E(XlyPf~07M^;R95!zD|02u{m6Vq-ciqb{(6;B}j^9 zSntrWIb4FIXomGp9h<`?NQ!1y@6xe3T!N%%hV^b8o5LkYie^~v(XlyPf~07M^_E7u{m6Vq-ciqaUGk(B}j^9Sf9|b zIb4FIXomGk9h<`?NQ!1ypVF~8T!N%%hV^M3o5LkYie^}!(XlyPf~07M^;sR8!zD}xou{m6Vq-ciqc^#X>B}j^9SYObwIb4FIXomGg9h<`?NQ!1yU(&HTT!N%%hV^9~ zo5LkYie^|}(XlyPf~07M^;I34!zD{a-u{m6Vq-ciqbsd|-B}j^9Sl`gGIb4FI zXomGo9h<`?NQ!1y-_o%;T!N%%hV^Y7o5LkYie^~f(XlyPf~07M^<5pC!zDiFQZ&Q*nU2lj5+p@4te@-H94!}^tu&EXOxMKi2l>)0GFK~gls`i+jw;SwZ8Gpyh0*c>iF zQZ&Q*osP}n5+p@4tl#U{94VE!}^ns&EXOxMKi2F z>)0GFK~gls`iqXu;SwZ8GpxVr*c>iFQZ&Q*n~u%l5+p@4tiS8n94!}^zw&EXOxMKi2_>)0GFK~gls`j3vy;SwZ8Gpq-VdEJ=T+4{&O zNQ!1y57x0cT!N%%hV>8~o5LkYie^|3)%_nwceO)7k2Bi#mHgR`lRRECGxup`W@ct) zW@hGYow0vKV_nVbl9p8|lN8Nj*c>kLFda$JEQZbD5)apr6wPAT94_$)9ZAtFhRxv; zkJOPA&0^RbF7YTGNzp8Z&EXP{){zv=V%Qum@faOR(JY3|;S!J4krd5h*c>kLI2}pR zEQZbD5|7uB6wPAT94_$$9ZAtFhRxv;Pt=hV&0^RbF7YHCNzp8Z&EXPH){zv=V%Qum z@f00N(JY3|;Sx{Pkrd5h*c>kLG#yFNEQZbD5>MBW6wPAT94_$;9ZAtFhRxv;&(x6= z&0^RbF7YfKNzp8Z&EXQy){zv=V%Qum;qAExuszzmPKTTG=5;zeHU96!b95v{vlupq zOFUOcQZ$QUbGXFwbRc(#xWo%|Bt^3rHit{RP)AZUi(zxP#EWz! zMY9+-hfBOzM^ZG4VRN{|OLQbfvlupqOT1J^QZ$QUbGXFIbRc(# zxWp@TBt^3rHit{RQb$rWi(zxP#H(~9MY9+-hfBO#M^ZG4VRN{|Yjh+c(#xWpTDBt^3rHit{RQAbiVi(zxP#G7;^MY9+- zhfBO!M^ZG4VRN{|TXZBvvlupqOT1M_QZ$QUbGXFYbRc(#xWqej zBt^3rHit{RQ%6!Xi(zxP#JhAPMY9+-hfBO$M^ZG4VRN{|dvqj4vlupqOT1S{QZ$QU zbGXF&bRc(#xWor^Bt^3rHit`mP)AZUi(zxP#D{bwMY9+-hf91| zM^ZG4VRN{|M|31bvlupqOMFyEQZ$QUbGXFEbRc(#xWp%PBt^3r zHit`mQb$rWi(zxP#HVy5MY9+-hf91~M^ZG4VRN{|XLKY*vlupqOMF&GQZ$QUbGXFk zbRc(#xWpH9Bt^3rHit`mQAbiVi(zxP#Fum=MY9+-hf91}M^ZG4 zVRN{|S9ByrvlupqOMF#FQZ$QUbGXFUbRc(#xWqSfBt^3rHit`m zQ%6!Xi(zxP#J6-LMY9+-hf920M^ZG4VRN{|cXT90vlupqOMF*HQZ$QUbGXF!bRc(#xWo^1Bt^3rHit|6P)AZUi(zxP#E*0&MY9+-hfDleM^ZG4VRN{| zPjnc(#xWq4XBt^3rHit|6Qb$rW zi(zxP#IJNDMY9+-hfDlgM^ZG4VRN{|Z*(L@vlupqOZ-+xQZ$QUbGXFsbR=G>c(#xWpfHBt^3rHit|6QAbiVi(zxP#GiB|MY9+-hfDlfM^ZG4VRN{|Uvwlz zvlupqOZ-(wQZ$QUbGXFcbRc(#xWqqnBt^3rHit|6Q%6!Xi(zxP z#J_YTMY9+-hfDlhM^ZG4VRN{|e{>{8vlupqOZ-kL2pvh$EQZbD5|7l86wPAT94_%F9ZAtFhRxv;kJgbC&0^RbF7X&0Nzp8Z&EXP{ z)sYmkL1RY7yEQZbD5>M2T6wPAT94_%B9ZAtF zhRxv;Pu7tX&0^RbF7Xr{Nzp8Z&EXPH)sYmkL z3>`_)EQZbD63^6;6wPAT94_%J9ZAtFhRxv;&(@I?&0^RbF7f~ANNkUOj*T?W@s-Qx zxH7*o5Lkus3R$w#jrVC;zc@=qFD@^!zEs7*o5LkusUs7*o5LmEs3R$w#jrVC;!Qe|qFD@^!zJFVBPp82usK}fEjp5-Sqz)QCEltdDVoKw zIb7mxI+CJU44cCx-mW7ln#Hg=T;d%%lA>7*o5LmEsUsI+CJU44cCx-mfDmn#Hg=T;c;dlA>7* zo5LkOs3R$w#jrVC;zK%;qFD@^!zDhfBPp82usK}fBRZ0zSqz)QB|fSnDVoKwIb7mn zI+CJU44cCxKCUAvn#Hg=T;dZtlA>7*o5LkOsUs7*o5Ll( zs3R$w#jrVC;!8S`qFD@^!zI3~BPp82usK}fD>{;*Sqz)QCBCX7DVoKwIb7mvI+CJU z44cCxzOExFn#Hg=T;dx#lA>7*o5Ll(sUs7*o5Ll3s3R$w z#jrVC;zv4?qFD@^!zF&KBPp82usK}fCpwa%Sqz)QC4Q7*o5Ll3sUs7*o5Lmks3R$w#jrVC z;!iq~qFD@^!zKQ#BPp82usK}fFFKN7*o5LmksUs)z517|IU|whIBg5u!i3jUQie@ov4wra{ zj-+T7!{%^_hw4a*W-)9Imw1?tq-Yky=5UFJ>qv@bF>DT(c!Z9mXcoifaEV9iNQ!1L zYz~)rl#Zlm7Q^OniAU>5ie@ov4wrb0j-+T7!{%^_$LdImW-)9Imw23xq-Yky=5UF} z>qv@bF>DT(c!G|kXcoifaET}CNQ!1LYz~)rl8&Tk7Q^Oni6`qwie@ov4wra}j-+T7 z!{%^_r|L+GW-)9Imw1|vq-Yky=5UFp>qv@bF>DT(c!rLoXcoifaEWK?NQ!1LYz~)r zmX4%o7Q^OniD&Cbie@ov4wvxO+yf+qEz{<8I^3`~uhZe_@_#4&7R_SV94_%(9ZAtF zhRxv;&(o0<&0^RbF7bRFNzp8Z&EXO+(2*3)V%Qum@j@L*(JY3|;Sw*>krd5h*c>kL zVjW4*EQZbD5--t_6wPAT94_%v9ZAtFhRxv;FVm3}&0^RbF7a|5Nzp8Z&EXQS(2*3) zV%Qum@k$*@(JY3|;S#UXkrd5h*c>kLY8^?@EQZbD60gyb6wPAT94_%%9ZAtFhRxv; zuhWqf&0^RbF7bLDNzp8Z&EXPn(2*3)V%Qum@kSj<(JY3|;Sz7skrd5h*c>kLW*te< zEQZbD5^vFw6wPAT94_%z9ZAtFhRxv;Z_|+!&0^RbF7b99Nzp8Z&EXR7(2*3)V%Qum z@lG8{(JY3|;S%rCkrd5h*c>kLZXHR{EQZbD67SKG6wPAT94_%*9ZAtFhRxv;@6(YK z&0^RbF7bXHNzp8Z&EXOs(2*3)V%Qum@j)F)(JY3|;SwLxkrd5h*c>kLVI4`)EQZbD z5+Bi#6wPAT94_%u9ZAtFhRxv;AJdT(&0^RbF7a_4Nzp8Z&EXQC(2*3)V%Qum@kt#? z(JY3|;S!(Hkrd5h*c>kLX&p(?EQZbD5}(nL6wPAT94_%$9ZAtFhRxv;pVN^P&0^Rb zF7bICNzp8Z&EXPX(2*3)V%Qum@kJd;(JY3|;Syickrd5h*c>kLWgSV;EQZbD5?|4g z6wPAT94_%y9ZAtFhRxv;U(=Bk&0^RbF7b68Nzp8Z&EXQ?(2*3)V%Qum@l72`(JY3| z;S%4{krd5h*c>kLZ5>I`EQZbD65r906wPAT94_%)9ZAtFhRxv;-_wy4&0^RbF7bUG zNzp8Z&EXP1(2*3)V%Qum@k1R+(JY3|;SxX6krd5h*c>kLV;xD+EQZbD5^(JY3|;S#^n zkrd5h*c>kLYaL0^EQZbD62H-r6wPAT94_%&9ZAtFhRxv;ztfQv&0^RbF7bOENzp8Z z&EXP%(2*3)V%Qum@kbp=(JY3|;Szt+krd5h*c>kLXB|n=EQZbD5`WQ=6wPAT94_%! z9ZAtFhRxv;f76i^&0^RbF7bCANzp8Z&EXRN(2*3)V%Qum@lPE|(JY3|;S&GSkrd5h z*c>kLZyia|EQZbD693VW6wPAT94_%+9ZAtFhRxv;|I?8a&0^RbF7Y7$xJim;F>DT( zc(9J7XcoifaEXWLNQ!1LYz~)rsE(v)7Q^OniHGS(ie@ov4wrbij-+T7!{%^_N9ah3 zW-)9Imw2R(q-Yky=5UEe=}3xZF>DT(c(jhBXcoifaEZt0NQ!1LYz~)rtd68;7Q^On ziO1DT(c(RV9 zXcoifaEYhrNQ!1LYz~)rs*a>+7Q^OniKppEie@ov4wrbkj-+T7!{%^_XXr?ZW-)9I zmw2X*q-Yky=5UE;=}3xZF>DT(c(#tDXcoifa0xeDA0R0jTc*wHbhu$}UZ;DGj{kRx zW-)9Imw2v@q-Yky=5UGU=}3xZF>DT(c)pILXcoifaETY_NQ!1LYz~)rp^l_z7Q^On zi5KZeie@ov4wrbbj-+T7!{%^_m*_}}W-)9Imw2g;q-Yky=5UFZ=}3xZF>DT(c)5DT(c)gCKXcoifaEUkQNQ!1LYz~)rqmHC#7Q^Oni8tv; zie@ov4wrbdj-+T7!{%^_x9CWUW-)9Imw2m=q-Yky=5UF(=}3xZF>DT(c)O0IXcoif zaEW*5NQ!1LYz~)rr;em(7Q^OniFfHpie@ov4wrbhj-+T7!{%^__vlE9W-)9Imw2y^ zq-Yky=5UGk=}3xZF>DT(c)yOMXcoifaETA-NQ!1LYz~+BppK+y7Q^Oni4W;Wie@ov z4wv|_j-+T7!{%^_kLXB>W-)9Im-wiTq-Yky=5UFR=}3xZF>DT(__&UwXcoifaEVXo zNQ!1LYz~+Bq>iL$7Q^OniBIWBie@ov4wv|}j-+T7!{%^_&*(^sW-)9Im-wuXq-Yky z=5UG6=}3xZF>DT(_`Hs!XcoifaEUMINQ!1LYz~+BqK>3!7Q^Oni7)9$ie@ov4wv|{ zj-+T7!{%^_ujojMW-)9Im-woVq-Yky=5UFx=}3xZF>DT(__~gyXcoifaEWi|NQ!1L zYz~+BrjDd&7Q^OniErshie@ov4wv}0j-+T7!{%^_@90R1W-)9Im-w!Zq-Yky=5UGc z=}3xZF>DT(_`Z&$XcoifaETx2NQ!1LYz~+Bp^l_z7Q^Oni67}mie@ov4wv|`j-+T7 z!{%^_pXf-6W-)9Im-wlUq-Yky=5UFh=}3xZF>DT(__>axXcoifaEV{&NQ!1LYz~+B zrH-U%7Q^OniC^hRie@ov4wv|~j-+T7!{%^_-{?q+W-)9Im-wxYq-Yky=5UGM=}3xZ zF>DT(_`Qy#XcoifaEU+YNQ!1LYz~+BqmHC#7Q^Oni9hK`ie@ov4wv||j-+T7!{%^_ zzvxJcW-)9Im-wrWq-Yky=5UF>=}3xZF>DT(_`8mzXcoifaEX8DNQ!1LYz~+Br;em( z7Q^OniGS%xie@ov4wv}1j-+T7!{%^_|L91HW-)9Im-w%aq-Yky=5UGs=}3xZF>DT( zc#yYaNQ!1LYz~)ru#Ti?7Q^OniHGP&ie@ov4wrbSj-+T7!{%^_hv`U)W-)9Imw332 zq-Yky=5UEe=tzoYF>DT(c%+V`XcoifaEV9hNQ!1LYz~)rw2q``7Q^OniO1+jie@ov z4wrbWj-+T7!{%^_$LUClW-)9Imw3F6q-Yky=5UE8=tzoYF>DT(c%qJ^XcoifaET}B zNQ!1LYz~)rvW}!^7Q^OniKpmDie@ov4wrbUj-+T7!{%^_r|C$FW-)9Imw394q-Yky z=5UE;=tzoYF>DT(c&3h|XcoifaEWK>NQ!1LYz~)rwvMD|7Q^On316dofTU;^woIGX z>2Sl|yiSLw%m1DByBIcyOFUOcQZ$QUbGXFwbRc(#xWo%|Bt^3r zHit{RP)AZUi(zxP#EWz!MY9+-hfBOzM^ZG4VRN{|OLQbfvlupqOT1J^QZ$QUbGXFI zbRc(#xWp@TBt^3rHit{RQb$rWi(zxP#H(~9MY9+-hfBO#M^ZG4 zVRN{|Yjh+c(#xWpTDBt^3rHit{R zQAbiVi(zxP#G7;^MY9+-hfBO!M^ZG4VRN{|TXZBvvlupqOT1M_QZ$QUbGXFYbRc(#xWqejBt^3rHit{RQ%6!Xi(zxP#JhAPMY9+-hfBO$M^ZG4VRN{| zdvqj4vlupqOT1S{QZ$QUbGXF&bRc(#xWor^Bt^3rHit`mP)AZU zi(zxP#D{bwMY9+-hf91|M^ZG4VRN{|M|31bvlupqOMFyEQZ$QUbGXFEbRc(#xWp%PBt^3rHit`mQb$rWi(zxP#HVy5MY9+-hf91~M^ZG4VRN{|XLKY* zvlupqOMF&GQZ$QUbGXFkbRc(#xWpH9Bt^3rHit`mQAbiVi(zxP z#Fum=MY9+-hf91}M^ZG4VRN{|S9ByrvlupqOMF#FQZ$QUbGXFUbRc(#xWqSfBt^3rHit`mQ%6!Xi(zxP#J6-LMY9+-hf920M^ZG4VRN{|cXT90vlupq zOMF*HQZ$QUbGXF!bRc(#xWo^1Bt^3rHit|6P)AZUi(zxP#E*0& zMY9+-hfDleM^ZG4VRN{|Pjnc(# zxWq4XBt^3rHit|6Qb$rWi(zxP#IJNDMY9+-hfDlgM^ZG4VRN{|Z*(L@vlupqOZ-+x zQZ$QUbGXFsbR=G>c(#xWpfHBt^3rHit|6QAbiVi(zxP#GiB|MY9+- zhfDlfM^ZG4VRN{|UvwlzvlupqOZ-(wQZ$QUbGXFcbRc(#xWqqn zBt^3rHit|6Q%6!Xi(zxP#J_YTMY9+-hfDlhM^ZG4VRN{|e{>{8vlupqOZ-7*o5Lj@tRpF!#jrVC;vqVcqFD@^!zCW7BPp82usK}f zVLFncSqz)QB_6ILDVoKwIb7lqI+CJU44cCx9;qWKn#Hg=T;fqWlA>7*o5Lj@ts^O# z#jrVC;xRgsqFD@^!zCW8BPp82usK}faXONsSqz)QB_6LMDVoKwIb7liI+CJU44cCx zo~R=!n#Hg=T;fSOlA>7*o5LlZtRpF!#jrVC;wd_kqFD@^!zG@oBPp82usK}fX*!ak zSqz)QC7!M$DVoKwIb7lyI+CJU44cCxo~a`#n#Hg=T;f?elA>7*o5LlZts^O##jrVC z!sdtvNQ!1L*fMQir^5|<^Ew@#F8_Cy-(hpO#B+5dMY9+-hf6$9M^ZG4VRN{|^K~Re zvlupqOT0iwQZ$QUbGXC{btFZz7&eDXyhukc(#xWtQfBt^3rHit{RL`PCIi(zxP z#7lJ~MY9+-hfBOnM^ZG4VRN{|%XK70vlupqOT0oyQZ$QUbGXDSbtFZz7&eDXyh=w> zG>c(#xWubvbeWvlupq zOT0lxQZ$QUbGXDCbtFZz7&eDXyh%q=G>c(#xWt=vBt^3rHit{RMMqLJi(zxP#9MVF zMY9+-hfBOoM^ZG4VRN{|+jS&GvlupqOT0rzQZ$QUbGXDibtFZz7&eDXyh}$?G>c(# zxWv14Bt^3rHit{RM@LdLi(zxP#CvrlMY9+-hfBOqM^ZG4VRN{|`*kEmvlupqOME~_ zQZ$QUbGXC@btFZz7&eDXd`L%9G>c(#xWtEbBt^3rHit`mL`PCIi(zxP#7A``MY9+- zhf91+M^ZG4VRN{|$8{t{vlupqOMF5{QZ$QUbGXDObtFZz7&eDXd`d@BG>c(#xWuP* zBt^3rHit`mMn_UKi(zxP#AkIRMY9+-hf91;M^ZG4VRN{|=XE4SvlupqOMF2`QZ$QU zbGXD8btFZz7&eDXd`U-AG>c(#xWt!rBt^3rHit`mMMqLJi(zxP#8-7BMY9+-hf91- zM^ZG4VRN{|*L5UCvlupqOMF8|QZ$QUbGXDebtFZz7&eDXd`m}CG>c(#xWu=0Bt^3r zHit`mM@LdLi(zxP#CLThMY9+-hf91c(#xWtcjBt^3rHit|6L`PCIi(zxP#7}i3MY9+-hfDlSM^ZG4 zVRN{|&vhh4vlupqOZ-AdQZ$QUbGXDWbtFZz7&eDX{7OesG>c(#xWun@Bt^3rHit|6 zMn_UKi(zxP#BX&ZMY9+-hfDlUM^ZG4VRN{|?{y?avlupqOZ-7cQZ$QUbGXDGbtFZz z7&eDX{7FYrG>c(#xWu1zBt^3rHit|6MMqLJi(zxP#9wtJMY9+-hfDlTM^ZG4VRN{| z-*qHKvlupqOZ-DeQZ$QUbGXDmbtFZz7&eDX{7XktG>c(#xWvD8Bt^3rHit|6M@LdL zi(zxP#D8@pMY9+-hfDlVM^ZG4VRN{|gM4+0q-Yky=5UDz>qv@bF>DT(c!-XqXcoif zaEXWNNQ!1LYz~)rn2w}q7Q^OniHGY*ie@ov4wra@j-+T7!{%^_N9st5W-)9Imw1$p zq-Yky=5UEe>qv@bF>DT(c#MvuXcoifaEZt2NQ!1LYz~)roQ|Yu7Q^OniO1_mie@ov z4wra>j-+T7!{%^_C+bLwW-)9Imw1wnq-Yky=5UE8>qv@bF>DT(c#4jsXcoifaEYht zNQ!1LYz~)rnvSGs7Q^OniKpvGie@ov4wra_j-+T7!{%^_XX;3bW-)9Imw1+rq-Yky z=5UE;>qv@bF>DT(u;ujulA>7*8(XH$>vYf2;jLZsIvxM-44cCxo~t7%n#Hg=T;h2; zlA>7*o5LlZuOlg%#jrVC;srXAqFD@^!zEs*BPp82usK}fMLLqASqz)QC0?u}DVoKw zIb7l;I+CJU44cCxUaBK0n#Hg=T;gRqlA>7*o5Lkut|KX$#jrVC;uSiQqFD@^!zEs+ zBPp82usK}fRXUQQSqz)QC0?x~DVoKwIb7m3I+CJU44cCxUaKQ1n#Hg=T;g>)lA>7* zo5LkuuOlg%#jrVC;te{IqFD@^!zJFRBPp82usK}fO*)dISqz)QCElzfDVoKwIb7l` zI+CJU44cCx-l`)hn#Hg=T;gpylA>7*o5LmEt|KX$#jrVC;vG7YqFD@^!zJFSBPp82 zusK}fT{@DYSqz)QCEl$gDVoKwIb7mBI+CJU44cCx-m4=in#Hg=T;hE?lA>7*o5LmE zuOlg%#jrVC;sZL8qFD@^!zDhbBPp82usK}fLpqY8Sqz)QB|fYpDVoKwIb7l+I+CJU z44cFK|2ev=B?@|*(YCLo$RO$Q!pxkUFU-u$%*@Qp%(ch)%QgCHUb|{(wcEr;btH?; z;Zih1d`w5O*c>iJGsMSrB#X`AQZz$+LPxUL94iJGsNe0B#X`AQZz$+K}WLK z94iJGsM?*B#X`AQZz$+Lr1dM94AbtH?;;Zih1d{0NR*c>iJGsO3GB#X`AQZz&SKu5CJ94iJGsMqzB#X`AQZz&SLPxUL942btH?;;Zih1{7y%**c>iJGsN$8B#X`AQZz&SK}WLK94iJ zGsNF@B#X`AQZz&SLr1dM94IbtH?;;Zih1{7*-+*c>iJGsJ^^A)aKhIb4cnh==G%7MsJRXoh&Gj%2Yp zT#9Chhv`Tbo5Q7OhIqJ+WU)D1ie`vM=tvfu!=-43c%+VGu{m6dW{5}WNEVyJrD%qD zw2ox4Ib4cnh{xzi7MsJRXoh&Kj%2YpT#9Ch$LUBGo5Q7OhIqV=WU)D1ie`u>=tvfu z!=-43c%qJEu{m6dW{4;0NEVyJrD%qDvW{f2Ib4cnh^OdC7MsJRXoh&Ij%2YpT#9Ch zr|C!*o5Q7OhIqP;WU)D1ie`vs=tvfu!=-43c&3hIu{m6dW{79$NEVyJrD%qDwvJ@6 zIb4cni09}?7MsJRXoh&Mj%2YpT#Cjm)8=(LoUk{q(_we{zg3>i5D(}`7MsJRXoh&6 zj%2YpT#9Ch=j%uoo5Q7OhIoOFWU)D1ie`ux>PQxw!=-43c#)1|u{m6dW{4N-NEVyJ zrD%qDiH>BkIb4cnh?nX}7MsJRXoh&1j%2YpT#9Chm+MFto5Q7OhIoaJWU)D1ie`vc z>PQxw!=-43c$JQ1u{m6dW{6koNEVyJrD%qDjgDloIb4cnh}Y^!7MsJRXoh&5j%2Yp zT#9Ch*Xu|Yo5Q7OhIoUHWU)D1ie`v6>PQxw!=-43c$1D~u{m6dW{5ZINEVyJrD%qD zi;iTmIb4cnh_~uU7MsJRXoh&3j%2YpT#9Chx9dn2o5Q7OhIogLWU)D1ie`v+>PQxw z!=-43c$bc3u{m6dW{7v|NEVyJrD%qDkB(%qIb4cni1+G97MsJRXoh&7j%2YpT#9Ch z_v=U&o5Q7OhWLPvWU)D1ie`up>PQxw!=-43_>hidu{m6dW{3~#NEVyJrD%ruh>m2j zIb4cnh>z+>7MsJRXomQhj%2YpT#9ChkLySlo5Q7OhWLbzWU)D1ie`vU>PQxw!=-43 z_>_)hu{m6dW{6MgNEVyJrD%rujE-cnIb4cnh|lUs7MsJRXomQlj%2YpT#9Ch&+AAQ zo5Q7OhWLVxWU)D1ie`u}>PQxw!=-43_>zufu{m6dW{5BANEVyJrD%ruijHKlIb4cn zh_C8M7MsJRXomQjj%2YpT#9Chuj@z_o5Q7OhWLh#WU)D1ie`v!>PQxw!=-43_?C`j zu{m6dW{7X=NEVyJrD%ruj*eupIb4cni0|r17MsJRXomQnj%2YpT#9Ch@9Rhwo5Q7O zhWLSwWU)D1ie`u(>PQxw!=-43_>qoeu{m6dW{4l_NEVyJrD%ruiH>BkIb4cnh@a|6 z7MsJRXomQij%2YpT#9ChpX*2#o5Q7OhWLe!WU)D1ie`vk>PQxw!=-43_?3=iu{m6d zW{6+wNEVyJrD%rujgDloIb4cnh~Mf+7MsJRXomQmj%2YpT#9Ch-|I*go5Q7OhWLYy zWU)D1ie`vE>PQxw!=-43_>+!gu{m6dW{5xQNEVyJrD%rui;iTmIb4cnh`;Jc7MsJR zXomQkj%2YpT#9Chzw1aAo5Q7OhWLk$WU)D1ie`v^>PQxw!=-43_?M1ku{m6dW{7|5 zNEVyJrD%rukB(%qIb4cni2v$H7MsJRXomQoj%2YpT#9Ch2fNLYWU)D1ie`w1=tvfu z!=-43c&LtKu{m6dW{8LBNEVyJrD%qDxQ=A8Ib4cnh)3v17MsJRXoh&Cj%2YpT#9Ch zN9jlwo5Q7OhIq7&WU)D1ie`w%=tvfu!=-43c&v_Ou{m6dW{Ah>NEVyJrD%qDypCkC zIb4cnh$rYs7MsJRXoh&Aj%2YpT#9ChC+SEQo5Q7OhIq1$WU)D1ie`wX=tvfu!=-43 zc&d(Mu{m6dW{9WhNEVyJrD%qDx{hSAIb4cnh-c_X7MsJRXoh&Ej%2YpT#9ChXX!{5 zo5Q7OhIqD)WU)D1ie`xC=tvfu!=-43c&?6Qu{m6dW^l{2d7Ta??9JPQxw!=-43c$to5u{m6dW{8*TNEVyJrD%qD zg^pygIb4cnh*#=J7MsJRXoh%|j%2YpT#9ChSL;X?o5Q7OhIoyRWU)D1ie`w{>PQxw z!=-43c%6=9u{m6dW{B78NEVyJrD%qDgN|geIb4cnh&Sp;7MsJRXoh%`j%2YpT#9Ch zH|t0io5Q7OhIosPWU)D1ie`wn>PQxw!=-43c$PQxw!=-43 zc%P1Bu{m6dW{CIeNEVyJrD%rufR1FbIb4cnh!5&W7MsJRXomQZj%2YpT#9Ch59>%4 zo5Q7OhWLn%WU)D1ie`w9>PQxw!=-43_?V7lu{m6dW{8jLNEVyJrD%rugpOpfIb4cn zh)?QB7MsJRXomQdj%2YpT#9ChPwPk)o5Q7OhWLz*WU)D1ie`w<>PQxw!=-43_?(Vp zu{m6dW{A)0NEVyJrD%ruf{tXdIb4cnh%f3$7MsJRXomQbj%2YpT#9ChFY8Dao5Q7O zhWLt(WU)D1ie`wf>PQxw!=-43_?nJnu{m6dW{9urNEVyJrD%ruhK^*hIb4cnh;Qmh z7MsJRXomQfj%2YpT#9ChZ|g`Fo5Q7OhWL(-WU)D1ie`xK>PQxw!=-43_@0hru{m6d zW{B_WNEVyJrD%rufsSOcIb4cnh#%@m7MsJRXomQaj%2YpT#9ChAL~dKo5Q7OhWLq& zWU)D1ie`wP>PQxw!=-43_?eDmu{m6dW{98bNEVyJrD%rug^pygIb4cnh+pbR7MsJR zXomQej%2YpT#9ChU+YK~o5Q7OhWL$+WU)D1ie`x4>PQxw!=-43_??bqu{m6dW{BVG zNEVyJrD%rugN|geIb4cnh(GE`7MsJRXomQcj%2YpT#9ChKkG;qo5Q7OhWLw)WU)D1 zie`wv>PQxw!=-43_?wPou{m6dW{AJ*NEVyJrD%ruhmK^iIb4cnh=1xx7MsJRXomQg zj%2YpT#9Chf9psVo5Q7OhWL+;WU)D1ie`xa>PQxw!=-43_@9nsu{m6dW{3y3d7axF zS!@oMq8Z{LI+Dfaa4DK09;zc*Yz~*A8RB6&lEvn5DViZ3t|M7&4ws@C;t@KM#pZA+ znjs#kBUx+?m!cWsQ96>v=5Q&RAs($GS!@oMq8Z{bI+Dfaa4DK09;+i+Yz~*A8RBs| zlEvn5DViZ3uOnG(4ws@C;t4vE#pZA+njxO3BUx+?m!cWsNjj3n=5Q&RA)c%wS!@oM zq8Z{TI+Dfaa4DK0o~k2RYz~*A8RBU=lEvn5DViakt|M7&4ws@C;u$)U#pZA+njxO4 zBUx+?m!cWsSvr!%=5Q&RA)c)xS!@oMq8Z{jI+Dfaa4DK0o~t8SYz~*A8NwTMZkaZ( z)8T}@d7Tcs%m1zMj0bcii_PIuG($X3N3z%)E=4oM^K~SP&EZlsL%cvove+ChMKi<; zbtH?;;Zih1yhul~*c>iJGsKH^B#X`AQZz%nL`SmN94iJGsLTPB#X`AQZz%n zMn|&P94vbfH&EZlsL%cypve+ChMKi=3btH?; z;Zih1yh%s0*c>iJGsK&9B#X`AQZz%nMMtvO94iJGsL@fB#X`AQZz%nM@O>Q z94iJGsK5=B#X`AQZz$+L`SmN94iJGsLHLB#X`AQZz$+Mn|&P94iJGsKs5B#X`AQZz$+MMtvO94iJGsL%bB#X`AQZz$+M@O>Q94iJ zGsKT|B#X`AQZz&SL`SmN94iJGsLfTB#X`AQZz&SMn|&P94iJGsK^D zB#X`AQZz&SMMtvO94iJGsM4jB#X`AQZz&SM@O>Q94j%2YpT#9Chhw4Zco5Q7OhIp8c zWU)D1ie`w1>qr)x!=-43c!Z8*u{m6dW{5}XNEVyJrD%qDl#XPvIb4cnh)3&47MsJR zXoh%qr)x!=-43c!G{(u{m6dW{4;1 zNEVyJrD%qDl8$7tIb4cnh$rhv7MsJRXoh%-j%2YpT#9Chr|L)+o5Q7OhIpEeWU)D1 zie`wX>qr)x!=-43c!rK-u{m6dW{79%NEVyJrD%qDmX2hxIb4cnh-d3a7MsJRXoh%> zj%2YpT#9Ch=juono5Q7OhVb^>gK*2Vd7Ta??9JhYz~*A8RFGClEvn5DViZ(qa#^t4ws@C;N=PS!@oMq8Z|iI+Dfaa4DK0-lQX0Yz~*A8RE@4lEvn5DVibPq9a*s z4ws@C;;lN8#pZA+njzk%BUx+?m!cWs?K+ah=5Q&RA>N@QS!@oMq8Z|yI+Dfaa4DK0 z-lZd1Yz~*A8RFeKlEvn5DVibPqa#^t4ws@C;=MYO#pZA+njzk&BUx+?m!cWs{W_Ax z=5Q&RAwHlZS!@oMq8Z|YI+Dfaa4DK0KBOaAYz~*A8REk_lEvn5DViZZq9a*s4ws@C z;-fl}#pZA+njt=>BUx+?m!cWs<2sVX=5Q&RAwHoaS!@oMq8Z|oI+Dfaa4DK0KBXgB zYz~*A8RFAAlEvn5DViZZqa#^t4ws@C;pGIf=5Q&RA-Yz~*A8RFME zlEvn5DViaEqa#^t4ws@C;dsj=5Q&RA^xEwS!@oMq8Z|!I+Dfaa4DK0{-q;XYz~*A8RFkMlEvn5 zDVibvqa#^t4ws@C;=ekQ#pZA+nj!wDBUx+?m!cWs!STR@NEVyJrD%qDh>m2jIb4cn zh==M(7MsJRXoh&0j%2YpT#9ChhwDfdo5Q7OhIoXIWU)D1ie`vM>PQxw!=-43c$AK0 zu{m6dW{5}YNEVyJrD%qDjE-cnIb4cnh{x(k7MsJRXoh&4j%2YpT#9Ch$LmNIo5Q7O zhIoRGWU)D1ie`u>>PQxw!=-43c#@7}u{m6dW{4;2NEVyJrD%qDijHKlIb4cnh^OjE z7MsJRXoh&2j%2YpT#9Chr|U=-o5Q7OhIodKWU)D1ie`vs>PQxw!=-43c$SW2u{m6d zW{79&NEVyJrD%qDj*eupIb4cni0A4^7MsJRXomRzbR=$>e!$H&5BM7915VgK;H}*U z{1fni-Q|J*e?5p~u{m6dW{BtMNEVyJrD%qDzK&$EIb4cnh!^Nc7MsJRXoh&9j%2Yp zT#9Ch7wJeAo5Q7OhIp}#WU)D1ie`wH=tvfu!=-43c&UzLu{m6dW{8*RNEVyJrD%qD zxsGJ9Ib4cnh*#)H7MsJRXoh&Dj%2YpT#9ChSLsL=o5Q7OhIqA(WU)D1ie`w{=tvfu z!=-43c&(0Pu{m6dW{B76NEVyJrD%qDy^dtDIb4cnh&Sj+7MsJRXoh&Bj%2YpT#9Ch zH|a1Yo5Q7O zhWN6MWU)D1ie`wf=tvfu!=-43_^OU%u{m6dW{9upNEVyJrD%rux{hSAIb4cnh;Qgf z7MsJRXomQvj%2YpT#9ChZ|O)Do5Q7OhWNIQWU)D1ie`xK=tvfu!=-43_^ys*u{m6d zW{B_UNEVyJrD%ruzK&$EIb4cnh#%-k7MsJRXomQqj%2YpT#9ChAL&RIo5Q7OhWN3L zWU)D1ie`wP=tvfu!=-43_^FO$u{m6dW{98ZNEVyJrD%ruxsGJ9Ib4cnh+pVP7MsJR zXomQuj%2YpT#9ChU+G8|o5Q7OhWNFPWU)D1ie`x4=tvfu!=-43_^pm)u{m6dW{BVE zNEVyJrD%ruy^dtDIb4cnh(G8^7MsJRXomQsj%2YpT#9ChKj}yoo5Q7OhWN9NWU)D1 zie`wv=tvfu!=-43_^Xa&u{m6dW{AJ(NEVyJrD%ruyN+bBIb4cnh=1rv7MsJRXomQw zj%2YpT#9Chf9XgTo5Q7OhWNLRWU)D1ie`xa=tvfu!=-43_^*y+u{m6dW{CgkNEVyJ zrD%qD@Po|j9%NqkAoIEhnb*0^kxS7G@em!!Vsp3@%@7aOkt{ZcOVJGRFdfNabGQ`E z5D(XpEH;Nr(G2kj9m!&IxD?G0kJOPYHit{m4Dl!($zpT36wMHi){!hWhfC26@faP+ zVsp3@%@B{(kt{ZcOVJGRI33AibGQ`E5Rcc9EH;Nr(G2kf9m!&IxD?G0Pt=htHit{m z4Dlo#$zpT36wMG%){!hWhfC26@f01&Vsp3@%@9x3kt{ZcOVJGRG#$xebGQ`E5Kq^U zEH;Nr(G2kn9m!&IxD?G0&(x7DHit{m4Dl=-$zpT36wMIN){!hWhfC26@f;n=Vsp3@ z%@EJkkt{ZcOVJGBt+@x0EZjzIUZ=xJeDgXTcA@`U>ABb(E=4oM^K>MO&EZlsLp)zc zve+ChMKi<;bR>(-;Zih1yiiB7*c>iJGsKH@B#X`AQZz%nSVywh94(-;Zih1yi!N9*c>iJGsLTO zB#X`AQZz%nT1T?j94vSZG&EZlsL%d!`ve+Ch zMKi=3bR>(-;Zih1yirH8*c>iJGsK&8B#X`AQZz%nSx2(i94(-;Zih1yi-TA*c>iJGsL@eB#X`A zQZz%nTSv0k94(-;Zih1d{9TS*c>iJGsK5(-;Zih1d{RfU*c>iJGsLHKB#X`AQZz$+ zT1T?j94(- z;Zih1d{IZT*c>iJGsKs4B#X`AQZz$+Sx2(i94(-;Zih1d{alV*c>iJGsL%aB#X`AQZz$+TSv0k z94N3z%)E=4oM_jDwS&EZlsLwsLHve+ChMKi(-;Zih1 z{7^@-*c>iJGsKT{B#X`AQZz&SSVywh94(-;Zih1{8C4<*c>iJGsLfSB#X`AQZz&ST1T?j94(-;Zih1{82}; z*c>iJGsK^CB#X`AQZz&SSx2(i94(-;Zih1{8LA=*c>iJGsM4iB#X`AQZz&STSv0k94zYz~*A8RDTjlEvn5 zDViZ3rXyKw4ws@C;^8`y#pZA+njs#cBUx+?m!cWskvfva=KMd7?rMjk-B_^bFI5Z$ zpBHAPljJJQ%*@Qp%*@Q{(UCR$G@mW)((*P*(G2k@9gEH3k`&DlkJho+94<-G4DlEp zi_PJZ6wMHi)v?$dE=kc0@i-le&Eb+1%@B{*vDh3gNzn}P1Raab;gS^15Kq*x*c>iN z(G2k<9gEH3k`&DlPu8*694<-G4Dl2li_PJZ6wMG%)v?$dE=kc0@iZNa&Eb+1%@9x5 zvDh3gNzn}P3>}Nj;gS^15YN=H*c>iN(G2l`j>YD1Ns4BOXX#jM4ws~8hIqD)#pZBH zie`xC=vZtHm!xQhaKrUMEH($PQJdH4XnfskUZ>;#ug&3-6wMIN)v?$dE=kc0@jM-i z&Eb+1%@EJmvDh3gNzn}P0v(IZ;gS^15HHlR*c>iN(G2k-9gEH3k`&DlFV?Zx94<-G z4Dk{ji_PJZ6wMGX)v?$dE=kc0@iHBY&Eb+1%@8lwvDh3gNzn}P3LT5h;gS^15UiN(G2k_9gEH3k`&Dluhy~H94<-G4DlKri_PJZ6wMH?)v?$dE=kc0@j4xg&Eb+1 z%@D8GvDh3gNzn}P1|5sd;gS^15O376*c>iN(G2k>9gEH3k`&DlZ`QHc94<-G4Dl8n zi_PJZ6wMHC)v?$dE=kc0@irZc&Eb+1%@A+bvDh3gNzn}P4jqfl;gS^15bxBn*c>iN z(G2k}9gEH3k`&Dl@7A%{94<-G4DlWvi_PJZ6wMIt)v?$dE=kc0@je}k&Eb+1%@FU` zvDh3gNzn}P0Ue9Y;gS^15FgaB*c>iN(G2k+9gEH3k`&DlAJ(zh94<-G4Dk^ii_PJZ z6wMGH)v?$dE=kc0@i85X&Eb+1%@7~gvDh3gNzn}P2_1{g;gS^15TDes*c>iN(G2k^ z9gEH3k`&DlpVqP194<-G4DlHqi_PJZ6wMHy)v?$dE=kc0@i`rf&Eb+1%@Cj0vDh3g zNzn}P1s#jc;gS^15MR`>*c>iN(G2k=9gEH3k`&DlU)HhM94<-G4Dl5mi_PJZ6wMG{ z)v?$dE=kc0@iiTb&Eb+1%@AMLvDh3gNzn}P4IPWk;gS^15Z~0X*c>iN(G2k|9gEH3 zk`&Dl-`26%94<-G4DlTui_PJZ6wMId)v?$dE=kc0@jV@j&Eb+1%@E($vDh3gNzn}P z109Ra;gS^15I@wh*c>iN(G2k;9gEH3k`&DlKi09>94<-G4Dk~ki_PJZ6wMGn)v?$d zE=kc0@iQHZ&Eb+1%@9A=vDh3gNzn}P3muEi;gS^15Wm#1*c>iN(G2k`9gEH3k`&Dl zzt*wX94<-G4DlNsi_PJZ6wMI7)v?$dE=kc0@jD%h&Eb+1%@DuWvDh3gNzn}P2OW#e z;gS^15P#IM*c>iN(G2k?9gEH3k`&Dlf7Y?s94<-G4DlBoi_PJZ6wMHS)v?$dE=kc0 z@i!fd&Eb+1%@BXrvDh3gNzn}P4;_om;gS^15dYM%*c>iN(G2k~9gEH3k`&Dl|JJeC z94<-G4DlZwi_PJZ6wMI-)v?$dE=kc0@nB!Qu-F_fNzn}P5FLxn;gS^15D(R{*c>iN z(G2l09gEH3k`&Dl57)8S94<-G4DkpZi_PJZ6wMHi)UntcE=kc0@hBaO&Eb+1%@B{) zvDh3gNzn}P7#)kv;gS^15RcWd*c>iN(G2l89gEH3k`&DlkJqu-94<-G4DkdVi_PJZ z6wMG%)UntcE=kc0@gyCK&Eb+1%@9x4vDh3gNzn}P6djAr;gS^15Kq;y*c>iN(G2l4 z9gEH3k`&DlPuH>794<-G4Dk#di_PJZ6wMIN)UntcE=kc0@qmuS=5R@hW{79$SZofL zq-chCwvNT-a7l`0i09~7Yz~*CXom1_bPr;&Ib6I(ZCk@9ZsSDtz*9=MKi>6 zbu2cAOHwpLJWt1BbGRf$GsN?CEH;NrQZz%nK*wTpxFkh0#0zySHit`6G()^d$6|B1 zBtEbu2cAOHwpL zyidnsbGRf$GsOFKEH;NrQZz$+K*wTpxFkh0#0PaOHit`6G(&ty$6|B1BtAbu2cAOHwpLd{4(>bGRf$ zGsO3GEH;NrQZz&SK*wTpxFkh0#1C~WHit`6G(-GI$6|B1Bt2bu2cAOHwpL{7%PWbGRf$GsN$8 zEH;NrQZz&SLC0cqxFkh0#2Ibu2cAOHwpLJlG927MsH*DViZ3qGPc+ zT#}+0;-NYgo5Lk3njs#hW3f40lA;;n;W`$Z!zC%2As(S)u{m6lq8Z|mIu@J5B`KOA z9;IWkIb4#W8RF487MsH*DViZ3qhql-T#}+0;;}jwo5Lk3njs#iW3f40lA;;n@j4cp z!zC%2A)cUPu{m6lq8Z|eIu@J5B`KOAo}^>3Ib4#W8RE%07MsH*DViakqGPc+T#}+0 z;;A|oo5Lk3njxO1W3f40lA;;n={gph!zC%2A)cXQu{m6lq8Z|uIu@J5B`KOA9?-Ga z94<-G4Dl=-i_PJZ6wMIN*0IiN(G2kd9gEH3k`&DlFVwNv z94<-G4Dlizi_PJZ6wMGX*0IiN(G2kl9gEH3k`&Dluhg;F94<-G4Dl)*i_PJZ6wMH?*0IiN(G2kh9gEH3k`&DlZ`85a94<-G z4Dlu%i_PJZ6wMHC*0IiN(G2kp9gEH3k`&Dl@6@r_94<-G4Dl`iN(G2kc9gEH3k`&DlAJnnf94<-G4Dlfy zi_PJZ6wMGH*0IiN z(G2kk9gEH3k`&DlpVYC~94<-G4Dl%)i_PJZ6wMHy*0IiN(G2kg9gEH3k`&DlU(~VK94<-G4Dlr$i_PJZ z6wMG{*0IiN(G2ko z9gEH3k`&Dl-_)_#94<-G4Dl@;i_PJZ6wMId*0IiN(G2ke9gEH3k`&DlKh&|<94<-G4Dll!i_PJZ6wMGn z*0I`3&Eb+1%@9A;vDh3gNzn}PGaZY~;gS^15I@(k*c>iN(G2km9gEH3 zk`&DlztpkV94<-G4Dl-+i_PJZ6wMI7*0IiN(G2ki9gEH3k`&Dlf7G$q94<-G4Dlx&i_PJZ6wMHS*0IiN(G2kq9gEH3k`&Dl z|J1SA94<-G4Dl}=i_PJZ6wMI-*0IbSyT9OHwpLJXXhIbGRf$GsNR` zEH;NrQZz$6UdLi{xFkh0#1nKZHit`6G($X5$6|B1BtVsp48 zMKi=xbSyT9OHwpLJXObHbGRf$GsM$$EH;NrQZz$6UB_Z`xFkh0#4~g(Hit`6G($X7 z$6|B1BtOQGu{m6lq8Z{XIu@J5B`KOA-l}7OTHu{m6l zq8Z{nIu@J5B`KOA-m7D=Ib4#W8RC697MsH*DVibPuVb+}T#}+0;sZJso5Lk3njt=@ zW3f40lA;;nLpm0l!zC%2AwH~Qu{m6lq8Z{NIu@J5B`KOAKB{A}Ib4#W8RBC)7MsH* zDViZZu4Az|T#}+0;uAU+o5Lk3njt=^W3f40lA;;nQ#ux#!zC%2AwI2Ru{m6lq8Z{d zIu@J5B`KOAKC5G~Ib4#W8RBy~7MsH*DViZZuVb+}T#}+0;tM(!o5Lk3njyZZW3f40 zlA;;nOF9;t!zC%2A-=3*u{m6lq8Z{VIu@J5B`KOAzN%xfIb4#W8RBa?7MsH*DVia^ zu4Az|T#}+0;u|^^o5Lk3njyZaW3f40lA;;nTRIk-!zC%2A-=6+u{m6lq8Z{lIu@J5 zB`KOAzN=%gIb4#W8RC077MsH*DVia^uVb+}T#}+0;s-hwo5Lk3njwCuW3f40lA;;n zM>-ap!zC%2A%3i5u{m6lq8Z{RIu@J5B`KOAeyU@!Ib4#W8RBO;7MsH*DViaEu4Az| zT#}+0;uks=o5Lk3njwCvW3f40lA;;nS2`A(!zC%2A%3l6u{m6lq8Z{hIu@J5B`KOA zeyd}#Ib4#W8RB<37MsH*DViaEuVb+}T#}+0;tx6&o5Lk3nj!wEW3f40lA;;nPdXNx z!zC%2A^xmmu{m6lq8Z{ZIu@J5B`KOA{;FfKIb4#W8RBm`7MsH*DVibvu4Az|T#}+0 z;vYH|o5Lk3nj!wFW3f40lA;;nUpf|>!zC%2A^xpnu{m6lq8Z{pIu@J5B`KOA{;OlL zIb4#W8REhI`JKh)a7l`0h==G{Yz~*CXoh&Gj>YD1Ns4BOhv`^s4ws~8hIqJ+#pZBH zie`vM=vZtHm!xQhc%+WS=5R@hW{5}WSZofLq-chCw2sB*a7l`0h{xzyYz~*CXoh&K zj>YD1Ns4BO$LUyX4ws~8hIqV=#pZBHie`u>=vZtHm!xQhc%qKQ=5R@hW{4;0SZofL zq-chCvW~^(a7l`0h^OdSYz~*CXoh&Ij>YD1Ns4BOr|DR14ws~8hIqP;#pZBHie`vs z=vZtHm!xQhc&3iU=5R@hW{3xLEH;NrQZz$6OUGh!xFkh0#ItoQHit`6G($W`$6|B1 zBtjWhf7j4Lp)!{ zVsp48MKi<;bSyT9OHwpLyimttbGRf$GsKH@EH;NrQZz%nSjS>>xFkh0#7lH6Hit`6 zG()^p$6|B1BtvSwOhf7j4L%d$cVsp48 zMKi=3bSyT9OHwpLyivzubGRf$GsK&8EH;NrQZz%nS;t~?xFkh0#9MSMHit`6G()^q z$6|B1Bt>xFkh0#7A^2Hit`6G(&t;$6|B1 zBt$6|B1Bt>xFkh0#7}fAHit`6G(-GU$6|B1Bt zbSyT9OHwpLJXXhIbGRf$GsNR`EH;NrQZz$6UdLi{xFkh0#1nKZHit`6G($X5$6|B1 zBtVsp48MKi=xbSyT9OHwpLJXObHbGRf$GsM$$EH;NrQZz$6 zUB_Z`xFkh0#4~g(Hit`6G($X7$6|B1BtOQGu{m6lq8Z{X zIu@J5B`KOA-l}7OTHu{m6lq8Z{nIu@J5B`KOA-m7D=Ib4#W8RC697MsH*DVibP zuVb+}T#}+0;sZJso5Lk3njt=@W3f40lA;;nLpm0l!zC%2AwH~Qu{m6lq8Z{NIu@J5 zB`KOAKB{A}Ib4#W8RBC)7MsH*DViZZu4Az|T#}+0;uAU+o5Lk3njt=^W3f40lA;;n zQ#ux#!zC%2AwI2Ru{m6lq8Z{dIu@J5B`KOAKC5G~Ib4#W8RBy~7MsH*DViZZuVb+} zT#}+0;tM(!o5Lk3njyZZW3f40lA;;nOF9;t!zC%2A-=3*u{m6lq8Z{VIu@J5B`KOA zzN%xfIb4#W8RBa?7MsH*DVia^u4Az|T#}+0;u|^^o5Lk3njyZaW3f40lA;;nTRIk- z!zC%2A-=6+u{m6lq8Z{lIu@J5B`KOAzN=%gIb4#W8RC077MsH*DVia^uVb+}T#}+0 z;s-hwo5Lk3njwCuW3f40lA;;nM>-ap!zC%2A%3i5u{m6lq8Z{RIu@J5B`KOAeyU@! zIb4#W8RBO;7MsH*DViaEu4Az|T#}+0;uks=o5Lk3njwCvW3f40lA;;nS2`A(!zC%2 zA%3l6u{m6lq8Z{hIu@J5B`KOAeyd}#Ib4#W8RB<37MsH*DViaEuVb+}T#}+0;tx6& zo5Lk3nj!wEW3f40lA;;nPdXNx!zC%2A^xmmu{m6lq8Z{ZIu@J5B`KOA{;FfKIb4#W z8RBm`7MsH*DVibvu4Az|T#}+0;vYH|o5Lk3nj!wFW3f40lA;;nUpf|>!zC%2A^xpn zu{m6lq8Z{pIu@J5B`KOA{;OlLIb4#W8REfhUf1SzZC=;rb!}eP=5>Ba(+u$t9gEH3 zk`&Dl57n{Q94<-G4Dm1>i_PJZ6wMG1*Rj|fE=kc0@dzD@&Eb+1%@B{&vDh3gNzn}P zC>@K<;gS^15RcZe*c>iN(G2kz9gEH3k`&DlkJYi*94<-G4DmP}i_PJZ6wMHi*Rj|f zE=kc0@dO=<&Eb+1%@9x2vDh3gNzn}PBpr**;gS^15Kq>z*c>iN(G2kv9gEH3k`&Dl zPt~#594<-G4DmD_i_PJZ6wMG%*Rj|fE=kc0@eCb{&Eb+1%@EJjvDh3gNzn}PfR4rH za7l`0h-c|oYz~*CXoh&Uj>YD1Ns4BO=jd2$4ws~8hWI}ni_PJZ6wMI6pz|8Fd7Tb7 z@y+XWIEDVV#vaervDh3gNzn}PJROV8;gS^15YN}K*c>iN(G2kd9gEH3k`&DlFVwNv z94<-G4Dlizi_PJZ6wMGX*0IiN(G2kl9gEH3k`&Dluhg;F94<-G4Dl)*i_PJZ6wMH?*0IiN(G2kh9gEH3k`&DlZ`85a94<-G z4Dlu%i_PJZ6wMHC*0IiN(G2kp9gEH3k`&Dl@6@r_94<-G4Dl`iN(G2kc9gEH3k`&DlAJnnf94<-G4Dlfy zi_PJZ6wMGH*0Ij& z|KsScb|~0&Mce+8XA(R1=PhPtxQm&YnVFfHnOV1;t*F&ge~vUfDwRt!#3ywuHix9R zG(&t!$6|9xic2%Zr*$kghorbPLwrWZVsl7}OEbi0bu2cAq_{Lgd``z=b4ZFyGsNe0 zEH;OvxHLn2LC0cqNQz4{#20leHix9RG(&tz$6|9xic2%Zmvt;QhorbPLwrTYVsl7} zOEbh*bu2cAq_{Lgd`-tb4ZFyGsO3GEH;Ov zxHLojK*wTpNQz4{#1C~WHix9RG(-GI$6|9xic2%Zk990IhorbPL;OU?Vsl7}OEbhz zbu2cAq_{Lg{7lDUb4ZFyGsMqzEH;OvxHLojLdRlrNQz4{#4mL$Hix9RG(-GK$6|9x zic2%ZuXQXohorbPL;Oa^Vsl7}OEbi8bu2cAq_{Lg{7%PWb4ZFyGsN$8EH;OvxHLoj zLC0cqNQz4{#2hi_IY^F3k`R)v?$dlH$?~@h}~W%^@i+%@7aQvDh4v;?fN92px;f zAt^4+5RcTc*c_7L(hTt^9gEE&DK5}NjAt^4+ z5YN=H*c_7L(hTt|9gEE&DK5jWhorbPLp)!{Vsl7}OEbg^bSyT9q_{Lgyimttb4ZFy zGsKH@EH;OvxHLn&SjS>>NQz4{#7lH6Hix9RG()^p$6|9xic2%Z%XBO@horbPL%dwa zVsl7}OEbhPbSyT9q_{Lgyi&(vb4ZFyGsLTOEH;OvxHLn&TE}8@NQz4{#A|dcHix9R zG()^r$6|9xic2%Z>vSwOhorbPL%d$cVsl7}OEbh9bSyT9q_{Lgyivzub4ZFyGsK&8 zEH;OvxHLn&S;t~?NQz4{#9MSMHix9RG()^q$6|9xic2%Z+jJ~8horbPL%dzbVsl7} zOEbhfbSyT9q_{Lgyi>>NQz4{#7A^2Hix9RG(&t;$6|9xic2%Z$8;<$6|9xic2%Z z_jD{ahorbPLwsMyVsl7}OEbg|bSyT9q_{Lg{7}bYb4ZFyGsKT{EH;OvxHLojSjS>> zNQz4{#7}fAHix9RG(-GU$6|9xic2%Z&vYy{horbPL;PIFVsl7}OEbhTbSyT9q_{Lg z{8Gnab4ZFyGsLfSEH;OvxHLojTE}8@NQz4{#BX#gHix9RG(-GW$6|9xic2%Z?{q9S zhorbPL;POHVsl7}OEbhDbSyT9q_{Lg{87hZb4ZFyGsK^CEH;OvxHLojS;t~?NQz4{ z#9wqQHix9RG(-GV$6|9xic2%Z-*hZChorbPL;PLGVsl7}OEbhjbSyT9q_{Lg{8Ptb zb4ZFyGsM4iEH;OvxHLojTgPH^NQz4{#D8=wHix9RG(-GX$6|9xic2%Z|8y)ihorbP zLp&&+_W+B{At^4+5D(U|*c_7L(hTts9gEE&DK5i_IY^F3k`R z*Rj|flH$?~@dzD@%^@i+%@B{&vDh4v;?fN9C>@Kz*c_7L(hTtw9gEE&DK5b4ZFyGsO3GEH;OvxHLojK*wTpNQz4{ z#1C~WHix9RG(-GI$6|9xic2%Zk990IhorbPL;OU?Vsl7}OEbhzbu2cAq_{Lg{7lDU zb4ZFyGsMqzEH;OvxHLojLdRlrNQz4{#4mL$Hix9RG(-GK$6|9xic2%ZuXQXohorbP zL;Oa^Vsl7}OEbi8bu2cAq_{Lg{7%PWb4ZFyGsN$8EH;OvxHLojLC0cqNQz4{#2x(Ceb+|o#KX@+>Pj>YDX z6qja*hv-;r4oPuohIpus#paL{mu85E=~!$INpWe0c({(m=8zPZW{5}VSZoeSacPEl zq>jbrkQA3@h)3yIYz|3rX@+>Tj>YDX6qja*$LLsW4oPuohIp)w#paL{mu85^=~!$I zNpWe0c)X6q=8zPZW{4-~SZoeSacPElqK?JpkQA3@h$rb-Yz|3rX@+>Rj>YDX6qja* zr|4L04oPuohIp!u#paL{mu85k=~!$INpWe0c)E_o=8zPZW{79#SZoeSacPElrjEtt zkQA3@h-c|oYz|3rX@+>Vj>YDX6qja*=jd2$4oPuohIp=y#paL{mu3iW%{{OQGu{k8gr5WNaIu@HlQe2uL-l}7OTHu{k8gr5WNqIu@HlQe2uL-m7D=IV8oU z8RC697Mnv-T$&-?uVb+}B*mo};sZJsn?q7unjt=@W3f3T#ibeILpm0lLsDFtAwH~Q zu{k8gr5WNQIu@HlQe2uLKB{A}IV8oU8RBC)7Mnv-T$&+1u4Az|B*mo};uAU+n?q7u znjt=^W3f3T#ibeIQ#ux#LsDFtAwI2Ru{k8gr5WNgIu@HlQe2uLKC5G~IV8oU8RBy~ z7Mnv-T$&+1uVb+}B*mo};tM(!n?q7unjyZZW3f3T#ibeIOF9;tLsDFtA-=3*u{k8g zr5WNYIu@HlQe2uLzN%xfIV8oU8RBa?7Mnv-T$&-iu4Az|B*mo};u|^^n?q7unjyZa zW3f3T#ibeITRIk-LsDFtA-=6+u{k8gr5WNoIu@HlQe2uLzN=%gIV8oU8RC077Mnv- zT$&-iuVb+}B*mo};s-hwn?q7unjwCuW3f3T#ibeIM>-apLsDFtA%3i5u{k8gr5WNU zIu@HlQe2uLeyU@!IV8oU8RBO;7Mnv-T$&+%u4Az|B*mo};uks=n?q7unjwCvW3f3T z#ibeIS2`A(LsDFtA%3l6u{k8gr5WNkIu@HlQe2uLeyd}#IV8oU8RB<37Mnv-T$&+% zuVb+}B*mo};tx6&n?q7unj!wEW3f3T#ibeIPdXNxLsDFtA^xmmu{k8gr5WNcIu@Hl zQe2uL{;FfKIV8oU8RBm`7Mnv-T$&;Nu4Az|B*mo};vYH|n?q7unj!wFW3f3T#ibeI zUpf|>LsDFtA^xpnu{k8gr5WNsIu@HlQe2uL{;OlLIV8oU8RCCB7Mnv-T$&*s79FpSF4Dk#d zi_IY^F3k|n)UntclH$?~@hlyS%^@i+%@EJlvDh4v;?fN9936|zAt^4+5YN@I*c_7L z(hT8*>jNw{2e($6*XeL#-@H!uJRSdUZ4OCsX@+>dj>YDX6qja*7wA}Q4oPuohIpZl z#paL{mu83;=~!$INpWe0c(IPf=8zPZW{8*QSZoeSacPElsgA|wkQA3@h?nVDYz|3r zX@+>Yj>YDX6qja*SLj%54oPuohIplp#paL{mu84p=~!$INpWe0c(snj=8zPZW{B75 zSZoeSacPElt&YX!kQA3@h}Y>@Yz|3rX@+>cj>YDX6qja*H|SVw4oPuohIpfn#paL{ zmu84J=~!$INpWe0c(abh=8zPZW{9`wSZoeSacPEltB%FykQA3@h_~rjYz|3rX@+>a zj>YDX6qja*cj#Db4oPuohIprr#paL{mu84}=~!$INpWe0c(;zl=8zPZW{CIbSZoeS zacPElua3p$kQA3@i1+DOYz|3rX@+>ej>YDX6qja*59nBI4oPuohWMb4#paL{mu83$ z=~!$INpWe0_^^(}=8zPZW{8jISZoeSacPG5sE)z)5Yz|3rX@>Z?j>YDX z6qja*Pv}@|4oPuohWMn8#paL{mu84h=~!$INpWe0__U72=8zPZW{A(|SZoeSacPG5 ztd7OzkQA3@h|lR*Yz|3rX@>Z`j>YDX6qja*FX&io4oPuohWMh6#paL{mu84B=~!$I zNpWe0__B`0=8zPZW{9uoSZoeSacPG5s*c6xkQA3@h_C5bYz|3rX@>Z^j>YDX6qja* zZ|GQT4oPuohWMtA#paL{mu84>=~!$INpWe0__mJ4=8zPZW{B_TSZoeSacPG5u8zg# zkQA3@i0|oGYz|3rX@>Z|j>YDX6qja*ALv+Y4oPuohWMe5#paL{mu83`=~!$INpWe0 z__2<~=8zPZW{98YSZoeSacPG5sgA|wkQA3@h@a_LYz|3rX@>Z@j>YDX6qja*U+7qD z4oPuohWMq9#paL{mu84x=~!$INpWe0__dD3=8zPZW{BVDSZoeSacPG5t&YX!kQA3@ zh~Md0Yz|3rX@>Z{j>YDX6qja*Kj>I&4oPuohWMk7#paL{mu84R=~!$INpWe0__L11 z=8zPZW{AJ&SZoeSacPG5tB%FykQA3@h`;GrYz|3rX@>Z_j>YDX6qja*f9P0j4oPuo zhWMwB#paL{mu856=~!$INpWe0__vP5=8zPZW{CgjSZoeSacPG5ua3p$kQA3@i2vzW zYz|3rX@+=^w^>+h4oPuohIp`!#paL{mu85E=vZtHNpWe0c&LuW=8zPZW{8LBSZoeS zacPElxQ@lDj>YDX6qja*N9kB>4oPuohIq7&#paL{mu85^ z=vZtHNpWe0c&v`a=8zPZW{Ah>SZoeSacPElypF}@kQA3@h$rY+Yz|3rX@+>Bj>YDX z6qja*C+S#h4oPuohIq1$#paL{mu85k=vZtHNpWe0c&d)Y=8zPZW{9WhSZoeSacPEl zx{k%>kQA3@h-c_nYz|3rX@+>Fj>YDX6qja*XX#jM4oPuohIqD)#paL{mu86P=vZtH zNpWe0c&?7c=8zPZW(Z%Sdw|8}khrzlyiSJ``{s2z>{kD`j%QL_njxOAW3f3T#ibeI z1v(a+LsDFtAzr9su{k8gr5WNyIu@HlQe2uLUaVuWIV8oU8R8{67Mnv-T$&+Xs$;P^ zB*mo};$=D(n?q7unjv1UW3f3T#ibeI6*?B1LsDFtAzrCtu{k8gr5WN?Iu@HlQe2uL zUae!XIV8oU8R9iM7Mnv-T$&+Xt7EY_B*mo};&nO}n?q7unjv1VW3f3T#ibeI4LTN^ zLsDFtA>OECu{k8gr5WN)Iu@HlQe2uL-mGJ>IV8oU8R9KE7Mnv-T$&-?s$;P^B*mo} z;%zz>n?q7unjzkOHDu{k8gr5WN~Iu@HlQe2uL-mPP? zIV8oU8R9)U7Mnv-T$&-?t7EY_B*mo};(a<6n?q7unjzk=W3f3T#ibeI13DI)LsDFt zAwH;Mu{k8gr5WNwIu@HlQe2uLKCEN0IV8oU8R8>47Mnv-T$&+1s$;P^B*mo};$u1% zn?q7unjt=}W3f3T#ibeI6FL@~LsDFtAwH>Nu{k8gr5WN=Iu@HlQe2uLKCNT1IV8oU z8R9cK7Mnv-T$&+1t7EY_B*mo};&VC{n?q7unjt=~W3f3T#ibeI3py5?LsDFtA-}f`LsDFtA^xaiu{k8gr5WN+ zIu@HlQe2uL{;XrMIV8oU8R9QG7Mnv-T$&;Ns$;P^B*mo};%_<@n?q7unj!wKW3f3T z#ibeIA37GBLsDFtA^xdju{k8gr5WO1Iu@HlQe2uL{;gxNIV8oU8R9=W7Mnv-T$&;N zt7EY_B*mo};(t08n?q7unjs$Ki_IY^F3k`R*Rj|flH$?~@dzD@%^@i+%@B{&vDh4v;?fN9C>@Kz*c_7L(hTtw9gEE&DK5r=uv`7#O3&ib z4Doy&i_IY^F3k`x(6QJYlH$?~@j@Mo%^@i+%@8lrvDh4v;?fN9VjYXkAt^4+5HHcO z*c_7L(hTuZ9gEE&DK5 zvDh4v;?fN9ZXJuwAt^4+5bx2k*c_7L(hTul9gEE&DK5PJ9FpSF4Dodxi_IY^F3k|%(6QJYlH$?~@l73z%^@i+%@E(xvDh4v;?fN9 zZ5@lvAt^4+5Z}?U*c_7L(hTuk9gEE&DK5(6QJY zlH$?~@k1Sp%^@i+%@9A*vDh4v;?fN9V;zglAt^4+5I@ne*c_7L(hTua9gEE&DK5iN(G2la9gEH3k`&DlPt&p394<-G z4Doawi_PJZ6wMIN(6QJYE=kc0@k||y&Eb+1%@EJhvDh3gNzn}PY#ocu;gS^15YN%E z*c>iN(G2li9gEH3k`&Dl&(pEk94<-G3}MUbgIH`1m!z<@+PqHp|LO1*uz8)1|96t2 z8R7vQi_PJZ6wMGX(6QJYE=kc0@j@Mo&Eb+1%@8lrvDh3gNzn}PVjYXk;gS^15HHcO z*c>iN(G2lY9gEH3k`&DlFVnHu94<-G4DoUui_PJZ6wMH?(6QJYE=kc0@k$+w&Eb+1 z%@D8BvDh3gNzn}PY8{Ks;gS^15UiN(G2lg9gEH3k`&DluhX&E94<-G4Dos$ zi_PJZ6wMHC(6QJYE=kc0@kSks&Eb+1%@A+WvDh3gNzn}PW*v*o;gS^15O2}3*c>iN z(G2lc9gEH3k`&DlZ_}~Z94<-G4Dogyi_PJZ6wMIt(6QJYE=kc0@lG9!&Eb+1%@FU> zvDh3gNzn}PZXJuw;gS^15bx2k*c>iN(G2lk9gEH3k`&Dl@6)l^94<-G4Do&)i_PJZ z6wMGH(6QJYE=kc0@j)Gn&Eb+1%@7~bvDh3gNzn}PVI7Oj;gS^15FgR8*c>iN(G2lX z9gEH3k`&DlAJehe94<-G4DoRti_PJZ6wMHy(6QJYE=kc0@kt$v&Eb+1%@Ci`vDh3g zNzn}PX&sBr;gS^15TDVp*c>iN(G2lf9gEH3k`&DlpVP6}94<-G4Dop#i_PJZ6wMG{ z(6QJYE=kc0@kJer&Eb+1%@AMGvDh3gNzn}PWgUyn;gS^15MR-;*c>iN(G2lb9gEH3 zk`&DlU(>PJ94<-G4Dodxi_PJZ6wMId(6QJYE=kc0@l73z&Eb+1%@E(xvDh3gNzn}P zZ5@lv;gS^15Z}?U*c>iN(G2lj9gEH3k`&Dl-_xiN(G2lZ9gEH3k`&Dl zKhv?;94<-G4DoXvi_PJZ6wMI7(6QJYE=kc0@kiN(G2lh9gEH3k`&DlztgeU94<-G4Dov%i_PJZ6wMHS(6QJYE=kc0 z@kbqt&Eb+1%@BXmvDh3gNzn}PXB~^p;gS^15P#9J*c>iN(G2ld9gEH3k`&Dlf77wp z94<-G4Dojzi_PJZ6wMI-(6QJYE=kc0@lPF#&Eb+1%@F_6vDh3gNzn}PZyk%x;gS^1 z5dYD!*c>iN(G2ll9gEH3k`&Dl|I@M994<-G4Dn$9=+0tuxFkh0#6xr}Hit`6G($X8 z$6|B1BtjWhf7j4Lp)!{Vsp48MPqBVd7Tb7 z_RZ^bcw7D7DbHqz2Xrhphf7j4L%cx8Vsp48MKi<;bu2cAOHwpLyhz7lbGRf$GsKH^ zEH;NrQZz%nM8{%txFkh0#7lK7Hit`6G()^h$6|B1Btvb$Phf7j4L%c!9Vsp48MKi=3bu2cAOHwpLyh+DmbGRf$GsK&9EH;Nr zQZz%nMaN=uxFkh0#9MVNHit`6G()^i$6|B1BtVsp48MKi=dbu2cAOHwpL{7c7TbGRf$ zGsM4jEH;NrQZz&SN5^7wxFkh0#D8@xHit`6G(-GP$6|B1BtN{6u{m6lq8Z|?Iu@J5B`KOA-lk)*Ib4#W8RG3a7MsH*DVibP zp<}T*T#}+0;+;Aco5Lk3njzk$W3f40lA;;n-8vSV!zC%2A>N~7u{m6lq8Z}7Iu@J5 zB`KOA-lt=+Ib4#W8RGpq7MsH*DViZZpkuK)T#}+0;)6OCo5Lk3njt=fNL!zC%2AwHvHu{m6lq8Z||Iu@J5B`KOA zKBr@`Ib4#W8RGLg7MsH*DVia^pkuK)T#}+0;)^;Ko5Lk3njyZVW3f40lA;;n%Q_aD z!zC%2A-kJ| zo5Lk3njxN|W3f40lA;;nsX7*$!zC%2A)cmVu{m6lq8Z}pIu@J5B`KOAo}pv0Ib4#W z8RD5b7MsH*DViakrDL%Hit`6G()^o$6|B1BtE zbSyT9OHwpLyjRC!bGRf$GsOFJEH;NrQZz%nU&mr|xFkh0#0PXNHit`6G(&t)$6|B1 zBtAbSyT9OHwpL zd{@U}bGRf$GsO3FEH;NrQZz$+U&mr|xFkh0#1C{VHit`6G(-GQ$6|B1Bt2bSyT9OHwpL{8qIbSyT9OHwpL{8z_fbGRf$ zGsORNEH;NrQZz$6c+Bg@yw3JT4ws~8hIojM#pZBHie`w1>R4YD1Ns4BON9$N@4ws~8hIovQ z#pZBHie`w%>R4YD1Ns4BOC+k>j4ws~8hIopO#pZBHie`wX>R4YD1Ns4BOXX{vO4ws~8hIo#S#pZBH zie`xC>R49`^o5Lk3njv1IW3f40 zlA;;nr8*Xy!zC%2Azr3qu{m6lq8Z}lIu@J5B`KOAUZG>LIb4#W8RC^X7MsH*DViZ( zrDL%|i1o5Lk3njzkzW3f40lA;;n ztvVK)!zC%2A>O8Au{m6lq8Z}tIu@J5B`KOA-l1c$Ib4#W8RDHf7MsH*DVibPrDL%< zT#}+0;@vtHo5Lk3njzk!W3f40lA;;ny*d_~!zC%2A>OBBu{m6lq8Z}-Iu@J5B`KOA zKA>Z$V~o5Lk3njyZTW3f40lA;;nt2!2&!zC%2 zA-<+#u{m6lq8Z}rIu@J5B`KOAzM*5WIb4#W8RDBd7MsH*DVia^rDL%S7`o5Lk3njwCoW3f40lA;;nr#cp!!zC%2A%3P~ zu{m6lq8Z}nIu@J5B`KOAexYNrIb4#W8RC~Z7MsH*DViaErDL%lP^!zC%2A%3T0u{m6lq8Z}%Iu@J5B`KOA{-9&AIb4#W8RCyR z7MsH*DVibvq+_u;T#}+0;?Fu3o5Lk3nj!w8W3f40lA;;nuR0c+!zC%2A^xUgu{m6l zq8Z}vIu@J5B`KOA{-I;BIb4#W8RDNh7MsH*DVibvrDL%(Jo5Lk3nj!w9 zW3f40lA;;nzd9D1!zC%2A^xXhu{m6lq8Z}B@xX&vYz~*CXoh%*j>YD1Ns4BOhw4~t z4ws~8hIp8c#pZBHie`w1>sV|Km!xQhc!Z9{=5R@hW{5}XSZofLq-chCl#a#ba7l`0 zh)3&KYz~*CXoh%YD1Ns4BO$Ld&Y4ws~8hIpKg#pZBHie`w%>sV|Km!xQhc!G|_ z=5R@hW{4;1SZofLq-chCl8(jZa7l`0h$rhYD1Ns4BOr|MX24ws~8 zhIpEe#pZBHie`wX>sV|Km!xQhc!rL}=5R@hW{79%SZofLq-chCmX5{da7l`0h-d3q zYz~*CXoh%>j>YD1Ns4BO=jvE&4ws~8hIpQi#pZBHie`xC>sV|Km!xQh`2Tb)Y^{F4 zCY%TSyXFIK>_6Zu;0OG&@PN0~1OM+lh{fh`Ns4BO7wA}Q4ws~8hIpZl#pZBHie`ux z=~!$Im!xQhc(IPf=5R@hW{8*QSZofLq-chCsgA|wa7l`0h?nVDYz~*CXoh&Xj>YD1 zNs4BOSLj%54ws~8hIplp#pZBHie`vc=~!$Im!xQhc(snj=5R@hW{B75SZofLq-chC zt&YX!a7l`0h}Y>@Yz~*CXoh&bj>YD1Ns4BOH|SVw4ws~8hIpfn#pZBHie`v6=~!$I zm!xQhc(abh=5R@hW{9`wSZofLq-chCtB%Fya7l`0h_~rjYz~*CXoh&Zj>YD1Ns4BO zcj#Db4ws~8hIprr#pZBHie`v+=~!$Im!xQhc(;zl=5R@hW{CIbSZofLq-chCua3p$ za7l`0i1+DOYz~*CXoh&dj>YD1Ns4BO59nBI4ws~8hWMb4#pZBHie`up=~!$Im!xQh z_^^(}=5R@hW{8jISZofLq-citsE)z)5Yz~*CXomQ>j>YD1Ns4BOPv}@| z4ws~8hWMn8#pZBHie`vU=~!$Im!xQh__U72=5R@hW{A(|SZofLq-cittd7Oza7l`0 zh|lR*Yz~*CXomQ_j>YD1Ns4BOFX&io4ws~8hWMh6#pZBHie`u}=~!$Im!xQh__B`0 z=5R@hW{9uoSZofLq-cits*c6xa7l`0h_C5bYz~*CXomQ@j>YD1Ns4BOZ|GQT4ws~8 zhWMtA#pZBHie`v!=~!$Im!xQh__mJ4=5R@hW{B_TSZofLq-citu8zg#a7l`0i0|oG zYz~*CXomQ{j>YD1Ns4BOALv+Y4ws~8hWMe5#pZBHie`u(=~!$Im!xQh__2<~=5R@h zW{98YSZofLq-citsgA|wa7l`0h@a_LYz~*CXomQ?j>YD1Ns4BOU+7qD4ws~8hWMq9 z#pZBHie`vk=~!$Im!xQh__dD3=5R@hW{BVDSZofLq-citt&YX!a7l`0h~Md0Yz~*C zXomQ`j>YD1Ns4BOKj>I&4ws~8hWMk7#pZBHie`vE=~!$Im!xQh__L11=5R@hW{AJ& zSZofLq-cittB%Fya7l`0h`;GrYz~*CXomQ^j>YD1Ns4BOf9P0j4ws~8hWMwB#pZBH zie`v^=~!$Im!xQh__vP5=5R@hW{CgjSZofLq-citua3p$a7l`0i2vzWYz~*CXoh(3 zgUst5WM20m^STF_*V(>EQZz$6M8{%txFkh0#6xu~Hit`6G($X0$6|B1Bt@Hhf7j4Lp(vpVsp48MKi<`bu2cAOHwpLJW0o5 zbGRf$GsKg1EH;NrQZz$6MaN=uxFkh0#8Y)FHit`6G($X1$6|B1Bt7MsH*DViZ(sbjG@T#}+0;#E2po5Lk3 znjv1TW3f40lA;;nH98iX!zC%2AzrIvu{m6lq8Z|KIu@J5B`KOAUaw=ZIb4#W8R88( z7MsH*DVibPsAI7?T#}+0;!Qdho5Lk3njzk-W3f40lA;;nEjkvP!zC%2A>OKEu{m6l zq8Z|CIu@J5B`KOA-mYV@Ib4#W8R8u}7MsH*DVibPsbjG@T#}+0;$1oxo5Lk3njzk; zW3f40lA;;nJvtVf!zC%2A>ONFu{m6lq8Z|SIu@J5B`KOA-mhb^Ib4#W8R7#v7MsH* zDViZZsAI7?T#}+0;zK$Xo5Lk3njt={W3f40lA;;nBRUqF!zC%2AwH^Ou{m6lq8Z|2 zIu@J5B`KOAKCWZ2Ib4#W8R8Q<7MsH*DViZZsbjG@T#}+0;!`>no5Lk3njt=|W3f40 zlA;;nGygwF_q0S&kR(v_m#V8$^?7aEnrYj%ZQHi3m^B?0>pbn}6LB+coz$^81WC~h zm-T5Kn?sNk&2U+t(XlxMNzn|K^;sR8Ly#2Ba9N+zu{i`u(F~XMc^#WWkQB{uSzpkx zIRr`3443sq9h*at6wPp1U(&HT1WC~hm-S^Gn?sNk&2U*?(XlxMNzn|K^;I34Ly#2B za9Ll|u{i`u(F~XMbsd{SkQB{uS>MpHIRr`3443sy9h*at6wPp1-_o%;1WC~hm-THO zn?sNk&2U-Y(XlxMNzn|K^<5pCLy#2Ba9Q8eu{i`u(F~XMeI1)akQB{uSwGORIRr`3 z443so9h*at6wPp1Khm)|1WC~hm-S;En?sNk&2U*i(XlxMNzn|K^-~?2Ly#2Ba9Kao zu{i`u(F~XMa~+#QkQB{uS-;S+IRr`3443sw9h*at6wPp1ztXWe1WC~hm-TBMn?sNk z&2U-2(XlxMNzn|K^;;dALy#2Ba9O|8u{i`u(F~XMdmWoYkQB{uS%1*6IRr`3443ss z9h*at6wPp1f6}oz1WC~hm-S~In?sNk&2U+N(XlxMNzn|K^;aF6Ly#2Ba9MxTu{i`u z(F~XMcO9EUkQB{uS^v)0HEq-ciAdW4S6AxMg5xU5I&*c^hSXokyrl#b0INQ!2- ztViqE9D<~1hRb@4j?E!Rie|X1$LiP|f~07M%X*xS%^^sNX1J`!>)0HEq-ciAdV-G4 zAxMg5xU47Y*c^hSXokyrl8((GNQ!2-tS9T(9D<~1hRb@2j?E!Rie|X1r|Q@of~07M z%X*rQ%^^sNX1J`U>)0HEq-ciAdWMe8AxMg5xU6UD*c^hSXokyrmX6IKNQ!2-tY_=k z9D<~1hRb@6j?E!Rie|X1=jzxTf~07M%W}i@0c;L|?bhaXI^66xuhadnj{iT0ASs&R zvYw}7a|n{687}MjIyQ$ODVpK3UZ7)h2$G^1F6)IlHisZ7n&Gluq+@dklA;+d>%}@Y zhaf4M;j&($V{-_Sq8Tphr8+i;ASs&RvR(x3ohaf4M;j&(%V{-_Sq8TphwK_J3ASs&RvR&-eghaf4M z;j-SMV{-_Sq8TphtvWV`ASs&Rvfid+a|n{687}MXIyQ$ODVpK3-l1c22$G^1F6*5- zHisZ7n&GnErDJmllA;+d>)kpwhaf4M;j-SNV{-_Sq8Tphy*f6BASs&Rvfig-a|n{6 z87}MnIyQ$ODVpK3KA>ZB2$G^1F6)CjHisZ7n&GlOq+@dklA;+d>%%%Whaf4M;j%uW zV{-_Sq8TphqdGQ+ASs&RvOcC`a|n{687}MNIyQ$ODVpK3KA~fC2$G^1F6)yzHisZ7 zn&GlOrDJmllA;+d>(e?mhaf4M;j%uXV{-_Sq8TphvpP11ASs&RvOcF{a|n{687}Md zIyQ$ODVpK3zMx}s2$G^1F6)arHisZ7n&Gm(q+@dklA;+d>&rSehaf4M;j+G>V{-_S zq8Tpht2#D^ASs&Rvc9Hca|n{687}MVIyQ$ODVpK3zM*4t2$G^1F6)~*HisZ7n&Gm( zrDJmllA;+d>)Sduhaf4M;j+G?V{-_Sq8TphyE-<9ASs&Rvc9Kda|n{687}MlIyQ$O zDVpK3exPG>2$G^1F6)OnHisZ7n&Gm3q+@dklA;+d>&H4ahaf4M;j(_BV{-_Sq8Tph zr#d!=ASs&RvVNvxa|n{687}MRIyQ$ODVpK3exYM?2$G^1F6);%HisZ7n&Gm3rDJml zlA;+d>(@Fqhaf4M;j(_CV{-_Sq8Tphw>mb5ASs&RvVNyya|n{687}MhIyQ$ODVpK3 z{-9%X2$G^1F6)mvHisZ7n&Gnkq+@dklA;+d>(4qihaf4M;j;dsV{-_Sq8TphuR1n| zASs&Rvi_!Ha|n{687}MZIyQ$ODVpK3{-I-Y2$G^1F6*B)$#yhaf4M;j;dtV{-_Sq8Tphf&Qh!<`5)BGhEh#bZibmQZ&P5Jy^%)5F|x2T-HN$ zYz{$EG{a>*RLABJBt*R>$TLBt*RmbKKBt*SI6cMBt$TLBtK~glsWqnY`<`5)BGhEh(bZibmQZ&P5 zeOSll5F|x2T-HZ)Yz{$EG{a?mRLABJBtg4na~h!)1M3$L0_uMKfI1Cv$TLBtbZibmQZ&P5{aDB55F|x2 zT-Hx?Yz{$EG{a^6RLABJBt$TLBt*(2X)Shaf4M;j$j2V{-_Sq8Tph z!8$gFASs&RvL2#ia|n{687}LgIyQ$ODVpK39;Rb+2$G^1F6-esHisZ7n&Gk@p<{Ch zlA;+d>ybJ(haf4M;j$j3V{-_Sq8Tph(Kxnuxhaf4M;j*5jV{-_Sq8Tph$vQTN zASs&RvYw)2a|n{687}LoIyQ$ODVpK3o~C1S2$G^1F6-$!HisZ7n&GmZp<{ChlA;+d z>zO(>haf4M;j*5kV{-_Sq8Tph**Z3dASs&RvYw-3a|n{687}L&IyQ$ODVpK3Y>s#U zn?sNkwp*Lm>2R~(yiSL=+J8@a7R_*3&(pCv1WC~hm-T!dn?sNk&2U*S(6KoLNzn|K z^+Fw+Ly#2Ba9JNU1WC~hm-TfWn?sNk z&2U-Y(6KoLNzn|K^-Ud{Ly#2Ba9Q8du{i`u(F~XMZ5^9KkQB{uS>MsIIRr`3443s? z9h*at6wPp1-_x-<1WC~hm-T%en?sNk&2U*i(6KoLNzn|K^+O$-Ly#2Ba9Kanu{i`u z(F~XMV;!4AkQB{uSwGRSIRr`3443s&9h*at6wPp1Khv=}1WC~hm-TZUn?sNk&2U-2 z(6KoLNzn|K^-CR_Ly#2Ba9O|7u{i`u(F~XMYaN?IkQB{uS-;V-IRr`3443s=9h*at z6wPp1ztgcf1WC~hm-Txcn?sNk&2U+N(6KoLNzn|K^+z3>Ly#2Ba9MxSu{i`u(F~XM zXC0eEkQB{uS%1;7IRr`3443s+9h*at6wPp1f77u!1WC~hm-TlYn?sNk&2U-&(6KoL zNzn|K^-mp}Ly#2Ba9RJ-u{i`u(F~XMZylRMkQB{uS^v?oIRr`3443slUw>kA2$G^1 zF6%)$HisZ7n&Gk@tYdQslA;+d>mfQehaf4M;j$j8V{-_Sq8TphVLCR4ASs&RvL3Eu za|n{687}J)IyQ$ODVpK39;st<2$G^1F6&V`HisZ7n&Gk@tz&ZtlA;+d>oGbuhaf4M z;j$j9V{-_Sq8TphaXL1KASs&RvL3Hva|n{687}JyIyQ$ODVpK3o~UDU2$G^1F6&7; zHisZ7n&GmZtYdQslA;+d>nS=mhaf4M;j*5pV{-_Sq8TphX*xECASs&RvYxJEa|n{6 z87}J?IyQ$ODVpK3o~dJV2$G^1F6&u3HisZ7n&GmZtz&ZtlA;+d>p40$haf4M;j*5q zV{-_Sq8TpBme&WcIRr`3*lulJr~6+W{w-`?r{n)m(F~XMJRO@ukQB{uSM;OIRr`3443r-9h*at6wPp1Kh&`~ z1WC~hm-QnZn?sNk&2U*i*0DJRNzn|K^%EVNLy#2Ba9Kaqu{i`u(F~XMGaZ{lkQB{u zSwGjYIRr`3443r_9h*at6wPp1ztpig1WC~hm-Q9h*at6wPp1f7G!#1WC~h zm-Qzdn?sNk&2U+N*0DJRNzn|K^%otRLy#2Ba9MxVu{i`u(F~XMHyxWpkQB{uS%25D zIRr`3443r}9h*at6wPp1|J1QL1WC~hm-R0ln?sNk&2U-&*0DJRNzn|K^&cIZLy#2B za9I!ZrFJ%lASs&RvL2*ka|n{687}L=IyQ$ODVpK39-?D&2$G^1F6*H>HisZ7n&Gk@ zrekvmlA;+d>)|>!haf4M;j$i~V{-_Sq8TphkvcYqASs&RvL2;la|n{687}M5IyQ$O zDVpK39;0J(2$G^1F6*&6HisZ7n&Gk@r(<&nlA;+d>+w1^haf4M;j*5fV{-_Sq8Tph zi8?liASs&RvYw=4a|n{687}L|IyQ$ODVpK3o}y!O2$G^1F6*f}HisZ7n&GmZrekvm zlA;+d>*+c+haf4M;j*5gV{-_Sq8TphnL0LyASs&RvYw@5a|n{687}MDIyQ$ODVpK3 zo}*)P2$G^1F6+5EHisZ7n&GnkN5|$6Bt|2^$FT-Nh+Yz{$E zG{a>*U&rPUBt=S z4na~h!)5(Y$L0_uMKfI1k92GfK~glsW&K#k<`5)BGhEhBbZibmQZ&P5{Zz;15F|x2 zT-MKYYz{$EG{a^6T*u}RBtvK~glsW&K&l<`5)BGhEhRbZibmQZ&P5{Z+^25F|x2T-M)o zYz{$EG{a^6UB~7SBt%lrUhaf4M;j$j0V{-_Sq8Tph zp*l8)ASs&RvL2>ma|n{687}MLIyQ$ODVpK39-(7%2$G^1F6)sxHisZ7n&Gk@rDJml zlA;+d>(M$khaf4M;j$j1V{-_Sq8Tphu{t(~ASs&RvL2^na|n{687}MbIyQ$ODVpK3 zo}goM2$G^1F6)UpHisZ7n&GmZq+@dklA;+d>&ZGchaf4M;j*5hV{-_Sq8TphsX8`? zASs&RvYw`6a|n{687}MTIyQ$ODVpK3o}puN2$G^1F6)^(HisZ7n&GmZrDJmllA;+d z>)ARshaf4M;j*5iV{-_Sq8TphxjHt7ASs&Rvi?WM<`5)BGhA%9Hm}p+X1{rz4sW&p zp7Fe_=jqrSf~07M%X+?!%^^sNX1J^u=-3>Bq-ciAdZCWZAxMg5xU3iH*c^hSXokyr zv5w6lNQ!2-te5E69D<~1hRb@Xj?E!Rie|X1m+9CXf~07M%X+zv%^^sNX1J_Z=-3>B zq-ciAdZmudAxMg5xU5&{*c^hSXokyrwT{gpNQ!2-tk>w+9D<~1hRb@bj?E!Rie|X1 z*Xh_Cf~07M%X+Bq-ciAdZUibAxMg5xU4tn*c^hSXokyrvyROn zNQ!2-theac9D<~1hRb@Zj?E!Rie|X1x9Qj%f~07M%X+(x%^^sNX1J_(=-3>Bq-ciA zdZ&)fAxMg5xU6^S*c^hSXokyrw~oyrNQ!2-toP{H9D<~1hRb@dj?E!Rie|X1_vzRi zf~07M%X+_#%^^sNX1J^m=-3>Bq-ciA`k;=@AxMg5xU3K9*c^hSXok!Bu#U|kNQ!2- ztdHo}9D<~1hRgb>j?E!Rie|X1kLlPPf~07M%lf#E%^^sNX1J_R=-3>Bq-ciA`lOD{ zAxMg5xU5g<*c^hSXok!Bw2sXoNQ!2-tk3A!9D<~1hRgb_j?E!Rie|X1&*|74f~07M z%lf>I%^^sNX1J^`=-3>Bq-ciA`l61_AxMg5xU4Vf*c^hSXok!BvX0FmNQ!2-tgqBq-ciA`lgP}AxMg5 zxU6sK*c^hSXok!BwvNpqNQ!2-tncX99D<~1hRgb{j?E!Rie|X1@9Eeaf~07M%lf{K z%^^sNX1J^$=-3>Bq-ciA`k{`^AxMg5xU3)P*c^hSXok!Bv5w6lNQ!2-te@!E9D<~1 zhRgb?j?E!Rie|X1pXt~ff~07M%lf&F%^^sNX1J_h=-3>Bq-ciA`lXJ|AxMg5xU664 z*c^hSXok!BwT{gpNQ!2-tl#L^9D<~1hRgb`j?E!Rie|X1-|5&Kf~07M%lf^J%^^sN zX1J_B=-3>Bq-ciA`lF7`AxMg5xU4_v*c^hSXok!BvyROnNQ!2-tiR~k9D<~1hRgb^ zj?E!Rie|X1zv=-3>Bq-ciA`lpV~AxMg5xU7Ha*c^hS zXok!Bw~oyrNQ!2-tpDiP9D<~1hRb^3nAh2=$RS9IX1J^e>DU~Cq-ciAda#boAxMg5 zxU7fh*c^hSXokyrsE*AcNQ!2-tcU5?9D<~1hRb@mj?E!Rie|X1N9fobf~07M%X*}a z%^^sNX1J_J>DU~Cq-ciAdbEzsAxMg5xU9$M*c^hSXokyrtd7kgNQ!2-tjFot9D<~1 zhWmdU-PNuJJI=7%TXHA16JK64Gvi*(%*@Qp%*@Q7J^oM8c#odrlBQ=>OgvG?Vv`ij z;WEUNbSySW(Ht&AJXyzLlN8P2GQ?AKEH+8e94#M5*vHc8POE<-$B z$6}Kd&EYb{GjuFANzoiGLp)Q*Vv`ij;WEUtbSySW(Ht&AJX^#Pf74Hc8POE<-$D$6}Kd&EYb{3v?_tNzoiGLwJMEc5CxG9lq>0 zuhZeF_J3#m#sfMQo1|zCmmyxLW3fq!=5QI}MLHInq-YM8AzrLwu}O;Na2etyIu@Ix zXbzVlUaDiUNs8uh8RBI+7MrAK4woTbu4A!Diso<`;uSg;o1|zCmmyxMW3fq!=5QI} zRXP@%q-YM8AzrOxu}O;Na2et?Iu@IxXbzVlUaMoVNs8uh8RB(17MrAK4woTbuVb-E ziso<`;te_$o1|zCmm%J$W3fq!=5QI}O*$5vq-YM8A>OQGu}O;Na2et)Iu@IxXbzVl z-l}7OTHu}O;Na2et~Iu@IxXbzVl-m7D=Ns8uh8RC697MrAK4woU`uVb-Eiso<` z;sZJso1|zCmmxl=W3fq!=5QI}Lpm0lq-YM8AwH~Qu}O;Na2etwIu@IxXbzVlKB{A} zNs8uh8RBC)7MrAK4woT5u4A!Diso<`;uAU+o1|zCmmxl>W3fq!=5QI}Q#ux#q-YM8 zAwI2Ru}O;Na2et=Iu@IxXbzVlKC5G~Ns8uh8RBy~7MrAK4woT5uVb-Eiso<`;tM(! zo1|zCmm$8WW3fq!=5QI}OF9;tq-YM8A-=3*u}O;Na2et&Iu@IxXbzVlzN%xfNs8uh z8RBa?7MrAK4woUmu4A!Diso<`;u|^^o1|zCmm$8XW3fq!=5QI}TRIk-q-YM8A-=6+ zu}O;Na2et|Iu@IxXbzVlzN=%gNs8uh8RC077MrAK4woUmuVb-Eiso<`;s-hwo1|zC zmmz+rW3fq!=5QI}M>-apq-YM8A%3i5u}O;Na2et!Iu@IxXbzVleyU@!Ns8uh8RBO; z7MrAK4woT*u4A!Diso<`;uks=o1|zCmmz+sW3fq!=5QI}S2`A(q-YM8A%3l6u}O;N za2et^Iu@IxXbzVleyd}#Ns8uh8RB<37MrAK4woT*uVb-Eiso<`;tx6&o1|zCmm&VB zW3fq!=5QI}PdXNxq-YM8A^xmmu}O;Na2et+Iu@IxXbzVl{;FfKNs8uh8RBm`7MrAK z4woVRu4A!Diso<`;vYH|o1|zCmm&VCW3fq!=5QI}Upf|>q-YM8A^xpnu}O;Na2eu1 zIu@IxXbzVl{;OlLNs8uh8RCCB7MrAK4woSwJmz&{UT3Q!NzoiGLp(&sVv`ij;WETS zbu2bX(Ht&AJWR)8lN8P2GQ`7mEH+8e94#3OYqHc8POE<-#@$6}Kd z&EYb{qjfAcNzoiGLp(;uVv`ij;WETybu2bX(Ht&AJWj`AlN8P2GQ{I`EH+8e94#1nNaHc8POE<-#?$6}Kd&EYb{lXWaMNzoiGLp(*tVv`ij;WETibu2bX z(Ht&AJWa=9lN8P2GQ`t$EH+8e94#4~j)Hc8POE<-#^$6}Kd&EYb{ zvvn*sNzoiGLp(>vVv`ij;WET?bu2bX(Ht&AJWt1BlN8P2GQ{(BEH+8e94gtzA&gzeVmbvk_6Z(gUvQ|9`^o1|zCmmyxFW3fq!=5QI}r8*Xyq-YM8Azr3qu}O;Na2ev|Iu@IxXbzVlUZG>L zNs8uh8RC^X7MrAK4woTbrDL&4iso<`;?+79o1|zCmmyxGW3fq!=5QI}wK^7?q-YM8 zAzr6ru}O;Na2ewDIu@IxXbzVl-k@W#Ns8uh8RCsP7MrAK4woU`q+_v3iso<`;>|i1 zo1|zCmm%JwW3fq!=5QI}tvVK)q-YM8A>O8Au}O;Na2ew5Iu@IxXbzVl-l1c$Ns8uh z8RDHf7MrAK4woU`rDL&4iso<`;@vtHo1|zCmm%JxW3fq!=5QI}y*d_~q-YM8A>OBB zu}O;Na2ewLIu@IxXbzVlKA>Z$V~o1|zCmm$8Q zW3fq!=5QI}t2!2&q-YM8A-<+#u}O;Na2ew3Iu@IxXbzVlzM*5WNs8uh8RDBd7MrAK z4woUmrDL&4iso<`;@dhFo1|zCmm$8RW3fq!=5QI}yE+z|q-YM8A-<<$u}O;Na2ewJ zIu@IxXbzVlexPHqNs8uh8RCaJ7MrAK4woT*q+_v3iso<`;>S7`o1|zCmmz+lW3fq! z=5QI}r#cp!q-YM8A%3P~u}O;Na2ev~Iu@IxXbzVlexYNrNs8uh8RC~Z7MrAK4woT* zrDL&4iso<`;@3JBo1|zCmmz+mW3fq!=5QI}w>lP^q-YM8A%3T0u}O;Na2ewFIu@Ix zXbzVl{-9&ANs8uh8RCyR7MrAK4woVRq+_v3iso<`;?Fu3o1|zCmm&V5W3fq!=5QI} zuR0c+q-YM8A^xUgu}O;Na2ew7Iu@IxXbzVl{-I;BNs8uh8RDNh7MrAK4woVRrDL&4 ziso<`;@>(Jo1|zCmm&V6W3fq!=5QI}zd9D1q-YM8A^xXhu}O;Na2evk@xX&vY?7im zT!wgvj>RS^n!{y?hw4~tlA<|WhIp8c#U?45!)1tv>sV}(qB&fKc!Z9{CMlZ3Wr#=W zSZtD_Ib4Q#l#azFDVoD&h)3&KY?7imT!wgzj>RS^n!{y?$Ld&YlA<|WhIpKg#U?45 z!)1ua>sV}(qB&fKc!G|_CMlZ3Wr!#0SZtD_Ib4Q#l8(hDDVoD&h$rhRS^n!{y?r|MX2lA<|WhIpEe#U?45!)1u4>sV}(qB&fKc!rL}CMlZ3Wr%0$SZtD_ zIb4Q#mX5_HDVoD&h-d3qY?7imT!wg#j>RS^n!{y?=jvE&lA<|WhIpQi#U?45!)1u) z>sV}(qB&fKc!7?^CMlZ3Wr+Vz$HI2&2W-rFz%85)__F^2Zwo)*KM)Uisy*=k&VyKN zlA<|WhIpZl#U?45!)1sU=~!%%qB&fKc(IPfCMlZ3Wr&yPSZtD_Ib4Q#sgA`aDVoD& zh?nVDY?7imT!whLj>RS^n!{y?SLj%5lA<|WhIplp#U?45!)1t9=~!%%qB&fKc(snj zCMlZ3Wr)}4SZtD_Ib4Q#t&YVeDVoD&h}Y>@Y?7imT!whPj>RS^n!{y?H|SVwlA<|W zhIpfn#U?45!)1s!=~!%%qB&fKc(abhCMlZ3Wr(-vSZtD_Ib4Q#tB%DcDVoD&h_~rj zY?7imT!whNj>RS^n!{y?cj#DblA<|WhIprr#U?45!)1tf=~!%%qB&fKc(;zlCMlZ3 zWr+9aSZtD_Ib4Q#ua3ngDVoD&i1+DOY?7imT!whRj>RS^n!{y?59nBIlA<|WhWMb4 z#U?45!)1sM=~!%%qB&fK_^^(}CMlZ3Wr&aHSZtD_Ib4SLsE)-ZDVoD&h>z)5Y?7im zT!#3#j>RS^n!{y?Pv}@|lA<|WhWMn8#U?45!)1t1=~!%%qB&fK__U72CMlZ3Wr)w{ zSZtD_Ib4SLtd7MdDVoD&h|lR*Y?7imT!#3(j>RS^n!{y?FX&iolA<|WhWMh6#U?45 z!)1ss=~!%%qB&fK__B`0CMlZ3Wr(lnSZtD_Ib4SLs*c4bDVoD&h_C5bY?7imT!#3% zj>RS^n!{y?Z|GQTlA<|WhWMtA#U?45!)1tX=~!%%qB&fK__mJ4CMlZ3Wr*+SSZtD_ zIb4SLu8zefDVoD&i0|oGY?7imT!#3*j>RS^n!{y?ALv+YlA<|WhWMe5#U?45!)1sc z=~!%%qB&fK__2<~CMlZ3Wr&~XSZtD_Ib4SLsgA`aDVoD&h@a_LY?7imT!#3$j>RS^ zn!{y?U+7qDlA<|WhWMq9#U?45!)1tH=~!%%qB&fK__dD3CMlZ3Wr*MCSZtD_Ib4SL zt&YVeDVoD&h~Md0Y?7imT!#3)j>RS^n!{y?Kj>I&lA<|WhWMk7#U?45!)1s+=~!%% zqB&fK__L11CMlZ3Wr)A%SZtD_Ib4SLtB%DcDVoD&h`;GrY?7imT!#3&j>RS^n!{y? zf9P0jlA<|WhWMwB#U?45!)1tn=~!%%qB&fK__vP5CMlZ3Wr+XiSZtD_Ib4SLua3ng zDVoD&i2vzWY?7imT!wh?gUst5WM20m^STF_*V(E_bGQug5FLw6QZ$Fl5D(R{*d#@B zxD4?y9g9s;G>6L&57)8SBt>($4DkpZi%n8AhszL;)UntkMRT|e@hBaOO;R+6%Mg#& zvDhR6L&kJqu-Bt>($4DkdVi%n8A zhszL8)UntkMRT|e@gyCKO;R+6%Mef2vDhR6L&PuH>7Bt>($4Dk#di%n8AhszMp)UntkMRT|e@hlySO;R+6%Mj1jvDhR< zbGQug936{IQZ$Fl5YN@I*d#@BxD4?;9g9s;G>6L&&)2coBt>($4DkXTi%n8AhszM& zntKq7jV;*bbvoPtU|y%g)9?Sz^1Dfj=5QI}g*q0Sq-YM8Azq|ou}O;Na2evoIu@Ix zXbzVlUZP{MNs8uh8RDfn7MrAK4woTbrem>5iso<`;^jIPo1|zCmmyxEW3fq!=5QI} zl{yxiq-YM8Azr0pu}O;Na2ev&Iu@IxXbzVlUZZ2NNs8uh8RE4%7MrAK4woTbr(>~6 ziso<`;`KTfo1|zCmm%JuW3fq!=5QI}jXD;aq-YM8A>O28u}O;Na2evwIu@IxXbzVl z-lAi%Ns8uh8RD%v7MrAK4woU`rem>5iso<`;_W&Xo1|zCmm%JvW3fq!=5QI}ojMkq zq-YM8A>O59u}O;Na2ev=Iu@IxXbzVl-lJo&Ns8uh8RES<7MrAK4woU`r(>~6iso<` z;{7@no1|zCmmxl&W3fq!=5QI}gE|(Qq-YM8AwHyIu}O;Na2evmIu@IxXbzVlKB8l> zNs8uh8RDZl7MrAK4woT5rem>5iso<`;^R6No1|zCmmxl(W3fq!=5QI}lR6fgq-YM8 zAwH#Ju}O;Na2ev$Iu@IxXbzVlKBHr?Ns8uh8RD}#7MrAK4woT5r(>~6iso<`;`2Hd zo1|zCmm$8OW3fq!=5QI}i#isYq-YM8A-<$zu}O;Na2evuIu@IxXbzVlzM^BXNs8uh z8RDxt7MrAK4woUmrem>5iso<`;_EsVo1|zCmm$8PW3fq!=5QI}n>rSoq-YM8A-<(! zu}O;Na2ev;Iu@IxXbzVlzN2HYNs8uh8REM-7MrAK4woUmr(>~6iso<`;`=%lo1|zC zmmz+jW3fq!=5QI}hdLIUq-YM8A%3J|u}O;Na2evqIu@IxXbzVlexhTsNs8uh8RDlp z7MrAK4woT*rem>5iso<`;^#URo1|zCmmz+kW3fq!=5QI}mpT@kq-YM8A%3M}u}O;N za2ev)Iu@IxXbzVlexqZtNs8uh8REA(7MrAK4woT*r(>~6iso<`;`cfho1|zCmm&V3 zW3fq!=5QI}k2)5cq-YM8A^xOeu}O;Na2evyIu@IxXbzVl{-R^CNs8uh8RD-x7MrAK z4woVRrem>5iso<`;_o^Zo1|zCmm&V4W3fq!=5QI}pE?$sq-YM8A^xRfu}O;Na2ev? zIu@IxXbzVl{-a~DNs8uh8REY>7MrAK4woVRr(>~6iso<`;=%r+WwA+$=5QI}AvzYD zq-YM8As(t@u}O;Na2euZIu@IxXbzVl9Fdo1|zCmm!|4W3fq!=5QI}DLNLLq-YM8 zA)cyZu}O;Na2euhIu@IxXbzVlo~~oDNs8uh8R8i_7MrAK4woUGsbjH8iso<`;#oQt zo1|zCmm!|5W3fq!=5QI}IXV`bq-YM8A)c#au}O;Na2euxIu@IxXbzVlp08uENs8uh z8R7*x7MrAK4woT(;rbvJo5U7u^Ew@F05Gr9J)q?8QZ$Fl5HHoS*d#@BxD4?!9g9s;G>6L&FW0fyBt>($ z4Dkvbi%n8AhszMJ)UntkMRT|e@hTmQO;R+6%Mh>DvDhR6L&uh+5IBt>($4DkjXi%n8AhszLe)UntkMRT|e@g^OMO;R+6 z%MfqYvDhR6L&Z`ZNdBt>($4Dk*f zi%n8AhszM})UntkMRT|e@h%;UO;R+6%MkC@vDhR6L&@7J-|Bt>($4DkUSi%n8AhszKj)UntkMRT|e@gW_HO;R+6%Mc&d zvDhR6L&AJ?(iBt>($4Dksai%n8A zhszM3)UntkMRT|e@hKgPO;R+6%MhQ|vDhR6L&pVzV2Bt>($4DkgWi%n8AhszLO)UntkMRT|e@g*ILO;R+6%Mf4IvDhR< zbGQug6&;IBQZ$Fl5MR}?*d#@BxD4?%9g9s;G>6L&U)QnNBt>($4Dk&ei%n8AhszM( z)UntkMRT|e@hu&TO;R+6%MjnzvDhR6L&-`BC&Bt>($4DkaUi%n8AhszK@)UntkMRT|e@gp6JO;R+6%Md@-vDhR6L&Ki9F?Bt>($4Dkyci%n8AhszMZ)Untk zMRT|e@hcsRO;R+6%MicTvDhR6L& zzt^$YBt>($4DkmYi%n8AhszLu)UntkMRT|e@h2UNO;R+6%MgFovDhR6L&f7h|tBt>($4Dk;gi%n8AhszNE)UntkMRT|e z@h=^VO;R+6%Mkz8vDhR9g9s;G>6L&5BBy6 zi%n8AhszKT(XrShMRT|e@lYL$O;R+6%McIKvDhR6L&kJ7Q&Bt>($4Do0ki%n8AhszL;(XrShMRT|e@mL*;O;R+6%Mg## zvDhR6L&Ptvj2Bt>($4Dn6L&&(g8jBt>($4DoCoi%n8AhszMp(XrShMRT|e@mw8?O;R+6%Mj1gvDhR< zbGQugd>xBTQZ$Fl5HHZN*d#@BxD4Sox(Bh?B!w;5=5;#U0AOCH`@cz@&Pj^qa2eu- zIu@IxXbzVlUZi8ONs8uh8REq{7MrAK4woTbqGPd1iso<`;-xwko1|zCmmyxJW3fq! z=5QI}N>4u}O;Na2eu_Iu@Ix zXbzVl-lSu(Ns8uh8RE@47MrAK4woU`qGPd1iso<`;;lLso1|zCmm%J!W3fq!=5QI} z?K&2lq-YM8A>N^5u}O;Na2evAIu@IxXbzVl-lb!)Ns8uh8RFeK7MrAK4woU`qhqm2 ziso<`;=MW+o1|zCmm%J#W3fq!=5QI}{W=z#q-YM8AwHmEu}O;Na2eu*Iu@IxXbzVl zKBQx@Ns8uh8REk_7MrAK4woT5qGPd1iso<`;-fkio1|zCmmxl;W3fq!=5QI}<2n|b zq-YM8AwHpFu}O;Na2ev0Iu@IxXbzVlKBZ%^Ns8uh8RFAA7MrAK4woT5qhqm2iso<` z;pB*jq-YM8 zA-ZKnq-YM8A^xFbu}O;N za2evCIu@IxXbzVl{-tBFNs8uh8RFkM7MrAK4woVRqhqm2iso<`;=ei;o1|zCmm&VA zW3fq!=5QI}!M+q@u}O;Na2etuIu@IxXbzVl9;#!pNs8uh8RB6&7MrAK4woSwu4A!D ziso<`;t@I)o1|zCmmwahW3fq!=5QI}Q92fzq-YM8As($`u}O;Na2et;Iu@IxXbzVl z9;;)qNs8uh8RBs|7MrAK4woSwuVb-Eiso<`;t4tyo1|zCmm!|0W3fq!=5QI}Njesr zq-YM8A)c&bu}O;Na2et$Iu@IxXbzVlo~mQ9Ns8uh8RBU=7MrAK4woUGu4A!Diso<` z;u$&?o1|zCmm!|1W3fq!=5QI}SvnS*q-YM8A)c*cu}O;Na2et`Iu@IxXbzVlo~vWA zNs8uh8RB_57MrAK4woUGuVb-Eiso<`;srVuo1|zCmmzG9co2(CQZ%+;o7d@Z1Auv* z4o|=TJLR`IT!wg|j>RS^n!{y?7wK4RlA<|WhIp}##U?45!)1t<=vZu$qB&fKc&U!X zCMlZ3Wr&yQSZtD_Ib4Q#xsJsqDVoD&h*#)XY?7imT!wh1j>RS^n!{y?SLs-6lA<|W zhIqA(#U?45!)1uq=vZu$qB&fKc&(1bCMlZ3Wr)}5SZtD_Ib4Q#y^h5uDVoD&h&Sk1 zY?7imT!wg~j>RS^n!{y?H|bbxlA<|WhIq4%#U?45!)1uK=vZu$qB&fKc&m=ZCMlZ3 zWr(-wSZtD_Ib4Q#yN<;sDVoD&hRS^n!{y?cj;JclA<|WhIqG* z#U?45!)1u~=vZu$qB&fKc(0DdCMlZ3Wr+9bSZtD_Ib4Q#zmCNwDVoD&h!5ykY?7im zT!#3dj>RS^n!{y?59wHJlA<|WhWN0K#U?45!)1t%=vZu$qB&fK_^6J>CMlZ3Wr&aI zSZtD_Ib4SLxQ@jpDVoD&h)?KPY?7imT!#3hj>RS^n!{y?Pw7}}lA<|WhWNCO#U?45 z!)1ui=vZu$qB&fK_^gh_CMlZ3Wr)w|SZtD_Ib4SLypF{tDVoFo&(S?CQMe?F8hxeg zLgMk-wz>U+jUVYbfk@JtrW{A)0SZofLq-citf{w-Ja7l`0h%f3` zYz~*CXomQbj>YD1Ns4BOFY8!r4ws~8hWLt(#pZBHie`wf>R4YD1Ns4BOZ|hiW4ws~8hWL(- z#pZBHie`xK>R4YD1Ns4BOAM03b4ws~8hWLq&#pZBHie`wP>R4YD1Ns4BOU+Y+G4ws~8hWL$+#pZBH zie`x4>R4YD1Ns4BOKkHa*4ws~8hWLw)#pZBHie`wv>R4Yz~*CXomQgj>YD1Ns4BOf9qIm4ws~8hWL+;#pZBHie`xa z>R4pePa7l`0h==M}Yz~*CXoh&0j>YD1Ns4BOhwE5u z4ws~8hIoXI#pZBHie`vM>R4YD1Ns4BO$Lm;Z4ws~8hIoRG#pZBHie`u>>R4YD1Ns4BOr|Vd34ws~8 zhIodK#pZBHie`vs>R4YD1Ns4BO=j&K(4ws~8hIoOF#pZBHie?B~ULV9_bGRghE!gIDy8oxc zSHOWIu{m6lq8Z{HIu@J5B`KOA-l=1;Ib4#W8RA_! z7MsH*DVibPtz)q{T#}+0;ypSRo5Lk3njzk+W3f40lA;;neL5DK!zC%2A>OZJu{m6l zq8Z`?Iu@J5B`KOAKB!}{Ib4#W8RA1a7MsH*DViZZtYfh`T#}+0;v+g1o5Lk3njt=_ zW3f40lA;;nV>%X_!zC%2AwI5Su{m6lq8Z{7Iu@J5B`KOAKB;4|Ib4#W8RAnq7MsH* zDViZZtz)q{T#}+0;xjrHo5Lk3njt=`W3f40lA;;nb2=8A!zC%2AwI8Tu{m6lq8Z`~ zIu@J5B`KOAzNlldIb4#W8RAPi7MsH*DVia^tYfh`T#}+0;ww59o5Lk3njyZbW3f40 zlA;;nYdRL2!zC%2A-=9-u{m6lq8Z{FIu@J5B`KOAzNureIb4#W8RAHjwt1ZnF94X=>2Uk~-zmS%5D(~BYz~*CXoh&9j>YD1Ns4BO7wK4R4ws~8hIp}# z#pZBHie`wH=vZtHm!xQhc&U!X=5R@hW{8*RSZofLq-chCxsJu=a7l`0h*#)XYz~*C zXoh&Dj>YD1Ns4BOSLs-64ws~8hIqA(#pZBHie`w{=vZtHm!xQhc&(1b=5R@hW{B76 zSZofLq-chCy^h7^a7l`0h&Sk1Yz~*CXoh&Bj>YD1Ns4BOH|bbx4ws~8hIq4%#pZBH zie`wn=vZtHm!xQhc&m=Z=5R@hW{9`xSZofLq-chCyN<=?a7l`0hYD1Ns4BOcj;Jc4ws~8hIqG*#pZBHie`xS=vZtHm!xQhc(0Dd=5R@hW{CIcSZofL zq-chCzmCP`a7l`0h!5ykYz~*CXomQpj>YD1Ns4BO59wHJ4ws~8hWN0K#pZBHie`w9 z=vZtHm!xQh_^6J>=5R@hW{8jJSZofLq-citxQ@lYD1 zNs4BOPw7}}4ws~8hWNCO#pZBHie`w<=vZtHm!xQh_^gh_=5R@hW{A(}SZofLq-cit zypF}@a7l`0h%e|^Yz~*CXomQrj>YD1Ns4BOFX>op4ws~8hWN6M#pZBHie`wf=vZtH zm!xQh_^OV@=5R@hW{9upSZofLq-citx{k%>a7l`0h;QgvYz~*CXomQvj>YD1Ns4BO zZ|PWU4ws~8hWNIQ#pZBHie`xK=vZtHm!xQh_^yt{=5R@hW{B_USZofLq-citzK+G_ za7l`0h#%-!Yz~*CXomQqj>YD1Ns4BOAL&?Z4ws~8hWN3L#pZBHie`wP=vZtHm!xQh z_^FP?=5R@hW{98ZSZofLq-citxsJu=a7l`0h+pVfYz~*CXomQuj>YD1Ns4BOU+GwE z4ws~8hWNFP#pZBHie`x4=vZtHm!xQh_^pn`=5R@hW{BVESZofLq-city^h7^a7l`0 zh(G99Yz~*CXomQsj>YD1Ns4BOKj~O(4ws~8hWN9N#pZBHie`wv=vZtHm!xQh_^Xb^ z=5R@hW{AJ(SZofLq-cityN<=?a7l`0h=1rYD1Ns4BOf9Y6k4ws~8 zhWNLR#pZBHie`xa=vZtHm!xQh_^*z|=5R@hW{3ydmdIjrxFkh0#6xr}Hit`6G($X8 z$6|B1BtjWhf7j4Lp)!{Vsp48MKi<;bSyT9 zOHwpL{Ev>s=5R@hX0Qd@yiSJ~0L<%jxc&a`wBI2f(6QJYE=kc0@j@Mo&Eb+1%@8lr zvDh3gNzn}PVjYXk;gS^15HHcO*c>iN(G2lY9gEH3k`&DlFVnHu94<-G4DoUui_PJZ z6wMH?(6QJYE=kc0@k$+w&Eb+1%@D8BvDh3gNzn}PY8{Ks;gS^15UiN(G2lg z9gEH3k`&DluhX&E94<-G4Dos$i_PJZ6wMHC(6QJYE=kc0@kSks&Eb+1%@A+WvDh3g zNzn}PW*v*o;gS^15O2}3*c>iN(G2lc9gEH3k`&DlZ_}~Z94<-G4Dogyi_PJZ6wMIt z(6QJYE=kc0@lG9!&Eb+1%@FU>vDh3gNzn}PZXJuw;gS^15bx2k*c>iN(G2lk9gEH3 zk`&Dl@6)l^94<-G4Do&)i_PJZ6wMGH(6QJYE=kc0@j)Gn&Eb+1%@7~bvDh3gNzn}P zVI7Oj;gS^15FgR8*c>iN(G2lX9gEH3k`&DlAJehe94<-G4DoRti_PJZ6wMHy(6QJY zE=kc0@kt$v&Eb+1%@Ci`vDh3gNzn}PX&sBr;gS^15TDVp*c>iN(G2lf9gEH3k`&Dl zpVP6}94<-G4Dop#i_PJZ6wMG{(6QJYE=kc0@kJer&Eb+1%@AMGvDh3gNzn}PWgUyn z;gS^15MR-;*c>iN(G2lb9gEH3k`&DlU(>PJ94<-G4Dodxi_PJZ6wMId(6QJYE=kc0 z@l73z&Eb+1%@E(xvDh3gNzn}PZ5@lv;gS^15Z}?U*c>iN(G2lj9gEH3k`&Dl-_xiN(G2lZ9gEH3k`&DlKhv?;94<-G4DoXvi_PJZ6wMI7(6QJYE=kc0@kiN(G2lh9gEH3k`&DlztgeU94<-G z4Dov%i_PJZ6wMHS(6QJYE=kc0@kbqt&Eb+1%@BXmvDh3gNzn}PXB~^p;gS^15P#9J z*c>iN(G2ld9gEH3k`&Dlf77wp94<-G4Dojzi_PJZ6wMI-(6QJYE=kc0@lPF#&Eb+1 z%@F_6vDh3gNzn}PZyk%x;gS^15dYD!*c>iN(G2ll9gEH3k`&Dl4{q~1+Y;FvE=kc0 z@em!0&Eb+1%@7aOvDh3gNzn}PFdd7{;gS^15D(X}*c>iN(G2kj9gEH3k`&DlkJPc) z94<-G4Dl!(i_PJZ6wMHi*0IiN(G2kf9gEH3k`&DlPt>v494<-G4Dlo#i_PJZ6wMG%*0IiN(G2kn9gEH3k`&Dl&(yKl94<-G z4Dl=-i_PJZ6wMIN*0IiN(G2kd9gEH3k`&Dl|D$8EIb4#W8NwHIwqTpr>F@%8d7Tco-~XNQ8xQDMYz~*C zXoh&9j>YD1Ns4BO7wK4R4ws~8hIp}##pZBHie`wH=vZtHm!xQhc&U!X=5R@hW{8*R zSZofLq-chCxsJu=a7l`0h*#)XYz~*CXoh&Dj>YD1Ns4BOSLs-64ws~8hIqA(#pZBH zie`w{=vZtHm!xQhc&(1b=5R@hW{B76SZofLq-chCy^h7^a7l`0h&Sk1Yz~*CXoh&B zj>YD1Ns4BOH|bbx4ws~8hIq4%#pZBHie`wn=vZtHm!xQhc&m=Z=5R@hW{9`xSZofL zq-chCyN<=?a7l`0hYD1Ns4BOcj;Jc4ws~8hIqG*#pZBHie`xS z=vZtHm!xQhc(0Dd=5R@hW{CIcSZofLq-chCzmCP`a7l`0h!5ykYz~*CXomQpj>YD1 zNs4BO59wHJ4ws~8hWN0K#pZBHie`w9=vZtHm!xQh_^6J>=5R@hW{8jJSZofLq-cit zxQ@lYD1Ns4BOPw7}}4ws~8hWNCO#pZBHie`w<=vZtH zm!xQh_^gh_=5R@hW{A(}SZofLq-citypF}@a7l`0h%e|^Yz~*CXomQrj>YD1Ns4BO zFX>op4ws~8hWN6M#pZBHie`wf=vZtHm!xQh_^OV@=5R@hW{9upSZofLq-citx{k%> za7l`0h;QgvYz~*CXomQvj>YD1Ns4BOZ|PWU4ws~8hWNIQ#pZBHie`xK=vZtHm!xQh z_^yt{=5R@hW{B_USZofLq-citzK+G_a7l`0h#%-!Yz~*CXomQqj>YD1Ns4BOAL&?Z z4ws~8hWN3L#pZBHie`wP=vZtHm!xQh_^FP?=5R@hW{98ZSZofLq-citxsJu=a7l`0 zh+pVfYz~*CXomQuj>YD1Ns4BOU+GwE4ws~8hWNFP#pZBHie`x4=vZtHm!xQh_^pn` z=5R@hW{BVESZofLq-city^h7^a7l`0h(G99Yz~*CXomQsj>YD1Ns4BOKj~O(4ws~8 zhWN9N#pZBHie`wv=vZtHm!xQh_^Xb^=5R@hW{AJ(SZofLq-cityN<=?a7l`0h=1r< zYz~*CXomQwj>YD1Ns4BOf9Y6k4ws~8hWNLR#pZBHie`xa=vZtHm!xQh_^*z|=5R@h zW{3xmdEJ=T*_O!Rk`&Dl57DvM94<-G4DnDMi_PJZ6wMG1)3MkbE=kc0@o*iB&Eb+1 z%@B{!vDh3gNzn}PNF9sK;gS^15RcNa*c>iN(G2lu9gEH3k`&DlkI}K%94<-G4DnbU zi_PJZ6wMHi)3MkbE=kc0@pv7J&Eb+1%@9w}vDh3gNzn}PL>-IG;gS^15Kq#v*c>iN z(G2lq9gEH3k`&DlPtmd194<-G4DnPQi_PJZ6wMG%)3MkbE=kc0@pK)F&Eb+1%@EJf zvDh3gNzn}POdX5O;gS^15YN)F*c>iN(G2ly9gEH3k`&Dl&(X2i94<-G4DnnYi_PJZ z6wMIN)3MkbE=kc0@q8VN&Eb+1%@8lpvDh3gNzn}PKROnh!zC%2A$&deAZ)=luhZcL z0P{K>ZomIK@qmuS=5R@hW{4N+SZofLq-chCk&eaYa7l`0h!^WvYz~*CXoh%+j>YD1 zNs4BOm+Dw-4ws~8hIpBd#pZBHie`wH>sV|Km!xQhc!iF|=5R@hW{6knSZofLq-chC zm5#;ca7l`0h*#@aYz~*CXoh%=j>YD1Ns4BO*Xmeo4ws~8hIpNh#pZBHie`w{>sV|K zm!xQhc!Q3`=5R@hW{5ZHSZofLq-chCla9saa7l`0h&St4Yz~*CXoh%;j>YD1Ns4BO zx9V7I4ws~8hIpHf#pZBHie`wn>sV|Km!xQhc!!R~=5R@hW{7v{SZofLq-chCmyX5e za7l`0hYD1Ns4BO_v%<|4ws~8hIpTj#pZBHie`xS>sV|Km!xQh z_<)YZ=5R@hW{3~!SZofLq-citkdDRXa7l`0h!5*nYz~*CXomQRj>YD1Ns4BOkLp-# z4ws~8hWMC{#pZBHie`w9>sV|Km!xQh_=Jwd=5R@hW{6MfSZofLq-citl#a#ba7l`0 zh)?TSYz~*CXomQVj>YD1Ns4BO&+1rg4ws~8hWMP0#pZBHie`w<>sV|Km!xQh_=1kb z=5R@hW{5B9SZofLq-citl8(jZa7l`0h%f6{Yz~*CXomQTj>YD1Ns4BOuj*KA4ws~8 zhWMI}#pZBHie`wf>sV|Km!xQh_=b+f=5R@hW{7XYD1Ns4BO@9J1=4ws~8hWMV2#pZBHie`xK>sV|Km!xQh_<@ea=5R@h zW{4l^SZofLq-citk&eaYa7l`0h#%`%Yz~*CXomQSj>YD1Ns4BOpXyj_4ws~8hWMF| z#pZBHie`wP>sV|Km!xQh_=S$e=5R@hW{6+vSZofLq-citm5#;ca7l`0h+peiYz~*C zXomQWj>YD1Ns4BO-|ARw4ws~8hWMS1#pZBHie`x4>sV|Km!xQh_=Aqc=5R@hW{5xP zSZofLq-citla9saa7l`0h(GICYz~*CXomQUj>YD1Ns4BOzv@_Q4ws~8hWML~#pZBH zie`wv>sV|Km!xQh_=k?g=5R@hW{7|4SZofLq-citmyX5ea7l`0h=1!?Yz~*CXomQY zj>YD1Ns4BO|LRz54ws~8hInv1@E{hO!zC%2As(V*u{m6lq8Z|$Iu@J5B`KOA9;Rcl zIb4#W8RFqO7MsH*DViZ3p<}T*T#}+0;*mNQo5Lk3njs#gW3f40lA;;n(K;5J!zC%2 zAs(Y+u{m6lq8Z|`Iu@J5B`KOA9;aimIb4#W8RGFe7MsH*DViakpkuK)T#}+0;)yyI zo5Lk3njxN~W3f40lA;;n$vPIB!zC%2A)caRu{m6lq8Z|;Iu@J5B`KOAo~C25Ib4#W z8RF?W7MsH*DViakp<}T*T#}+0;+Z-Yo5Lk3njxO0W3f40lA;;n**X@R!zC%2A)cdS zu{m6lq8Z}3Iu@J5B`KOAo~L86Ib4#W8RGdm7MsH*DViZ(pkuK)T#}+0;(v53Hit`6 zG(-G99Sd8qAFx^H0k3sF;01sOd{z8_e<~hu`#tc#=Rqtshf7j4L%dMOVsp48MKi>U zbSyT9OHwpLyjaI#bGRf$GsH`DEH;NrQZz%nRL5d-xFkh0#LILnHit`6G()^x$6|B1 zBt!bSyT9OHwpLyjsU%bGRf$GsJ6jEH;NrQZz%n zR>xvkbSyT9 zOHwpLyjjO$bGRf$GsIhTEH;NrQZz%nRmWm;xFkh0#M^W%Hit`6G()^y$6|B1Bt^bSyT9OHwpLyj#a&bGRf$GsJszEH;NrQZz%nSI1&= zxFkh0#QStCHit`6G()^!$6|B1BtQbSyT9OHwpL zd|1a~bGRf$GsH)9EH;NrQZz$+RL5d-xFkh0#K&|jHit`6G(&t`$6|B1BtwbSyT9OHwpLd|Jn1bGRf$GsI_fEH;NrQZz$+R>xvgbSyT9OHwpLd|Ah0 zbGRf$GsIVPEH;NrQZz$+RmWm;xFkh0#Mg8zHit`6G(&t{$6|B1Bt=bSyT9OHwpLd|St2bGRf$GsJgvEH;NrQZz$+SI1&=xFkh0#P@V8 zHit`6G(&t}$6|B1BtYbSyT9OHwpL{8-0gbGRf$ zGsI7HEH;NrQZz&SRL5d-xFkh0#LsjrHit`6G(-Gc$6|B1Bt&bSyT9OHwpL{94CibGRf$GsJInEH;NrQZz&SR>xvhf7j4L;O+4Vsp48MKi>obSyT9OHwpL{8`6hbGRf$GsItX zEH;NrQZz&SRmWm;xFkh0#NTu*Hit`6G(-Gd$6|B1Bt|bSyT9OHwpL{9DIjbGRf$GsJ&%EH;NrQZz&SSI1&=xFkh0#DgF7z=K$94ws~8 zhIojM#pZBHie`w1>R4YD1Ns4BON9$N@4ws~8hIovQ#pZBHie`w%>R4YD1Ns4BOC+k>j4ws~8hIopO z_5V4#s~rkMD*>agMA-(9S9f=xsk^(oySux)x0y8!SzLYBBxmP8K#&y8aJZ}|>(~TI z(F}*ndWw!skQB{uxU8q@*aS(@42R2lnvPA76wPqBtf%YP1WC~hhs%0~j!lph&2YG^ zXX@AlNzn|4%X*fMO^_7LaJZ~z>(~TI(F}*ndXA1wkQB{uxUA>u*aS(@42R2lo{mkB z6wPqBtmo_41WC~hhs*NS+ymGIUduMG)8VE7^Ew?)$^Wix50au84wv-;9h)F2n&EI+ zFVwLKlA;+7m-QkYn;*0Bkaq8SdC^%)(TASs&R za9N+#u?do*84j2AIUSoIDVpJMS)bRj36i224wv->9h)F2n&EI+U(~S)lA;+7m-Qtb zn;M;O36i224wv-<9h)F2n&EI+Kh&`alA;+7m-QnZn;DUBG(F}*ndbo~F zkQB{uxU5I$*aS(@42R2lq>fFH6wPqBtVikC1WC~hhs%1jj!lph&2YG^$LQDuNzn|4 z%X+MiO^_7LaJa0;>DUBG(F}*ndc2NJkQB{uxU47W*aS(@42R2lqK-|F6wPqBtS9N% z1WC~hhs%1hj!lph&2YG^r|8%ONzn|4%X+GgO^_7LaJa0e>DUBG(F}*ndb*BHkQB{u zxU6UB*aS(@42R2lrjAXJ6wPqBtY_)i1WC~hhs%1lj!lph&2YG^=jhl3Nzn|4%X+Sk zO^_7LaJa1J>DUBG(F}*ndcKZLkQB{uxGev0eE^#v@mjWdoennznAhq4SI7UaASs&R za9JQ7XASs&Ra9OX=u?do*84j2AN*$XZDVpJMS+CNu36i22 z4wv<69h)F2n&EI+uhFpylA;+7m-Sj5n;!VbASs&Ra9Quru?do*84j2AP92*dDVpJMS?|)Z36i224wvbQDVpJMSs&7|36i224wv;|9h)F2n&EI+AJMT1lA;+7m-SH{n;H1WASs&Ra9N+wu?do*84j2ANgbOYDVpJMS)bCe36i224wv<59h)F2 zn&EI+pV6@ilA;+7m-Sg4n;)3FJXq8SdC^?4neASs&Ra9Ll_u?do*84j2A zMIDrPaASs&Ra9Q8bu?do*84j2AO&yycDVpJMS>MvJ36i224wv<99h)F2n&EI+ z-_fxNlA;+7m-Ss8n;ZDYASs&Ra9O|5u?do*84j2AOC6gaDVpJMS-;Y;36i224wv<79h)F2n&EI+ztOP? zlA;+7m-Sm6n;836i224wv<39h)F2n&EI+f6=iClA;+7m-Sa2n;-bc zASs&Ra9RJ*u?do*84j2APaT^eDVpJMS^v_p36i224wv zU|y%gDf!=(_M#aMm-PZ2n;)UgSYq8SdC^(h^j zASs&Ra9N+$u?do*84j2A86BG-DVpJMS)bLh36i224wv;g9h)F2n&EI+pVzSolA;+7 zm-Pi5n;DVpJMS>M&M36i224wv;k9h)F2n&EI+-`BATlA;+7m-Pc3 zn;36i224wv;i9h)F2n&EI+zt^z|lA;+7m-Po7n;u?do* z84j2AA03+@DVpJMSr7CNFg8I_G{fPt9;9OvBt!CU}K~gls;j$j4V-qArGaN4K;W{=!QZ&QivL2yh6C_1594_mTIyOO4G{fPt9;IUw zBt#;gEK~gls;j$j5V-qArGaN4K@j5m^QZ&Qi zvYw!06C_1594_mLIyOO4G{fPto}^!~_6 zK~gls;j*5lV-qArGaN4K={hz+QZ&QivYw%16C_1594_mbIyOO4G{fPto~2_GBt$y5MK~gls;j*5mV-qArGaN4K`8qa1QZ&Qivb-Ge z05(BVG+xU#uhZeC0P{K>PRakSvNyxwvR!mt2K~gls;j&()V-qArGaN4K$N&IK~gls z;j&(*V-qArGaN4K^*S~|QZ&QivfiL$6C_1594_mPIyOO4G{fPt-lSs_Bt#aIAK~gls;j-SQV-qArGaN4K?K(C=QZ&QivfiO%6C_15 z94_mfIyOO4G{fPt-lby`Bt%BTQK~gls;j-SR zV-qArGaN4K{W>;5QZ&QivOb_=6C_1594_mFIyOO4G{fPtKBQw4Bt!Uh0K~gls;j%uaV-qArGaN4K<2p7$QZ&QivOb|>6C_1594_mV zIyOO4G{fPtKBZ$5Bt$5sGK~gls;j%ubV-qAr zGaN4K^Ex&`QZ&Qivc8~W6C_1594_mNIyOO4G{fPtzNBLlBt#I68K~gls;j+G_V-qArGaN4K>pC_;QZ&Qivc92X6C_1594_mdIyOO4 zG{fPtzNKRmBt$^HOK~gls;j+G`V-qArGaN4K z`#Ls3QZ&QivVNdr6C_1594_mJIyOO4G{fPtexzd)Bt!&(4K~gls;j(_FV-qArGaN4K=Q=h)QZ&QivVNgs6C_1594_mZIyOO4G{fPt zex+j*Bt$f^KK~gls;j(_GV-qArGaN4K_c}H~ zQZ&Qivi_iB6C_1594_mRIyOO4G{fPt{-k3QBt#sUCK~gls;j;dwV-qArGaN4K?>aU?QZ&Qivi_lC6C_1594_mhIyOO4G{fPt{-t9R zBtw#`-ViP1qGaN4KK{_@;QZ&QivL38s6C_15 z94_l2IyOO4G{fPt9;#y#Btk&FOK~gls;j$j7 zV-qArGaN4KQ93q3QZ&QivL3Bt6C_1594_lIIyOO4G{fPt9;;&$Btj^qGK~gls;j*5nV-qArGaN4KNjf$`QZ&QivYxDC6C_1594_lA zIyOO4G{fPto~mOLBtlr#WK~gls;j*5oV-qAr zGaN4KSvodBQZ&QivYxGD6C_1594_lQIyOO4G{fPto~vUMBtUZ>;#S2G+g>jgSCK~gls;j&(+V-qAr zGaN4KMLIS?QZ&QivRlHdSK~gls;j&(-V-qArGaN4KRXR37QZ&QivRkT?KK~gls;j-SSV-qArGaN4K zO*%F~QZ&Qivfiv?6C_1594_lEIyOO4G{fPt-l}60Btm52aK~gls;j-STV-qArGaN4KT{<>FQZ&Qivfiy@6C_1594_lUIyOO4G{fPt z-m7C1BtjOGAK~gls;j%ucV-qArGaN4KLpnA= zQZ&QivOcV16C_1594_l4IyOO4G{fPtKB{9ABtk~RQK~gls;j%udV-qArGaN4KQ#v+5QZ&QivOcY26C_1594_lKIyOO4G{fPtKC5FB zBtkB$IK~gls;j+G{V-qArGaN4KOFA||QZ&Qi zvc9Zi6C_1594_lCIyOO4G{fPtzN%vrBtl->Y zK~gls;j+G|V-qArGaN4KTRJvDQZ&Qivc9cj6C_1594_lSIyOO4G{fPtzN=#sBtjyeEK~gls;j(_HV-qArGaN4KM>;k^QZ&QivVN>% z6C_1594_l8IyOO4G{fPteyU>=BtlZpUK~gls z;j(_IV-qArGaN4KS2{L9QZ&QivVN^&6C_1594_lOIyOO4G{fPteyd{>Btkm3MK~gls;j;dyV-qArGaN4KPdYY1QZ&Qivi_`N6C_15 z94_lGIyOO4G{fPt{;FdWBtmNEcK~gls;j;dz zV-qArGaN4KUph8HQZ&Qivi_}O6C_1594_lWIyOO4G{fPt9_VIuHbGJ}!{M?Xq+=5# zMKc^O>%lrUK~gls;j$j0V-qArGaN4Kp*l7}QZ&QivL2>m6C_1594_nOIyOO4G{fPt z9-(6sBt(M$kK~gls;j$j1V-qArGaN4Ku{t(E zQZ&QivL2^n6C_1594_neIyOO4G{fPto}gnBBt&ZGcK~gls;j*5hV-qArGaN4KsX8`6QZ&QivYw`66C_1594_nWIyOO4G{fPto}ptC zBt)ARsK~gls;j*5iV-qArGaN4KxjHsMQZ&Qi zvYw}76C_1594_nmIyOO4G{fPt{zu0qNQ!1ScrDw!PKTQU%d`=-32F z(F}*ndZCU@kQB{uxU3iH*aS(@42R2lv5rlU6wPqBte5E61WC~hhs%1Yj!lph&2YG^ zm+9C9Nzn|4%X+zvO^_7LaJZ~j=-32F(F}*ndZms{kQB{uxU5&{*aS(@42R2lwT?}Y z6wPqBtk>w+1WC~hhs%1cj!lph&2YG^*Xh^IO^_7LaJZ~5=-32F(F}*n`l60akQB{u zxU4Vf*aS(@42R45vW`uV6wPqBtgq(~TI(F}*ndWeoqkQB{uxU7fj*aS(@42R2ln2t@56wPqB ztcUB^1WC~hhs%0|j!lph&2YG^N9x!FNzn|4%X*ZKO^_7LaJZ~T>(~TI(F}*ndW?=u zkQB{uxU9$O*aS(@42R2loQ_S96wPqBtjFuv1WC~hhs%0`j!lph&2YG^C+gS)Nzn|4 z%X*TIO^_7LaJZ}|>(~TI(F}*ndWw!skQB{uxU8q@*aS(@42R2lnvPA76wPqBtf%YP z1WC~hhs%0~j!lph&2YG^XX@AlNzn|4%X*fMO^_7LaJZ~z>(~TI(F}*ndXA1wkQB{u zxUA>u*aS(@42R2lo{mkB6wPqBtmo_41WC~hhs*jO9h)F2n&EKqTDEze4mSmu*XeLd z{&yYwWxYVhCP<2AI9%2Xb!>v9XokaOy-3Fv9XokaOy-LR> zNQ!1ST-K{~Y=Wd{hQnpOM#m;die@-m)@yZaf~07M!)3ir$0kUMW;k5d>ve2`q-ci2 zWxYYiCP<2AI9%2nb!>v9XokaOy-CL=NQ!1ST-KX)Y=Wd{hQnpOMaL#cie@-m)?0OK zf~07M!)3iq$0kUMW;k5d+jVS$q-ci2WxYekCP<2AI9%2{b!>v9XokaOy-UX?NQ!1S zT-LjFY=Wd{hQnpON5>{eie@-m)_Zkqf~07M!)3is$0kUMW;k5d`*m!Bq-ci2Wqm-$ zCP<2AI9%2Tb!>v9XokaOeMrY9NQ!1ST-JwmY=Wd{hQnojM8_sbie@-m)<<=0f~07M z!)1L;$0kUMW;k5d$8~Iiq-ci2Wqm@&CP<2AI9%2zb!>v9XokaOeM-kBNQ!1ST-K*` zY=Wd{hQnojM#m;die@-m)@OBWf~07M!)1L=$0kUMW;k5d=XGp?q-ci2Wqm=%CP<2A zI9%2jb!>wFtVkh?JU1nxxW@ct)W@ctouh)uJjrRCR*0I`3 zO;Q{#%@9A;vDhTV;nEE8GaZXfQXDSL5I@(k*d)c_(hTtn9g9s;94^feztpkVB*o#< z4Dl-+i%n7-F3k|X*0Iv4B*o#< z4Dlo#i%n7-F3k{6*0IG;1h#EWz+Hc4@~G()^t$6}Kdhf6cWOLQzYNpZL|L%dYSVv`hyOEbjFbSySWakw-? zyj;g(lN5(bGsG)&EH+7TxHLn&QpaMG6o*SQ#H(~HHc4@~G()^v$6}Kdhf6cWYji9& zNpZL|L%deUVv`hyOEbjlbSySWakw-?yk5s*lN5(bGsGKoEH+7TxHLn&QO9DF6o*SQ z#G7<1Hc4@~G()^u$6}Kdhf6cWTXZZoNpZL|L%dbTVv`hyOEbjVbSySWakw-?yj{m) zlN5(bGsHV|EH+7TxHLn&Q^#VH6o*SQ#JhAXHc4@~G()^w$6}Kdhf6cWdvq)|NpZL| zL%dhVVv`hyOEbj#bSySWakw-?ykEy+lN5(bGsFjUEH+7TxHLn2P{(4E6o*SQ#D{b& zHc4@~G(&t?$6}Kdhf6cWM|3PUNpZL|Lwr=nVv`hyOEbjBbSySWakw-?d|bz3lN5(b zGsGu!EH+7TxHLn2QpaMG6o*SQ#HVyDHc4@~G(&t^$6}Kdhf6cWXLKw!NpZL|Lwr`p zVv`hyOEbjhbSySWakw-?d|t<5lN5(bGsG8kEH+7TxHLn2QO9DF6o*SQ#Fum|Hc4@~ zG(&t@$6}Kdhf6cWS9B~kNpZL|Lwr@oVv`hyOEbjRbSySWakw-?d|k(4lN5(bGsHJ^ zEH+7TxHLn2Q^#VH6o*SQ#J6-THc4@~G(&t_$6}Kdhf6cWcXTW^NpZL|Lwr}qVv`hy zOEbjxbSySWakw-?d|$_6lN5(bGsF*cEH+7TxHLojP{(4E6o*SQ#E*0=Hc4@~G(-GY z$6}Kdhf6cWPjoCcNpZL|L;O_7Vv`hyOEbjJbSySWakw-?{9MOklN5(bGsG`+EH+7T zxHLojQpaMG6o*SQ#IJNLHc4@~G(-Ga$6}Kdhf6cWZ*(j+NpZL|L;P09Vv`hyOEbjp zbSySWakw-?{9eamlN5(bGsGWsEH+7TxHLojQO9DF6o*SQ#GiC5Hc4@~G(-GZ$6}Kd zhf6cWUvw-sNpZL|L;O|8Vv`hyOEbjZbSySWakw-?{9VUllN5(bGsHi1EH+7TxHLoj zQ^#VH6o*SQ#J_YbHc4@~G(-Gb$6}Kdhf6cWe{?K1NpZL|L;P3AVv`hyOEbj(bSySW zakw-?JaEkG#=OoJM3UlgX@+=^j>RS^4wq(#2kTgDlHzb_hIojM#U?2Zmu85E>R4=& z;&5q(c$kjGCMgb=W{8LDSZtEwaA}5kgpS1~DGrxrh)3#JY?9(|X@+=|j>RS^4wq(# zN9$N@lHzb_hIovQ#U?2Zmu85^>R4=&;&5q(c$|*KCMgb=W{Ah@SZtEwaA}5kf{w)| zDGrxrh$re;Y?9(|X@+=`j>RS^4wq(#C+k>jlHzb_hIopO#U?2Zmu85k>R4=&;&5q( zc$$vICMgb=W{9WjSZtEwaA}5khK|K1DGrxrh-d0pY?9(|X@+=~j>RS^4wq(#XX{vO zlHzb_hIo#S#U?2Zmu86P>R4=&;&5q(c%F{MCMgb=W{BtOSZtEwaA}5kfsVx{DGrxr zh!^UxE!(_KhnoV->vVWZ{{Is%(y`bi#o^Kn@nRi|O;Q{#%@8lqvDhTV;nEE8QXPv; zQXDSL5HHiQ*d)c_(hTu(9g9s;94^feuh6mBB*o#<4Dm`Gi%n7-F3k|H(y`bi#o^Kn z@oF85O;Q{#%@D8AvDhTV;nEE8S{;i`QXDSL5U9g9s;94^feZ_u&W zB*o#<4Dm)Ci%n7-F3k{c(y`bi#o^Kn@n#*1O;Q{#%@A+VvDhTV;nEE8Rvn8?QXDSL z5O345*d)c_(hTu-9g9s;94^fe@6fT>B*o#<4Dn7Ki%n7-F3k|{(y`bi#o^Kn@opW9 zO;Q{#%@FU=vDhTV;nEE8ULA`~QXDSL5bx8m*d)c_(hTu_9g9s;94^feAJDPbB*o#< z4Dmr7i%n7-F3k`h(y`bi#o^Kn@nIc{O;Q{#%@7~avDhTV;nEE8Q5}m-QXDSL5FgXA z*d)c_(hTu&9g9s;94^fepU|<`B*o#<4Dm@Fi%n7-F3k|1(y`bi#o^Kn@o624O;Q{# z%@Ci_vDhTV;nEE8SsjZ_QXDSL5TDbr*d)c_(hTu=9g9s;94^feU(m7GB*o#<4Dm%B zi%n7-F3k{M(y`bi#o^Kn@ns#0O;Q{#%@AMFvDhTV;nEE8RUL~>QXDSL5MR@=*d)c_ z(hTu+9g9s;94^fe-_WtxB*o#<4Dn4Ji%n7-F3k|%(y`bi#o^Kn@ogQ8O;Q{#%@E(w zvDhTV;nEE8T^)-}QXDSL5Z}|W*d)c_(hTu^9g9s;94^feKhUw*B*o#<4Dmx9i%n7- zF3k`>(y`bi#o^Kn@nao}O;Q{#%@9A)vDhTV;nEE8Qyq&2O;Q{#%@BXlvDhTV;nEE8R~?H@QXDSL5P#FL*d)c_(hTu;9g9s; z94^fe|Io46B*o#<4DnALi%n7-F3k}C(y`bi#o^Kn@oycAO;Q{#%@F_5vDhTV;nEE8 zUmc50QXDSL5dYJ$*d)c_(hTvyc+mq`Y?9(|X@+=^j>RS^4wq(#2kTgDlHzb_hIojM z#U?2Zmu85E>R4=&;&5q(c$kjGCMgb=W{8LDSZtEwaA}5kgpS1~DGrxrh)3#JY?9(| zX@+=|j>RS^4wq(#N9$N@lHzb_hIovQ#U?2Zmu85^>R4=&;&5q(c$|*KCMgb=W{Ah@ zSZtEwaA}5kf{w)|DGrxrh$re;Y?9(|X@+=`j>RS^4wq(#C+k>jlHzb_hIopO#U?2Z zmu85k>R4=&;&5q(c$$vICMgb=W{9WjSZtEwaA}5khK|K1DGrxrh-d0pY?9(|X@+=~ zj>RS^4wq(#XX{vOlHzb_hIo#S#U?2Zmu86P>R4=&;&5q(c%F{MCMgb=W{BtOSZtEw zaA}5kfsVx{DGrxrh!^Tu*p~ew8+cyiR?io?Dd0ukK7Ns3G+yK>`J(?j4`8uLio>ND z;>9`^o1{2gnjv1IW3fq!!=)MGr8*Xyq&QrfAzr3qu}O-L zNs7az8RC^X7Mr9vT$&+XrDL&4io>ND;?+79o1{2gnjv1JW3fq!!=)MGwK^7?q&Qrf zAzr6ru}O-ND;>|i1 zo1{2gnjzkzW3fq!!=)MGtvVK)q&QrfA>O8Au}O-ND;@vtHo1{2gnjzk!W3fq!!=)MGy*d_~q&QrfA>OBB zu}O-ZND;=?)?o1{2g znjt=-W3fq!!=)MGqdFFwq&QrfAwH&Ku}O-ND;?p`7o1{2gnjt=;W3fq!!=)MGvpN==q&QrfAwH*Lu}O-< zr5WP$Iu@IxI9!?`zMx~VNs7az8RCmN7Mr9vT$&-iq+_v3io>ND;>$V~o1{2gnjyZT zW3fq!!=)MGt2!2&q&QrfA-<+#u}O-ND;@dhFo1{2gnjyZUW3fq!!=)MGyE+z|q&QrfA-<<$u}O-ND;>S7`o1{2gnjwCoW3fq! z!=)MGr#cp!q&QrfA%3P~u}O-ND;@3JBo1{2gnjwCpW3fq!!=)MGw>lP^q&QrfA%3T0u}O-ND;?Fu3o1{2gnj!w8W3fq!!=)MG zuR0c+q&QrfA^xUgu}O-ND;@>(Jo1{2gnj!w9W3fq!!=)MGzd9D1q&QrfA^xXhu}O-Vv`hyOEbh%bSySWakw-?JXObHlN5(bGsM$$EH+7T zxHLmNUB_aR6o*SQ#4~g(Hc4@~G($X7$6}Kdhf6cWvve#rNpZL|Lp)o@Vv`hyOEbiC zbSySWakw-?JXgnJlN5(bGsN?BEH+7TxHLmNU&msT6o*SQ#0zvRHc4@~G()^l$6{lv zwt1ZnHwu{7>F_lD|7ZE!B*o#<4Dn(ei%n7-F3k`x(XrSh#o^Kn@lqX&O;Q{#%@8ls zvDhTV;nEE8avh6JQXDSL5U(XrSh#o^Kn@lzd(O;Q{#%@9A+vDhTV;nEE8a~+FKQXDSL z5Wmo|*d)c_(hTuS9g9s;94^feztXYTB*o#<4Do9ni%n7-F3k|X(XrSh#o^Kn@mn2> zO;Q{#%@DuSvDhTV;nEE8dmW2SQXDSL5P#6I*d)c_(hTuO9g9s;94^fef6}qoB*o#< z4Dn|ji%n7-F3k{s(XrSh#o^Kn@mC#-O;Q{#%@BXnvDhTV;nEE8cO8pOQXDSL5dYAz z*d)c_(hTuW9g9s;94^fe|I)G8B*o#<4DoLri%n7-F3k}C(XrSh#o^Kn@n0Q_O;Q{# z%@F_7vDhTV;nEE8K;J-FY?9(|X@+=^j>RS^4wq(#2kTgDlHzb_hIojM#U?2Zmu85E z>R4=&;&5q(c$kjGCMgb=W{8LDSZtEwaA}5kgpS1~DGrxrh)3#JY?9(|X@+=|j>RS^ z4wq(#N9$N@lHzb_hIovQ#U?2Zmu85^>R4=&;&5q(c$|*KCMgb=W{Ah@SZtEwaA}5k zf{w)|DGrxrh$re;Y?9(|X@+=`j>RS^4wq(#C+k>jlHzb_hIopO#U?2Zmu85k>R4=& z;&5q(c$$vICMgb=W{9WjSZtEwaA}5khK|K1DGrxrh-d0pY?9(|X@+=~j>RS^4wq(# zXX{vOlHzb_hIo#S#U?2Zmu86P>R4=&;&5q(c%F{MCMgb=W{BtOSZtEwaA}5kfsVx{ zDGrxrh!^TuY!X|w&FgfyQNX-T_aYttcQ#3JxHLn&SjS?M6o*SQ#7lH6Hc4@~G()^p z$6}Kdhf6cW%XBO@NpZL|L%dwaVv`hyOEbhPbSySWakw-?yi&(vlN5(bGsLTOEH+7T zxHLn&TE}9O6o*SQ#A|dcHc4@~G()^r$6}Kdhf6cW>vSwONpZL|L%d$cVv`hyOEbh9 zbSySWakw-?yivzulN5(bGsK&8EH+7TxHLn&S;u0N6o*SQ#9MSMHc4@~G()^q$6}Kd zhf6cW+jJ~8NpZL|L%dzbVv`hyOEbhfbSySWakw-?yi>$6}Kdhf6cW_jD{aNpZL|LwsMyVv`hyOEbg|bSySWakw-?{7}bY zlN5(bGsKT{EH+7TxHLojSjS?M6o*SQ#7}fAHc4@~G(-GU$6}Kdhf6cW&vYy{NpZL| zL;PIFVv`hyOEbhTbSySWakw-?{8GnalN5(bGsLfSEH+7TxHLojTE}9O6o*SQ#BX#g zHc4@~G(-GW$6}Kdhf6cW?{q9SNpZL|L;POHVv`hyOEbhDbSySWakw-?{87hZlN5(b zGsK^CEH+7TxHLojS;u0N6o*SQ#9wqQHc4@~G(-GV$6}Kdhf6cW-*hZCNpZL|L;PLG zVv`hyOEbhjbSySWakw-?{8PtblN5(bGsM4iEH+7TxHLojTgPIP6o*SQ#D8=wHc4@~ zG(-GX$6}Kdhf6cW|8y)iNpZL|Lp;#iA}lsZakw-?JV?i4lN5(bGsJ^+EH+7TxHLmN zM8{&26o*SQ#6xu~Hc4@~G($X0$6}Kdhf6cW!*wh+NpZL|Lp(yqVv`hyOEbhHbu2bX zakw-?JW9u6lN5(bGsL5HEH+7TxHLmNM#o~46o*SQ#A9_VHc4@~G($X2$6}Kdhf6cW z<8>@HNpZL|Lp(vpVv`hyOEbh1bu2bXakw-?JW0o5lN5(bGsKg1EH+7TxHLmNMaN>3 z6o*SQ#8Y)FHc4@~G($X1$6}Kdhf6cW({(I1NpZL|Lp(#rVv`hyOEbhXbu2bXakw-? zJWI!7lN5(bGsLrXEH+7TxHLmNN5^856o*SQ#B+5lHc4@~G($X3$6}Kdhf6cW^K~pX zNpZL|L%cx8Vv`hyOEbg^bu2bXVXL-zoenn&nAhp>H2wc4eHMpHGsKH^EH+7TxHLn& zM8{&26o*SQ#7lK7Hc4@~G()^h$6}Kdhf6cW%XKU^NpZL|L%c%AVv`hyOEbhPbu2bX zakw-?yh_JnlN5(bGsLTPEH+7TxHLn&M#o~46o*SQ#A|gdHc4@~G()^j$6}Kdhf6cW z>vb$PNpZL|L%c!9Vv`hyOEbh9bu2bXakw-?yh+DmlN5(bGsK&9EH+7TxHLn&MaN>3 z6o*SQ#9MVNHc4@~G()^i$6}Kdhf6cW+jT59NpZL|L%c)BVv`hyOEbhfbu2bXakw-? zyi3PolN5(bGsL@fEH+7TxHLn&N5^856o*SQ#CvrtHc4@~G()^k$6}Kdhf6cW`*kcf zNpZL|LwrETVv`hyOEbg=bu2bXakw-?d`QP)lN5(bGsK5=EH+7TxHLn2M8{&26o*SQ z#7A{3Hc4@~G(&t$$6}Kdhf6cW$8{_=NpZL|LwrKVVv`hyOEbhLbu2bXakw-?d`ib+ zlN5(bGsLHLEH+7TxHLn2M#o~46o*SQ#AkIZHc4@~G(&t&$6}Kdhf6cW=XESLNpZL| zLwrHUVv`hyOEbh5bu2bXakw-?d`ZV*lN5(bGsKs5EH+7TxHLn2MaN>36o*SQ#8-7J zHc4@~G(&t%$6}Kdhf6cW*L5s5NpZL|LwrNWVv`hyOEbhbbu2bXakw-?d`rh-lN5(b zGsL%bEH+7TxHLn2N5^856o*SQ#CLTpHc4@~G(&t($6}Kdhf6cW_jN2bNpZL|L;OI; zVv`hyOEbg|bu2bXakw-?{7A=QlN5(bGsKT|EH+7TxHLojM8{&26o*SQ#7}iBHc4@~ zG(-GM$6}Kdhf6cW&vh&|NpZL|L;OO=Vv`hyOEbhTbu2bXakw-?{7T1SlN5(bGsLfT zEH+7TxHLojM#o~46o*SQ#BX&hHc4@~G(-GO$6}Kdhf6cW?{zFTNpZL|L;OL36o*SQ#9wtRHc4@~G(-GN z$6}Kdhf6cW-*qfDNpZL|L;OR>Vv`hyOEbhjbu2bXakw-?{7c7TlN5(bGsM4jEH+7T zxHLojN5^856o*SQ#D8@xHc4@~G(-GP$6}Kdhf6cW1O2m$#U?2Zmu83u=~!%%;&5q( zc(9JeCMgb=W{8LASZtEwaA}5ksE)-ZDGrxrh==J|Y?9(|X@+>Xj>RS^4wq(#N9b5= zlHzb_hIpio#U?2Zmu84Z=~!%%;&5q(c(jhiCMgb=W{Ah=SZtEwaA}5ktd7MdDGrxr zh{x$zY?9(|X@+>bj>RS^4wq(#C+JvglHzb_hIpcm#U?2Zmu843=~!%%;&5q(c(RVg zCMgb=W{9WgSZtEwaA}5ks*c4bDGrzB|8aB|OBC%mq6L3R&$eXg^NN|7tNIo*Gcz+Y zGc(7_?r`K8t+59>JFFp|u4Az|B*mo};u$&?n?q7unjxO4W3f3T#ibeISvnS*LsDFt zA)c*cu{k8gr5WNmIu@HlQe2uLo~vWAIV8oU8RB_57Mnv-T$&-CuVb+}B*mo};srVu zn?q7unjv1OW3f3T#ibeIMLHInLsHnPZCb4ZFyGsO3G zEH;OvxHLojK*wTpNQz4{#1C~WHix9RG(-GI$6|9xic2%Zk990IhorbPL;OU?Vsl7} zOEbhzbu2cAq_{Lg{7lDUb4ZFyGsMqzEH;OvxHLojLdRlrNQz4{#4mL$Hix9RG(-GK z$6|9xic2%ZuXQXohorbPL;Oa^Vsl7}OEbi8bu2cAq_{Lg{7%PWb4ZFyGsN$8EH;Ov zxHLojLC0cqNQz4{#2>NQz4{ z#6xr}Hix9RG($X8$6|9xic2%Z!*nb*horbPLp)r^Vsl7}OEbhHbSyT9q_{LgJW|JE zb4ZFyGsL5GEH;OvxHLmNTE}8@NQz4{#A9?UHix9RG($XA$6|9xic2%Z<8&-GhorbP zLp)x`Vsl7}OEbh1bSyT9q_{LgJWjWhorbPLp)!{ zVsl7}OEbg^bSyT9q_{Lgyimttb4ZFyGsKH@EH;OvxY(*~UZ?vX9llaFuha3rr?@mj zJfLH-IV8oU8REq{7Mnv-T$&+XqGPc+B*mo};-xwkn?q7unjv1MW3f3T#ibeIN>4u{k8gr5WOlIu@HlQe2uL-lSu( zIV8oU8RE@47Mnv-T$&-?qGPc+B*mo};;lLsn?q7unjzk%W3f3T#ibeI?K&2lLsDFt zA>N^5u{k8gr5WO#Iu@HlQe2uL-lb!)IV8oU8RFeK7Mnv-T$&-?qhql-B*mo};=MW+ zn?q7unjzk&W3f3T#ibeI{W=z#LsDFtAwHmEu{k8gr5WObIu@HlQe2uLKBQx@IV8oU z8REk_7Mnv-T$&+1qGPc+B*mo};-fkin?q7unjt=>W3f3T#ibeI<2n|bLsDFtAwHpF zu{k8gr5WOrIu@HlQe2uLKBZ%^IV8oU8RFAA7Mnv-T$&+1qhql-B*mo};pB*jLsDFtA-ZKnLsDFtA^xFbu{k8gr5WO%Iu@Hl zQe2uL{-tBFIV8oU8RFkM7Mnv-T$&;Nqhql-B*mo};=ei;n?q7unjs$K#dH>%LsDFt zAs(z_u{k8gr5WNOIu@HlQe2uL9;#!pIV8oU8RB6&7Mnv-T$&*su4Az|B*mo};t@I) zn?q7unjs#kW3f3T#ibeIQ92fzLsDFtAs($`u{k8gr5WNeIu@HlQe2uL9;;)qIV8oU z8RBs|7Mnv-T$&*suVb+}B*mo};t4tyn?q7unjxO3W3f3T#ibeINjesrLsDFtA)c&b zu{k8gr5WNWIu@HlQe2uLo~mQ9IV8oU8RBU=7Mnv-T$&-Cu4Az|B*mo};u$&?n?q7u znjxO4W3f3T#ibeISvnS*LsDFtA)c*cu{k8gr5WNmIu@HlQe2uLo~vWAIV8oU8RB_5 z7Mnv-T$&-CuVb+}B*mo};srVun?q7unjv1OW3f3T#ibeIMLHInLsDECTeZ#Wba+v~ zyiSMP^#9KF+YIr5j>YDX6qja*7wcGT4oPuohIomN#paL{mu85U>R4YDX6qja*SL;}84oPuo zhIoyR#paL{mu869>R4L=8zPZW{B78SZoeSacPElgO0`KkQA3@h&Sq3 zYz|3rX@+={j>YDX6qja*H|tnz4oPuohIosP#paL{mu85!>R40j>YDX6qja*ck5Ve4oPuohIo&T z#paL{mu86f>R4Zaj>YDX6qja*59?TL4oPuohWLn%#paL{mu85M>R4Zej>YDX6qja*PwQB04oPuohWLz*#paL{ zmu861>R4Zc zj>YDX6qja*FY8!r4oPuohWLt(#paL{mu85s>R4Zgj>YDX6qja*Z|hiW4oPuohWL(-#paL{mu86X z>R4Zbj>YDX z6qja*AM03b4oPuohWLq&#paL{mu85c>R4Zfj>YDX6qja*U+Y+G4oPuohWL$+#paL{mu86H>R4Zdj>YDX6qja* zKkHa*4oPuohWLw)#paL{mu85+>R4Yz|3rX@>Zhj>YDX6qja*f9qIm4oPuohWL+;#paL{mu86n>R4>NQz4{#6xr}Hix9RG($X8$6|9xic2%Z!*nb*horbPLp)r^ zVsl7}OEbhHbSyT9q_{LgJW|JEb4ZFyGsL5GEH;OvxHLmNTE}8@NQz4{#A9?UHix9R zG($XA$6|9xic2%Z<8&-GhorbPLp)x`Vsl7}OEbh1bSyT9q_{LgJWjWhorbPLp)!{Vsl7}OEbg^bSyT9q_{Lgyimttb4ZFyGsKH@EH;Ov zxHN;U+U9jSyeME^r^9Xff2aKp@qmuS=8zPZW{4N-SZoeSacPEliH^nQkQA3@h?nYE zYz|3rX@+>2j>YDX6qja*m+M$;4oPuohIoaJ#paL{mu84p>R46j>YDX6qja**Xvkp4oPuohIoUH z#paL{mu84J>R44j>YDX6qja*x9eDJ4oPuohIogL#paL{mu84}>R48j>YDX6qja*_v=_}4oPuohWLPv#paL{ zmu83$>R4hjp=8zPZW{3~#SZoeSacPG5h>pePkQA3@h>z-6Yz|3rX@>Zi zj>YDX6qja*kLy@$4oPuohWLbz#paL{mu84h>R4_*t=8zPZW{6MgSZoeS zacPG5jE=?TkQA3@h|lU+Yz|3rX@>Zmj>YDX6qja*&+Axh4oPuohWLVx#paL{mu84B z>R4zvr=8zPZW{5BASZoeSacPG5ijKwRkQA3@h_C8cYz|3rX@>Zkj>YDX z6qja*uj^QB4oPuohWLh##paL{mu84>>R4Zoj>YDX6qja*@9S7>4oPuohWLSw#paL{mu83`>R4qpq=8zPZW{4l_SZoeSacPG5iH^nQkQA3@h@a|MYz|3rX@>Zjj>YDX6qja* zpX*p`4oPuohWLe!#paL{mu84x>R4u=8zPZW{6+wSZoeSacPG5jgH0U zkQA3@h~Mg1Yz|3rX@>Znj>YDX6qja*-|JXx4oPuohWLYy#paL{mu84R>R4+#s=8zPZW{5xQSZoeSacPG5i;l(SkQA3@h`;JsYz|3rX@>Zlj>YDX6qja*zw20R z4oPuohWLk$#paL{mu856>R4sV|KNpWe0c!-Y0=8zPZW{8LCSZoeSacPEl zn2yEfkQA3@h==P~Yz|3rX@+=&j>YDX6qja*N9tH?4oPuohIo{Y#paL{mu84Z>sV|K zNpWe0c#Mw4=8zPZW{Ah?SZoeSacPEloQ}ojkQA3@h{x+#Yz|3rX@+=$j>YDX6qja* zC+b*i4oPuohIo>W#paL{mu843>sV|KNpWe0c#4k2=8zPZW{9WiSZoeSacPElnvTWh zkQA3@h^OmVYz|3rX@+=)j>YDX6qja*XX;pN4oPuohIp2a#paL{mu84(>sV|KNpWe0 zc#e+6=8zPZW{BtNSZoeSacPElo{q)lkQA3@i0A8AYz|3rX@+=#j>YDX6qja*7wTAS z4oPuohIo;V#paL{mu86n(P2}Md7TblDVx{n_}??c13DI)LsDFtAzrLwu{k8gr5WNS zIu@HlQe2uLUaDiUIV8oU8RBI+7Mnv-T$&+Xu4Az|B*mo};uSg;n?q7unjv1PW3f3T z#ibeIRXP@%LsDFtAzrOxu{k8gr5WNiIu@HlQe2uLUaMoVIV8oU8RB(17Mnv-T$&+X zuVb+}B*mo};te_$n?q7unjzk(W3f3T#ibeIO*$5vLsDFtA>OQGu{k8gr5WNaIu@Hl zQe2uL-l}7OTHu{k8gr5WNqIu@HlQe2uL-m7D=IV8oU8RC697Mnv-T$&-?uVb+} zB*mo};sZJsn?q7unjt=@W3f3T#ibeILpm0lLsDFtAwH~Qu{k8gr5WNQIu@HlQe2uL zKB{A}IV8oU8RBC)7Mnv-T$&+1u4Az|B*mo};uAU+n?q7unjt=^W3f3T#ibeIQ#ux# zLsDFtAwI2Ru{k8gr5WNgIu@HlQe2uLKC5G~IV8oU8RBy~7Mnv-T$&+1uVb+}B*mo} z;tM(!n?q7unjyZZW3f3T#ibeIOF9;tLsDFtA-=3*u{k8gr5WNYIu@HlQe2uLzN%xf zIV8oU8RBa?7Mnv-T$&-iu4Az|B*mo};u|^^n?q7unjyZaW3f3T#ibeITRIk-LsDFt zA-=6+u{k8gr5WNoIu@HlQe2uLzN=%gIV8oU8RC077Mnv-T$&-iuVb+}B*mo};s-hw zn?q7unjwCuW3f3T#ibeIM>-apLsDFtA%3i5u{k8gr5WNUIu@HlQe2uLeyU@!IV8oU z8RBO;7Mnv-T$&+%u4Az|B*mo};uks=n?q7unjwCvW3f3T#ibeIS2`A(LsDFtA%3l6 zu{k8gr5WNkIu@HlQe2uLeyd}#IV8oU8RB<37Mnv-T$&+%uVb+}B*mo};tx6&n?q7u znj!wEW3f3T#ibeIPdXNxLsDFtA^xmmu{k8gr5WNcIu@HlQe2uL{;FfKIV8oU8RBm` z7Mnv-T$&;Nu4Az|B*mo};vYH|n?q7unj!wFW3f3T#ibeIUpf|>LsDFtA^xpnu{k8g zr5WNsIu@HlQe2uL{;OlLIV8oU8R9`>UN`1-wi|Ltic2%ZgLN!6horbPLp(&sVsl7} zOEbhnbu2cAq_{LgJWR)8b4ZFyGsMGnEH;OvxHLmNLdRlrNQz4{#3OYqHix9RG($W} z$6|9xic2%ZqjfAchorbPLp(;uVsl7}OEbh{bu2cAq_{LgJWj`Ab4ZFyGsNR{EH;Ov zxHLmNLC0cqNQz4{#1nNaHix9RG($W|$6|9xic2%ZlXWaMhorbPLp(*tVsl7}OEbh% zbu2cAq_{LgJWa=9b4ZFyGsM$%EH;OvxHLmNL&susNQz4{#4~j)Hix9RG($W~$6|9x zic2%Zvvn*shorbPLp(>vVsl7}OEbiCbu2cAq_{LgJWt1Bb4ZFyGsN?CEH;OvxHLn& zK*wTpNQz4{#0zySHix9RG()^d$6|9xic2%Z|LCw)+q_PP7X{4gbhu6b@5BQ-7Mnv- zT$&+XtYfh`B*mo};w3s3n?q7unjv1QW3f3T#ibeIWjYp{LsDFtAzrRyu{k8gr5WNC zIu@HlQe2uLUa4cTIV8oU8RAts7Mnv-T$&+Xtz)q{B*mo};x#%Jn?q7unjv1RW3f3T z#ibeIbvhQCLsDFtAzrUzu{k8gr5WN4Iu@HlQe2uL-l$`-IV8oU8RAVk7Mnv-T$&-? ztYfh`B*mo};w?HBn?q7unjzk*W3f3T#ibeIZ8{d4LsDFtA>OWIu{k8gr5WNKIu@Hl zQe2uL-l=1;IV8oU8RA_!7Mnv-T$&-?tz)q{B*mo};ypSRn?q7unjzk+W3f3T#ibeI zeL5DKLsDFtA>OZJu{k8gr5WM_Iu@HlQe2uLKB!}{IV8oU8RA1a7Mnv-T$&+1tYfh` zB*mo};v+g1n?q7unjt=_W3f3T#ibeIV>%X_LsDFtAwI5Su{k8gr5WNAIu@HlQe2uL zKB;4|IV8oU8RAnq7Mnv-T$&+1tz)q{B*mo};xjrHn?q7unjt=`W3f3T#ibeIb2=8A zLsDFtAwI8Tu{k8gr5WN2Iu@HlQe2uLzNlldIV8oU8RAPi7Mnv-T$&-itYfh`B*mo} z;ww59n?q7unjyZbW3f3T#ibeIYdRL2LsDFtA-=9-u{k8gr5WNIIu@HlQe2uLzNure zIV8oU8RAIu@HlQe2uLo~C25IV8oU8RF?W7Mnv-T$&-Cp<}T*B*mo};+Z-Y zn?q7unjxO0W3f3T#ibeI**X@RLsDFtA)cdSu{k8gr5WP6Iu@HlQe2uLo~L86IV8oU z8RGdm7Mnv-T$&+XpkuK)B*mo};)OaEn?q7unjv1KW3f3T#ibeIe{?Kt)qcRHo(H`C z`G6M%9`Kd&1OEAVz-{`#|DONHVsl7}OEbiabu2cAq_{LgyhO)hb4ZFyGsH`EEH;Ov zxHLn&Ovhq#NQz4{#LIOoHix9RG()^X$6|9xic2%ZD|IY3horbPL%d4IVsl7}OEbi) zbu2cAq_{Lgyhg`jb4ZFyGsJ6kEH;OvxHLn&PRC+%NQz4{#Ork|Hix9RG()^W$6|9x zic2%Z8+9x;horbPL%d1HVsl7}OEbiqbu2cAq_{LgyhX=ib4ZFyGsIhUEH;OvxHLn& zO~+z$NQz4{#M^Z&Hix9RG()^Y$6|9xic2%ZJ9R8JhorbPL%d7JVsl7}OEbi~bu2cA zq_{Lgyhq1kb4ZFyGsJs!EH;OvxHLn&Psd_&NQz4{#QSwDHix9RG(&tq$6|9xic2%Z z2X!nqhorbPLwrcbVsl7}OEbiWbu2cAq_{Lgd_>1$b4ZFyGsH)AEH;OvxHLn2Ovhq# zNQz4{#K(0kHix9RG(&ts$6|9xic2%ZCv_|~horbPLwridVsl7}OEbi$bu2cAq_{Lg zd`8D&b4ZFyGsI_gEH;OvxHLn2PRC+%NQz4{#OHM^Hix9RG(&tr$6|9xic2%Z7j-N) zhorbPLwrfcVsl7}OEbimbu2cAq_{Lgd_~7%b4ZFyGsIVQEH;Ov`2QT;(-MU-wy4op zN@r#wkJq+soVIP-wr$&W#_mduTz%K6TC@I@G{a?mO~)oUBtCO9NTGhEiUb!>t|QZ&P5eMiS8I3z_gT-JAWY=T2l zG{a?mPsb)WBt zb!>t|QZ&P5{Y1wmI3z_gT-Hx@Y=T2lG{a^6OvffTBtt|QZ&P5{YJ+oI3z_gT-I-OY=T2lG{a^6 zPRAxVBtt| zQZ&P5{YA$nI3z_gT-IN8Y=T2lG{a^6O~)oUBtt|QZ&P5{YS?pI3z_gT-JYeY=T2lG{a>*@B!v^ z4=}HLfO*{m%m@oi!67M{ z;j&(;V-p;bq8TphWjZ#&At{>SvRoqzy!67M{;j&(SvRn%Dq!67M{;j-SU zV-p;bq8TphZ8|o=At{>Svfi#^6C9GF87}J`IyS)}DVpK3-l<~~9Fn3LF6&)7Ho+k& zn&GnEtz#1$lA;+d>peO)!67M{;j-SVV-p;bq8TpheL6P5At{>Svfi&_6C9GF87}Js zIyS)}DVpK3KB!|89Fn3LF6%=&Ho+k&n&GlOtYZ@#lA;+d>mxcg!67M{;j%ueV-p;b zq8TphV>&j$At{>SvOcb36C9GF87}J+IyS)}DVpK3KB;399Fn3LF6&b|Ho+k&n&GlO ztz#1$lA;+d>oYnw!67M{;j%ufV-p;bq8Tphb2>J`At{>SvOce46C9GF87}J!IyS)} zDVpK3zNljp9Fn3LF6&D=Ho+k&n&Gm(tYZ@#lA;+d>nl1o!67M{;j+G}V-p;bq8Tph zYdSW;At{>Svc9fk6C9GF87}J^IyS)}DVpK3zNupq9Fn3LF6&!5Ho+k&n&Gm(tz#1$ zlA;+d>pMC&!67M{;j+G~V-p;bq8Tphdpb73At{>Svc9il6C9GF87}JwIyS)}DVpK3 zeyC#;9Fn3LF6&1+Ho+k&n&Gm3tYZ@#lA;+d>nA!k!67M{;j(_JV-p;bq8TphXF4{) zAt{>SvVN{(6C9GF87}J=IyS)}DVpK3eyL*<9Fn3LF6&o1Ho+k&n&Gm3tz#1$lA;+d z>o+SvVN~)6C9GF87}J&IyS)}DVpK3{-|RU z9Fn3LF6&P^Ho+k&n&GnktYZ@#lA;+d>n}Ps!67M{;j;d!V-p;bq8TphZ#p)?At{>S zvi`1P6C9GF87}J|IyS)}DVpK3{;6XV9Fn3LF6&=9Ho+k&n&Gnktz#1$lA;+d>pwa+ z!67M{;j;d#V-p;bq8Tphfqq%C2@Xlo443sF9h=~g6wPp157w~>4oT4rm-P@Go8XWX z&2U){)v*Z}-`kQB{uS0b^==Sf%I3z_g zT-M)oY=T2lG{a^6UB@OkBt* zQpYAZBt*QO71YBtf;CLsB%uWj$5LCO9NTGhEiwbZmk{QZ&P5Jzd8pI3z_gT-GymY=T2lG{a>*Q^zJa zBtjtxX1J_Z z=-32@q-ciAdZms{a7c<~xU5&{*aU~9XokyrwT?}2NQ!2-tk>w+1c#((hRb@bj!ke# zie|X1*Xh^jtxX1J_3=-32@q-ciAdZUg_a7c<~xU4tn*aU~9Xokyr zvyM%0NQ!2-theac1c#((hRb@Zj!ke#ie|X1x9QjfhooqR%X+(xO>jtxX1J_(=-32@ zq-ciAdZ&&}a7c<~xU6^S*aU~9Xokyrw~kG4NQ!2-toP{H1c#((hRb@dj!ke#ie|X1 z_vzRKhooqR%X+_#O>jtxX1J^m=-32@q-ciA`k;j!ke#ie|X1kLlP1hooqR%lf#EO>jtxX1J_R=-32@q-ciA z`lOCca7c<~xU5g<*aU~9Xok!Bw2n=1NQ!2-tk3A!1c#((hRgb_j!ke#ie|X1&*|6% zhooqR%lf>IO>jtxX1J^`=-32@q-ciA`l60aa7c<~xU4Vf*aU~9Xok!BvW`t~NQ!2- ztgqjtxX1J_x=-32@q-ciA`lgOe za7c<~xU6sK*aU~9Xok!BwvJ73NQ!2-tncX91c#((hRgb{j!ke#ie|X1@9EeChooqR z%lf{KO>jtxX1J^$=-32@q-ciA`k{_Za7c<~xU3)P*aU~9Xok!Bv5rk}NQ!2-te@!E z1c#((hRgb?j!ke#ie|X1pXt~HhooqR%lf&FO>jtxX1J_h=-32@q-ciA`lXIda7c<~ zxU664*aU~9Xok!BwT?}2NQ!2-tl#L^1c#((hRgb`j!ke#ie|X1-|5%{hooqR%lf^J zO>jtxX1J_B=-32@q-ciA`lF6ba7c<~xU4_v*aU~9Xok!BvyM%0NQ!2-tiR~k1c#(( zhRgb^j!ke#ie|X1zvjtxX1J_>=-32@q-ciA`lpUfa7c<~xU7Ha z*aU~9Xok!Bw~kG4NQ!2-tpDiP1c#((hRgb|j!ke#ie|X12l~ero8XWX&2U){(y<8+ zNzn|K^;o8XWX&2U+d(y<8+Nzn|K^=KWN;E)u}a9NMhu?Y@I(F~XMSRI?- zkQB{uS&!4P2@Xlo443tI9h=~g6wPp1PtdUm4oT4rm-R#)o8XWX&2U*y(y<8+Nzn|K z^<*8J;E)u}a9K~$u?Y@I(F~XMR2`e(kQB{uSx?ik2@Xlo443tE9h=~g6wPp1&(N_6 z4oT4rm-S2?o8XWX&2U-I(y<8+Nzn|K^=uuR;E)u}a9PjMu?Y@I(F~XMTpgR>kQB{u zS+1;E)u}a9J2@Xlo443sr9h=~g6wPp1 zZ_=>|4oT4rm-S{Ho8XWX&2U+7(Xj~*Nzn|K^;R95;E)u}a9MBDu?Y@I(F~XMb{(7G zkQB{uS?|!X2@Xlo443sz9h=~g6wPp1@6xde4oT4rm-TKPo8XWX&2U-o(Xj~*Nzn|K z^MpH z2@Xlo443sy9h=~g6wPp1-_o%O4oT4rm-THOo8XWX&2U-Y(Xj~*Nzn|K^<5pC;E)u} za9Q8eu?Y@I(F~XMeI1+NkQB{uSwGOR2@Xlo443so9h=~g6wPp1Khm)Y4oT4rm-S;E zo8XWX&2U*i(Xj~*Nzn|K^-~?2;E)u}a9Kaou?Y@I(F~XMa~+%DkQB{uS-;S+2@Xlo z443sw9h=~g6wPp1ztXV@4oT4rm-TBMo8XWX&2U-2(Xj~*Nzn|K^;;dA;E)u}a9O|8 zu?Y@I(F~XMdmWqLkQB{uS%1*62@Xlo443ss9h=~g6wPp1f6}oD4oT4rm-S~Io8XWX z&2U+N(Xj~*Nzn|K^;aF6;E)u}a9MxTu?Y@I(F~XMcO9GHkQB{uS^v7`V;E)u}a9NMgu?Y@I(F~XMNFAHtkQB{uS&!1O2@Xlo443t29h=~g6wPp1kI}IS z4oT4rm-Sd3o8XWX&2U+d)3FH-Nzn|K^>`hd;E)u}a9K~#u?Y@I(F~XML>-&pkQB{u zSx?fj2@Xlo443s}9h=~g6wPp1Ptman4oT4rm-SQ~o8XWX&2U*y)3FH-Nzn|K^>iJZ z;E)u}a9PjLu?Y@I(F~XMOdXrxkQB{uSSvRySvRy0`#!67M{;j-SOV-p;bq8Tph%{n&0At{>SvfiR&6C9GF87}LsIyS)}DVpK3-lk&{ z9Fn3LF6-?&Ho+k&n&GnEp<@#qlA;+d>zz6_!67M{;j-SPV-p;bq8Tph-8weGAt{>S zvfiU(6C9GF87}L+IyS)}DVpK3-lt;|9Fn3LF6;d|Ho+k&n&GlOpkosplA;+d>w`Kr z!67M{;j%uYV-p;bq8Tph!#Xy>At{>SvOc0?6C9GF87}LiIyS)}DVpK3KBi+69Fn3L zF6-kuHo+k&n&GlOp<@#qlA;+d>ytV*!67M{;j%uZV-p;bq8Tph(>gZ6At{>SvOc3@ z6C9GF87}LyIyS)}DVpK3KBr?79Fn3LF6;9;Ho+k&n&Gm(pkosplA;+d>x()z!67M{ z;j+G@V-p;bq8Tph%Q`l}At{>Svc95Y6C9GF87}LqIyS)}DVpK3zNTXn9Fn3LF6-+$ zHo+k&n&Gm(p<@#qlA;+d>zg_@!67M{;j+G^V-p;bq8Tph+d4MEAt{>Svc98Z6C9GF z87}L)IyS)}DVpK3zNcdo9Fn3LF6;X`Ho+k&n&Gm3pkosplA;+d>xViv!67M{;j(_D zV-p;bq8Tph$2vB_At{>SvVNjt6C9GF87}LmIyS)}DVpK3ex_p+9Fn3LF6-wyHo+k& zn&Gm3p<@#qlA;+d>z6tSvVNmu6C9GF87}L$ zIyS)}DVpK3ey3v-9Fn3LF6;L?Ho+k&n&GnkpkosplA;+d>yJ7%!67M{;j;duV-p;b zq8Tph&pI~2At{>Svi_oD6C9GF87}LuIyS)}DVpK3{-$FS9Fn3LF6-|)Ho+k&n&Gnk zp<@#qlA;+d>z_I{!67M{;j;dvV-p;bq8Tph-#RwIAt{>Svi_rE6C9GF87}L;IyS)} zDVpK39_S`?Ho+k&n&Gk@q+=5tlA;+d>%lrU!67M{;j$j0V-p;bq8Tphp*l9fAt{>S zvL2>m6C9GF87}MLIyS)}DVpK39-(6s9Fn3LF6)sxHo+k&n&Gk@rDGEulA;+d>(M$k z!67M{;j$j1V-p;bq8Tphu{t)vAt{>SvL2^n6C9GF87}MbIyS)}DVpK3o}gnB9Fn3L zF6)UpHo+k&n&GmZq+=5tlA;+d>&ZGc!67M{;j*5hV-p;bq8TphsX8{nAt{>SvYw`6 z6C9GF87}MTIyS)}DVpK3o}ptC9Fn3LF6)^(Ho+k&n&GmZrDGEulA;+d>)ARs!67M{ z;j*5iV-p;bq8TphxjHt%At{>SvYw}76C9GF87}MjIyS)}DVpK3UZ7(W9Fn3LF6)Il zHo+k&n&Gluq+=5tlA;;BzHMHo!_5Qcbvm57|66SzF6+fQHo+k&n&GluqGJ;rlA;+d z>!mt2!67M{;j&()V-p;bq8TphSvR$N&I!67M{;j&(*V-p;bq8Tph^*T1eAt{>S zvfiL$6C9GF87}LMIyS)}DVpK3-lSs_9Fn3LF6+%YHo+k&n&GnEqGJ;rlA;+d>#aIA z!67M{;j-SQV-p;bq8Tph?K(EWAt{>SvfiO%6C9GF87}LcIyS)}DVpK3-lby`9Fn3L zF6-SoHo+k&n&GnEqhk{slA;+d>%BTQ!67M{;j-SRV-p;bq8Tph{W>SvOb_= z6C9GF87}LCIyS)}DVpK3KBQw49Fn3LF6+ZOHo+k&n&GlOqGJ;rlA;+d>!Uh0!67M{ z;j%uaV-p;bq8Tph<2p9MAt{>SvOb|>6C9GF87}LSIyS)}DVpK3KBZ$59Fn3LF6+}e zHo+k&n&GlOqhk{slA;+d>$5sG!67M{;j%ubV-p;bq8Tph^Ex)cAt{>Svc8~W6C9GF z87}LKIyS)}DVpK3zNBLl9Fn3LF6+xWHo+k&n&Gm(qGJ;rlA;+d>#I68!67M{;j+G_ zV-p;bq8Tph>pC{UAt{>Svc92X6C9GF87}LaIyS)}DVpK3zNKRm9Fn3LF6-MmHo+k& zn&Gm(qhk{slA;+d>$^HO!67M{;j+G`V-p;bq8Tph`#LtkAt{>SvVNdr6C9GF87}LG zIyS)}DVpK3exzd)9Fn3LF6+lSHo+k&n&Gm3qGJ;rlA;+d>!&(4!67M{;j(_FV-p;b zq8Tph=Q=jQAt{>SvVNgs6C9GF87}LWIyS)}DVpK3ex+j*9Fn3LF6-AiHo+k&n&Gm3 zqhk{slA;+d>$f^K!67M{;j(_GV-p;bq8Tph_c}JgAt{>Svi_iB6C9GF87}LOIyS)} zDVpK3{-k3Q9Fn3LF6+-aHo+k&n&GnkqGJ;rlA;+d>#sUC!67M{;j;dwV-p;bq8Tph z?>aWYAt{>Svi_lC6C9GF87}LeIyS)}DVpK3{-t9R9Fn3LF6-YqHo+k&n&Gnkqhk{s zlA;+d>%TfS!67M{;j$j+)j~GGAt{>SvL2*k6C9GF87}L=IyS)}DVpK39-?Ct9Fn3L zF6*H>Ho+k&n&Gk@rehNvlA;+d>)|>!!67M{;j$i~V-p;bq8TphkvcZPAt{>SvL2;l z6C9GF87}M5IyS)}DVpK39;0Iu9Fn3LF6*&6Ho+k&n&Gk@r(+WwlA;+d>+w1^!67M{ z;j*5fV-p;bq8Tphi8?mHAt{>SvYw=46C9GF87}L|IyS)}DVpK3o}yzD9Fn3LF6*f} zHo+k&n&GmZrehNvlA;+d>*+c+!67M{;j*5gV-p;bq8TphnL0MXA^$%|cdsV}(Lvd+_ zc#e+6COH(BW{BtNSZtC*acPElo{q&PITV*>i0A8AY?4E9X@+=#j>RT96qja*7wTAS zl0$K6hIo;V#U?ovmu9ei+q_PPn+MG6ba?Cj-)YYwUZP{MNe;!O8RDfn7MtWyT$&+X zrem>54#lMz;^jIPo8(Yjnjv1HW3fpN#ibeIl{yxi~64#lMz;`KTfo8(YjnjzkxW3fpN#ibeI zjXD;aO28u}Kcar5WPQIu@JcP+XcJ-lAi%Ne;!O8RD%v7MtWyT$&-?rem>5 z4#lMz;_W&Xo8(YjnjzkyW3fpN#ibeIojMkqO59u}Kcar5WPgIu@JcP+XcJ z-lJo&Ne;!O8RES<7MtWyT$&-?r(>~64#lMz;{7@no8(Yjnjt=*W3fpN#ibeIgE|(Q zNe;!O8RDZl7MtWyT$&+1rem>54#lMz z;^R6No8(Yjnjt=+W3fpN#ibeIlR6fg~64#lMz;`2Hdo8(YjnjyZRW3fpN#ibeIi#isY54#lMz;_EsV zo8(YjnjyZSW3fpN#ibeIn>rSo~64#lMz;`=%lo8(YjnjwCmW3fpN#ibeIhdLIU54#lMz;^#URo8(Yj znjwCnW3fpN#ibeImpT@k~64#lMz;`cfho8(Yjnj!w6W3fpN#ibeIk2)5c54#lMz;_o^Zo8(Yjnj!w7 zW3fpN#ibeIpE?$s7MtWy zT$&;Nr(>~64#lMz;(={mXKNvw54#lMz;^8_Lo8(Yjnjs#cW3fpN#ibeIkvbNe~64#lMz;_*5bo8(Yj znjxN`W3fpN#ibeIi8>aW54#lMz;^{gTo8(YjnjxN{W3fpN#ibeInK~Am~64#lMz;`urjo8(Yjnjv1G zW3fpN#ibeIg*q0S?8awsm% z5HHoS*d&MI(hTu39g9tJC@#$qFW0fyB!}YC4Dkvbi%oJUF3k|H)UntkhvL!<@hTmQ zO>!tM%@D8FvDhSs;?fN98Xb#Gawsm%5U!tM%@A+avDhSs;?fN979ERCawsm%5O3A7 z*d&MI(hTu79g9tJC@#$qZ`ZNdB!}YC4Dk*fi%oJUF3k|{)UntkhvL!<@h%;UO>!tM z%@FU_vDhSs;?fN99vzEKawsm%5bxEo*d&MI(hTuF9g9tJC@#$q@7J-|B!}YC4DkUS zi%oJUF3k`h)UntkhvL!<@gW_HO>!tM%@7~fvDhSs;?fN95gm(7awsm%5FgdC*d&MI z(hTu29g9tJC@#$qAJ?(iB!}YC4Dksai%oJUF3k|1)UntkhvL!<@hKgPO>!tM%@Ci~ zvDhSs;?fN986AsFawsm%5TDht*d&MI(hTuA9g9tJC@#$qpVzV2B!}YC4DkgWi%oJU zF3k{M)UntkhvL!<@g*ILO>!tM%@AMKvDhSs;?fN96&;IBawsm%5MR}?*d&MI(hTu6 z9g9tJC@#$qU)QnNB!}YC4Dk&ei%oJUF3k|%)UntkhvL!<@hu&TO>!tM%@E(#vDhSs z;?fN99UY5Jawsm%5Z~3Y*d&MI(hTuE9g9tJC@#$q-`BC&B!}YC4DkaUi%oJUF3k`> z)UntkhvL!<@gp6JO>!tM%@9A!tM%@DuVvDhSs;?fN9 z8y$;Hawsm%5Wm&2*d&MI(hTuC9g9tJC@#$qzt^$YB!}YC4DkmYi%oJUF3k{s)Untk zhvL!<@h2UNO>!tM%@BXqvDhSs;?fN97afaDawsm%5P#LN*d&MI(hTu89g9tJC@#$q zf7h|tB!}YC4Dk;gi%oJUF3k}C)UntkhvL!<@h=^VO>!tM%@F_AvDhSs;?fN9A03NL zawsm%5dYP&*d&MI(hTuG9g9tJC@#$q4;=HlF|V_=kmOKYnjs#fW3fpN#ibeI!8#V3 zIu@JcP+XcJo~C25Ne;!O8RF?W7MtWyT$&-Cp<}U04#lMz;+Z-Y zo8(YjnjxO0W3fpN#ibeI**X@ROECu}Kcar5WN)Iu@JcP+XcJ-mGJ>Ne;!O z8R9KE7MtWyT$&-?s$;Q94#lMz;%zz>o8(YjnjzkOHD zu}Kcar5WN~Iu@JcP+XcJ-mPP?Ne;!O8R9)U7MtWyT$&-?t7EZA4#lMz;(a<6o8(Yj znjzk=W3fpN#ibeI13DI)4 z7MtWyT$&+1s$;Q94#lMz;$u1%o8(Yjnjt=}W3fpN#ibeI6FL@~Nu}Kca zr5WN=Iu@JcP+XcJKCNT1Ne;!O8R9cK7MtWyT$&+1t7EZA4#lMz;&VC{o8(Yjnjt=~ zW3fpN#ibeI3py5?}f`!tM%@7aL zvDhSs;?fN9U>%E1awsm%5D(F@*d&MI(hTuX9g9tJC@#$q57V*OB!}YC4DoOsi%oJU zF3k{+(6QJghvL!<@kkwuO>!tM%@B{$vDhSs;?fN9XdR19awsm%5RcKZ*d&MI(hTuf z9g9tJC@#$qkJGW(B!}YC4Dom!i%oJUF3k{6(6QJghvL!<@kAYqO>!tM%@9x0vDhSs z;?fN9WF3o5awsm%5Kqyu*d&MI(hTub9g9tJC@#$qPt&p3B!}YC4Doawi%oJUF3k|n z(6QJghvL!<@k||yO>!tM%@EJhvDhSs;?fN9Y#obDawsm%5YN%E*d&MI(hTuj9g9tJ zC@#$q&(pEkB!}YC4Doy&i%oJUF3k`x(6QJghvL!<@j@MoO>!tM%@8lrvDhSs;?fN9 zVjTh?nVD zY?4E9X@+>Yj>RT96qja*SLj%5l0$K6hIplp#U?ovmu84p=~!%%Lvd+_c(snjCOH(B zW{B75SZtC*acPElt&YVeITV*>h}Y>@Y?4E9X@+>cj>RT96qja*H|SVwl0$K6hIpfn z#U?ovmu84J=~!%%Lvd+_c(abhCOH(BW{9`wSZtC*acPEltB%DcITV*>h_~rjY?4E9 zX@+>aj>RT96qja*cj#Dbl0$K6hIprr#U?ovmu84}=~!%%Lvd+_c(;zlCOH(BW{CIb zSZtC*acPElua3ngITV*>i1+DOY?4E9X@+>ej>RT96qja*59nBIl0$K6hWMb4#U?ov zmu83$=~!%%Lvd+__^^(}COH(BW{8jISZtC*acPG5sE)-ZITV*>h>z)5Y?4E9X@>Z? zj>RT96qja*Pv}@|l0$K6hWMn8#U?ovmu84h=~!%%Lvd+___U72COH(BW{A(|SZtC* zacPG5td7MdITV*>h|lR*Y?4E9X@>Z`j>RT96qja*FX&iol0$K6hWMh6#U?ovmu84B z=~!%%Lvd+___B`0COH(BW{9uoSZtC*acPG5s*c4bITV*>h_C5bY?4E9X@>Z^j>RT9 z6qja*Z|GQTl0$K6hWMtA#U?ovmu84>=~!%%Lvd+___mJ4COH(BW{B_TSZtC*acPG5 zu8zefITV*>i0|oGY?4E9X@>Z|j>RT96qja*ALv+Yl0$K6hWMe5#U?ovmu83`=~!%% zLvd+___2<~COH(BW{98YSZtC*acPG5sgA`aITV*>h@a_LY?4E9X@>Z@j>RT96qja* zU+7qDl0$K6hWMq9#U?ovmu84x=~!%%Lvd+___dD3COH(BW{BVDSZtC*acPG5t&YVe zITV*>h~Md0Y?4E9X@>Z{j>RT96qja*Kj>I&l0$K6hWMk7#U?ovmu84R=~!%%Lvd+_ z__L11COH(BW{AJ&SZtC*acPG5tB%DcITV*>h`;GrY?4E9X@>Z_j>RT96qja*f9P0j zl0$K6hWMwB#U?ovmu856=~!%%Lvd+___vP5COH(BW{CgjSZtC*acPG5ua3ngITV*> zi2vzWY?4E9X@+><1I+6lU|#nC^STF^*V$S~acPElkdDPBITV*>hzILfY?4E9X@+=+ zj>RT96qja*hw4~tl0$K6hIp8c#U?ovmu85E>sV}(Lvd+_c!Z9{COH(BW{5}XSZtC* zacPEll#azFITV*>h)3&KY?4E9X@+==j>RT96qja*$Ld&Yl0$K6hIpKg#U?ovmu85^ z>sV}(Lvd+_c!G|_COH(BW{4;1SZtC*acPEll8(hDITV*>h$rhRT9 z6qja*r|MX2l0$K6hIpEe#U?ovmu85k>sV}(Lvd+_c!rL}COH(BW{79%SZtC*acPEl zmX5_HITV*>h-d3qY?4E9X@+=?j>RT96qja*=jvE&l0$K6hIpQi#U?ovmu86P>sV}( zLvd+_c!7?^COH(BW{4N+SZtC*acPElk&eYCITV*>h!^WvY;5T^uhZd%0`oc@-p>Db zmggop6qja*m+Dw-l0$K6hIpBd#U?ovmu85U>sV}(Lvd+_c!iF|COH(BW{6knSZtC* zacPElm5#+GITV*>h*#@aY?4E9X@+=>j>RT96qja**Xmeol0$K6hIpNh#U?ovmu869 z>sV}(Lvd+_c!Q3`COH(BW{5ZHSZtC*acPElla9qEITV*>h&St4Y?4E9X@+=RT9 z6qja*x9V7Il0$K6hIpHf#U?ovmu85!>sV}(Lvd+_c!!R~COH(BW{7v{SZtC*acPEl zmyX3IITV*>hRT96qja*_v%<|l0$K6hIpTj#U?ovmu86f>sV}( zLvd+__<)YZCOH(BW{3~!SZtC*acPG5kdDPBITV*>h!5*nY?4E9X@>ZSj>RT96qja* zkLp-#l0$K6hWMC{#U?ovmu85M>sV}(Lvd+__=JwdCOH(BW{6MfSZtC*acPG5l#azF zITV*>h)?TSY?4E9X@>ZWj>RT96qja*&+1rgl0$K6hWMP0#U?ovmu861>sV}(Lvd+_ z_=1kbCOH(BW{5B9SZtC*acPG5l8(hDITV*>h%f6{Y?4E9X@>ZUj>RT96qja*uj*KA zl0$K6hWMI}#U?ovmu85s>sV}(Lvd+__=b+fCOH(BW{7X zh;QpyY?4E9X@>ZYj>RT96qja*@9J1=l0$K6hWMV2#U?ovmu86X>sV}(Lvd+__<@ea zCOH(BW{4l^SZtC*acPG5k&eYCITV*>h#%`%Y?4E9X@>ZTj>RT96qja*pXyj_l0$K6 zhWMF|#U?ovmu85c>sV}(Lvd+__=S$eCOH(BW{6+vSZtC*acPG5m5#+GITV*>h+pei zY?4E9X@>ZXj>RT96qja*-|ARwl0$K6hWMS1#U?ovmu86H>sV}(Lvd+__=AqcCOH(B zW{5xPSZtC*acPG5la9qEITV*>h(GICY?4E9X@>ZVj>RT96qja*zv@_Ql0$K6hWML~ z#U?ovmu85+>sV}(Lvd+__=k?gCOH(BW{7|4SZtC*acPG5myX3IITV*>h=1!?Y?4E9 zX@>ZZj>RT96qja*|LRz5l0$K6hWMY3#U?ovmu83u`o+j%lN^dmGsJ^*EH=rZxHLmN zSjS?M9EwXb#6xr}Hp!v5G($X8$6}Klic2%Z!*nb*$)UJ3Lp)r^Vv`(-OEbhHbSyT> zp|~_dJW|JElN^dmGsL5GEH=rZxHLmNTE}9O9EwXb#A9?UHp!v5G($XA$6}Klic2%Z z<8&-G$)UJ3Lp)x`Vv`(-OEbh1bSyT>p|~_dJWp|~_d zJX6PFlN^dmGsLrWEH=rZxHLmNTgPIP9EwXb#B+2kHp!v5G($XB$6}Klic2%Z^K>jW z$)UJ3Lp)!{Vv`(-OEbg^bSyT>p|~_dyimttlN^dmGsKH@EH=rZxHLn&SjS?M*wSrY zr^5{e=5@N4==lF1$lN^dmGsH)AEH=rZxHLn2OvhrA9EwXb#K(0kHp!v5G(&ts$6}Klic2%ZCv_|~ z$)UJ3LwridVv`(-OEbi$bu2c?p|~_dd`8D&lN^dmGsI_gEH=rZxHLn2PRC-C9EwXb z#OHM^Hp!v5G(&tr$6}Klic2%Z7j-N)$)UJ3LwrfcVv`(-OEbimbu2c?p|~_dd_~7% zlN^dmGsIVQEH=rZxHLn2O~+!B9EwXb#MgB!Hp!v5G(&tt$6}Klic2%ZH+3vF$)UJ3 zLwrleVv`(-OEbi`bu2c?p|~_dd`HJ(lN^dmGsJgwEH=rZxHLn2Psd`D9EwXb#P@Y9 zHp!v5G(-GA$6}Klic2%Z4|Oay$)UJ3L;Og`Vv`(-OEbiebu2c?p|~_d{6xoMlN^dm zGsI7IEH=rZxHLojOvhrA9EwXb#LsmsHp!v5G(-GC$6}Klic2%ZFLf+7$)UJ3L;Om| zVv`(-OEbi;bu2c?p|~_d{6@!OlN^dmGsJIoEH=rZxHLojPRC-C9EwXb#P4-1Hp!v5 zG(-GB$6}Klic2%ZA9XA?$)UJ3L;Oj{Vv`(-OEbiubu2c?p|~_d{6)uNlN^dmGsItY zEH=rZxHLojO~+!B9EwXb#NTx+Hp!v5G(-GD$6}Klic2%ZKXoiN$)UJ3L;Op}Vv`(- zOEbj3bu2c?p|~_d{71)PlN^dmGsJ&&EH=rZxHLojPsd`D9EwXb!~=cZ!D5pfic2%Z zgLEu5$)UJ3Lp)f=Vv`(-OEbhnbSyT>p|~_dJXFVGlN^dmGsMGmEH=rZxHLmNT*qRQ z9EwXb#3OVpHp!v5G($X6$6}Klic2%ZqjW4b$)UJ3Lp)l?Vv`(-OEbh{bSyT>p|~_d zJXXhIlN^dmGsNR`EH=rZxHLmNUdLjS9EwXb#1nKZHp!v5G($X5$6}Klic2%ZlXNUL z$)UJ3Lp)i>Vv`(-OEbh%bSyT>p|~_dJXObHlN^dmGsM$$EH=rZxHLmNUB_aR9EwXb z#4~g(Hp!v5G($X7$6}Klic2%Zvve#r$)UJ3Lp)o@Vv`(-OEbiCbSyT>p|~_dJXgnJ zlN^dmGsN?BEH=rZxHLmNU&msT9EwXb#0zvRHp!v5G()^l$6}Klic2%Zi*zhD$)UJ3 zL%dkWVv`(f={B#^;f4b9Ivw85|98^!P+XcJUaDiUNe;!O8RBI+7MtWyT$&+Xu4A!D z4#lMz;uSg;o8(Yjnjv1PW3fpN#ibeIRXP@%OQGu}Kcar5WNaIu@JcP+XcJ-l}7OTHu}Kcar5WNqIu@JcP+XcJ-m7D= zNe;!O8RC697MtWyT$&-?uVb-E4#lMz;sZJso8(Yjnjt=@W3fpN#ibeILpm0l=bSyT9OHwpLd|St2bGRf$GsJgvEH;NrQZz$+SI1&=xFkh0#P@V8Hit`6 zG(&t}$6|B1BtYbSyT9OHwpL{8-0gbGRf$GsI7H zEH;NrQZz&SRL5d-xFkh0#LsjrHit`6G(-Gc$6|B1Bt&bSyT9OHwpL{94CibGRf$GsJInEH;NrQZz&SR>xvhf7j4L;O+4Vsp48MKi>obSyT9OHwpL{8`6hbGRf$GsItXEH;Nr zQZz&SRmWm;xFkh0#NTu*Hit`6G(-Gd$6|B1Bt| zbSyT9OHwpL{9DIjbGRf$GsJ&%EH;NrQZz&SSI1&=xFkh0!~^^ji^b+}Ns4BO2kKaC z4ws~8hIo*U#pZBHie`uh>sV|Km!xQhc!-Y0=5R@hW{8LCSZofLq-chCn2yEfa7l`0 zh==P~Yz~*CXoh%%j>YD1Ns4BON9tH?4ws~8hIo{Y#pZBHie`vM>sV|Km!xQhc#Mw4 z=5R@hW{Ah?SZofLq-chCoQ}oja7l`0h{x+#Yz~*CXoh%#j>YD1Ns4BOC+b*i4ws~8 zhIo>W#pZBHie`u>>sV|Km!xQhc#4k2=5R@hW{9WiSZofLq-chCnvTWha7l`0h^OmV zYz~*CXoh%(j>YD1Ns4BOXX;pN4ws~8hIp2a#pZBHie`vs>sV|Km!xQhc#e+6=5R@h zW{BtNSZofLq-chCo{q)la7l`0i0A8AYz~*CXoh%!j>YD1Ns4BO7wTAS4ws~8hIo;V z#pZBHZ0RiN(G2lw9gEH3k`&DluhFsC z94<-G4DnhWi_PJZ6wMH?)3MkbE=kc0@p>JL&Eb+1%@A+UvDh3gNzn}PMjeaI;gS^1 z5O314*c>iN(G2ls9gEH3k`&DlZ_%;X94<-G4DnVSi_PJZ6wMHC)3MkbE=kc0@pc`H z&Eb+1%@FUiN(G2l!9gEH3k`&Dl@6oZ?94<-G z4Dntai_PJZ6wMIt)3MkbE=kc0@qQhP&Eb+1%@7~ZvDh3gNzn}PK^=?D;gS^15FgU9 z*c>iN(G2ln9gEH3k`&DlAJMVc94<-G4DnGNi_PJZ6wMGH)3MkbE=kc0@o^oC&Eb+1 z%@Ci^vDh3gNzn}PNga#L;gS^15TDYq*c>iN(G2lv9gEH3k`&DlpV6_{94<-G4DneV zi_PJZ6wMHy)3MkbE=kc0@p&DK&Eb+1%@AMEvDh3gNzn}PMIDRH;gS^15MR=<*c>iN z(G2lr9gEH3k`&DlU(vDH94<-G4DnSRi_PJZ6wMG{)3MkbE=kc0@pT=G&Eb+1%@E(v zvDh3gNzn}PO&yEP;gS^15Z}_V*c>iN(G2lz9gEH3k`&Dl-_fzy94<-G4DnqZi_PJZ z6wMId)3MkbE=kc0@qHbO&Eb+1%@9A(vDh3gNzn}PLmi9F;gS^15I@qf*c>iN(G2lp z9gEH3k`&DlKhd$+94<-G4DnMPi_PJZ6wMGn)3MkbE=kc0@pB!E&Eb+1%@DuPvDh3g zNzn}POC5{N;gS^15Wmu~*c>iN(G2lx9gEH3k`&DlztOSS94<-G4DnkXi_PJZ6wMI7 z)3MkbE=kc0@p~PM&Eb+1%@BXkvDh3gNzn}PM;(jJ;gS^15P#CK*c>iN(G2lt9gEH3 zk`&Dlf6=kn94<-G4DnYTi_PJZ6wMHS)3MkbE=kc0@pm1I&Eb+1%@F_4vDh3gNzn}P zPaTWR;gS^15dYG#*c>iN(G2l#9gEH3k`&Dl|IxA794<-G4Dnwbi_PJZ6wMG1@M;o^ z&Eb+1%@7aNvDh3gNzn}PARUX%;gS^15D(U|*c>iN(G2kr9gEH3k`&Dl57n{Q94<-G z4Dm1>i_PJZ6wMG1*Rj|fE=kc0@dzD@&Eb+1%@B{&vDh3gNzn}PC>@K<;gS^15RcZe z*c>iN(G2kz9gEH3k`&DlkJYi*94<-G4DmP}i_PJZ6wMHi*Rj|fE=kc0@dO=<&Eb+1 z%@9x2vDh3gNzn}PBpr**;gS^15Kq>z*c>iN(G2kv9gEH3k`&DlPt~#594<-G4DmD_ zi_PJZ6wMG%*Rj|fE=kc0@eCb{&Eb+1%@EJjvDh3gNzn}PEFFu@;gS^15YN`J*c>iN z(G2k%9gEH3k`&Dl&(*Qm94<-G4Dmc2i_PJZ6wMIN*Rj|fE=kc0@d6!-&Eb+1%@8lt zvDh3gNzn}PA{~p(;gS@#beq@dUaZ5fp3UoY{NG86W{8*QSZofLq-chCsgA|wa7l`0 zh?nVDYz~*CXoh&Xj>YD1Ns4BOSLj%54ws~8hIplp#pZBHie`vc=~!$Im!xQhc(snj z=5R@hW{B75SZofLq-chCt&YX!a7l`0h}Y>@Yz~*CXoh&bj>YD1Ns4BOH|SVw4ws~8 zhIpfn#pZBHie`v6=~!$Im!xQhc(abh=5R@hW{9`wSZofLq-chCtB%Fya7l`0h_~rj zYz~*CXoh&Zj>YD1Ns4BOcj#Db4ws~8hIprr#pZBHie`v+=~!$Im!xQhc(;zl=5R@h zW{CIbSZofLq-chCua3p$a7l`0i1+DOYz~*CXoh&dj>YD1Ns4BO59nBI4ws~8hWMb4 z#pZBHie`up=~!$Im!xQh_^^(}=5R@hW{8jISZofLq-citsE)z)5Yz~*C zXomQ>j>YD1Ns4BOPv}@|4ws~8hWMn8#pZBHie`vU=~!$Im!xQh__U72=5R@hW{A(| zSZofLq-cittd7Oza7l`0h|lR*Yz~*CXomQ_j>YD1Ns4BOFX&io4ws~8hWMh6#pZBH zie`u}=~!$Im!xQh__B`0=5R@hW{9uoSZofLq-cits*c6xa7l`0h_C5bYz~*CXomQ@ zj>YD1Ns4BOZ|GQT4ws~8hWMtA#pZBHie`v!=~!$Im!xQh__mJ4=5R@hW{B_TSZofL zq-citu8zg#a7l`0i0|oGYz~*CXomQ{j>YD1Ns4BOALv+Y4ws~8hWMe5#pZBHie`u( z=~!$Im!xQh__2<~=5R@hW{98YSZofLq-citsgA|wa7l`0h@a_LYz~*CXomQ?j>YD1 zNs4BOU+7qD4ws~8hWMq9#pZBHie`vk=~!$Im!xQh__dD3=5R@hW{BVDSZofLq-cit zt&YX!a7l`0h~Md0Yz~*CXomQ`j>YD1Ns4BOKj>I&4ws~8hWMk7#pZBHie`vE=~!$I zm!xQh__L11=5R@hW{AJ&SZofLq-cittB%Fya7l`0h`;GrYz~*CXomQ^j>YD1Ns4BO zf9P0j4ws~8hWMwB#pZBHie`v^=~!$Im!xQh__vP5=5R@hW{CgjSZofLq-citua3p$ za7l`0hzEG#oWsV|Km!xQhc!-Y0=5R@h zW{8LCSZofLq-chCn2yEfa7l`0h==P~Yz~*CXoh%%j>YD1Ns4BON9tH?4ws~8hIo{Y z#pZBHie`vM>sV|Km!xQhc#Mw4=5R@hW{Ah?SZofLq-chCoQ}oja7l`0h{x+#Yz~*C zXoh%#j>YD1Ns4BOC+b*i4ws~8hIo>W#pZBHie`u>>sV|Km!xQhc#4k2=5R@hW{9Wi zSZofLq-chCnvTWha7l`0h^OmVYz~*CXoh%(j>YD1Ns4BOXX;pN4ws~8hIp2a#pZBH zie`vs>sV|Km!xQhc#e+6=5R@hW{BtNSZofLq-chCo{q)la7l`0i0A8AYz~*CXoh%! zj>YD1Ns4BO7wTAS4ws~8hIo;V#pZBHipG|1^Ew?~C@`YD1Ns4BO*XUSm4ws~8hIp-x#pZBHie`w{=~!$Im!xQhc)gCr=5R@h zW{5ZFSZofLq-chCqmISqa7l`0h&Sn2Yz~*CXoh&Rj>YD1Ns4BOx9C`G4ws~8hIp%v z#pZBHie`wn=~!$Im!xQhc)O0p=5R@hW{7v_SZofLq-chCr;f$ua7l`0hYD1Ns4BO_vlz`4ws~8hIp@z#pZBHie`xS=~!$Im!xQhc)yOt=5R@hW{3~y zSZofLq-citppM1na7l`0h!5#lYz~*CXomQ(j>YD1Ns4BOkLXxz4ws~8hWMzC#pZBH zie`w9=~!$Im!xQh__&V6=5R@hW{6MdSZofLq-citq>jbra7l`0h)?NQYz~*CXomQ- zj>YD1Ns4BO&*)fe4ws~8hWMYD1Ns4BOujp884ws~8hWM(E#pZBHie`wf z=~!$Im!xQh__~h8=5R@hW{7X-SZofLq-citrjEtta7l`0h;QjwYz~*CXomQYD1 zNs4BO@90=;4ws~8hWM_I#pZBHie`xK=~!$Im!xQh_`Z(C=5R@hW{4l?SZofLq-cit zp^nAoa7l`0h#%=#Yz~*CXomQ)j>YD1Ns4BOpXgX@4ws~8hWM$D#pZBHie`wP=~!$I zm!xQh__>b7=5R@hW{6+tSZofLq-citrH;ksa7l`0h+pYgYz~*CXomQ;j>YD1Ns4BO z-{@Fu4ws~8hWM?H#pZBHie`x4=~!$Im!xQh_`QzB=5R@hW{5xNSZofLq-citqmISq za7l`0h(GCAYz~*CXomQ+j>YD1Ns4BOzvx(O4ws~8hWM+F#pZBHie`wv=~!$Im!xQh z_`8n9=5R@hW{7|2SZofLq-citr;f$ua7l`0h=1u=Yz~*CXomQ=j>YD1Ns4BO|L9n3 z4ws~8hWM|J#pZBHie`uh*ha`=bGRf$GsFXREH;NrQZz$6NXKGxxFkh0#DjG#Hit`6 zG($W@$6|B1BtEH;Nr zQZz$6OUGh!xFkh0#ItoQHit`6G($W`$6|B1Bthf7j4Lp)E%Vsp48MKi?n zbu2cAOHwpLygc=5;#U&i^~@ zJH$(LEH;NrQZz%nRL5d-xFkh0#LILnHit`6G()^x$6|B1Bt!bSyT9OHwpLyjsU%bGRf$GsJ6jEH;NrQZz%nR>xvkbSyT9OHwpLyjjO$bGRf$GsIhT zEH;NrQZz%nRmWm;xFkh0#M^W%Hit`6G()^y$6|B1Bt^bSyT9OHwpLyj#a&bGRf$GsJszEH;NrQZz%nSI1&=xFkh0#QStCHit`6G()^! z$6|B1BtQbSyT9OHwpLd|1a~bGRf$GsH)9EH;Nr zQZz$+RL5d-xFkh0#K&|jHit`6G(&t`$6|B1Btw zbSyT9OHwpLd|Jn1bGRf$GsI_fEH;NrQZz$+R>xvgbSyT9OHwpLd|Ah0bGRf$GsIVPEH;NrQZz$+ zRmWm;xFkh0#Mg8zHit`6G(&t{$6|B1Bt=bSyT9 zOHwpLd|St2bGRf$GsJgvEH;NrQZz$+SI1&=xFkh0#P@V8Hit`6G(&t}$6|B1BtYbSyT9OHwpL{8-0gbGRf$GsI7HEH;NrQZz&SRL5d- zxFkh0#LsjrHit`6G(-Gc$6|B1Bt&bSyT9OHwpL z{94CibGRf$GsJInEH;NrQZz&SR>xv zhf7j4L;O+4Vsp48MKi>obSyT9OHwpL{8`6hbGRf$GsItXEH;NrQZz&SRmWm;xFkh0 z#NTu*Hit`6G(-Gd$6|B1Bt|bSyT9OHwpL{9DIj zbGRf$GsJ&%EH;NrQZz&SSI1&=xFkh0!~@#A&Nf0ehf7j4Lp)H&Vsp48MKi>MbSyT9 zOHwpLJXptKbGRf$GsHu5EH;NrQZz$6RL5d-xFkh0#KUwfHit`6G($XG$6|B1BtsbSyT9OHwpLJX*(MbGRf$GsI(bEH;NrQZz$6R>xv< zxFkh0#N%`cbSyT9OHwpL zJXyzLbGRf$GsIJLEH;NrQZz$6RmWm;xFkh0#M5*vHit`6G($XH$6|B1Bt+bSyT9OHwpLJX^UbSyT9OHwpLyjX|L zKjw8h{OZ}fPRIY9Azq?mu{m6lq8Z|)Iu@J5B`KOAUZ!KQIb4#W8RF$S7MsH*DViZ( zp<}T*T#}+0;*~lUo5Lk3njv1LW3f40lA;;n)jAfN!zC%2Azq_nu{m6lq8Z|~Iu@J5 zB`KOAUZ-QRIb4#W8RGRi7MsH*DVibPpkuK)T#}+0;*B~Mo5Lk3njzk#W3f40lA;;n z%{msF!zC%2A>N{6u{m6lq8Z|?Iu@J5B`KOA-lk)*Ib4#W8RG3a7MsH*DVibPp<}T* zT#}+0;+;Aco5Lk3njzk$W3f40lA;;n-8vSV!zC%2A>N~7u{m6lq8Z}7Iu@J5B`KOA z-lt=+Ib4#W8RGpq7MsH*DViZZpkuK)T#}+0;)6OCo5Lk3njt=fNL!zC%2AwHvHu{m6lq8Z||Iu@J5B`KOAKBr@` zIb4#W8RGLg7MsH*DVia^pkuK)T#}+0;)^;Ko5Lk3njyZVW3f40lA;;n%Q_aD!zC%2 zA- zbSyT9OHwpLJXXhIbGRf$GsNR`EH;NrQZz$6UdLi{xFkh0#1nKZHit`6G($X5$6|B1 zBtVsp48MKi=xbSyT9OHwpLJXObHbGRf$GsM$$EH;NrQZz$6 zUB_Z`xFkh0#4~g(Hit`6G($X7$6|B1Bt6bSyT9 zOHwpLJXgnJbGRf$GsN?BEH;NrQZz$6U&mr|xFkh0#0zvRHit`6G()^l$6|B1BtiN(G2lQ9gEH3k`&DluhOyD94<-G4Do6mi_PJZ6wMH? z(XrSZE=kc0@md{=&Eb+1%@D8CvDh3gNzn}PdL4_+;gS^15O2`2*c>iN(G2lM9gEH3 zk`&DlZ_=^Y94<-G4Dn_ii_PJZ6wMHC(XrSZE=kc0@m3v+&Eb+1%@A+XvDh3gNzn}P zb{&h&;gS^15bw~j*c>iN(G2lU9gEH3k`&Dl@6xf@94<-G4DoIqi_PJZ6wMIt(XrSZ zE=kc0@m?K^&Eb+1%@FU?vDh3gNzn}PejSU=;gS^15FgO7*c>iN(G2lH9gEH3k`&Dl zAJVbd94<-G4Dn$di_PJZ6wMGH(XrSZE=kc0@lhR%&Eb+1%@7~cvDh3gNzn}PaUF}z z;gS^15TDSo*c>iN(G2lP9gEH3k`&DlpVG0|94<-G4Do3li_PJZ6wMHy(XrSZE=kc0 z@mU><&Eb+1%@Ci{vDh3gNzn}Pc^!+*;gS^15MR)-*c>iN(G2lL9gEH3k`&DlU(&JI z94<-G4Dn?hi_PJZ6wMG{(XrSZE=kc0@l_p*&Eb+1%@AMHvDh3gNzn}PbsdY%;gS^1 z5Z}iN(G2lT9gEH3k`&Dl-_o(z94<-G4DoFpi_PJZ6wMId(XrSZE=kc0@m(E@ z&Eb+1%@E(yvDh3gNzn}PeI1L<;gS^15I@kd*c>iN(G2lJ9gEH3k`&DlKhm+-94<-G z4Dn+fi_PJZ6wMGn(XrSZE=kc0@lzd(&Eb+1%@9A+vDh3gNzn}Pa~+G#;gS^15Wmo| z*c>iN(G2lR9gEH3k`&DlztXYT94<-G4Do9ni_PJZ6wMI7(XrSZE=kc0@mn2>&Eb+1 z%@DuSvDh3gNzn}PdmW3-;gS^15P#6I*c>iN(G2lN9gEH3k`&Dlf6}qo94<-G4Dn|j zi_PJZ6wMHS(XrSZE=kc0@mC#-&Eb+1%@BXnvDh3gNzn}PcO8q(;gS^15dYAz*c>iN z(G2lV9gEH3k`&Dl|I)G894<-G4DoLri_PJZ6wMI-(XrSZE=kc0@n0Q_&Eb+1%@7ZW zm;65#o5Lk3njs#jW3f40lA;;nK{^(j!zC%2As(z_u{m6lq8Z{LIu@J5B`KOA9;#!p zIb4#W8RB6&7MsH*DViZ3u4Az|T#}+0;t@I)o5Lk3njs#kW3f40lA;;nQ92fz!zC%2 zAs($`u{m6lq8Z{bIu@J5B`KOA9;;)qIb4#W8RBs|7MsH*DViZ3uVb+}T#}+0;t4ty zo5Lk3njxO3W3f40lA;;nNjesr!zC%2A)c&bu{m6lq8Z{TIu@J5B`KOAo~mQ9Ib4#W z8RBU=7MsH*DViaku4Az|T#}+0;u$&?o5Lk3njxO4W3f40lA;;nSvnS*!zC%2A)c*c zu{m6lq8Z{j|DU6KTGlAm7B%`xSxHwOZ`rnO+qP}nHtV#rE7fxKU8idHf6PS3<`5)B zGhEj5bZibmQZ&P5JzvM>5F|x2T-FP8Yz{$EG{a@RP{-yFBtvU`mK~glsWxZa<<`5)BGhEgibZibmQZ&P5y-~;J z5F|x2T-KX(Yz{$EG{a@RS;yuOBtBCK~glsWqn-7 z<`5)BGhEgubZibmQZ&P5eNxBf5F|x2T-K*_Yz{$EG{a?mTF2%PBtm|F4na~h!)1L{$L0_uMKfI1*K}+SK~glsWqn=8<`5)B zGhEg;bZibmQZ&P5eN)Hg5F|x2T-LXAYz{$EG{a?mTgT=QBto<`5)BGhEg$ zbZibmQZ&P5{Zhx~5F|x2T-L92Yz{$EG{a^6TF2%PBt}+8kQB{uSew8Dq-ciAdYz8VAxMg5xUARf z*c^hSXokyrgO1H1NQ!2-tT*b|9D<~1hRb@Bj?E!Rie|X1H|y9Of~07M%X*8B%^^sN zX1J`k>ew8Dq-ciAdYg{TAxMg5xU9G9*c^hSXokyrhmOr5NQ!2-tas|z9D<~1hRb@F zj?E!Rie|X1ck9?3f~07M%X*KF%^^sNX1J{P>ew8Dq-ciAdY_KXAxMg5xUBc<*c^hS zXok!BfR4=}NQ!2-tPkqg9D<~1hRgbpj?E!Rie|X159`<*f~07M%le3p%^^sNX1J`6 z>ew8Dq-ciA`k0Q*AxMg5xU7%s*c^hSXok!BgpSQ2NQ!2-tWWCL9D<~1hRgbtj?E!R zie|X1PwUtmf~07M%leFt%^^sNX1J`+>ew8Dq-ciA`kaoew8D zq-ciA`kIc-AxMg5xU8@1*c^hSXok!BhK|i4NQ!2-tZ(Yr9D<~1hRgbvj?E!Rie|X1 zZ|m3`f~07M%leLv%^^sNX1J{H>ew8Dq-ciA`ks!>AxMg5xUBE%*c^hSXok!BfsV}~ zNQ!2-tRL#w9D<~1hRgbqj?E!Rie|X1AM4m0f~07M%le6q%^^sNX1J`M>ew8Dq-ciA z`k9W+AxMg5xU8S+*c^hSXok!Bg^tZ3NQ!2-tY7Nb9D<~1hRgbuj?E!Rie|X1U+dT$ zf~07M%leIu%^^sNX1J{1>ew8Dq-ciA`kju=AxMg5xUApn*c^hSXok!BgO1H1NQ!2- ztUv159D<~1hRgbsj?E!Rie|X1KkL{Wf~07M%leCs%^^sNX1J`s>ew8Dq-ciA`kRi; zAxMg5xU9eH*c^hSXok!BhmOr5NQ!2-tbgj*9D<~1hRgbwj?E!Rie|X1f9u#Bf~07M z%leOw%^^sNX1J{X>ew8Dq-ciA`k#)?AxMg5xU2{IOOVYWNQ!2-tOx1X9D<~1hRb@e zj?E!Rie|X1hv?WGf~07M%X+Ae%^^sNX1J_}>DU~Cq-ciAdbp0wAxMg5xU5I$*c^hS zXokyrq>jxYNQ!2-tVikC9D<~1hRb@ij?E!Rie|X1$LQD`f~07M%X+Mi%^^sNX1J`! z>DU~Cq-ciAdc2O!AxMg5xU47W*c^hSXokyrqK?fWNQ!2-tS9N%9D<~1hRb@gj?E!R zie|X1r|8%mf~07M%X+Gg%^^sNX1J`U>DU~Cq-ciAdb*CyAxMg5xU6UB*c^hSXokyr zrjE@aNQ!2-tY_)i9D<~1hRb@kj?E!Rie|X1=jhlRf~07M%X+Sk%^^sNX1J{9>DU~C zq-ciAdcKa$AxMg5xU3iG*c^hSXokyrp^nWVNQ!2-tQYCn9D<~1hRb@fj?E!Rie|X1 zm+06W0IkQB{uS#Q;`IRr`3443sb9h*at6wPp1Z`ZLo1WC~hm-P-En?sNk&2U-o z)Ui1PNzn|K^)4NoLy#2Ba9Quxu{i`u(F~XM9vz!QkQB{uS?|@cIRr`3443sj9h*at z6wPp1@7J+81WC~hm-PW1n?sNk&2U*C)Ui1PNzn|K^&uUbLy#2Ba9JPLu{i`u(F~XM z5gnUDkQB{uSs&H0IRr`3443sW9h*at6wPp1AJ?%t1WC~hm-Pu9n?sNk&2U+t)Ui1P zNzn|K^(h^jLy#2Ba9N+$u{i`u(F~XM86BHLkQB{uS)bLhIRr`3443se9h*at6wPp1 zpVzTD1WC~hm-Pi5n?sNk&2U*?)Ui1PNzn|K^(7sfLy#2Ba9Lm0u{i`u(F~XM6&;&H zkQB{uSzpz$IRr`3443sa9h*at6wPp1U)QlY1WC~hm-P)Dn?sNk&2U-Y)Ui1PNzn|K z^(`HnLy#2Ba9Q8hu{i`u(F~XM9UYrPkQB{uS>M&MIRr`3443si9h*at6wPp1-`BA@ z1WC~hm-Pc3n?sNk&2U*i)Ui1PNzn|K^&=gdLy#2Ba9Karu{i`u(F~XM6CImFkQB{u zSwGdWIRr`3443sY9h*at6wPp1Ki9E21WC~hm-P!Bn?sNk&2U-2)Ui1PNzn|K^(!5l zLy#2Ba9O|Bu{i`u(F~XM8y%ZNkQB{uS-;h>IRr`3443sg9h*at6wPp1zt^!j1WC~h zm-Po7n?sNk&2U+N)Ui1PNzn|K^(P&hLy#2Ba9MxWu{i`u(F~XM7af~JkQB{uS%1~B zIRr`3443sc9h*at6wPp1f7h`&1WC~hm-P=Fn?sNk&2U-&)Ui1PNzn|K^)DTpLy#2B za9RJ>u{i`u(F~XMA03-RkQB{uS^w3sIRr`3443sk9h*at6wPp15A@Xrn?sNk&2U){ z(y=)NNzn|K^1WC~hm-R>;n?sNk&2U+d(y=)NNzn|K^=KWNLy#2Ba9NMhu{i`u(F~XM zSRI=~kQB{uS&!4PIRr`3443tI9h*at6wPp1PtdVB1WC~hm-R#)n?sNk&2U*y(y=)N zNzn|K^<*8JLy#2Ba9K~$u{i`u(F~XMR2`c`kQB{uSx?ikIRr`3443tE9h*at6wPp1 z&(N_s1WC~hm-S2?n?sNk&2U-I(y=)NNzn|K^=uuRLy#2Ba9PjMu{i`u(F~XMTpgQ3 zkQB{uSt#ANhaf4M;j&(?V{-_S zq8Tph6*@MDASs&RvRvcLdhaf4M;j&(@V{-_Sq8Tph4LUZ5ASs&Rvfij;a|n{687}KhIyQ$O zDVpK3-mGJD2$G^1F6%8iHisZ7n&GnEs$+8qlA;+d>uowVhaf4M;j-SYV{-_Sq8Tph z9Xd9LASs&RvfimwP*lhaf4M;j-SZV{-_Sq8Tph13ET`ASs&RvOcI|a|n{687}KXIyQ$ODVpK3 zKCEMN2$G^1F6$#YHisZ7n&GlOs$+8qlA;+d>ti}Lhaf4M;j%uiV{-_Sq8Tph6FN4B zASs&RvOcL}a|n{687}KnIyQ$ODVpK3KCNSO2$G^1F6%QoHisZ7n&GlOt7CHrlA;+d z>vK9bhaf4M;j%ujV{-_Sq8Tph3pzH3ASs&Rvc9Nea|n{687}KfIyQ$ODVpK3zN}+& z2$G^1F6%2gHisZ7n&Gm(s$+8qlA;+d>uWkThaf4M;j+H2V{-_Sq8Tph8#*?JASs&R zvc9Qfa|n{687}KvIyQ$ODVpK3zO7?(2$G^1F6%owHisZ7n&Gm(t7CHrlA;+d>w7vj zhaf4M;j+H3V{-_Sq8Tph2Rb%~ASs&RvVN#za|n{687}KbIyQ$ODVpK3eyn422$G^1 zF6$>cHisZ7n&Gm3s$+8qlA;+d>t{MPhaf4M;j(_NV{-_Sq8Tph7dkeFASs&RvVN&! za|n{687}KrIyQ$ODVpK3eywA32$G^1F6%csHisZ7n&Gm3t7CHrlA;+d>vuXfhaf4M z;j(_OV{-_Sq8Tph4>~r7ASs&Rvi_)Ja|n{687}KjIyQ$ODVpK3{;Xqj2$G^1F6%Ek zHisZ7n&Gnks$+8qlA;+d>u)+Xhaf4M;j;d&V{-_Sq8TphA38RNASs&Rvi_-Ka|n{6 z87}KzIyQ$ODVpK3{;gwk2$G^1F6%!!HisZ7n&Gnkt7CHrlA;+d>wh{nhaf4M;j$j+ zKdjgsf~07M%X*NG%^^sNX1J^e>)0HEq-ciAdWeqAAxMg5xU7fj*c^hSXokyrn2yaM zNQ!2-tcUB^9D<~1hRb?{j?E!Rie|X1N9x!df~07M%X*ZK%^^sNX1J_J>)0HEq-ciA zdW??EAxMg5xU9$O*c^hSXokyroQ};QNQ!2-tjFuv9D<~1hRb?_j?E!Rie|X1C+gT7 zf~07M%X*TI%^^sNX1J^;>)0HEq-ciAdWw$CAxMg5xU8q@*c^hSXokyrnvTsONQ!2- ztf%YP9D<~1hRb?}j?E!Rie|X1XX@A-f~07M%X*fM%^^sNX1J_p>)0HEq-ciAdXA3G zAxMg5xUA>u*c^hSXokyro{r5SNQ!2-tmo_49D<~1hRb?^j?E!Rie|X17wXs?f~07M z%X*QH%^^sNX1J^u>)0HEq-ciAdWnwBAxH|Zd7IbiaFc;~oern?|E;ta&2U*S)3G@O zNzn|K^>Q7XLy#2Ba9OX=u{i`u(F~XMN*$X+kQB{uS+CNuIRr`3443t49h*at6wPp1 zuhFqN1WC~hm-Sj5n?sNk&2U+-)3G@ONzn|K^?DtfLy#2Ba9MBAu{i`u(F~XMMje|& zkQB{uS#Q#@IRr`3443t09h*at6wPp1Z_%+i1WC~hm-SX1n?sNk&2U+7)3G@ONzn|K z^>!VbLy#2Ba9Quru{i`u(F~XMP92*=kQB{uS?|)ZIRr`3443t89h*at6wPp1@6oY2 z1WC~hm-Sv9n?sNk&2U-o)3G@ONzn|K^?n_jLy#2Ba9JPFu{i`u(F~XMK^>bzkQB{u zSs&7|IRr`3443s`9h*at6wPp1AJMTn1WC~hm-SH{n?sNk&2U*C)3G@ONzn|K^>H1W zLy#2Ba9N+wu{i`u(F~XMNgbO*kQB{uS)bCeIRr`3443t39h*at6wPp1pV6^71WC~h zm-Sg4n?sNk&2U+t)3G@ONzn|K^?4neLy#2Ba9Ll_u{i`u(F~XMMID<%kQB{uSzpqz zIRr`3443s~9h*at6wPp1U(vBS1WC~hm-SU0n?sNk&2U*?)3G@ONzn|K^>rPaLy#2B za9Q8bu{i`u(F~XMO&yyMvJIRr`3443t79h*at6wPp1-_fx-1WC~hm-Ss8 zn?sNk&2U-Y)3G@ONzn|K^?eZDYLy#2Ba9O|5 zu{i`u(F~XMOC6g-kQB{uS-;Y;IRr`3443t59h*at6wPp1ztOQd1WC~hm-Sm6n?sNk z&2U-2)3G@ONzn|K^?MzgLy#2Ba9MxQu{i`u(F~XMM;)6(kQB{uS%1>8IRr`3443t1 z9h*at6wPp1f6=iy1WC~hm-Sa2n?sNk&2U+N)3G@ONzn|K^>-bcLy#2Ba9RJ*u{i`u z(F~XMPaT^>kQB{uS^v_pIRr`3443t99h*at6wPp1|Ix8I1WC~hm-SyAn?sNk&2U-& z)3G@ONzn|K^+2~Fu{i`u(F~XMARU`SkQB{uSr68+IRr`3443r~9h*at6wPp157n_b z1WC~hm-R3mn?sNk&2U){*ReSSNzn|K^#~oCLy#2Ba9NMku{i`u(F~XMC>@(akQB{u zS&!DSIRr`3443s79h*at6wPp1kJYg`1WC~hm-RRun?sNk&2U+d*ReSSNzn|K^#mQ8 zLy#2Ba9K~(u{i`u(F~XMBpsVWkQB{uSx?rnIRr`3443s39h*at6wPp1Pt~zG1WC~h zm-RFqn?sNk&2U*y*ReSSNzn|K^$Z=GLy#2Ba9PjPu{i`u(F~XMEFGIekQB{uS ze-+JeSufMEIRr`3443tC9h*at6wPp1uh6kM1WC~hm-R{=n?sNk&2U+-(y=)NNzn|K z^=ciPLy#2Ba9OX>u{i`u(F~XMS{<81kQB{uS+CQvIRr`3443tK9h*at6wPp1Z_u$h z1WC~hm-R*+n?sNk&2U+7(y=)NNzn|K^=2KLLy#2Ba9MBBu{i`u(F~XMRvnu|kQB{u zS#Q&^IRr`3443tG9h*at6wPp1@6fS11WC~hm-S8^n?sNk&2U-o(y=)NNzn|K^==)T zLy#2Ba9Qusu{i`u(F~XMULBi5kQB{uS?|-aIRr`3443tO9h*at6wPp1AJDNm1WC~h zm-Rs%n?sNk&2U*C(y=)NNzn|K^GLy#2Ba9JPGu{i`u(F~XMQ5~B@kQB{uSs&A} zIRr`3443tB9h*at6wPp1pU|;61WC~hm-R^MyKIRr`3443tN9h*at6wPp1KhUu`1WC~hm-Ry(n?sNk z&2U*i(y=)NNzn|K^n?sNk&2U-2(y=)NNzn|K^=loQLy#2Ba9O|6u{i`u z(F~XMTOFH2kQB{uS-;btF1WC~hm-Qqan?sNk&2U*y*0DJRNzn|K^%NbOLy#2B za9K~)u{i`u(F~XMG##5mkQB{uSx?uoIRr`3443r`9h*at6wPp1&(yIw1WC~hm-Q?i zn?sNk&2U-I*0DJRNzn|K^&B0WLy#2Ba9PjQu{i`u(F~XMJRO@ukQB{uS*YE&haf4M;j&(#V{-_Sq8Tphl{z+uASs&R zvR-9P| zhaf4M;j-SKV{-_Sq8TphjXE}mASs&RvfiX)a|n{687}M1IyQ$ODVpK3-lAi32$G^1 zF6*s2HisZ7n&GnErekvmlA;+d>+L!=haf4M;j-SLV{-_Sq8TphojNv$ASs&Rvfia* za|n{687}MHIyQ$ODVpK3-lJo42$G^1F6+HIHisZ7n&GnEr(<&nlA;+d>-{=5haf4M z;j%uUV{-_Sq8TphgE}^cASs&RvOc6^a|n{687}L?IyQ$ODVpK3KB8lD2$G^1F6*N@ zHisZ7n&GlOrekvmlA;+d>*G2$haf4M;j%uVV{-_Sq8TphlR7qsASs&RvOc9_a|n{6 z87}M7IyQ$ODVpK3KBHrE2$G^1F6*;8HisZ7n&GlOr(<&nlA;+d>+?D`haf4M;j+G< zV{-_Sq8Tphi#j%kASs&Rvc9Baa|n{687}L~IyQ$ODVpK3zM^Au2$G^1F6*m0HisZ7 zn&Gm(rekvmlA;+d>+3o;haf4M;j+G=V{-_Sq8Tphn>sd!ASs&Rvc9Eba|n{687}MF zIyQ$ODVpK3zN2Gv2$G^1F6+BGHisZ7n&I;QIJ&DH3VIw-qp#$Soy2~;W@cubznOcQ znVFfHnOSGeQMBsnyDn*am*V)Yjzv;z4wq(#@99`1#pZBnhWNgYMN(`Imu83`=vXAh z=5T3-_@RzPQfv;FW{4l@SR}>faA}74v5rMjYz~)Zh@a?KB*o@%X@>Zzjzv;z4wq(# zpXpd6#pZBnhWNRTMN(`Imu84x=vXAh=5T3-_@$0TQfv;FW{6+uSR}>faA}74wT?wn zYz~)Zh~MZ~B*o@%X@>Z%jzv;z4wq(#-|1K+#pZBnhWNdXMN(`Imu84R=vXAh=5T3- z_@jfaA}74vyMelYz~)Zh`;DqB*o@%X@>Z#jzv;z4wq(#zv);c z#pZBnhWNXVMN(`Imu856=vXAh=5T3-_@|CVQfv;FW{7|3SR}>faA}74w~j?pYz~)Z zi2vwVB*o@%X@>Z(jzv;z4wq(#2ir2pA}Kb9OEbhnbS#o$bGS4^JXFUbDK>{oGsMGm zERte#xHLmNT*o3QHit_y#3OVpl45hXG($X6$08{{oGsNR`ERte#xHLmNUdJLSHit_y#1nKZl45hXG($X5 z$08{A}Kb9OEbh%bS#o$bGS4^JXOacDK>{oGsM$$ERte# zxHLmNUB@CRHit_y#4~g(l45hXG($X7$08{{oGsN?BERte#xHLmNU&kUTHit_y#0zvRl45hXG()^l$08{< zhf6cWi*ziKVsp4OL%dkWA}Kb9OEbhvbS#o$bGS4^yi~^`DK>{oGsMeuERte#xHN-p z-sW{W++<*0r^8$P|DX08;sG6tq}UuT%@8lwu}F%|;nEE83LT52*c>j+5Uj+5O376NQ%wj(hTt?9gC#c94^feZ`QF$ip}BD4Dl8ni=@~b zF3k}Ct7DNAo5Q6U;;lLsNwGOxnjzk%W04e_!=)MG?K&1ou{m6tA>N^5krbQ5r5WO# zIu=Q>Ib50{-lb!a6r01P8RFeK7D=%=T$&-?qhpa2o5Q6U;=MW+NwGOxnjzk&W04e_ z!=)MG{W=y&u{m6tAwHmEkrbQ5r5WObIu=Q>Ib50{KBQxj6r01P8REk_7D=%=T$&+1 zqGOR1o5Q6U;-fkiNwGOxnjt=>W04e_!=)MG<2n{eu{m6tAwHpFkrbQ5r5WOrIu=Q> zIb50{KBZ%k6r01P8RFAA7D=%=T$&+1qhpa2o5Q6U;Ib50{zNBN36r01P8RE-27D=%=T$&-iqGOR1 zo5Q6U;;T9qNwGOxnjyZXW04e_!=)MG>pB)mu{m6tA-Ib50{ zzNKT46r01P8RFYI7D=%=T$&-iqhpa2o5Q6U;=4K)NwGOxnjyZYW04e_!=)MG`#Kg$ zu{m6tA%37^krbQ5r5WOfIu=Q>Ib50{exzfO6r01P8REw}7D=%=T$&+%qGOR1o5Q6U z;-@+mNwGOxnjwCsW04e_!=)MG=QIb50{ex+lP z6r01P8RFME7D=%=T$&+%qhpa2o5Q6U;Ib50{{-k4(6r01P8RE}67D=%=T$&;NqGOR1o5Q6U;;%Xu zNwGOxnj!wCW04e_!=)MG?>ZJqu{m6tA^xFbkrbQ5r5WO%Iu=Q>Ib50{{-tA)6r01P z8RFkM7D=%=T$&;Nqhpa2o5Q6U;=ei;NwGOxnjs$C=5@9Vk`$Z6r5WNOIu=Q>Ib50{ z9;#!J6r01P8RB6&7D=%=T$&*su49oDo5Q6U;t@I)NwGOxnjs#kW04e_!=)MGQ92e$ zu{m6tAs($`krbQ5r5WNeIu=Q>Ib50{9;;)K6r01P8RBs|7D=%=T$&*suVaxEo5Q6U z;t4tyNwGOxnjxO3W04e_!=)MGNjeruu{m6tA)c&bkrbQ5r5WNWIu=Q>Ib50{o~mP! z6r01P8RBU=7D=%=T$&-Cu49oDo5Q6U;u$&?NwGOxnjxO4W04e_!=)MGSvnR;u{m6t zA)c*ckrbQ5r5WNmIu=Q>Ib50{o~vV#6r01P8RB_57D=%=T$&-CuVaxEo5Q6U;srVu zNwGOxnjv1OW04e_!=)MGMLHHqu{m6tAzrLwkrbQ5r5WNSIu=Q>Ib50{UaDh}6r01P z8RBI+7D=%=T$&;NM~4kT=5;!J9c^BxfaA}5kwT?wnYz~)Zh}Y;?B*o@%X@+>Mjzv;z4wq(# z*XdX!#pZBnhIqY>MN(`Imu84J=vXAh=5T3-c%zO*Qfv;FW{5ZGSR}>faA}5kvyMel zYz~)Zh_~oiB*o@%X@>Y;9gC#c94^feZ`H9#ip}BD4DmJ{i=@~bF3k{c*Re>7&Ee7v z@eUn}q}UuT%@FU@u}F%|;nEE8E**=c*c>j+5bxHpNQ%wj(hTt)9gC#c94^fe@71wL zip}BD4Dmi4i=@~bF3k|{*Re>7&Ee7v@c|u+q}UuT%@7~du}F%|;nEE8AsvgP*c>j+ z5FggDNQ%wj(hTtt9gC#c94^feAJwr)ip}BD4Dm4?i=@~bF3k`h*Re>7&Ee7v@d+J^ zq}UuT%@Ci|u}F%|;nEE8DIJTX*c>j+5TDkuNQ%wj(hTt#9gC#c94^fepVhHQip}BD z4DmS~i=@~bF3k|1*Re>7&Ee7v@dX`=q}UuT%@AMIu}F%|;nEE8B^`^T*c>j+5MS1@ zNQ%wj(hTtx9gC#c94^feU)8Zlip}BD4DmG`i=@~bF3k{M*Re>7&Ee7v@eLh|q}UuT z%@E(zu}F%|;nEE8Egg%b*c>j+5Z~6ZNQ%wj(hTt(9gC#c94^fe-_@~5ip}BD4Dmf3 zi=@~bF3k|%*Re>7&Ee7v@dF);q}UuT%@9A-u}F%|;nEE8BOQyR*c>j+5I@$jNQ%wj z(hTtv9gC#c94^feKh?2Fip}BD4DmA^i=@~bF3k`>*Re>7&Ee7v@e3V`q}UuT%@DuT zu}F%|;nEE8D;j+5Wm*3NQ%wj(hTt%9gC#c94^feztyowip}BD4DmZ1i=@~b zF3k|X*Re>7&Ee7v@dq7?q}UuT%@BXou}F%|;nEE8CmoBV*c>j+5P#OONQ%wj(hTtz z9gC#c94^fef7P)_ip}BD4DmM|i=@~bF3k{s*Re>7&Ee7v@edt~q}UuT%@F_8u}F%| z;nEE8FCB}d*c>j+5dYS(NQ%wj(hTt*9gC#c94^fe|JAWbip}BD4DsMGuN(6^TLvjM zhf6cWLv$>XVsp4OLp)T+A}Kb9OEbj7bS#o$bGS4^JY2^jDK>{oGsGiwERte#xHLmN zQpX}GHit_y#G`a9l45hXG($XE$08{{oGsF{gERte#xHLmNQO6=FHit_y#FKO^l45hXG($XD$08{{oGsH7=ERte#xHLmNQ^z7H zHit_y#ItlPl45hXG($XF$08{{oGsFvYERte#xHLn&P{$%EHit_y#EWz+l45hXG()^t$08{R2Sj=5T3-c$JPtQfv;FW{6koSR}>faA}5kjgCc9 zYz~)Zh}Y^^B*o@%X@+>6jzv;z4wq(#*Xvj$#pZBnhIoUHMN(`Imu84J>R2Sj=5T3- zc$1DrQfv;FW{5ZISR}>faA}5ki;hK7Yz~)Zi2v2GNQ%wj(hTud9gC#c94^feZ_}|z zip}BD4Dogyi=@~bF3k|{(6LC0&Ee7v@lG9!q}UuT%@FU>u}F%|;nEE8ZXJuH*c>j+ z5bx2kNQ%wj(hTul9gC#c94^fe@6)kJip}BD4Do&)i=@~bF3k`h(6LC0&Ee7v@j)Gn zq}UuT%@7~bu}F%|;nEE8VI7O4*c>j+5FgR8NQ%wj(hTuY9gC#c94^feAJef&ip}BD z4DoRti=@~bF3k|1(6LC0&Ee7v@kt$vq}UuT%@Ci`u}F%|;nEE8X&sBC*c>j+5TDVp zNQ%wj(hTug9gC#c94^fepVP5Oip}BD4Dop#i=@~bF3k{M(6LC0&Ee7v@kJerq}UuT z%@AMGu}F%|;nEE8WgUy8*c>j+5MR-;NQ%wj(hTuc9gC#c94^feU(>Njip}BD4Dodx zi=@~bF3k|%(6LC0&Ee7v@l73zq}UuT%@E(xu}F%|;nEE8Z5@lG*c>j+5Z}?UNQ%wj z(hTuk9gC#c94^fe-_x;3ip}BD4Do#(i=@~bF3k`>(6LC0&Ee7v@k1Spq}UuT%@9A* zu}F%|;nEE8V;zg6*c>j+5I@neNQ%wj(hTua9gC#c94^feKhv>Dip}BD4DoXvi=@~b zF3k|X(6LC0&Ee7v@kj+5Wmr}NQ%wj(hTui z9gC#c94^feztgcuip}BD4Dov%i=@~bF3k{s(6LC0&Ee7v@kbqtq}UuT%@BXmu}F%| z;nEE8XB~^A*c>j+5P#9JNQ%wj(hTue9gC#c94^fef77u@ip}BD4Dojzi=@~bF3k}C z(6LC0&Ee7v@lPF#q}UuT%@F_6u}F%|;nEE8Zyk%I*c>j+5dYD!NQ%wj(hTum9gC#c z94^fe4~_>O#3Cs+hf6cWLv$>XVsp4OLp)T+A}Kb9OEbj7bS#o$bGS4^JY2^jDK>{o zGsGiwERte#xHLmNQpX}GHit_y#G`a9l45hXG($XE$08{{oGsF{gERte#xHLmNQO6=FHit_y#FKO^l45hX zG($XD$08{{oGsH7= zERte#xHLmNQ^z7HHit_y#ItlPl45hXG($XF$08{{oGsFvYERte#xHLn&P{$%EHit_y#EWz+l45hXG()^t z$08{ZQc*q5cGgsM;~yL z!2`aIe!xF24|t0|@PFq)ERte#xHLn&T*o3QHit_y#4B_xl45hXG()^n$08{{oGsNq3ERte#xHLn&UdJLS zHit_y#2a)hl45hXG()^m$08{faA}5kn~p_NYz~)Zh_~xlB*o@%X@+=*jzv;z4wq(#cj{Oq z#pZBnhIp5bMN(`Imu84}>sTbk=5T3-c#n=nQfv;FW{CIdSR}>faA}5kpN>URYz~)Z zi1+JQB*o@%X@>ZKjzv;z4wq(#59(MX#pZBnhWL<sTbk=5T3-_=t{0 zQfv;FW{8jKSR}>faA}74n2tqKYz~)Zh>z=7B*o@%X@>ZOjzv;z4wq(#PwH4C#pZBn zhWM0@MN(`Imu84h>sTbk=5T3-_>7K4Qfv;FW{A(~SR}>faA}74oQ_3OYz~)Zh|lX- zB*o@%X@>ZMjzv;z4wq(#FX~t%#pZBnhWL_>MN(`Imu84B>sTbk=5T3-_==82Qfv;F zW{9uqSR}>faA}74nvO+MYz~)Zh_CBdB*o@%X@>ZQjzv;z4wq(#Z|Ybi#pZBnhWM6_ zMN(`Imu84>>sTbk=5T3-_>PW6Qfv;FW{B_VSR}>faA}74o{mLQYz~)Zi0|uIB*o@% zX@>ZLjzv;z4wq(#AL>{n#pZBnhWL?=MN(`Imu83`>sTbk=5T3-_=%21Qfv;FW{98a zSR}>faA}74nT|zLYz~)Zh@b0NB*o@%X@>ZPjzv;z4wq(#U+P#S#pZBnhWM3^MN(`I zmu84x>sTbk=5T3-_>GQ5Qfv;FW{BVFSR}>faA}74osLCPYz~)Zh~Mj2B*o@%X@>ZN zjzv;z4wq(#Kk8T{#pZBnhWL|?MN(`Imu84R>sTbk=5T3-_=}E3Qfv;FW{AJ)SR}>f zaA}74n~p_NYz~)Zh`;MtB*o@%X@>ZRjzv;z4wq(#f9hBy#pZBnhWM9`MN(`Imu856 z>sTbk=5T3-_>Yc7Qfv;FW{CglSR}>faA}5k@Po|j9%NqkAoIEhnb+Ae$l=lq@em!0 zq}UuT%@7aOu}F%|;nEE8Fdd7e*c>j+5D(X}NQ%wj(hTtk9gC#c94^fekJPb9ip}BD z4Dl!(i=@~bF3k{+*0D&6&Ee7v@faP8q}UuT%@B{(u}F%|;nEE8I30_m*c>j+5Rccf zNQ%wj(hTtg9gC#c94^fePt>tUip}BD4Dlo#i=@~bF3k{6*0D&6&Ee7v@f014q}UuT z%@9x3u}F%|;nEE8G#!hi*c>j+5Kq^!NQ%wj(hTto9gC#c94^fe&(yIj+5YN}KNQ%wj z(hTte9gC#c94^feFVwL}ip}BD4Dlizi=@~bF3k`x*0D&6&Ee7v@e&=2q}UuT%@8lu zu}F%|;nEE8G98Pg*c>j+5dWiNk=XieUZ=y22j+D;yzT%0S)NI;Ib50{Uan)26r01P z8R8W>7D=%=T$&+Xsbi58o5Q6U;#E2pNwGOxnjv1TW04e_!=)MGH98hau{m6tAzrIv zkrbQ5r5WONIu=Q>Ib50{Uaw=36r01P8R88(7D=%=T$&-?sAG{7o5Q6U;!QdhNwGOx znjzk-W04e_!=)MGEjkuSu{m6tA^um#A}Kb9OEbh{oGsN3< zERte#xHLn&L&qX1Hit_y#5;8?l45hXG()^g$08{DK>{oGsOFKERte#xHLn2K*u5}Hit_y#0PaOl45hXG(&ty z$08{{oGsMSrERte# zxHLn2LdPO0Hit_y#3ywul45hXG(&t!$08{{oGsNe0ERte#xHLn2LB}E~Hit_y#20lel45hXG(&tz$08{< zhf6cWmvt{oGsM?*ERte#xHLn2 zL&qX1Hit_y#5Z*;l45hXG(&t#$08{{oGsO3GERte#xHLojK*u5}Hit_y#1C~Wl45hXG(-GI$08{{oGsMqzERte#xHLojLdPO0 zHit_y#4mL$l45hXG(-GK$08{{oGsN$8ERte#xHLojLB}E~Hit_y#2{oGsNF@ERte#xHLojL&qX1Hit_y z#6NW`l45hXG(-GL$08{Ib50{9;IWE6r01P8RF487D=%=T$&*sqhpa2o5Q6U;;}jwNwGOxnjs#i zW04e_!=)MG@j4bsu{m6tA)cUPkrbQ5r5WOhIu=Q>Ib50{o}^=u6r01P8RE%07D=%= zT$&-CqGOR1o5Q6U;;A|oNwGOxnjxO1W04e_!=)MG={goku{m6tA)cXQkrbQ5r5WOx zIu=Q>Ib50{o~2`v6r01P8RFSG7D=%=T$&-Cqhpa2o5Q6U;<-8&NwGOxnjxO2W04e_ z!=)MG`8pO!u{m6tAzq+kkrbQ5r5WOdIu=Q>Ib50{UZi7@6r01P8REq{7D=%=T$&+X zqGOR1o5Q6U;-xwkNwGOxnjv1MW04e_!=)MGe{?L8!q#u|Ivs92Ft5`+pyU5eQfv;F zW{8*TSR}>faA}5kg^op1Yz~)Zh*#=ZB*o@%X@+=}jzv;z4wq(#SL;|L#pZBnhIoyR zMN(`Imu869>R2Sj=5T3-c%6<#Qfv;FW{B78SR}>faA}5kgN{W~Yz~)Zh&Sq3B*o@% zX@+={jzv;z4wq(#H|tm=#pZBnhIosPMN(`Imu86n)v-v5&Ee7v@m3v+q}UuT%@A+X zu}F%|;nEE8b{&hP*c>j+5bw~jNQ%wj(hTuV9gC#c94^fe@6xeIip}BD4DoIqi=@~b zF3k|{(XmL1&Ee7v@m?K^q}UuT%@FU?u}F%|;nEE8ejSUX*c>j+5FgO7NQ%wj(hTuI z9gC#c94^feAJVZ%ip}BD4Dn$di=@~bF3k`h(XmL1&Ee7v@lhR%q}UuT%@7~cu}F%| z;nEE8aUF}K*c>j+5TDSoNQ%wj(hTuQ9gC#c94^fepVF~Nip}BD4Do3li=@~bF3k|1 z(XmL1&Ee7v@mU>j+5MR)-NQ%wj(hTuM9gC#c z94^feU(&Hiip}BD4Dn?hi=@~bF3k{M(XmL1&Ee7v@l_p*q}UuT%@AMHu}F%|;nEE8 zbsdYO*c>j+5Z}j+5I@kdNQ%wj(hTuK9gC#c94^fe zKhm*Cip}BD4Dn+fi=@~bF3k`>(XmL1&Ee7v@lzd(q}UuT%@9A+u}F%|;nEE8a~+GM z*c>j+5Wmo|NQ%wj(hTuS9gC#c94^feztXWtip}BD4Do9ni=@~bF3k|X(XmL1&Ee7v z@mn2>q}UuT%@DuSu}F%|;nEE8dmW3U*c>j+5P#6INQ%wj(hTuO9gC#c94^fef6}o? zip}BD4Dn|ji=@~bF3k{s(XmL1&Ee7v@mC#-q}UuT%@BXnu}F%|;nEE8cO8qQ*c>j+ z5dYAzNQ%wj(hTuW9gC#c94^fe|I)EYip}BD4DoLri=@~bF3k}C(XmL1&Ee7v@n0Q_ zq}UuT%@7avH3o~M*c>j+5D(F@NQ%wj(hTuX9gC#c94^fe57V(oip}BD4DoOsi=@~b zF3k{+(6LC0&Ee7v@kkwuq}UuT%@B{$u}F%|;nEE8XdR2B*c>j+5RcKZNQ%wj(hTuf z9gC#c94^fekJGV8ip}BD4Dom!i=@~bF3k{6(6LC0&Ee7v@kAYqq}UuT%@9x0u}F%| z;nEE8WF3p7*c>j+5KqyuNQ%wj(hTub9gC#c94^fePt&nTip}BD4Doawi=@~bF3k|n z(6LC0&Ee7v@k||yq}UuT%@EJhu}F%|;nEE8Y#ocF*c>j+5YN%ENQ%wj(hTuj9gC#c z94^fe&(pC;ip}BD4Doy&i=@~bF3k`x(6LC0&Ee7v@j@Moq}UuT%@8lru}F&l$I(44 zQP^XR8oi}dlBvsU+qVC<-Cx_bZQHIrc2{b=N6&E%X04SOBtE!+Nof z&EXOxMKi3I=-3=CK~glsdZ~`h;SwZ8Gpv{C*c>i_t>5N#I=pybUZ=xt|G#s6gQRGN z^>Q7X!zD~M#u{m6Vq-ciqN*$ZSB}j^9Sg+EtIb4FIXomG_9h<`?NQ!1yuhFqN zT!N%%hV@z{~~u{m6Vq-ciqMje~OB}j^9 zSZ~s?Ib4FIXomG>9h<`?NQ!1yZ_%+iT!N%%hV@n*o5LkYie^}E)3G^Rf~07M^>!Vb z!zD z!+MX7&EXOxMKi4T>ew7EK~glsdY_KX;SwZ8GpzUP*c>iFQZ&Q*fR4@K5+p@4tPkqg z94!}^Gh&EXOxMKi3A>ew7EK~gls`k0Q*;SwZ8 zGpvv6*c>iFQZ&Q*gpSSO5+p@4tWWCL94!}^Sl z&EXOxMKi3=>ew7EK~gls`kao<;SwZ8Gpx_+*c>iFQZ&Q*f{xAM5+p@4tS{==94!}^Mj&EXOxMKi3g>ew7EK~gls`kIc-;SwZ8Gpw)c z*c>iFQZ&Q*hK|kQ5+p@4tZ(Yr94!}^Yn&EXOx zMKi4L>ew7EK~gls`ks!>;SwZ8Gpz6H*c>iFQZ&Q*fsW1L5+p@4tRL#w94!}^Ji&EXOxMKi3Q>ew7EK~gls`k9W+;SwZ8GpwKM*c>iF zQZ&Q*g^tbP5+p@4tY7Nb94!}^Vm&EXOxMKi45 z>ew7EK~gls`kju=;SwZ8Gpyh1*c>iFQZ&Q*gO1JN5+p@4tUv1594!}^Pk&EXOxMKi3w>ew7EK~gls`kRi;;SwZ8GpxVs*c>iFQZ&Q* zhmOtR5+p@4tbgj*94!}^bo&EXOxMKi4b>ew7E zK~glsdXRrku{m6Vq-ciqU>%#oB}j^9SP#*$Ib4FIXomGr9h<`?NQ!1y57V(ZT!N%% zhV^hAo5LkYie^}k(6KpOf~07M^++9?!zD}BXu{m6Vq-ciqXdRowB}j^9SdY=M zIb4FIXomGz9h<`?NQ!1ykJGU^T!N%%hV^(Io5LkYie^|((6KpOf~07M^+X+;!zD`_!M zu{m6Vq-ciqVjY{qB}j^9STE7BIb4FIXomGt9h<`?NQ!1yFVnF(T!O^bZ}U1GUOX_b z)8V%N-wEHOXomH29h<`?NQ!1yuh6kMT!N%%hV@Dvo5LkYie^}^(y=*Qf~07M^=ciP z!zD~M$u{m6Vq-ciqS{<9iB}j^9Sg+HuIb4FIXomHA9h<`?NQ!1yZ_u$hT!N%% zhV@1ro5LkYie^}E(y=*Qf~07M^=2KL!zD|00u{m6Vq-ciqRvnweB}j^9SZ~v@ zIb4FIXomH69h<`?NQ!1y@6fS1T!N%%hV@Pzo5LkYie^~v(y=*Qf~07M^?;7e;SwZ8 zGpu*(*c>iFQZ&PQkB-gZ5+p@4toQ2J94!}@@Z z&EXOxMKi1q>ew7EK~gls`jC#z;SwZ8GprBm*c>iFQZ&Q*h>p$S5+p@4tdHv094!}^4d&EXOxMKi2V>ew7EK~gls`jn2%;SwZ8GptYR z*c>iFQZ&Q*jE>FW5+p@4tk3G$94!}@}b&EXOx zMKi1~>ew7EK~gls`jU>#;SwZ8GpsM`*c>iFQZ&Q*ijK|U5+p@4tgq_W94!}^Af&EXOxMKi2#>ew7EK~gls`j(E(;SwZ8Gpujx*c>iF zQZ&Q*j*iXY5+p@4tncdB94!}@`a&EXOxMKi1) z>ew7EK~gls`jL*!;SwZ8Gprx$*c>iFQZ&Q*iH^!}^7e&EXOxMKi2l>ew7EK~gls`jw8&;SwZ8Gpt|h*c>iFQZ&Q* zjgHOX5+p@4tl#R`94!}^1c&EXOxMKi2F>ew7E zK~gls`jd{$;SwZ8Gps-B*c>iFQZ&Q*i;m6V5+p@4tiS5m94E!}^Dg&EXOxMKi2_>ew7EK~gls`j?K);SwZ8Gpv8>*c>iFQZ&Q*kB-gZ z5+p@4tpDoR94!+Nle&EXOxMKi32=-3=CK~glsdZ>=g;SwZ8 zGpvW{*c>iFQZ&PQxQ@-?5+p@4tVihB94!+Nxi z&EXOxMKi3&=-3=CK~glsdaRDk;SwZ8Gpxty*c>iFQZ&PQypGM`5+p@4tS9K$94!+Nrg&EXOxMKi3Y=-3=CK~glsda91i;SwZ8GpwiS z*c>iFQZ&PQx{l4^5+p@4tY_%h94!+N%k&EXOx zMKi4D=-3=CK~glsdajPm;SwZ8Gpy(7*c>iFQZ&PQzK+e|5+p@4tQY9m94E!+Nof&EXOxMKi3I=-3=CK~glsdZ~`h;SwZ8Gpv{C*c>iF zQrP-!UZ?v%9ezb^UZ>;#pQLDp^>Q7X!zD~M#u{m6Vq-ciqN*$ZSB}j^9Sg+Et zIb4FIXomG_9h<`?NQ!1yuhFqNT!N%%hV@z{~~u{m6Vq-ciqMje~OB}j^9SZ~s?Ib4FIXomG>9h<`?NQ!1yZ_%+iT!N%%hV@n* zo5LkYie^}E)3G^Rf~07M^>!Vb!zD!+MX7&EXOxMKi4T>ew7EK~glsdY_KX;SwZ8GpzUP z*c>iFQZ&Q*fR4@K5+p@4tPkqg94!}^Gh&EXOx zMKi3A>ew7EK~gls`k0Q*;SwZ8Gpvv6*c>iFQZ&Q*gpSSO5+p@4tWWCL94!}^Sl&EXOxMKi3=>ew7EK~gls`kao<;SwZ8Gpx_+*c>iF zQZ&Q*f{xAM5+p@4tS{==94!}^Mj&EXOxMKi3g z>ew7EK~gls`kIc-;SwZ8Gpw)c*c>iFQZ&Q*hK|kQ5+p@4tZ(Yr94!}^Yn&EXOxMKi4L>ew7EK~gls`ks!>;SwZ8Gpz6H*c>iFQZ&Q* zfsW1L5+p@4tRL#w94!}^Ji&EXOxMKi3Q>ew7E zK~gls`k9W+;SwZ8GpwKM*c>iFQZ&Q*g^tbP5+p@4tY7Nb94!}^Vm&EXOxMKi45>ew7EK~gls`kju=;SwZ8Gpyh1*c>iFQZ&Q*gO1JN z5+p@4tUv1594!}^Pk&EXOxMKi3w>ew7EK~gls z`kRi;;SwZ8GpxVs*c>iFQZ&Q*hmOtR5+p@4tbgj*94!}^bo&EXOxMKi4b>ew7EK~glsdXN{%*&HrGQZ&PQu#U~)5+p@4tcU2>94!+N-m&EXOxMKi2N=-3=CK~glsdZdoc;SwZ8GptAH z*c>iFQZ&PQw2sZ;5+p@4tjFls94!+N}q&EXOx zMKi1?=-3=CK~glsdZLca;SwZ8Gpr}+*c>iFQZ&PQvX0H+5+p@4tf%PM94!+N@o&EXOxMKi2t=-3=CK~glsdZv!e;SwZ8GpuLn*c>iF zQZ&PQwvNr=5+p@4tmo+194!+O4s&EXOxMKi1y z=-3=CK~glsdZCWZ;SwZ8GprZs*c>iFQZ&PQv5w8*5+p@4te5E694wtkz}>G0x#d7Tco{r^t+Hp6!+NET z&EXOxMKi2d>DU}DK~glsdbN(t;SwZ8GpyI>*c>iFQZ&PQt&Yv%5+p@4tk>z-94!+N8R&EXOxMKi27>DU}DK~glsdb5tr;SwZ8Gpx7h z*c>iFQZ&PQtB%d#5+p@4thedd94!+NKV&EXOx zMKi2->DU}DK~glsdO*kKa0!y48P>aXYz~(oDVkxuN5|%H36i22)_Zkq4woP)nqj?9 z$L4SelA;;b`*my%mmn#cVSPZy=5Ps;q8Zi)b!-loASs$*eMraVa0!y48Pn0G4woP)nqhrS$L4SelA;;b*L7?Tmmn#cVSPi#=5Ps;q8ZjVb!-lo zASs$*eM`sYa0!y48P>OTYz~(oDVkw@N5|%H36i22)^~Mm4woP)nqhrU$L4SelA;;b z_jPOzmmn#cVf{eI=5Ps;q8Zi?b!-loASs$*{Yb~=a0!y48P<<=Yz~(oDVkyZM91cE z36i22)=zb84woP)nqmD+$L4SelA;;b&vk4Lmmn#cVf{kK=5Ps;q8ZjNb!-loASs$* z{YuB?a0!y48P>0LYz~(oDVkyZM#tuG36i22)^Bxe4woP)nqmD;$L4SelA;;b?{#br zmmn#cVf{hJ=5Ps;q8Zj7b!-loASs$*{Yl5>a0!y48P=b5Yz~(oDVkyZMaSlF36i22 z)?amO4woP)nqmD-$L4SelA;;b-*s#bmmn#cVf{nL=5Ps;q8Zjdb!-loASs$*{Y%H@ za0!y48P>mbYz~(oDVkyZN5|%H36i22)_-+u4woP)nqfW2_CPj=OOO=JupX>qbGQUa z(G2S$IyQ$(kQB|Z9;#z=xCBYj4C`S!Hit`)6wR<6u48k!1WC~h>k&FOhf9zY&9EM+ zV{^C!Nzn}JQ93qxCBYj4C`?^Hit`) z6wR<6uVZt#1WC~h>j^qGhf9zY&9I)RV{^C!Nzn}JNjf%%OOO=Ju%4`AbGQUa(G2S; zIyQ$(kQB|Zo~mPWxCBYj4C`q+Hit`)6wR=nu48k!1WC~h>lr#Whf9zY&9I)SV{^C! zNzn}JSvod{OOO=Ju%4}BbGQUa(G2T3IyQ$(kQB|Zo~vVXxCBYj4C{G1Hit`)6wR=n zuVZt#1WC~h>jgSChf9zY&9GjmV{^C!Nzn}JMLITzOOO=JuwJZVbGQUa(G2S)IyQ$( zkQB|ZUaDhrxCBYj4C`e&Hit`)6wP4kw|SioFCLiJ>2TZs@3il*Uan(vxCBYj4C@s- zHit`)6wR<+sbh1v1WC~h>s2~7hf9zY&9GjrV{^C!Nzn}JH99tjOOO=JuwJWUbGQUa z(G2T#IyQ$(kQB|ZUawSsAF@u1WC~h>rFZ~hf9zY&9L6A zV{^C!Nzn}JEjl)bOOO=Ju->X;bGQUa(G2TtIyQ$(kQB|Z-mYVFxCBYj4C@^_Hit`) z6wR>Ssbh1v1WC~h>s>lFhf9zY&9ENOu{m6Vq-ciqZXKJ$B}j^9SntuXIb4FIXomG( z9h<`?NQ!1y@6)k4T!N%%hV_0Oo5LkYie^|J(6KpOf~07M^+6q*!zD_E6u{m6V zq-ciqVI7;pB}j^9SRc``Ib4FIXomGs9h<`?NQ!1yAJefpT!N%%hV^kBo5LkYie^}! z(6KpOf~07M^+_F@!zD}xnu{m6Vq-ciqX&sxxB}j^9SfA0cIb4FIXomG!9h<`? zNQ!1ypVP59T!N%%hV^+Jo5LkYie^|}(6KpOf~07M^+g?{a+u{m6Vq-ciq zWgVNtB}j^9SYOexIb4FIXomGw9h<`?NQ!1yU(>NUT!N%%hV^wFo5LkYie^~f(6KpO zf~07M^-Ud{!zD`Pcu{m6Vq-ciqV;!5r zB}j^9SU=IRIb4FIXomGu9h<`?NQ!1yKhv=}T!N%%hV^qDo5LkYie^~9(6KpOf~07M z^-CR_!zD~+{u{m6Vq-ciqYaN@zB}j^9SijM+Ib4FIXomG$9h<`?NQ!1yztgcf zT!N%%hV^?Lo5LkYie^}U(6KpOf~07M^+z3>!zD|mHu{m6Vq-ciqXC0fvB}j^9 zSbx#6Ib4FIXomGy9h<`?NQ!1yf77u!T!N%%hV^$Ho5LkYie^~<(6KpOf~07M^-mp} z!zD^o=u{m6Vq-ciqP#v4YB}j^9SP#>&Ib4FIXomH09h<`?NQ!1y zkI=C>T!N%%hV@7to5LkYie^}k(y=*Qf~07M^=KWN!zD}BWu{m6Vq-ciqSRI?g zB}j^9SdY`OIb4FIXomH89h<`?NQ!1yPtdVBT!N%%hV?`po5LkYie^|((y=*Qf~07M z^<*8J!zD`_!Lu{m6Vq-ciqQXQMaB}j^9STEDDIb4FIXomHFI&2a$uhZdI)aG?M{{I=) z%XMrHmmn#cVZB1f=5Ps;q8ZjJb!-loASs$*y-LUCa0!y48P=ve1nmmn#cVZA}e=5Ps;q8Zj3b!-loASs$* zy-COBa0!y48P=P1Yz~(oDVkxuMaSlF36i22)?0OK4woP)nqj?7$L4SelA;;b+jVRX zmmn#cVZB4g=5Ps;q8ZjZb!-loASs$*y-UaDa0!y48P)?jHit`)6wR>Stz&bz1WC~h z>peO)hf9zY&9L69V{^C!Nzn}JeL6OWOOO=Ju->m@bGQUa(G2SYIyQ$(kQB|ZKB!}J zxCBYj4C_NWHit`)6wRmxcghf9zY&9FYIV{^C!Nzn}JV>&j6OOO=J zus*J1bGQUa(G2SoIyQ$(kQB|ZKB;4KxCBYj4C_-mHit`)6wRoYnw zhf9zY&9FYJV{^C!Nzn}Jb2>JMOOO=Jus*M2bGQUa(G2SgIyQ$(kQB|ZzNlk!xCBYj z4C_leHit`)6wR={tYdSy1WC~h>nl1ohf9zY&9J_zV{^C!Nzn}JYdSWEOOO=Ju)eNi zbGQUa(G2SwIyQ$(kQB|ZzNuq#xCBYj4C`AuHit`)6wR={tz&bz1WC~h>pMC&hf9zY z&9J_!V{^C!Nzn}Jdpb6UOOO=Ju)eQjbGQUa(G2ScIyQ$(kQB|ZeyC$}xCBYj4C_Za zHit`)6wR=HtYdSy1WC~h>nA!khf9zY&9Hu|V{^C!Nzn}JXF4{AOOO=Juzs#%bGQUa z(G2SsIyQ$(kQB|ZeyL+~xCBYj4C_}qHit`)6wR=Htz&bz1WC~h>o+ytYdSy1WC~h>n}Pshf9zY&9MHeV{^C!Nzn}JZ#p)IOOO=Ju>P)NbGQUa(G2S! zIyQ$(kQB|Z{;6YgxCBYj4C`MyHit`)6wR>ytz&bz1WC~h>pwa+hf9zY&9MHfV{^C! zNzn}JL1SJw=5@9QatV^68PCzC4woP)nqfUn$L4SelA;;b z({*ePmmn#cVLd~~=5Ps;q8ZjRb!-loASs$*Jxj;ta0!y48P>CPYz~(oDVkwDN5|%H z36i22)^l}i4woP)nqfUp$L4SelA;;b^L1v4woP)nqj?4$L4SelA;;b zt95J+mmn#cVZBDj=5Ps;q8Zj}b!-loASs$*y-vsGa0!y48P@A{Yz~(oDVkxuLC5BB z36i22)*E$f4woP)nqj?3$L4SelA;;bn{{jsmmn#cVZBAi=5Ps;q8Zj(b!-loASs$* zy-mmFa0!y48P?l%Yz~(oDVkxuL&xTD36i22);o1<4woP)nqj?5$L4SelA;;b13ET` zOOO=Ju->g>bGQUa(G2T7IyQ$(kQB|Z-m7DCxCBYj4C{S5Hit`)6wR>SuVZt#1WC~h z>jOGAhf9zY&9FYGV{^C!Nzn}JLpnBxOOO=Jus*C~bGQUa(G2S&IyQ$(kQB|ZKB{AL zxCBYj4C`Y$Hit`)6wRk~RQhf9zY&9FYHV{^C!Nzn}JQ#v+>OOO=J zus*G0bGQUa(G2S|IyQ$(kQB|ZKC5GMxCBYj4C`|`Hit`)6wRkB$I zhf9zY&9J_xV{^C!Nzn}JOFA}(OOO=Ju)eHgbGQUa(G2S=IyQ$(kQB|ZzN%w$xCBYj z4C`w;Hit`)6wR={u48k!1WC~h>l->Yhf9zY&9J_yV{^C!Nzn}JTRJv}OOO=Ju)eKh zbGQUa(G2T5IyQ$(kQB|ZzN=$%xCBYj4C{M3Hit`)6wR={uVZt#1WC~h>jyeEhf9$E zkE6Rt5+KGEExIMOY)SU=nwgoInVFfHnVA{mpZCLYa&*U)QK~GN;c$r`=|~ovq8SdC z__2;;u_>D2aEYJjNEVx-84j2Dsg7i^DVpJMiJ$367Mr3O4wv}3j%2YZn&EJXU+72{ zo1z&Gm-wZQWU(ol;c$sx=|~ovq8SdC__dB?u_>D2aEagONEVx-84j2Dt&U`|DVpJM ziQnl+7Mr3O4wv}7j%2YZn&EJXKj=sno1z&Gm-wTOWU(ol;c$sR=|~ovq8SdC__K~= zu_>D2aEZU@NEVx-84j2DtBz!`DVpJMiNEPc7Mr3O4wv}5j%2YZn&EJXf9OaSo1z&G zm-wfSWU(ol;c$t6=|~ovq8SdC__vN^u_>D2aEbruNEVx-84j2Dua0D~DVpJMiT~+H z7Mr3O4wrafy!-(qi%roChf6$2N3z%y&2YHHgLNc}P0OaJa-nbtH>T z(F})6JWNNj*c8ohxWvPCB#TYa42MfRLPxUL6wPqB#3OYii%roChf6$4N3z%y&2YHH zqje;UP0OaJa-{btH>T(F})6JWfZl*c8ohxWwaiB#TYa42MfRK}WLK z6wPqB#1nNSi%roChf6$3N3z%y&2YHHlXWDEP0OaJa-%btH>T(F})6 zJWWTk*c8ohxWvOaJa;CbtH>T(F})6JWofm*c8ohxWw~yB#TYa42Mg+Ku5CJ6wPqB z#0zyKi%roChfBOjN3z%y&2YHHi*+Q6P0OaJa-vbtH>T(F})6yi7;p z*6)|QN$BOalfK->gO~e?`sMyI^Kw7!U;cmR0VIn}(F})6yh2B^*c8ohxWp@UB#TYa z42Mg+N=LHT6wPqB#H)2Ai%roChfBOhN3z%y&2YHHYjq@xP0OaJaT(F})6yg^5@*c8ohxWpTEB#TYa42Mg+Nk_8S6wPqB#G7>_i%roChfBOgN3z%y z&2YHHTXiIhP0OaJaT(F})6yhBH_*c8ohxWqekB#TYa42Mg+ zOGmQU6wPqB#JhDQi%roChfBOiN3z%y&2YHHdvzp>P0OaJa<#btH>T z(F})6d_YIC*c8ohxWor_B#TYa42Mg6NJp~R6wPqB#D{exi%roChf91!N3z%y&2YHH zM|C8NP0OaJaT(F})6d_qUE*c8ohxWp%QB#TYa42Mg6N=LHT z6wPqB#HV#6i%roChf91$N3z%y&2YHHXLTftP0OaJaT(F})6 zd_hOD*c8ohxWpHAB#TYa42Mg6Nk_8S6wPqB#Fup>i%roChf91#N3z%y&2YHHS9K(d zP0OaJaT(F})6d_zaF*c8ohxWqSgB#TYa42Mg6OGmQU6wPqB z#J6=Mi%roChf91%N3z%y&2YHHcXcF-P0OaJaT(F})6{6I&t z*c8ohxWo^2B#TYa42MhnNJp~R6wPqB#E*3(i%roChfDlKN3z%y&2YHHPjw`VP0OaJaT(F})6{6a^v*c8ohxWq4YB#TYa42MhnN=LHT6wPqB#IJQE zi%roChfDlMN3z%y&2YHHZ*?S#P0OaJaT(F})6{6R;u*c8oh zxWpfIB#TYa42MhnNk_8S6wPqB#GiE}i%roChfDlLN3z%y&2YHHUv(slP0OaJaT(F})6{6j~w*c8ohxWqqoB#TYa42MhnOGmQU6wPqB#J_bUi%roC zhfDlNN3z%y&2YHHe|02_P0OaJa++A7Ebh0Q0&BnAbhPyw2@`G{fN% z57Ln=HbpZWF7aR;$zoG9!{HJS(UB}RMKc^O@lYMfVpBB3;Svwikt{YvGaN4Qa2?5F zQ#8Zj5|7Z4EH*_m94_%l9m!%-G{fN%kJ6DWHbpZWF7ap`$zoG9!{HK-(UB}RMKc^O z@mL+nVpBB3;S!J2kt{YvGaN4Qcpb@NQ#8Zj5>L>PEH*_m94_%h9m!%-G{fN%PtuVr zHbpZWF7ad?$zoG9!{HK7(UB}RMKc^O@l+kjVpBB3;Sx{Nkt{YvGaN4QbREfJQ#8Zj z63@_)EH*_m94_%p9m!%-G{fN%&(e`BHbpZWF7a#~$zoG9!{HLo(UB}RMKc^O@mw9r zVpBB3;S$f&kt{YvGaN4Qd>zSRQ#8Zj5--q^EH*_m94_%f9m!%-G{fN%FVc}LHbpZW zF7aX=$zoG9!{HJy(UB}RMKc^O@lqYhVpBB3;Sw*?ku2N}ZeFLuW(4y(9o`E6|D@+) zQ#8Zj60gvaEH*_m94_%n9m!%-G{fN%uhNk$HbpZWF7av|$zoG9!{HLI(UB}RMKc^O z@md|pVpBB3;S#UYkt{YvGaN4QdL7APQ#8Zj5^vCvEH*_m94_%j9m!%-G{fN%Z_<%0 zHbpZWF7aj^$zoG9!{HKd(UB}RMKc^O@m3wlVpBB3;Sz7tkt{YvGaN4Qb{)xLQ#8Zj z67SHFEH*_m94_%r9m!%-G{fN%@6wShHbpZWF7a+1$zoG9!{HL|(UB}RMKc^O@m?Lt zVpBB3;S%rDkt{YvGaN4QejUkTQ#8Zj5+Bf!EH*_m94_%e9m!%-G{fN%AJUO5HbpZW zF7aU<$zoG9!{HJi(UB}RMKc^O@lhSgVpBB3;SwLykt{YvGaN4QaUIEGQ#8Zj5}(kK zEH*_m94_%m9m!%-G{fN%pVE;mHbpZWF7as{$zoG9!{HL2(UB}RMKc^O@mU?oVpBB3 z;S!(Ikt{YvGaN4Qc^%1OQ#8Zj5?|1fEH*_m94_%i9m!%-G{fN%U(%5*HbpZWF7ag@ z$zoG9!{HKN(UB}RMKc^O@l_qkVpBB3;Syidkt{YvGaN4QbsfoKQ#8Zj65r5~EH*_m z94_%q9m!%-G{fN%-_nsRHbpZWF7a(0$zoG9!{HL&(UB}RMKc^O@m(FsVpBB3;S%4| zkt{YvGaN4QeI3bSQ#8Zj5$zoG9 z!{HJ?(UB}RMKc^O@lzeiVpBB3;SxX7kt{YvGaN4Qa~;WIQ#8Zj62H)qEH*_m94_%o z9m!%-G{fN%ztWK`HbpZWF7ay}$zoG9!{HLY(UB}RMKc^O@mn3qVpBB3;S#^okt{Yv zGaN4QdmYJQQ#8Zj5`WNEH*_m94_%79m!%-G{fN%57v<^HbpZWF7Xf@$zoG9!{HJS)sZYVMKc^O@h~09 zVpBB3;Svwmkt{YvGaN4Q2p!2{Q#8Zj5|7l8EH*_m94_%F9m!%-G{fN%kJgbaHbpZW zF7X&0$zoG9!{HK-)sZYVMKc^O@i-mHVpBB3;S!J6kt{YvGaN4Q1Rcp@Q#8Zj5>M2T zEH*_m94_%B9m!%-G{fN%Pu7tvHbpZWF7Xr{$zoG9!{HK7)sZYVMKc^O@iZODVpBB3 z;Sx{Rkt{YvGaN4Q3?0d0Q#8Zj63^6;EH*_m94_%J9m!%-G{fN%&(@JFHbpZWF7X^4 z$zoG9!{HLo)sZYVMKc^O@jM;LVpBB3;S$f+kt{YvGaN4Q0v*X>Q#8Zj5--$|EH*_m z94_%99m!%-G{fN%FV>MPHbpZWF7Xl_$zoG9!{HJy)sZYVMKc^O@iHCBV&isj^Ew?i zBbe9eUasT+&SFzE!{HLI(2*=QMKc^O@k$-ZVpBB3;S#UXkt{YvGaN4QY8}a9Q#8Zj z60gybEH*_m94_%%9m!%-G{fN%uhWq%HbpZWF7bLD$zoG9!{HKd(2*=QMKc^O@kSlV zVpBB3;Sz7skt{YvGaN4QW*y05Q#8Zj5^vFwEH*_m94_%z9m!%-G{fN%Z_|-1HbpZW zF7b99$zoG9!{HL|(2*=QMKc^O@lGAdVpBB3;S%rCkt{YvGaN4QZXL;DQ#8Zj67SKG zEH*_m94_%*9m!%-G{fN%@6(YiHbpZWF7bXH$zoG9!{HJi(2*=QMKc^O@j)HQVpBB3 z;SwLxkt{YvGaN4QVI9e0Q#8Zj5+Bi#EH*_m94_%u9m!%-G{fN%AJdU6HbpZWF7a_4 z$zoG9!{HL2(2*=QMKc^O@kt%YVpBB3;S!(Hkt{YvGaN4QX&uR8Q#8Zj5}(nLEH*_m z94_%$9m!%-G{fN%pVN^nHbpZWF7bIC$zoG9!{HKN(2*=QMKc^O@kJfUVpBB3;Syic zkt{YvGaN4QWgW?4Q#8Zj5?|4gEH*_m94_%y9m!%-G{fN%U(=B+HbpZWF7b68$zoG9 z!{HL&(2*=QMKc^O@l74cVpBB3;S%4{kt{YvGaN4QZ5_#CQ#8Zj65r90EH*_m94_%) z9m!%-G{fN%-_wySHbpZWF7bUG$zoG9!{HJ?(2*=QMKc^O@k1TSVpBB3;SxX6kt{Yv zGaN4QV;#w2Q#8Zj54Q#8Zj5)ajp zEH*_m94_%N9m!%-G{fN%57&__HbpZWF7XH*$zoG9!{HK-)R8PUMKc^O@hBb1VpBB3 z;S!J5kt{YvGaN4Q7#+!CQ#8Zj5|7o9EH*_m94_%V9m!%-G{fN%kJphbHbpZWF7X5% z$zoG9!{HK7)R8PUMKc^O@gyC|VpBB3;Sx{Qkt{YvGaN4Q6dlQ8Q#8Zj5>M5UEH*_m z94_%R9m!%-G{fN%PuGzwHbpZWF7XT<$zoG9!{HLo)R8PUMKc^O@hlz5VpBB3;S$f* zkt{YvGaN4Q939DGQ#8Zj63^9$zoG9!{HL|)R8PUMKc^O@h%<7VpBB3;S%rG zkt{YvGaN4Q9v#VIQ#8Zj67SWKEH*_m94_%b9m!%-G{fN%@7IwmHbpZWF7W{!$zoG9 z!{HJi)R8PUMKc^O@gW__VpBB3;SwL#kt{YvGaN4Q5go~5Q#8Zj5+Bu(EH*_m94_%O z9m!%-G{fN%AJ>sAHbpZWF7XK+$zoG9!{HL2)R8PUMKc^O@hKh2VpBB3;S!(Lkt{Yv zGaN4Q86C-DQ#8Zj5}(zPEH*_m94_%W9m!%-G{fN%pVyHrHbpZWF7X8&$zoG9!{HKN z)R8PUMKc^O@g*I}VpBB3;Syigkt{YvGaN4Q6&=Z9Q#8Zj5?|GkEH*_m94_%S9m!%- zG{fN%U)PZ=HbpZWF7XW=$zoG9!{HL&)R8PUMKc^O@hu(6VpBB3;S%50kt{YvGaN4Q z9UaMHQ#8Zj65rL4EH*_m94_%a9m!%-G{fN%-`9~WHbpZWF7X2$$zoG9!{HJ?)R8PU zMKc^O@gp6{VpBB3;SxXAkt{YvGaN4Q6CKH7Q#8Zj5OaJa<7btH>T(F})6JVHmZ*c8ohxWprMB#TYa z42MfRN=LHT6wPqB#G`d2i%roChf6$0N3z%y&2YHHV|65pP0OaJaT(F})6JV8gY*c8ohxWp56B#TYa42MfRNk_8S6wPqB#FKR-i%roChf6#~N3z%y z&2YHHQ*|VZP0OaJaT(F})6JVQsa*c8ohxWqGcB#TYa42MfR zOGmQU6wPqB#ItoIi%roChf6$1N3z%y&2YHHb9E$(P0OaJaT z(F})6yg)~?*c8ohxWo%}B#TYa42Mg+NJp~R6wPqB#EW$#i%roChfBOfN3z%y&2YHH zOLZiRP0H+$T;i2FlEtQI zhQlRZr6XBvie@-m;?+8m#inS6!zEs$BUx;UW;k5pwK|f;rf7!4C0?f^S!{}CI9%fO zI+DevXokZj-k>8{Y>H+$T;h#7lEtQIhQlS^q$62uie@-m;>|je#inS6!zJFLBUx;U zW;k5ptvZs$rf7!4CElhZS!{}CI9%fGI+DevXokZj-k~E|Y>H+$T;iQNlEtQIhQlS^ zr6XBvie@-m;@vuu#inS6!zJFMBUx;UW;k5py*iS`rf7!4CElkaS!{}CI9%fWI+Dev zXokZjKAH+$T;hW|lEtQIhQlR3q$62uie@-m;=?+U#inS6!zDhVBUx;UW;k5p zqdJnsrf7!4B|fGjS!{}CI9%f6I+DevXokZjKA|I7Y>H+$T;h{DlEtQIhQlR3r6XBv zie@-m;?p{k#inS6!zDhWBUx;UW;k5pvpSN+rf7!4B|fJkS!{}CI9%fMI+DevXokZj zzMvynY>H+$T;hv5lEtQIhQlSkq$62uie@-m;>$Xc#inS6!zI3=BUx;UW;k5pt2&a! zrf7!4CBCL3S!{}CI9%fEI+DevXokZjzM&&oY>H+$T;iKLlEtQIhQlSkr6XBvie@-m z;@dis#inS6!zI3>BUx;UW;k5pyE>A^rf7!4CBCO4S!{}CI9%fUI+DevXokZjexM^+ zY>H+$T;hj1lEtQIhQlR(q$62uie@-m;>S9Y#inS6!zF&ABUx;UW;k5pr#h0wrf7!4 zC4QzOS!{}CI9%fAI+DevXokZjexV~-Y>H+$T;i8HlEtQIhQlR(r6XBvie@-m;@3Ko z#inS6!zF&BBUx;UW;k5pw>px=rf7!4C4Q$PS!{}CI9%fQI+DevXokZj{-7gSY>H+$ zT;h*9lEtQIhQlTPq$62uie@-m;?Fvg#inS6!zKQrBUx;UW;k5puR4;&rf7!4CH|%( zS!{}CI9%fII+DevXokZj{-GmTY>H+$T;iWPlEtQIhQlTPr6XBvie@-m;@>)w#inS6 z!zKQsBUx;UW;k5pzdDk|rf7!4CH|))S!{}CI9%d^wil5sHbpZWF7Y58$zoG9!{HJS z){!hWMKc^O@em!!VpBB3;Svwkkt{YvGaN4QFdfNaQ#8Zj5)aprEH*_m94_$)9m!%- zG{fN%kJOPYHbpZWF7YTG$zoG9!{HK-){!hWMKc^O@faP+VpBB3;S!J4kt{YvGaN4Q zI33AiQ#8Zj5|7uBEH*_m94_$$9m!%-G{fN%Pt=htHbpZWF7YHC$zoG9!{HK7){!hW zMKc^O@f01&VpBB3;Sx{Pkt{YvGaN4QG#$xeQ#8Zj5>MBWEH*_m94_$;9m!%-G{fN% z&(x7DHbpZWF7YfK$zoG9!{HLo){!hWMKc^O@f;n=VpBB3;S$f)kt{YvGaN4QJRQkm zQ#8Zj63^F>EH*_m94_$!9m!%-G{fN%FVvANHbpZWF7YBA$zoG9!{HJy){!hWMKc^O z@e&=$VpBB3;Sw*^kt{YvGaN4QG9AfcQ#6Cy!OiP*FW2E~Yx6oC|96_D2aEUkQNEVx-84j0tqmE>;DVpJMi8tv;7Mr3O4wrbdj%2YZ zn&EJXx9CU~o1z&Gmw2m=WU(ol;c$t!=|~ovq8SdCc)N~du_>D2aEW*5NEVx-84j0t zr;cQ?DVpJMiFfHp7Mr3O4wrbhj%2YZn&EJX_vlC#o1z&Gmw2y^WU(ol;c$uf=|~ov zq8SdCc)yNhu_>D2aETA-NEVx-84j2DppIm*DVpJMi4W;W7Mr3O4wv|_j%2YZn&EJX zkLXAio1z&Gm-wiTWU(ol;c$tM=|~ovq8SdC__&T_u_>D2aEVXoNEVx-84j2Dq>f~< zDVpJMiBIWB7Mr3O4wv|}j%2YZn&EJX&*(@No1z&Gm-wuXWU(ol;c$u1=|~ovq8SdC z_`Hr}u_>D2aEUMINEVx-84j2DqK;&-DVpJMi7)9$7Mr3O4wv|{j%2YZn&EJXujoh? zo1z&Gm-woVWU(ol;c$ts=|~ovq8SdC__~f{u_>D2aEWi|NEVx-84j2DrjBH>DVpJM ziErsh7Mr3O4wv}0j%2YZn&EJX@90Pto1z&Gm-w!ZWU(ol;c$uX=|~ovq8SdC_`Z&0 zu_>D2aETx2NEVx-84j2Dp^jv+DVpJMi67}m7Mr3O4wv|`j%2YZn&EJXpXf*yo1z&G zm-wlUWU(ol;c$tc=|~ovq8SdC__>Z`u_>D2aEV{&NEVx-84j2DrH*8=DVpJMiC^hR z7Mr3O4wv|~j%2YZn&EJX-{?pdo1z&Gm-wxYWU(ol;c$uH=|~ovq8SdC_`Qx~u_>D2 zaEU+YNEVx-84j2DqmE>;DVpJMi9hK`7Mr3O4wv||j%2YZn&EJXzvxI7o1z&Gm-wrW zWU(ol;c$t+=|~ovq8SdC_`8l|u_>D2aEX8DNEVx-84j2Dr;cQ?DVpJMiGS%x7Mr3O z4wv}1j%2YZn&EJX|L8~-o1z&Gm-w%aWU(ol;c$un=|~ovq8SdCc%V(=B#TYa42MfR zNJp~R6wPqB#DjGti%roChf6#}N3z%y&2YHHLvOaJa<7btH>T z(F})6JVHmZ*c8ohxWprMB#TYa42MfRN=LHT6wPqB#G`d2i%roChf6$0N3z%y&2YHH zV|65pP0OaJaT(F})6JV8gY*c8ohxWp56B#TYa42MfRNk_8S z6wPqB#FKR-i%roChf6#~N3z%y&2YHHQ*|VZP0OaJaT(F})6 zJVQsa*c8ohxWqGcB#TYa42MfROGmQU6wPqB#ItoIi%roChf6$1N3z%y&2YHHb9E$( zP0OaJaT(F})6yg)~?*c8ohxWo%}B#TYa42Mg+NJp~R6wPqB z#EW$#i%roChfBOf_y0J$t7Qv&8_}Y#q}Z}0Jzk*0%*;vuVPqOl#^yiSLg5zOm!xE22Ily5V{13DI) zq8Z|qIu@Jca4DK0UZrEPNe-8y8RFGC7MtX7DViZ(qhqm24ws@C z;N>4u}Kb>q8Z|iIu@Jca4DK0-lSu( zNe-8y8RE@47MtX7DVibPqGPd14ws@C;;lLso8)jQnjzk%W3fpNm!cWs?K&2lN^5u}Kb>q8Z|yIu@Jca4DK0-lb!)Ne-8y8RFeK7MtX7DVibPqhqm24ws@C;=MW+ zo8)jQnjzk&W3fpNm!cWs{W=z#q8Z|YIu@Jca4DK0KBQx@Ne-8y z8REk_7MtX7DViZZqGPd14ws@C;-fkio8)jQnjt=>W3fpNm!cWs<2n|bq8Z|oIu@Jca4DK0KBZ%^Ne-8y8RFAA7MtX7DViZZqhqm24ws@C;q8Z|gIu@Jca4DK0zNBNZNe-8y8RE-2 z7MtX7DVia^qGPd14ws@C;;T9qo8)jQnjyZXW3fpNm!cWs>pB*j zq8Z|wIu@Jca4DK0zNKTaNe-8y8RFYI7MtX7DVia^qhqm24ws@C;=4K)o8)jQnjyZY zW3fpNm!cWs`#Khzq8Z|cIu@Jca4DK0exzfuNe-8y8REw}7MtX7 zDViaEqGPd14ws@C;-@+mo8)jQnjwCsW3fpNm!cWs=Qq8Z|s zIu@Jca4DK0ex+lvNe-8y8RFME7MtX7DViaEqhqm24ws@C;q8Z|kIu@Jca4DK0{-k5ENe-8y8RE}67MtX7DVibv zqGPd14ws@C;;%Xuo8)jQnj!wCW3fpNm!cWs?>ZKnq8Z|!Iu@Jc za4DK0{-tBFNe-8y8RFkM7MtX7DVibvqhqm24ws@C;=ei;o8)jQnjs!+Dq8Z{bIu@Jca4DK09;;)qNe-8y z8RBs|7MtX7DViZ3uVb-E4ws@C;t4tyo8)jQnjxO3W3fpNm!cWsNjesrq8Z{TIu@Jca4DK0o~mQ9Ne-8y8RBU=7MtX7DViaku4A!D4ws@C;u$&?o8)jQ znjxO4W3fpNm!cWsSvnS*q8Z{jIu@Jca4DK0o~vWANe-8y8RB_5 z7MtX7DViakuVb-E4ws@C;srVuo8)jQnjv1OW3fpNm!cWsMLHIn zq8Z{PIu@Jca4DK0UaDiUNe-8y8RBI+7MtX7DViZ(u4A!D4ws@CYzH^5)8Sq8Z|~Iu@Jca4DK0UZ-QRNe-8y8RGRi7MtX7DVibPpkuK~4ws@C;*B~M zo8)jQnjzk#W3fpNm!cWs%{msFN{6u}Kb>q8Z|?Iu@Jca4DK0-lk)*Ne-8y z8RG3a7MtX7DVibPp<}U04ws@C;+;Aco8)jQnjzk$W3fpNm!cWs-8vSVN~7 zu}Kb>q8Z}7Iu@Jca4DK0-lt=+Ne-8y8RGpq7MtX7DViZZpkuK~4ws@C;)6OCo8)jQ znjt=q8Z|&Iu@Jca4DK0KBi-_Ne-8y8RFwQ z7MtX7DViZZp<}U04ws@C;*&ZSo8)jQnjt==W3fpNm!cWs(>fNL zq8Z||Iu@Jca4DK0KBr@`Ne-8y8RGLg7MtX7DVia^pkuK~4ws@C;)^;Ko8)jQnjyZV zW3fpNm!cWs%Q_aDq8Z|=Iu@Jca4DK0zNTZbNe-8y8RF|Y7MtX7 zDVia^p<}U04ws@C;+r}ao8)jQnjyZWW3fpNm!cWs+d3ATq8Z}5 zIu@Jca4DK0zNcfcNe-8y8RGjo7MtX7DViaEpkuK~4ws@C;)gmGo8)jQnjwCqW3fpN zm!cWs$2u09q8Z|+Iu@Jca4DK0ex_rwNe-8y8RF+U7MtX7DViaE zp<}U04ws@C;+HxWo8)jQnjwCrW3fpNm!cWs*E$xPq8Z}1Iu@Jc za4DK0ey3xxNe-8y8RGXk7MtX7DVibvpkuK~4ws@C;*UBOo8)jQnj!wAW3fpNm!cWs z&pH;Hq8Z|^Iu@Jca4DK0{-$HGNe-8y8RG9c7MtX7DVibvp<}U0 z4ws@C;-5Meo8)jQnj!wBW3fpNm!cWs-#QkXq8Z}9Iu@Jca4DK0 z9^B@2wgR$A4ws@C;vqT~o8)jQnjs#lW3fpNm!cWsVLBF@HZGsGixEH=sEQZz$6O2=Z894CBoLp)B$Vv`&$MKi?Xbu2c?;Zih1JVD1|lN>HZGsF{hEH=sEQZz$6 zNylQ794CBoLp)8#Vv`&$MKi?Hbu2c? z;Zih1JVVD~lN>HZGsH7>EH=sEQZz$6OUGi994$>CBoLp)E%Vv`&$MKi?nbu2c?;Zih1ygHZGsFvZEH=sEQZz%nNXKH6 z94CBoL%dAKVv`&$MKi?9bu2c?;Zih1 z{I3ohhs^7A__eiposR#1hIl~7Vv`&$MKi=JbSyT>;Zih1yi&(vlN>HZGsLTOEH=sE zQZz%nTE}9O94vSwO$>CBoL%d$cVv`&$MKi=3 zbSyT>;Zih1yivzulN>HZGsK&8EH=sEQZz%nS;u0N94CBoL%dzbVv`&$MKi=ZbSyT>;Zih1yi>HZGsL@eEH=sEQZz%n zTgPIP94CBoL%d(dVv`&$MKi<)bSyT> z;Zih1d{DHZGsK5CBoLwsDvVv`&$MKi=FbSyT>;Zih1d{W0^lN>HZGsLHKEH=sEQZz$+TE}9O z94CBoLwsJxVv`&$MKi<~bSyT>;Zih1 zd{M_@lN>HZGsKs4EH=sEQZz$+S;u0N94CBoLwsGwVv`&$MKi=VbSyT>;Zih1d{f6_lN>HZGsL%aEH=sEQZz$+TgPIP94$6}KlE=4oM_jD{a$>CBoLwsMyVv`&$MKi;Zih1{7}bY zlN>HZGsKT{EH=sEQZz&SSjS?M94CBo zL;PIFVv`&$MKi=NbSyT>;Zih1{8GnalN>HZGsLfSEH=sEQZz&STE}9O94CBoL;POHVv`&$MKi=7bSyT>;Zih1{87hZlN>HZ zGsK^CEH=sEQZz&SS;u0N94CBoL;PLG zVv`&$MKi=dbSyT>;Zih1{8PtblN>HZGsM4iEH=sEQZz&STgPIP94(#t%@B{) zvDhSsOVJGR7#)jEa<~-D5RcWd*d&Kb(G2l89g9tJxD?G0kJqu-B!^4U4DkdVi%oL4 z6wMG%)UntkhfC26@gyCKO>(#t%@9x4vDhSsOVJGR6dj9Aa<~-D5Kq;y*d&Kb(G2l4 z9g9tJxD?G0PuH>7B!^4U4Dk#di%oL46wMIN)UntkhfC26@hlySO>(#t%@EJlvDhSs zOVJGR936{Ia<~-D5YN@I*d&Kb(G2lC9g9tJxD?G0&)2coB!^4U4DkXTi%oL46wMGX z)UntkhfC26@gg0IO>(#t%@8lvvDhSsOVJGR5*>?8a<~-D5HHoS*d&Kb(G2l29g9tJ zxD?G0FW0fyB!^4U4Dr7@YzH^5)8SRT9T#9ChSLs-6lEbBFhIqA(#U?piie`w{=vZu$!=-43c&(1bCOKS+W{B76SZtER zrD%qDy^h5uIb4cnh&Sk1Y?8yJXoh&Bj>RT9T#9ChH|bbxlEbBFhIq4%#U?piie`wn z=vZu$!=-43c&m=ZCOKS+W{9`xSZtERrD%qDyN<;sIb4cnhRT9 zT#9Chcj;JclEbBFhIqG*#U?piie`xS=vZu$!=-43c(0DdCOKS+W{CIcSZtERrD%qD zzmCNwIb4cnh!5ykY?8yJXomQpj>RT9T#9Ch59wHJlEbBFhWN0K#U?piie`w9=vZu$ z!=-43_^6J>COKS+W{8jJSZtERrD%ruxQ@jpIb4cnh)?KPY?8yJXomQtj>RT9T#9Ch zPw7}}lEbBFhWNCO#U?piie`w<=vZu$!=-43_^gh_COKS+W{A(}SZtERrD%ruypF{t zIb4cnh%e|^Y?8yJXomQrj>RT9T#9ChFX>oplEbBFhWN6M#U?piie`wf=vZu$!=-43 z_^OV@COKS+W{9upSZtERrD%rux{k#rIb4cnh;QgvY?8yJXomQvj>RT9T#9ChZ|PWU zlEbBFhWNIQ#U?piie`xK=vZu$!=-43_^yt{COKS+W{B_USZtERrD%ruzK+EvIb4cn zh#%-!Y?8yJXomQqj>RT9T#9ChAL&?ZlEbBFhWN3L#U?piie`wP=vZu$!=-43_^FP? zCOKS+W{98ZSZtERrD%ruxsJsqIb4cnh+pVfY?8yJXomQuj>RT9T#9ChU+GwElEbBF zhWNFP#U?piie`x4=vZu$!=-43_^pn`COKS+W{BVESZtERrD%ruy^h5uIb4cnh(G99 zY?8yJXomQsj>RT9T#9ChKj~O(lEbBFhWN9N#U?piie`wv=vZu$!=-43_^Xb^COKS+ zW{AJ(SZtERrD%ruyN<;sIb4cnh=1rRT9T#9Chf9Y6klEbBFhWNLR z#U?piie`xa=vZu$!=-43_^*z|COKS+W{3yJ0}o=cNe-8y8R8*27MtX7DViZ3s$;Q9 z4ws@C;$b=#o8)jQnj!v2$6}KlE=4oM!*wh+$>CBoLp(yqVv`&$MKi=Bbu2c?;Zih1 zJW9u6lN>HZGsL5HEH=sEQZz$6M#o~494@H z$>CBoLp(vpVv`&$MKi<`bu2c?;Zih1JW0o5lN>HZGsKg1EH=sEQZz$6MaN>394CBoLp(#rVv`&$MKi=Rbu2c?;Zih1JWI!7 zlN>HZGsLrXEH=sEQZz$6N5^8594CBo zL%cx8Vv`&$MKi<;bu2c?;Zih1yhz7llN>HZGsKH^EH=sEQZz%nM8{&294CBoL;SCfh3()E*f{inS4(#t%@D8DvDhSsOVJGRDjkbWa<~-D5UO>(#t%@A+YvDhSs zOVJGRCLN1Sa<~-D5O3D8*d&Kb(G2kx9g9tJxD?G0Z`HBbB!^4U4DmJ{i%oL46wMHC z*Rj|nhfC26@eUn}O>(#t%@FU@vDhSsOVJGRE**(#t%@7~dvDhSsOVJGR zAsvfNa<~-D5FggD*d&Kb(G2ks9g9tJxD?G0AJwtgB!^4U4Dm4?i%oL46wMGH*Rj|n zhfC26@d+J^O>(#t%@Ci|vDhSsOVJGRDIJSVa<~-D5TDku*d&Kb(G2k!9g9tJxD?G0 zpVhJ0B!^4U4DmS~i%oL46wMHy*Rj|nhfC26@dX`=O>(#t%@AMIvDhSsOVJGRB^`@R za<~-D5MS1@*d&Kb(G2kw9g9tJxD?G0U)8bLB!^4U4DmG`i%oL46wMG{*Rj|nhfC26 z@eLh|O>(#t%@E(zvDhSsOVJGREgg$Za<~-D5Z~6Z*d&Kb(G2k&9g9tJxD?G0-_^0$ zB!^4U4Dmf3i%oL46wMId*Rj|nhfC26@dF);O>(#t%@9A-vDhSsOVJGRBOQxPa<~-D z5I@$j*d&Kb(G2ku9g9tJxD?G0Kh?3=B!^4U4DmA^i%oL46wMGn*Rj|nhfC26@e3V` zO>(#t%@DuTvDhSsOVJGRD;(#t%@BXovDhSsOVJGRCmoATa<~-D5P#OO z*d&Kb(G2ky9g9tJxD?G0f7P+rB!^4U4DmM|i%oL46wMHS*Rj|nhfC26@edt~O>(#t z%@F_8vDhSsOVJGRFCB|ba<~-D5dYS(*d&Kb(G2k)9g9tJxD?G0|JAYBB!^4U4DsLx znb$qYyzW8fbq_MHvlWm_(G2kr9g9tJxD?G057n{QB!^4U4Dm1>i%oL46wMI-qhqm2 z4ws@C;^8_Lo8)jQnjs#cW3fpNm!cWskvbNeq8Z}RIu@Jca4DK0 z9;0KiNe-8y8RD@z7MtX7DViZ3r(>~64ws@C;_*5bo8)jQnjxN`W3fpNm!cWsi8>aW zq8Z}JIu@Jca4DK0o}y#1Ne-8y8RDrr7MtX7DViakrem>54ws@C z;^{gTo8)jQnjxN{W3fpNm!cWsnK~Amq8Z}ZIu@Jca4DK0o}**2 zNe-8y8REG*7MtX7DViakr(>~64ws@C;`urjo8)jQnjv1GW3fpNm!cWsg*q0Sq8Z}FIu@Jca4DK0UZP{MNe-8y8RDfn7MtX7DViZ(rem>54ws@C;^jIP zo8)jQnj!vI$6{lPxOtrpFDRJT>2Q1e-&ww!q8Z|qIu@Jca4DK0 zUZrEPNe-8y8RFGC7MtX7DViZ(qhqm24ws@C;N>4u}Kb>q8Z|iIu@Jca4DK0-lSu(Ne-8y8RE@47MtX7DVibPqGPd14ws@C z;;lLso8)jQnjzk%W3fpNm!cWs?K&2lN^5u}Kb>q8Z|yIu@Jca4DK0-lb!) zNe-8y8RFeK7MtX7DVibPqhqm24ws@C;=MW+o8)jQnjzk&W3fpNm!cWs{W=z#q8Z|YIu@Jca4DK0KBQx@Ne-8y8REk_7MtX7DViZZqGPd14ws@C;-fki zo8)jQnjt=>W3fpNm!cWs<2n|bq8Z|oIu@Jca4DK0KBZ%^Ne-8y z8RFAA7MtX7DViZZqhqm24ws@C;q8Z|gIu@Jca4DK0zNBNZNe-8y8RE-27MtX7DVia^qGPd14ws@C;;T9qo8)jQ znjyZXW3fpNm!cWs>pB*jq8Z|wIu@Jca4DK0zNKTaNe-8y8RFYI z7MtX7DVia^qhqm24ws@C;=4K)o8)jQnjyZYW3fpNm!cWs`#Khz zq8Z|cIu@Jca4DK0exzfuNe-8y8REw}7MtX7DViaEqGPd14ws@C;-@+mo8)jQnjwCs zW3fpNm!cWs=Qq8Z|sIu@Jca4DK0ex+lvNe-8y8RFME7MtX7 zDViaEqhqm24ws@C;q8Z|k zIu@Jca4DK0{-k5ENe-8y8RE}67MtX7DVibvqGPd14ws@C;;%Xuo8)jQnj!wCW3fpN zm!cWs?>ZKnq8Z|!Iu@Jca4DK0{-tBFNe-8y8RFkM7MtX7DVibv zqhqm24ws@C;=ei;o8)jQnjs$SFESRJq8Z|$Iu@Jca4DK09;Rcl zNe-8y8RCC*EH=sEQZz$6T*qRQ94CBo zLp)l?Vv`&$MKi=>bSyT>;Zih1JXXhIlN>HZGsNR`EH=sEQZz$6UdLjS94CBoLp)i>Vv`&$MKi=xbSyT>;Zih1JXObHlN>HZ zGsM$$EH=sEQZz$6UB_aR94CBoLp)o@ zVv`&$MKi>6bSyT>;Zih1JXgnJlN>HZGsN?BEH=sEQZz$6U&msT94CBoL%dkWVv`&$MKi=pbSyT>;Zih1yi~_xlN>HZGsMeu zEH=sEQZz%nT*qRQ94TbCQZz%nLdRm094CBoL%c@EVv`&$MKi=}bu2c?;Zih1yiUhr zlN>HZGsNq4EH=sEQZz%nLC0c~94CBo zL%c=DVv`&$MKi=(bu2c?;Zih1yiLbqlN>HZGsN3CBoL%c`FVv`&$MKi>Ebu2c?;Zih1yidnslN>HZ zGsOFKEH=sEQZz$+K*wT}94CBoLwrQX zVv`&$MKi=lbu2c?;Zih1d`!n;lN>HZGsMSrEH=sEQZz$+LdRm094CBoLwrWZVv`&$MKi=_bu2c?;Zih1d``z=lN>HZGsNe0 zEH=sEQZz$+LC0c~94CBoLwrTYVv`&$ zMKi=#bu2c?;Zih1d`-tHZGsM?*EH=sEQZz$+L&sv194CBoLwrZaVv`&$MKi>Abu2c?;Zih1d{4(>lN>HZGsO3GEH=sE zQZz&SK*wT}94CBo^Zz)yryc;BtWl$X zsZv#2KW}W~9UEtC+qP}no}BefDyy%a`%ZScYqNf$V{^C!Nzn}Jr#d!=OOO=Juzsdv zbGQUa(G2V7IyQ$(kQB|ZexYM?xCBYj4C|LVHit`)6wR=HrDJor1WC~h>(@Fqhf9zY z&9Hu>V{^C!Nzn}Jw>mb5OOO=JuzsgwbGQUa(G2VNIyQ$(kQB|Z{-9%XxCBYj4C{|N zHit`)6wR>yq+@fq1WC~h>(4qihf9zY&9MHWV{^C!Nzn}JuR1n|OOO=Ju>PiFbGQUa z(G2VFIyQ$(kQB|Z{-I-YxCBYj4C|jdHit`)6wR>yrDJor1WC~h>)$#yhf9zY&9MHX zV{^C!Nzn}JzdAODOOO=JupZ>=2{wmIkQB|Z9;{tQ-Jhf9zY&9EM>V{^C!Nzn}J5jr-9OOO=JupX&nbGQUa(G2TRIyQ$(kQB|Z z9<5_@xCBYj4C^sEHit`)6wR<6t7CJx1WC~h>v1|Zhf9zY&9EM?V{^C!Nzn}J2|6~1 zOOO=Ju%4)6bGQUa(G2TJIyQ$(kQB|Zo~&bYxCBYj4C^U6Hit`)6wR=ns$+Aw1WC~h z>uEYRhf9zY&9I)XV{^C!Nzn}J0UeveB}j^9SkKV0Ib4FIXomGn9h<`?NQ!1y&(g6u zT!N%%hV^V6o5LkYie^~P(XlyPf~07M^;{jB!zDxy^B}j^9 zSTE4AIb4FIXomGd9h<`?NQ!1yFVe9&T!N%%hV^0{o5LkYie^|Z(XlyPf~07M^->+1 z!zD_!Nu{m6Vq-ciqavht)C9p-@yiSK36wK>%czgWsT+bjWnqj>{$L4SelA;;b zD|KuRmmn#cVZBPn=5Ps;q8Zk!b!-loASs$*y++68a0!y48P;ocYz~(oDVkxuPRHhO z36i22*6Vd_4woP)nqj>`$L4SelA;;b8+B|Bmmn#cVZBMm=5Ps;q8Zkkb!-loASs$* zy+z07a0!y48P;2MYz~(oDVkxuO~>YN36i22*4uS#4woP)nqj>|$L4SelA;;bJ9TUh zmmn#cVZBSo=5Ps;q8Zk^b!-loASs$*y+_C9a0!y48P z4woP)nqhrG$L4SelA;;b7jIYz~(oDVkw@O~>YN36i22*4K4x4woP)nqhrI$L4SelA;;bH+5_dmmn#cVSP)- z=5Ps;q8Zk=b!-loASs$*eMiUUa0!y48P<1oYz~(oDVkw@PsiqP36i22*7tR64woP) znqmDw$L4SelA;;b4|Qw~mmn#cVf{$Q=5Ps;q8ZkYb!-loASs$*{Y1y+a0!y48P-pA zYz~(oDVkyZOvmPM36i22*3Wfp4woP)nqmDy$L4SelA;;bFLi7Vmmn#cVf{+S=5Ps; zq8Zk&b!-loASs$*{YJ;;a0!y48P;!gYz~(oDVkyZPRHhO36i22*6(#}4woP)nqmDx z$L4SelA;;bA9ZXFmmn#cVf{(R=5Ps;q8Zkob!-loASs$*{YA&-a0!y48P;EQYz~(o zDVkyZO~>YN36i22*57q(4woP)nqmDz$L4SelA;;bKXq&lmmn#cVf{4woP)nqfUz$L4SelA;;bQ*>+&mmn#c zVLesH=5Ps;q8ZlHbZicnASs$*JzdAzO(> zhf9zY&9I)OV{^C!Nzn}J**Z3dOOO=Ju%4r1bGQUa(G2UkIyQ$(kQB|Zo~L7TxCBYj z4D0ziHit`)6wR<+pks5m1WC~h>xDWthf9zY&9GjiV{^C!Nzn}J#X2^JOOO=JuwJ5L zbGQUa(G2UQIyQ$(kQB|ZUZ!JnxCBYj4D01OHit`)*dlITr^5{j=5;!}J^pvXGbx&3 zy+X(4a0!y48P+RxYz~(oDVkxuO2_7K36i22)~j`F4woP)nqj?0$L4SelA;;bYjtc6 zmmn#cVZBbr=5Ps;q8Zlfb!-loASs$*y+Oz3a0!y48P*$hYz~(oDVkxuNyp}J36i22 z)|+)~4woP)nqj>~$L4SelA;;bTXk#>mmn#cVZBYq=5Ps;q8ZlPb!-loASs$*y+g<5 za0!y48P+>>Yz~(oDVkxuOULGL36i22*1L6V4woP)nqj?1$L4SelA;;bdv$CMmmn#c zVZBes=5Ps;q8Zlvb!-loASs$*eL%=5Ps; zq8Zlrb!-loASs$*{Xoa&a0!y48P*SVYz~(oDVkyZNXO=I36i22){k{;4woP)nqmD! z$L4SelA;;bPjze#mmn#cVf{?U=5Ps;q8ZlDb!-loASs$*{X)m)a0!y48P+d#Yz~(o zDVkyZO2_7K36i22)~|JJ4woP)nqmD$$L4SelA;;bZ*^=Ammn#cVf{|W=5Ps;q8Zlj zb!-loASs$*{Xxg(a0!y48P*?lYz~(oDVkyZNyp}J36i22)}M834woP)nqmD#$L4Se zlA;;bUv+E_mmn#cVf{_V=5Ps;q8ZlTb!-loASs$*{X@s*a0!y48P-2_Yz~(oDVkyZ zOULGL36i22*1vUZ4woP)nqmD%$L4SelA;;be|2mQmmn#cVLiyLL~IV1ASs$*Jy^%) za0!y48P-E|Yz~(oDVkwDRLACU36i22*28pc4woP)nqfU$$L4SelA;;bBXn#Immn#c zVLejE=5Ps;q8ZksbZicnASs$*JzB@+a0!y48P;QTYz~(oDVkwDR>$UW36i22*5h<+ z4woP)nqfU&$L4SelA;;b6Lf42mmn#cVLegD=5Ps;q8ZkcbZicnASs$*Jz2-*a0!y4 z8P-#DYz~(oDVkwDRmbLV36i22*3)!s4woP)nqfU%$L4SelA;;b13ET`OOO=Ju%4k~ zbGQUa(G2UEIyQ$(kQB|Zo~2`RxCBYj4C~oCHit`)6wR=nqhoWp1WC~h>$y5Mhf9zY z&9I)QV{^C!Nzn}J`8qa-OOO=JuwI~JbGQUa(G2T_IyQ$(kQB|ZUZi7lxCBYj4C}=@ zHit`)6wR<+qGNNo1WC~h>!mt2hf9zY&9GjkV{^C!Nzn}J-9P|hf9zY&9L5}V{^C!Nzn}JjXE}mOOO=J zu->F&bGQUa(G2U&IyQ$(kQB|Z-lAi3xCBYj4C}2rHit`)6wR>Srekxs1WC~h>+L!= zhf9zY&9L5~V{^C!Nzn}JojNv$OOO=Ju->I(bGQUa(G2U|IyQ$(kQB|Z-lJo4xCBYj z4C}o*Hit`)6wR>Sr(<)t1WC~h>-{=5hf9zY&9FY8V{^C!Nzn}JgE}^cOOO=Jus)*G2$hf9zY z&9FY9V{^C!Nzn}JlR7qsOOO=Jus)?@bGQUa(G2U;IyQ$(kQB|ZKBHrExCBYj4C}Kx zHit`)6wR+?D`hf9zY&9J_pV{^C!Nzn}Ji#j%kOOO=Ju)d^YbGQUa z(G2U$IyQ$(kQB|ZzM^AuxCBYj4C|{pHit`)6wR={rekxs1WC~h>+3o;hf9zY&9J_q zV{^C!Nzn}Jn>sd!OOO=Ju)d{ZbGQUa(G2U`IyQ$(kQB|ZzN2GvxCBYj4C}i(Hit`) z6wR={r(<)t1WC~h>-#!3hf9zY&9Hu;V{^C!Nzn}JhdMTgOOO=JuzsXtbGQUa(G2Uy zIyQ$(kQB|ZexhS@xCBYj4C|*lHit`)6wR=Hrekxs1WC~h>*qQ)hf9zY&9Hu-Rb~hf9zY&9MHUV{^C!Nzn}Jk2*GoOOO=Ju>PcDbGQUa(G2U)IyQ$( zkQB|Z{-R@ZxCBYj4C}8tHit`)6wR>yrekxs1WC~h>+d=?hf9zY&9MHVV{^C!Nzn}J zpE@>&OOO=Ju>PfEbGQUa(G2U~IyQ$(kQB|Z{-a}axCBYj4C}u-Hit`)6wR<6rpy3hf9zY&9EM=V{^C!Nzn}JF*-JfOOO=JupX;p zbGQUa(G2TxIyQ$(kQB|Z9q$B`hf9zY z&9I)VV{^C!Nzn}JDLOWXOOO=Ju%4=8bGQUa(G2TpIyQ$(kQB|Zo~~naxCBYj4C?_M zo5LkYie^~P(6KpOf~07M^-LX`!zD_!M zu{m6Vq-ciqVjY{qB}j^9STE7BIb4FIXomGt9h<`?NQ!1yFVnF(T!N%%hV^nCo5LkY zipCak^Ew@FP%y94;qCFiQ=ZMRUZG=ixCBYj4C|FTHit`)6wR<+rDJor1WC~h>(x3o zhf9zY&9GjhV{^C!Nzn}JwK_J3OOO=JuwJKQbGQUa(G2VLIyQ$(kQB|Z-k@W1xCBYj z4C{?LHit`)6wR>Sq+@fq1WC~h>&-eghf9zY&9L60V{^C!Nzn}JtvWV`OOO=Ju->L) zbGQUa(G2VDIyQ$(kQB|Z-l1c2xCBYj4C|dbHit`)6wR>SrDJor1WC~h>)kpwhf9zY z&9L61V{^C!Nzn}Jy*f6BOOO=Ju->O*bGQUa(G2VTIyQ$(kQB|ZKA>ZBxCBYj4C{kB zHit`)6wR%%%Whf9zY&9FYAV{^C!Nzn}JqdGQ+OOO=Jus)_^bGQUa z(G2V3IyQ$(kQB|ZKA~fCxCBYj4C|9RHit`)6wR(e?mhf9zY&9FYB zV{^C!Nzn}JvpP11OOO=Jus)|_bGQUa(G2VJIyQ$(kQB|ZzMx}sxCBYj4C{+JHit`) z6wR={q+@fq1WC~h>&rSehf9zY&9J_rV{^C!Nzn}Jt2#D^OOO=Ju)d~abGQUa(G2VB zIyQ$(kQB|ZzM*4txCBYj4C|XZHit`)6wR={rDJor1WC~h>)Sduhf9zY&9J_sV{^C! zNzn}JyE-<9OOO=Ju)e2bbGQUa(G2VRIyQ$(kQB|ZexPG>xCBYj4C{wFHit`)6wR=H zq+@fq1WC~h>&H4ahf9zY&9Hu=V{^C!Nzn}Jr#d!=OOO=JuzsdvbGQUa(G2V7IyQ$( zkQB|ZexYM?xCBYj4C|LVHit`)6wR=HrDJor1WC~h>(@Fqhf9zY&9Hu>V{^C!Nzn}J zw>mb5OOO=JuzsgwbGQUa(G2VNIyQ$(kQB|Z{-9%XxCBYj4C{|NHit`)6wR>yq+@fq z1WC~h>(4qihf9zY&9MHWV{^C!Nzn}JuR1n|OOO=Ju>PiFbGQUa(G2VFIyQ$(kQB|Z z{-I-YxCBYj4C|jdHit`)6wR>yrDJor1WC~h>)$#yhf9zY&9MHXV{^C!Nzn}JzdAOD zOOO=JupVUFADhD^NQ!1y57x0cT!N%%hV>8~o5LkYie^|3)v-BTf~07M^)MZq!zD^o`u{m6Vq-ciq2pyZlB}j^9SdY}PIb4FIXomGD9h<`?NQ!1ykJhm{T!N%%hV>X7 zo5LkYie^}k)v-BTf~07M^*9}y!zD}Bcu{m6Vq-ciq1Ra~hB}j^9SWnckIb4FI zXomG99h<`?NQ!1yPu8(HT!N%%hV>L3o5LkYie^|()v-BTf~07M^)wxu!zD`!+N%k&EXOx zMKi4D=-3=CK~glsdajPm;SwZ8Gpy(7*c>iFQZ&PQzK+e|5+p@4tQY9m94E!+Nof&EXOxMKi3I=-3=CK~glsdZ~`h;SwZ8Gpv{C*c>iF zQZ&PQxsJ`@5+p@4*dlITr^5{j=5;!}J^pvvb6Bs?u{m6Vq-ciqN*$ZSB}j^9Sg+Et zIb4FIXomG_9h<`?NQ!1yuhFqNT!N%%hV@z{~~u{m6Vq-ciqMje~OB}j^9SZ~s?Ib4FIXomG>9h<`?NQ!1yZ_%+iT!N%%hV@n* zo5LkYie^}E)3G^Rf~07M^>!Vb!zD_E4 zu{m6Vq-ciqK^>dJB}j^9SRc}{Ib4FIXomG+9h<`?NQ!1yAJMTnT!N%%hV@Y$o5LkY zie^|J)3G^Rf~07M^>H1W!zD}xlu{m6Vq-ciqNgbQRB}j^9SfA3dIb4FIXomG^ z9h<`?NQ!1ypV6^7T!N%%hV@w;o5LkYie^}!)3G^Rf~07M^?4ne!zD{a)u{m6V zq-ciqMID>NB}j^9SYOhyIb4FIXomG=9h<`?NQ!1yU(vBST!N%%hV@k)o5LkYie^|} z)3G^Rf~07M^>rPa!zD`Pau{m6Vq-ciq zLmivLB}j^9SU=LSIb4FIXomG;9h<`?NQ!1yKhd!{T!N%%hV@e&o5LkYie^|p)3G^R zf~07M^>ZDY!zD~+_u{m6Vq-ciqOC6iTB}j^9SijP-Ib4FIXomG`9h<`?NQ!1y zztOQdT!N%%hV@$=o5LkYie^~9)3G^Rf~07M^?Mzg!zD|mFu{m6Vq-ciqM;)8P zB}j^9Sbx&7Ib4FIXomG?9h<`?NQ!1yf6=iyT!N%%hV@q+o5LkYie^}U)3G^Rf~07M z^>-bc!zD%#oB}j^9SP#*$Ib4FIXomGr9h<`? zNQ!1y57V(ZT!N%%hV^hAo5LkYie^}k(6KpOf~07M^++9?!zD}BXu{m6Vq-ciq zXdRowB}j^9SdY=MIb4FIXomGz9h<`?NQ!1ykJGU^T!N%%hV^(Io5LkYie^|((6KpO zf~07M^+X+;!zD`iFQZ&PQmX6Kg z5+p@4tY_=k94!+M^M&EXOxMKi4D>)0GFK~gls zdV!A3;SwZ8GprZt*c>iFQZ&PQk&eyb5+p@4tQYIp94!+M#H&EXOxMKi3I>)0GFK~gls`hPlXCNi(n;j3)(IvxLahV=>^o5LkYie^}^ z)Ui2Sf~07M^(q~k!zD~M*u{m6Vq-ciq8XcR%B}j^9Sg+NwIb4FIXomGV9h<`? zNQ!1yuh+3TT!N%%hV=#=o5LkYie^}E)Ui2Sf~07M^(Gyg!zD|05u{m6Vq-ciq z79E?zB}j^9SZ~#_Ib4FIXomGR9h<`?NQ!1yZ`ZLoT!N%%hV>2|o5LkYie^~v)Ui2S zf~07M^)4No!zD_EAu{m6Vq-ciq5gnVu zB}j^9SRd7~Ib4FIXomGM9h<`?NQ!1yAJ?%tT!N%%hV=;@o5LkYie^}!)Ui2Sf~07M z^(h^j!zD}xru{m6Vq-ciq86BI$B}j^9SfACgIb4FIXomGU9h<`?NQ!1ypVzTD zT!N%%hV=y{a=u{m6Vq-ciq6&;(yB}j^9 zSYOq#Ib4FIXomGQ9h<`?NQ!1yU)QlYT!N%%hV=~{o5LkYie^~f)Ui2Sf~07M^(`Hn z!zD`Pgu{m6Vq-ciq6CInwB}j^9SU=UV zIb4FIXomGO9h<`?NQ!1yKi9E2T!N%%hV=^_o5LkYie^~9)Ui2Sf~07M^(!5l!zD~-0u{m6Vq-ciq8y%a&B}j^9SijY=Ib4FIXomGW9h<`?NQ!1yzt^!jT!N%%hV=&> zo5LkYie^}U)Ui2Sf~07M^(P&h!zD|mLu{m6Vq-ciq7ag0!B}j^9Sbx>AIb4FI zXomGS9h<`?NQ!1yf7h`&T!N%%hV>5}o5LkYie^~<)Ui2Sf~07M^)DTp!zD%lrUhf9zY&9EM# zV{^C!Nzn}Jp*l8)OOO=JupXvkbGQUa(G2V1IyQ$(kQB|Z9-(7%xCBYj4C|3PHit`) z6wR<6rDJor1WC~h>(M$khf9zY&9EM$V{^C!Nzn}Ju{t(~OOO=JupXylbGQUa(G2VH zIyQ$(kQB|Zo}goMxCBYj4C{$HHit`)6wR=nq+@fq1WC~h>&ZGchf9zY&9I)LV{^C! zNzn}JsX8`?OOO=Ju%4!4bGQUa(G2V9IyQ$(kQB|Z9?-ElT!N%%hV={`o5LkYie^~P z)Ui2Sf~07M^(-Bm!zD_!Qu{m6Vq-ciq z5*?evB}j^9STEJFIb4FIXomGN9h<`?NQ!1yFW0d-T!N(d{~X;@vqr(rsL{Waoler- zKX2Q%ZQHhO+cxWr^HtZFSI_;dm3OYr;S#UVVT-tVoenoBnAhp>_V~XOuhfw&ie}gx zF7YZI$)ae6&EXQS){!iVX4o7q@fsb;qG*QA;S#Uakt~X4*c>kLIvvTPXok(<60g^h zEQ)5>94_$&9m%3-hRxv;Z`6@2ie}gxF7YNE$)ae6&EXPn){!iVX4o7q@fID)qG*QA z;Sz7vkt~X4*c>kLHXX^LXok(<5^vX$EQ)5>94_$=9m%3-hRxv;@6?ejie}gxF7YlM z$)ae6&EXR7){!iVX4o7q@g5z?qG*QA;S%rFkt~X4*c>kLJ{`%TXok(<67ScMEQ)5> z94_$z9m%3-hRxv;AJma7ie}gxF7Y89$)ae6&EXOs){!iVX4o7q@ev)#qG*QA;SwL! zkt~X4*c>kLF&)XGXok(<5+B!*EQ)5>94_$*9m%3-hRxv;pVW~oie}gxF7YWH$)ae6 z&EXQC){!iVX4o7q@fjV-qG*QA;S!(Kkt~X4*c>kLIUUKOXok(<5}((REQ)5>94_$% z9m%3-hRxv;U(}H-ie}gxF7YKD$)ae6&EXPX){!iVX4o7q@f97(qG*QA;Syifkt~X4 z*c>kLH66*KXok(<5?|MmEQ)5>94_$<9m%3-hRxv;-_(&Tie}gxF7YiL$)ae6&EXQ? z){!iVX4o7q@f{t>qG*QA;S%4~kt~X4*c>kLJsruSXok(<65rR6EQ)5>94_$#9m%3- zhRxv;Kh%*die}gxF7YEB$)ae6&EXP1){!iVX4o7q@e>`%qG*QA;SxX9kt~X4*c>kL zGabpIXok(<594_$-9m%3-hRxv;ztoW|ie}gxF7YcJ$)ae6&EXQi){!iV zX4o7q@f#hkLI~~cQXok(<62I4xEQ)5>94_$(9m%3-hRxv; zf7FpIie}gxF7YQF$)ae6&EXP%){!iVX4o7q@fRJ*qG*QA;SztkLHyz2M zXok(<5`Wi`EQ)5>94_$>9m%3-hRxv;|J0Ezie}gxF7YoN$)ae6&EXRN){!iVX4o7q z@gE(@qG*QA;S&GVkt~X4*c>kLKOM=UXok(<5)X`5K7eFVG{fd_i3jOO7DY2`4wrba zj$~0Z!{%^_hv-NaMKf#;mw2d-WKlH3=5UFJ=|~nuGi(l*c({&aQ8dHmaEV9gNESsi zYz~)rq>f}!G{fd_iAU*37DY2`4wrbej$~0Z!{%^_$LL5FMKf#;mw2p>WKlH3=5UF} z=|~nuGi(l*c)X5eQ8dHmaET}ANESsiYz~)rqK;%yG{fd_i6`ku7DY2`4wrbcj$~0Z z!{%^_r|3u)MKf#;mw2j*rOiaIbld4G z-JtMFUuD12FFmjH_ITz0KMx>T6wR*&W(F~izB|ferSrpB%Ib7ls zI+8`v44cCxKB*&F6wRSrpB%Ib7l&I+8`v44cCx{;4Bb z6wR##y(F~iz zB_8+y^STF^*FC_z?g8d?w*4_|4wrb4j$~0Z!{%^_2kS@{MKf#;mw1SdWKlH3=5UFJ z>PQwvGi(l*c$ki4Q8dHmaEXWONESsiYz~)rgpOoUG{fd_iAU;47DY2`4wrb8j$~0Z z!{%^_N9#xyMKf#;mw1ehWKlH3=5UF}>PQwvGi(l*c$|)8Q8dHmaEZt3NESsiYz~)r zf{tWSG{fd_i6`nv7DY2`4wrb6j$~0Z!{%^_C+kQSMKf#;mw1YfWKlH3=5UFp>PQwv zGi(l*c$$u6Q8dHmaEYhuNESsiYz~)rhK^)WG{fd_iD&9a7DY2`4wrbAj$~0Z!{%^_ zXX{87MKf#;mw1kjWKlH3=5UGU>PQwvGi(l*c%F`AQ8dHmaEa&ZNESsiYz~)rfsSNR zG{fd_i5Kcf7DY2`4wrb5j$~0Z!{%^_7wbqCMKf#;mw1VeWKlH3=5UFZ>PQwvGi(l* zc$to5Q8dHmaEX`eNESsiYz~)rg^pxl+qik14mT~B*Xi(<`M;B%i=r7ehfBOlN3tlI zVRN{|t92xcq8T=aOT0!$vM8EibGXE7btH?T88(MYyiP~5D4Jn&xWwyqB#WXMHit{R zK}WJEnqhOe#2a-ai=r7ehfBOkN3tlIVRN{|n{_0Mq8T=aOT0x#vM8EibGXD?btH?T z88(MYyiG^4D4Jn&xWwCaB#WXMHit{RLr1bGnqhOe#5;8)i=r7ehfBOmN3tlIVRN{| zyLBXsq8T=aOT0%%vM8EibGXENbtH?T88(MYyiZ56D4Jn&xWxN)B#WXMHit`mKu5AD znqhOe#0PaGi=r7ehf91&N3tlIVRN{|hjk>2q8T=aOMFB}vM8EibGXDubtH?T88(MY zd`w5OD4Jn&xWvbGB#WXMHit`mLPxSFnqhOe#3ywmi=r7ehf91)N3tlIVRN{|r*$NY zq8T=aOMFI0vM8EibGXE3btH?T88(MYd`?HQD4Jn&xWwmmB#WXMHit`mK}WJEnqhOe z#20lWi=r7ehf91(N3tlIVRN{|mvtnIq8T=aOMFE~vM8EibGXD;btH?T88(MYd`(BP zD4Jn&xWw0WB#WXMHit`mLr1bGnqhOe#5Z*$i=r7ehf91*N3tlIVRN{|w{;|oq8T=a zOMFL1vM8EibGXEJbtH?T88(MYd{0NRD4Jn&xWxB$B#WXMHit|6Ku5ADnqhOe#1C~O zi=r7ehfDlON3tlIVRN{|k98!Aq8T=aOZ-GfvM8EibGXD$btH?T88(MY{7gr(D4Jn& zxWvzOB#WXMHit|6LPxSFnqhOe#4mLui=r7ehfDlQN3tlIVRN{|uXQAgq8T=aOZ-Mh zvM8EibGXEBbtH?T88(MY{7y%*D4Jn&xWw;uB#WXMHit|6K}WJEnqhOe#2(S88(MYJX}YzD4Jn&xWprLB#WXMHit_*Qb)2V znqhOe#G`a1i=r7ehf6$KN3tlIVRN{|V{{~oq8T=aOFULbvM8EibGXFgbR>(S88(MY zJYGk#D4Jn&xWp55B#WXMHit_*QAe^UnqhOe#FKO+i=r7ehf6$JN3tlIVRN{|Q*(S88(MYJY7e!D4Jn&xWqGbB#WXMHit_*Q%ABWnqhOe z#ItlHi=r7ehf6$LN3tlIVRN{|b95w&q8T=aOFUOcvM8EibGXFwbR>(S88(MYJYPq$ zD4Jn&xWo%|B#WXMHit{RP)D*TnqhOe#EWz!i=r7ehfBOzN3tlIVRN{|OLQcQq8T=a zOT1J^vM8EibGXFIbR>(S88(MYyj(}JD4Jn&xWp@TB#Xkfaq~JIZdx#})4fv1|38bO z88(MYyh=y1D4Jn&xWubvbfHq8T=aOT0lxvM8EibGXDCbtH?T88(MYyh%s0D4Jn&xWt=vB#WXMHit{RMMttI znqhOe#9MVFi=r7ehfBOoN3tlIVRN{|+jS(1q8T=aOT0rzvM8EibGXDibtH?T88(MY zyh}&2D4Jn&xWv14B#WXMHit{RM@O(S88(MY zJXlAvD4Jn&xWq$rB#WXMHit_*R7bKXnqhOe#KUwXi=r7ehf6$MN3tlIVRN{|BXlH- zq8T=aOFU9XvM8EibGXE#bR>(S88(MYJX%MxD4Jn&xWr?0B#WXMHit_*R!6cZnqhOe z#N%`%i=r7ehf6$ON3tlIVRN{|6Lchtq8T=aOFU6WvM8EibGXElbR>(S88(MYJXuGw zD4Jn&xWrR*B#WXMHit_*RY$TYnqhOe#M5*ni=r7ehf6$NN3tlIVRN{|Gjt@2q8T=a zOFUCYvM8EibGXE_bR>(S88(MYJX=SyD4Jn&xWsdGB#WXMHit_*S4XlanqhOe#Pf6{ zi=r7ehf6$PN3tlIVRN{|3v?ulq8T=aOT17=vM8EibGXEdbR>(S88(MYyjVxFD4Jn& zxWr3zB#WXMHit{RR7bKXnqhOe#LILfi=r7ehfBO%N3tlIVRN{|D|94_qOon8(c+33XDbHru94_%H9m%3-hRxv;uhx+)ie}gxF7X;2$)ae6&EXQS)sZZUX4o7q z@j4yJqG*QA;S#Uckt~X4*c>kL1|7+wXok(<5^vOzEQ)5>94_%D9m%3-hRxv;Z`P44 zie}gxF7Xx}$)ae6&EXPn)sZZUX4o7q@iraFqG*QA;Sz7xkt~X4*c>kL4jsv&Xok(< z67STJEQ)5>94_%L9m%3-hRxv;@79qlie}gxF7X~6$)ae6&EXR7)sZZUX4o7q@je~N zqG*QA;S%rHkt~X4*c>kL0UgPrXok(<5+Br&EQ)5>94_%89m%3-hRxv;AJ&m9ie}gx zF7Xi^$)ae6&EXOs)sZZUX4o7q@i86AqG*QA;SwL$kt~X4*c>kL2_4CzXok(<5}(wO zEQ)5>94_%G9m%3-hRxv;pVpBqie}gxF7X*1$)ae6&EXQC)sZZUX4o7q@i`sIqG*QA z;S!(Mkt~X4*c>kL1s%zvXok(<5?|DjEQ)5>94_%C9m%3-hRxv;U)GTkL4IRm%Xok(<65rI3EQ)5> z94_%K9m%3-hRxv;-`0^Vie}gxF7X{5$)ae6&EXQ?)sZZUX4o7q@jV^MqG*QA;S%51 zkt~X4*c>kL10BhtXok(<594_%A9m%3-hRxv;Kh}{fie}gxF7Xo`$)ae6 z&EXP1)sZZUX4o7q@iQICqG*QA;SxXBkt~X4*c>kL3mwU#Xok(<62H`uEQ)5>94_%I z9m%3-hRxv;zt)i~ie}gxF7X>3$)ae6&EXQi)sZZUX4o7q@jD&KqG*QA;S#^skt~X4 z*c>kL2OY_xXok(<5`WZ@EQ)5>94_%E9m%3-hRxv;f7X#Kie}gxF7X!~$)ae6&EXP% z)sZZUX4o7q@i!gGqG*QA;Szt>kt~X4*c>kL4;{&(Xok(<693eZEQ)5>94_%M9m%3- zhRxv;|JIQ#ie}gxF7Y27$)ae6&EXRN)sZZUX4o7q@jo5OqG*QA;Svw@A50{Rq8T=a zOFT$NvM8EibGXEVbtH?T88(MYJVZybD4Jn&xWq$sB#WXMHit_*Oh>XPnqhOe#KUzY zi=r7ehf6#{N3tlIVRN{|BXuN;q8T=aOFT+PvM8EibGXE#btH?T88(MYJVr;dD4Jn& zxWr?1B#WXMHit_*PDipRnqhOe#N%}&i=r7ehf6#`N3tlIVRN{|6Llnuq8T=aOFT(O zvM8EibGXElbtH?T88(MYJVi&cD4Jn&xWrR+B#WXMHit_*O-HgQnqhOe#M5;oi=r7e zhf6#|N3tlIVRN{|Gj$}3q8T=aOFTXPnqhOe#LIOgi=r7ehfBOd zN3tlI!M1VpIvs9WFt5|$E%Se;J%`QV60g#cEQ)5>94_%{9m%3-hRxv;uhEe#ie}gx zF7a9&$)ae6&EXQS(~&HSX4o7q@p>J}qG*QA;Sz7qkt~X4*c>kLMjgqbXok(<5^vIx zEQ)5>94_%@9m%3-hRxv;Z_$w~ie}gxF7Z|!$)ae6&EXPn(~&HSX4o7q@pc`_qG*QA z;S%rAkt~X4*c>kLP94djXok(<67SNHEQ)5>94_&09m%3-hRxv;@6nMgie}gxF7aL+ z$)ae6&EXR7(~&HSX4o7q@qQi2qG*QA;SwLvkt~X4*c>kLK^@7WXok(<5+Bl$EQ)5> z94_%;9m%3-hRxv;AJLI4ie}gxF7Z(v$)ae6&EXOs(~&HSX4o7q@o^o=qG*QA;S!(F zkt~X4*c>kLNgc_eXok(<5}(qMEQ)5>94_%`9m%3-hRxv;pV5&lie}gxF7a6%$)ae6 z&EXQC(~&HSX4o7q@p&D|qG*QA;Syiakt~X4*c>kLMIFhaXok(<5?|7hEQ)5>94_%? z9m%3-hRxv;U(t~)ie}gxF7Z_z$)ae6&EXPX(~&HSX4o7q@pT=^qG*QA;S%4_kt~X4 z*c>kLO&!UiXok(<65rC1EQ)5>94_%~9m%3-hRxv;-_emQie}gxF7aI*$)ae6&EXQ? z(~&HSX4o7q@qHc1qG*QA;SxX4kt~X4*c>kLLmkPYXok(<594_%=9m%3- zhRxv;Khcpaie}gxF7ZkL zOC8CgXok(<62H=sEQ)5>94_%|9m%3-hRxv;ztNE_ie}gxF7aC($)ae6&EXQi(~&HS zX4o7q@p~P~qG*QA;Szt)kt~X4*c>kLM;*zcXok(<5`WT>EQ)5>94_%^9m%3-hRxv; zf6kLPaVmk zXok(<693YXEQ)5>94_&19m%3-hRxv;|Iv{wie}gxF7aO-$)ae6&EXRN(~&HSX4o7q z@j$l?kt~X4*c>kLARWn~Xok(<5)amqEQ)5>94_$?9m%3-hRxv;57m(@ie}gxF7YrO z$)ae6&EXOc*O4rWX4o7q@dzEsqG*QA;S!J3kt~X4*c>kLC>_b7Xok(<5|7rAEQ)5> z94_$~9m%3-hRxv;kJXVZie}gxF7Y@W$)ae6&EXP{*O4rWX4o7q@dO>oqG*QA;Sx{O zkt~X4*c>kLBpu13Xok(<5>M8VEQ)5>94_$`9m%3-hRxv;Pt}nuie}gxF7Y%S$)ae6 z&EXPH*O4rWX4o7q@eCcwqG*QA;S$f(kt~X4*c>kLEFH94_%3 z9m%3-hRxv;&()DEie}gxF7Z4a$)ae6&EXQy*O4rWX4o7q@d6#mqG*QA;Sw*@kt~X4 z*c>kLA|1)1Xok(<5--+~EQ)5>94_$^9m%3-hRxv;FV&GOie}gxF7YxQ$)ae6&EXO+ z*O4rWX4o7q@d_QuqG*PVZR6&3x>xG(^|pDPj{kp#&EXQS(vd8RX4o7q@oF8(qG*QA z;S#UWkt~X4*c>kLS{=!vXok(<60g&dEQ)5>94_&C9m%3-hRxv;Z_tq}ie}gxF7ZYk z$)ae6&EXPn(vd8RX4o7q@n#*#qG*QA;Sz7rkt~X4*c>kLRvpQrXok(<5^vLyEQ)5> z94_&89m%3-hRxv;@6eGfie}gxF7Zws$)ae6&EXR7(vd8RX4o7q@opW-qG*QA;S%rB zkt~X4*c>kLULDDzXok(<67SQIEQ)5>94_&G9m%3-hRxv;AJCC3ie}gxF7ZJf$)ae6 z&EXOs(vd8RX4o7q@nIdwqG*QA;SwLwkt~X4*c>kLQ60&mXok(<5+Bo%EQ)5>94_&3 z9m%3-hRxv;pU{ykie}gxF7Zhn$)ae6&EXQC(vd8RX4o7q@o62&qG*QA;S!(Gkt~X4 z*c>kLSslruXok(<5}(tNEQ)5>94_&B9m%3-hRxv;U(k^(ie}gxF7ZVj$)ae6&EXPX z(vd8RX4o7q@ns#!qG*QA;Syibkt~X4*c>kLRUOHqXok(<5?|AiEQ)5>94_&79m%3- zhRxv;-_VgPie}gxF7Ztr$)ae6&EXQ?(vd8RX4o7q@ogQ+qG*QA;S%4`kt~X4*c>kL zT^-4yXok(<65rF2EQ)5>94_&F9m%3-hRxv;KhTjZie}gxF7ZPh$)ae6&EXP1(vd8R zX4o7q@napyqG*QA;SxX5kt~X4*c>kLQys~oXok(<594_&59m%3-hRxv; zztE8^ist`ubWh6~Hp!w!Zz;QwxV*M)8|!alwQbwBZO0yaMa6iJp7V;C^NY%)XomQO zj>YD1Ns4BOU+P$F4ws~8hWM3^#pZBHie`vk>sV|Km!xQh_>GRm=5R@hW{BVFSZofL zq-citosPxka7l`0h~Mj2Yz~*CXomQMj>YD1Ns4BOKk8U)4ws~8hWL|?#pZBHie`vE z>sV|Km!xQh_=}Fk=5R@hW{AJ)SZofLq-citn~ufia7l`0h`;MtYz~*CXomQQj>YD1 zNs4BOf9hCl4ws~8hWM9`#pZBHie`v^>sV|Km!xQh_>Ydo=5R@hW{CglSZofLq-chC zu$RGEYz~*CXoh%*j>YD1Ns4BOhw4~t4ws~8hIp8c#pZBHie`w1>sV|Km!xQhc!Z9{ z=5R@hW{5}XSZofLq-chCl#a#ba7l`0h)3&KYz~*CXoh%YD1Ns4BO$Ld&Y4ws~8 zhIpKg#pZBHie`w%>sV|Km!xQhc!G|_=5R@hW{4;1SZofLq-chCl8(jZa7l`0h$rh< zYz~*CXoh%-j>YD1Ns4BOr|MX24ws~8hIpEe#pZBHie`wX>sV|Km!xQhc!rL}=5R@h zW{79%SZofLq-chCmX5{da7l`0h-d3qYz~*CXoh%>j>YD1Ns4BO=jvE&4ws~8hIpQi z#pZBHie`xC>sV|Km!xQhc!7?^=5R@hW{4N+SZofLq-chCk&eaYa7l`0h!^WvYz~*C zXoh%+j>YD1Ns4BOm+Dw-4ws~8hIpBd#pZBHie`wH>sV|Km!xQhc!iF|=5R@hW{6kn zSZofLq-chCm5#;ca7l{BwsG@19bQ^6uhZd{`M*=X%@7ahSZofLq-chCwT{K+a7l`0 zh}Y;?Yz~*CXoh&Lj>YD1Ns4BO*XdYn4ws~8hIqY>#pZBHie`v6=vZtHm!xQhc%zQR z=5R@hW{5ZGSZofLq-chCvyR2)a7l`0h_~oiYz~*CXomP-9gEH3k`&DlZ`HBb94<-G z4DmJ{i_PJZ6wMHC*Rj|fE=kc0@eUn}&Eb+1%@FU@vDh3gNzn}PE**=_;gS^15bxHp z*c>iN(G2k(9gEH3k`&Dl@71x`94<-G4Dmi4i_PJZ6wMIt*Rj|fE=kc0@c|u+&Eb+1 z%@7~dvDh3gNzn}PAsvg&;gS^15FggD*c>iN(G2ks9gEH3k`&DlAJwtg94<-G4Dm4? zi_PJZ6wMGH*Rj|fE=kc0@d+J^&Eb+1%@Ci|vDh3gNzn}PDIJT=;gS^15TDku*c>iN z(G2k!9gEH3k`&DlpVhJ094<-G4DmS~i_PJZ6wMHy*Rj|fE=kc0@dX`=&Eb+1%@AMI zvDh3gNzn}PB^`^+;gS^15MS1@*c>iN(G2kw9gEH3k`&DlU)8bL94<-G4DmG`i_PJZ z6wMG{*Rj|fE=kc0@eLh|&Eb+1%@E(zvDh3gNzn}PEgg%^;gS^15Z~6Z*c>iN(G2k& z9gEH3k`&Dl-_^0$94<-G4Dmf3i_PJZ6wMId*Rj|fE=kc0@dF);&Eb+1%@9A-vDh3g zNzn}PBOQy);gS^15I@$j*c>iN(G2ku9gEH3k`&DlKh?3=94<-G4DmA^i_PJZ6wMGn z*Rj|fE=kc0@e3V`&Eb+1%@DuTvDh3gNzn}PD;iN(G2k$9gEH3 zk`&DlztyqW94<-G4DmZ1i_PJZ6wMI7*Rj|fE=kc0@dq7?&Eb+1%@BXovDh3gNzn}P zCmoB;;gS^15P#OO*c>iN(G2ky9gEH3k`&Dlf7P+r94<-G4DmM|i_PJZ6wMHS*Rj|f zE=kc0@edt~&Eb+1%@F_8vDh3gNzn}PFCB}`;gS^15dYS(*c>iN(G2k)9gEH3k`&Dl z|JAYB94<-G4Dn!F{8(%bm!xQhc!-Y0=5R@hW{8LCSZofLq-chCn2yEfa7l`0h==P~ zYz~*CXoh%%j>YD1Ns4BON9tH?4ws~8hIo{Y#pZBHie`vM>sV|Km!xQhc#Mw4=5R@h zW{Ah?SZofLq-chCoQ}oja7l`0h{x+#Yz~*CXoh%#j>YD1Ns4BOC+b*i4ws~8hIo>W z#pZBHie`u>>sV|Km!xQhc#4k2=5R@hW{9WiSZofLq-chCnvTWha7l`0h^OmVYz~*C zXoh%(j>YD1Ns4BOXX;pN4ws~8hIp2a#pZBHie`vs>sV|Km!xQhc#e+6=5R@hW{BtN zSZofLq-chCo{q)la7l`0i0A8AYz~*CXoh%!j>YD1Ns4BO7wTAS4ws~8hIo;V#pZBH zie`ux>sV|Km!xQhc!`e1=5R@hW{8*SSZofLq-chCnU2Nga7l`0h?nbFYz~*CXoh%& zj>YD1Ns4BOSL#@74ws~8hIo~Z#pZBHie|8F+`LYQmln+Hbhu^y@3ij_59nBI4ws~8 zhIqA(#pZBHie`w{=vZtHm!xQhc&(1b=5R@hW{B76SZofLq-chCy^h7^a7l`0h&Sk1 zYz~*CXoh&Bj>YD1Ns4BOH|bbx4ws~8hIq4%#pZBHie`wn=vZtHm!xQh_+K51&Eb+1 z%@A+ZvDh3gNzn}PHXV!2;gS^15O3G9*c>iN(G2kp9gEH3k`&Dl@6@r_94<-G4Dl`< zi_PJZ6wMIt*0IiN z(G2kc9gEH3k`&DlAJnnf94<-G4Dlfyi_PJZ6wMGH*0IiN(G2kk9gEH3k`&DlpVYC~94<-G4Dl%)i_PJZ z6wMHy*0IiN(G2kg z9gEH3k`&DlU(~VK94<-G4Dlr$i_PJZ6wMG{*0IiN(G2ko9gEH3k`&Dl-_)_#94<-G4Dl@;i_PJZ6wMId z*0IiN(G2ke9gEH3 zk`&DlKh&|<94<-G4Dll!i_PJZ6wMGn*0I`3&Eb+1%@9A;vDh3gNzn}P zGaZY~;gS^15I@(k*c>iN(G2km9gEH3k`&DlztpkV94<-G4Dl-+i_PJZ6wMI7*0IiN(G2ki9gEH3k`&Dl zf7G$q94<-G4Dlx&i_PJZ6wMHS*0IiN(G2kq9gEH3k`&Dl|J1SA94<-G4Dl}=i_PJZ6wMI-*0IiN(G2lu9gEH3 zk`&DlkI}K%94<-G4DnbUi_PJZ6wMHi)3MkbE=kc0@pv7J&Eb+1%@9w}vDh3gNzn}P zL>-IG;gS^15Kq#v*c>iN(G2lq9gEH3k`&DlPtmd194<-G4DnPQi_PJZ6wMG%)3Mkb zE=kc0@pK)F&Eb+1%@EJfvDh3gNzn}POdX5O;gS^15YN)F*c>iN(G2ly9gEH3k`&Dl z&(X2i94<-G4DnnYi_PJZ6wMIN)3MkbE=kc0@q8VN&Eb+1%@8lpvDh3gNzn}PLLH0E z;gS^15HHfP*c>iN(G2lo9gEH3k`&DlFVV5s94<-G4DnJOi_PJZ6wMGX)3MkbE=kc0 z@p2uD&Eb+1%@D89vDh3gNzn}PN*#;M;gS^15UiN(G2lFI&3g9uhZez+vasT z{{I=`0Ue9Y;gS^15UiN(G2k#9gEH3k`&Dluhp^G94<-G4DmW0i_PJZ6wMH? z*Rj|fE=kc0@dh1>&Eb+1%@A+YvDh3gNzn}PCLN2-;gS^15O3D8*c>iN(G2kx9gEH3 zk`&Dl|EpuMIb4#W8RD%v7MsH*DVibPrem==T#}+0;_W&Xo5Lk3njzkyW3f40lA;;n zojMkq!zC%2A>O59u{m6lq8Z}dIu@J5B`KOA-lJo&Ib4#W8RES<7MsH*DVibPr(>}> zT#}+0;{7@no5Lk3njt=*W3f40lA;;ngE|(Q!zC%2AwHyIu{m6lq8Z}DIu@J5B`KOA zKB8l>Ib4#W8RDZl7MsH*DViZZrem==T#}+0;^R6No5Lk3njt=+W3f40lA;;nlR6fg z!zC%2AwH#Ju{m6lq8Z}TIu@J5B`KOAKBHr?Ib4#W8RD}#7MsH*DViZZr(>}>T#}+0 z;`2Hdo5Lk3njyZRW3f40lA;;ni#isY!zC%2A-<$zu{m6lq8Z}LIu@J5B`KOAzM^BX zIb4#W8RDxt7MsH*DVia^rem==T#}+0;_EsVo5Lk3njyZSW3f40lA;;nn>rSo!zC%2 zA-<(!u{m6lq8Z}bIu@J5B`KOAzN2HYIb4#W8REM-7MsH*DVia^r(>}>T#}+0;`=%l zo5Lk3njwCmW3f40lA;;nhdLIU!zC%2A%3J|u{m6lq8Z}HIu@J5B`KOAexhTsIb4#W z8RDlp7MsH*DViaErem==T#}+0;^#URo5Lk3njwCnW3f40lA;;nmpT@k!zC%2A%3M} zu{m6lq8Z}XIu@J5B`KOAexqZtIb4#W8REA(7MsH*DViaEr(>}>T#}+0;`cfho5Lk3 znj!w6W3f40lA;;nk2)5c!zC%2A^xOeu{m6lq8Z}PIu@J5B`KOA{-R^CIb4#W8RD-x z7MsH*DVibvrem==T#}+0;_o^Zo5Lk3nj!w7W3f40lA;;npE?$s!zC%2A^xRfu{m6l zq8Z}fIu@J5B`KOA{-a~DIb4#W8REY>7MsH*DViZ3Jmz&{UT2FRhf7j4Lp(&sVsp48 zMKi=hbu2cAOHwpLJWR)8bGRf$GsMGnEH;NrQZz$6LdRlrxFkh0#3OYqHit`6G($W} z$6|B1Btbu2cAOHwpLJWj`AbGRf$GsNR{EH;Nr zQZz$6LC0cqxFkh0#1nNaHit`6G($W|$6|B1BtvVsp48MKi>6bu2cAOHwpLJWt1BbGRf$GsN?CEH;NrQZz%n zK*wTpxFkh0#0zySHit`6G()^d$6|B1Bt zHit`6G(-GE$6|B1BtiN(G2lW9gEH3k`&Dl57V*O94<-G4DoOsi_PJZ6wMHi(6QJYE=kc0 z@kkwu&Eb+1%@B{$vDh3gNzn}PXdR2q;gS^15RcKZ*c>iN(G2le9gEH3k`&DlkJGW( z94<-G4Dom!i_PJZ6wMG%(6QJYE=kc0@kAYq&Eb+1%@9x0vDh3gNzn}PWF3pm;gS^1 z5Kqyu*c>iN(G2la9gEH3k`&DlPt&p394<-G4Doawi_PJZ6wMIN(6QJYE=kc0@k||y z&Eb+1%@EJhvDh3gNzn}PY#ocu;gS^15YN%E*c>iN(G2li9gEH3k`&Dl&(pEk94<-G z4Doy&i_PJZ6wMGX(6QJYE=kc0@j@Mo&Eb+1%@8lrvDh3gNzn}PVjYXk;gS^15HHcO z*c>iN(G2lY9gEH3k`&DlFVnHu94<-G4DoUui_PJZ6wMH?(6QJYE=kc0@k$+w&Eb+1 z%@D8BvDh3gNzn}PKROn+jXz+6(F0yZeZWf#5BT-=1O6lQfLrE)|9>9DVsp48MKi>! zbu2cAOHwpLyhg`jbGRf$GsJ6kEH;NrQZz%nPRC+%xFkh0#Ork|Hit`6G()^W$6|B1 zBtkbu2cAOHwpLyhX=ibGRf$GsOSuSZofLq-chC ztB%Fya7l`0h_~rjYz~*CXoh&Zj>YD1Ns4BOcj#Db4ws~8hIprr#pZBHie`v+=~!$I zm!xQhc(;zl=5R@hW{CIbSZofLq-chCua3p$a7l`0i1+DOYz~*CXoh&dj>YD1Ns4BO z59nBI4ws~8hWMb4#pZBHie`up=~!$Im!xQh_^^(}=5R@hW{8jISZofLq-citsE)z)5Yz~*CXomQ>j>YD1Ns4BOPv}@|4ws~8hWMn8#pZBHie`vU=~!$Im!xQh z__U72=5R@hW{A(|SZofLq-cittd7Oza7l`0h|lR*Yz~*CXomQ_j>YD1Ns4BOFX&io z4ws~8hWMh6#pZBHie`u}=~!$Im!xQh__B`0=5R@hW{9uoSZofLq-cits*c6xa7l`0 zh_C5bYz~*CXomQ@j>YD1Ns4BOZ|GQT4ws~8hWMtA#pZBHie`v!=~!$Im!xQh__mJ4 z=5R@hW{B_TSZofLq-citu8zg#a7l`0i0|oGYz~*CXomQ{j>YD1Ns4BOALv+Y4ws~8 zhWMe5#pZBHie`u(=~!$Im!xQh__2<~=5R@hW{98YSZofLq-citsgA|wa7l`0h@a_L zYz~*CXomQ?j>YD1Ns4BOU+7qD4ws~8hWMq9#pZBHie`vk=~!$Im!xQh__dD3=5R@h zW{BVDSZofLq-citt&YX!a7l`0h~Md0Yz~*CXomQ`j>YD1Ns4BOKj>I&4ws~8hWMk7 z#pZBHie`vE=~!$Im!xQh__L11=5R@hW{AJ&SZofLq-cittB%Fya7l`0h`;GrYz~*C zXomQ^j>YD1Ns4BOf9P0j4ws~8hWMwB#pZBHie`v^=~!$Im!xQh__vP5=5R@hW{Cgj zSZofLq-citua3p$a7l`0hzCE&yzW8fbq_MHdysjZEq)|LGsHu5EH;NrQZz$6RL5d- zxFkh0#KUwfHit`6G($XG$6|B1BtsbSyT9OHwpL zJX*(MbGRf$GsI(bEH;NrQZz$6R>xvcbSyT9OHwpLJXyzLbGRf$GsIJLEH;NrQZz$6RmWm;xFkh0 z#M5*vHit`6G($XH$6|B1Bt+bSyT9OHwpLJX^UbSyT9OHwpLyjaI#bGRf$GsH`DEH;NrQZz%nRL5d-xFkh0#LILn zHit`6G()^x$6|B1Bt!bSyT9OHwpL{Ev>s##VCk zIvrkQFt5|$Hu}G_d^d+nQZz%nTE}8@xFkh0#A|dcHit`6G()^r$6|B1BtvSwO zhf7j4L%d$cVsp48MKi=3bSyT9OHwpLyivzubGRf$GsK&8EH;NrQZz%nS;t~?xFkh0 z#9MSMHit`6G(-Haj>YD1Ns4BOx9V7I4ws~8hIpHf#pZBHie`wn>sV|Km!xQhc!!R~ z=5R@hW{7v{SZofLq-chCmyX5ea7l`0hYD1Ns4BO_v%<|4ws~8 zhIpTj#pZBHie`xS>sV|Km!xQh_<)YZ=5R@hW{3~!SZofLq-citkdDRXa7l`0h!5*n zYz~*CXomQRj>YD1Ns4BOkLp-#4ws~8hWMC{#pZBHie`w9>sV|Km!xQh_=Jwd=5R@h zW{6MfSZofLq-citl#a#ba7l`0h)?TSYz~*CXomQVj>YD1Ns4BO&+1rg4ws~8hWMP0 z#pZBHie`w<>sV|Km!xQh_=1kb=5R@hW{5B9SZofLq-citl8(jZa7l`0h%f6{Yz~*C zXomQTj>YD1Ns4BOuj*KA4ws~8hWMI}#pZBHie`wf>sV|Km!xQh_=b+f=5R@hW{7X< zSZofLq-citmX5{da7l`0h;QpyYz~*CXomQXj>YD1Ns4BO@9J1=4ws~8hWMV2#pZBH zie`xK>sV|Km!xQh_<@ea=5R@hW{4l^SZofLq-citk&eaYa7l`0h#%`%Yz~*CXomQS zj>YD1Ns4BOpXyj_4ws~8hWMF|#pZBHie`wP>sV|Km!xQh_=S$e=5R@hW{6+vSZofL zq-citm5#;ca7l`0h+peiYz~*CXomQWj>YD1Ns4BO-|ARw4ws~8hWMS1#pZBHie`x4 z>sV|Km!xQh_=Aqc=5R@hW{5xPSZofLq-citla9saa7l`0h(GICYz~*CXomQUj>YD1 zNs4BOzv@_Q4ws~8hWML~#pZBHie`wv>sV|Km!xQh_=k?g=5R@hW{7|4SZofLq-cit zmyX5ea7l`0h=1!?Yz~*CXomQYj>YD1Ns4BO|LRz54ws~8hIp{Qpjd1Um!xQhc!-Y0 z=5R@hW{8LCSZofLq-chCn2yEfa7l`0h==P~Yz~*CXoh%%j>YD1Ns4BON9tH?4ws~8 zhIo{Y#pZBHie`vM>sV|Km!xQhc#Mw4=5R@hW{Ah?SZofLq-chCoQ}oja7l`0h{x+# zYz~*CXoh%#j>YD1Ns4BOC+b*i4ws~8hIo>W#pZBHie`u>>sV|Km!xQhc#4k2=5R@h zW{9WiSZofLq-chCnvTWha7l`0h^OmVYz~*CXoh%(j>YD1Ns4BOXX;pN4ws~8hIp2a z#pZBHie`vs>sV|Km!xQhc#e+6=5R@hW{BtNSZofLq-chCo{q)la7l`0i0A8AYz~*C zXoh%!j>YD1Ns4BO7wTAS4ws~8hIo;V#pZBHie`ux>sV|Km!xQhc!`e1=5R@hW{8*S zSZofLq-chCnU2Nga7l`0h?nbFYz~*CXoh%&j>YD1Ns4BOSL#@74ws~8hIo~Z#pZBH zie`xa(XrSZY$Z3Z)8R!1^E%xFI{yFJ94<-G4Do6mi_QPz=&p7EYOO_$z7heZJzm}2 z-R;!f-QC^WzwYkM8M`5atM8sSsAF@u1WC~h>rFZ~hf9zY&9L6AV{^C!Nzn}J zEjl)bOOO=Ju->X;bGQUa(G2TtIyQ$(kQB|Z-mYVFxCBYj4C@^_Hit`)6wR>Ssbh1v z1WC~h>s>lFhf9zY&9L6BV{^C!Nzn}JJvugrOOO=Ju->aq9y=hf9zY&9FYKV{^C!Nzn}JBRV#R zOOO=Jus*6|bGQUa(G2TjIyQ$(kQB|ZKCWYPxCBYj4C@m*Hit`)6wRr*;5hf9zY&9FYLV{^C!Nzn}JGdebhOOO=Jus*9}bGQUa(G2TzIyQ$(kQB|ZKCfeQ zxCBYj4C@OzHit`)6wR={sAF@u1WC~h>q|N|hf9zY&9J_#V{^C!Nzn}JD>^oZOOO=J zu)eBebGQUa(G2TrIyQ$(kQB|ZzOG|)xCBYj4C@;@Hit`)6wR={sbh1v1WC~h>svZD zhf9zY&9J_$V{^C!Nzn}JJ32OpOOO=Ju)eEfbGQUa(G2T*IyQ$(kQB|ZzOQ3*xCBYj z4C@CvHit`)6wR=HsAF@u1WC~h>qj~^hf9zY&9Hu~V{^C!Nzn}J0UeveB}j^9SU=IR zIb4FIXomGu9h<`?NQ!1yKhv=}T!N%%hV^qDo5LkYie^~9(6KpOf~07M^-CR_!zD~+{u{m6Vq-ciqYaN@zB}j^9SijM+Ib4FIXomG$9h<`?NQ!1yztgcfT!N%%hV^?L zo5LkYie^}U(6KpOf~07M^+z3>!zD|mHu{m6Vq-ciqXC0fvB}j^9Sbx#6Ib4FI zXomGy9h<`?NQ!1yf77u!T!N%%hV^$Ho5LkYie^~<(6KpOf~07M^-mp}!zD^o^u{m6Vq-ciqFddu2B}j^9SP$2+Ib4FIXomF&9h<`?NQ!1y zkJPa_T!N%%hV>{No5LkYie^}k*0DKUf~07M^%xzS!zD}Bau{m6Vq-ciqI31hA zB}j^9SdZ7SIb4FIXomF!9h<`?NQ!1yPt>tFT!N%%hV>*Jo5LkYie^|(*0DKUf~07M z^%NbO!zD`#Ho5LkYie^|Z*0DKUf~07M^%5PM z!zD_!Pu{m6Vq-ciqG98=4B}j^9STEPHIb4FIXomF)9h<`?NQ!1yuhg+QT!N%% zhV?2Po5LmWD!F-`4mUEG*XeK?{cl}+kQB|ZUaezuxCBYj4C^&IHit`)6wR<+t7CJx z1WC~h>vcLdhf9zY&9GjtV{^C!Nzn}J4LUZ5OOO=Ju->R+bGQUa(G2TNIyQ$(kQB|Z z-mGJDxCBYj4C^gAHit`)6wR>Ss$+Aw1WC~h>uowVhf9zY&9L6CV{^C!Nzn}J9Xd9L zOOO=Ju->U-bGQUa(G2TdIyQ$(kQB|Z-mPPExCBYj4C_5QHit`)6wR>St7CJx1WC~h z>wP*lhf9zY&9L6DV{^C!Nzn}J13ET`OOO=Jus*0`bGQUa(G2TDIyQ$(kQB|ZKCEMN zxCBYj4C^C0Hit`)6wRti}Lhf9zY&9FYMV{^C!Nzn}J6FN4BOOO=J zus*3{bGQUa(G2TTIyQ$(kQB|ZKCNSOxCBYj4C^yGHit`)6wRvK9b zhf9zY&9FYNV{^C!Nzn}J3pzH3OOO=Ju)e5cbGQUa(G2TLIyQ$(kQB|ZzN}+&xCBYj z4C^a8Hit`)6wR={s$+Aw1WC~h>uWkThf9zY&9J_%V{^C!Nzn}J8#*?JOOO=Ju)e8d zbGQUa(G2TbIyQ$(kQB|ZzO7?(xCBYj4C^~OHit`)6wR={t7CJx1WC~h>w7vjhf9zY z&9J_&V{^C!Nzn}J2Rb%~OOO=JuzsjxbGQUa(G2THIyQ$(kQB|Zeyn42xCBYj4C?_M zo5LkYie^|p(XlyPf~07M^-~?2!zD`Pdu{m6Vq-ciqa~+$*B}j^9SijJ*Ib4FI zXomGm9h<`?NQ!1yztXWeT!N%%hV^S5o5LkYie^~9(XlyPf~07M^;;dA!zD~+| zu{m6Vq-ciqdmWp@B}j^9Sbxy5Ib4FIXomGi9h<`?NQ!1yf6}ozT!N%%hV^G1o5LkY zie^}U(XlyPf~07M^;aF6!zD|mIu{m6Vq-ciqcO9F^pMXA+yk zB}j^9SP#~*Ib4FIXomF=9h<`?NQ!1y57n_bT!N%%hV?KVo5LkYie^|3*ReTVf~07M z^#~oC!zD}BZu{m6Vq-ciqC>@)_B}j^9SdZ4RIb4FIXomF|9h<`?NQ!1ykJYg` zT!N%%hV?ido5LkYie^}k*ReTVf~07M^#mQ8!zD`B}j^9 zSWnimIb4FIXomF^9h<`?NQ!1yPt~zGT!N%%hV?WZo5LkYie^|(*ReTVf~07M^$Z=G z!zD_!Ou{m6Vq-ciqA|0E~M(u{m6Vq-ciqDjl1{B}lwVZeFLujSS{>I-ExTTVYR%W>~M*u{m6Vq-ciq8XcR% zB}j^9Sg+NwIb4FIXomGV9h<`?NQ!1yuh+3TT!N%%hV=#=o5LkYie^}E)Ui2Sf~07M z^(Gyg!zD|05u{m6Vq-ciq79E?zB}j^9SZ~#_Ib4FIXomGR9h<`?NQ!1yZ`ZLo zT!N%%hV>2|o5LkYie^~v)Ui2Sf~07M^)4No!zD_EAu{m6Vq-ciq5gnVuB}j^9SRd7~Ib4FIXomGM9h<`?NQ!1yAJ?%tT!N%% zhV=;@o5LkYie^}!)Ui2Sf~07M^(h^j!zD}xru{m6Vq-ciq86BI$B}j^9SfACg zIb4FIXomGU9h<`?NQ!1ypVzTDT!N%%hV=y{a=u{m6Vq-ciq6&;(yB}j^9SYOq#Ib4FIXomGQ9h<`?NQ!1yU)QlYT!N%%hV=~{ zo5LkYie^~f)Ui2Sf~07M^(`Hn!zD`Pg zu{m6Vq-ciqfR4@K5+p@4te@!E94!}__7&EXOx zMKi2l=-3=CK~gls`lXJ|;SwZ8Gpt|f*c>iFQZ&Q*wT{i<5+p@4tl#L^94 zj?Li`Bt!}`6B&EXOxMKi2F=-3=CK~gls`lF7`;SwZ8Gps-9*c>iF zQZ&Q*vyRQ-5+p@4tiR~k94!}`09&EXOxMKi2_ z=-3=CK~gls`lpV~;SwZ8Gpv8<*c>iFQZ&Q*w~o!>5+p@4tpDiP94)0GFK~glsdWeqA;SwZ8GpvW|*c>iFQZ&PQn2yci5+p@4 ztcUB^94!+MmC&EXOxMKi2N>)0GFK~glsdW??E z;SwZ8Gpxtz*c>iFQZ&PQoQ}=m5+p@4tjFuv94 z!+MgA&EXOxMKi1?>)0GFK~glsdWw$C;SwZ8GpwiT*c>iFQZ&PQnvTuk5+p@4tf%YP z94!+MsE&EXOxMKi2t>)0GFK~glsdXA3G;SwZ8 zGpy(8*c>iFQZ&PQo{r7o5+p@4tmo_494!+Md9 z&EXOxMKi1y>)0GFK~glsdWnwB;SwZ8Gpv{D*c>iFQZ&PQnU2lj5+p@4te5N994!+MpD&EXOxg;&YV>vaE5hp)WN>va6zN{VJ!uhy|S zT!N%%hV>d9o5LkYie^}^)v-BTf~07M^*SA!!zD~M+u{m6Vq-ciq1|6HjB}j^9 zSZ~y^Ib4FIXomGB9h<`?NQ!1yZ`QFnT!N%%hV>R5o5LkYie^}E)v-BTf~07M^)?-w z!zD|06u{m6Vq-ciq4jr4rB}j^9Snt%aIb4FIXomGJ9h<`?NQ!1y@7A$7T!N%% zhV>pDo5LkYie^~v)v-BTf~07M^*$Y&!zDC0o5LkYie^|J)v-BTf~07M^)Vfr!zD_EBu{m6Vq-ciq2_2imB}j^9SfA9fIb4FIXomGE9h<`?NQ!1ypVqNCT!N%%hV>a8 zo5LkYie^}!)v-BTf~07M^*J4z!zD}xsu{m6Vq-ciq1s$8iB}j^9SYOn!Ib4FI zXomGA9h<`?NQ!1yU)HfXT!N%%hV>O4o5LkYie^|})v-BTf~07M^)(%v!zD{a> zu{m6Vq-ciq4IP`qB}j^9Sl`sKIb4FIXomGI9h<`?NQ!1y-`24?T!N%%hV>mCo5LkY zie^~f)v-BTf~07M^*tS%!zDgB}j^9SU=RUIb4FIXomG8 z9h<`?NQ!1yKi081T!N%%hV_7s&EXOxMKi3Q=-3=CK~gls`l*i1;SwZ8GpwKK*c>iF zQZ&Q*xsJ`@5+p@4tY7HZ94!}_(3&EXOxMKi45 z=-3=CK~gls`mK)5;SwZ8Gpyg~*c>iFQZ&Q*y^hV{5+p@4tUu`394!}_z1&EXOxMKi3w=-3=CK~gls`m2u3;SwZ8GpxVq*c>iFQZ&Q* zyN=D_5+p@4tbgd(94!}_<5&EXOxMKi4b=-3=C zK~gls`mc`7;SwZ8Gpq->@te)z5+p@4tOx7Z94 z!+MyG&EXOxMKi32>)0GFK~glsdW4S6;SwZ8GptAI*c>iFQZ&PQl#b2e5+p@4tViqE z94!+M;K&EXOxMKi3&>)0GFK~glsdV-G4;SwZ8 zGpr}-*c>iFQZ&PQl8(*c5+p@4tS9T(94!+M&I z&EXOxMKi3Y>)0GFK~glsdWMe8;SwZ8GpuLo*c>iFQZ&PQmX6Kg5+p@4tY_=k94!+M^M&EXOxMKi4D>)0GFK~glsdV!A3;SwZ8GprZt z*c>iFQZ&PQk&eyb5+p@4tQYIp94!+M#H&EXOx zMKi3I>)0GFK~glsdWDY7;SwZ8GptwY*c>iFQZ&PQm5$Bf5+p_ARdVw>9d2YWuhZc) z`rj&hGptwZ*c>iFQZ&PQjgHOX5+p@4tk>$;94 z!+L{`&EXOxMKi27>ew7EK~glsdXtXL;SwZ8Gpsl3*c>iFQZ&PQi;m6V5+p@4thege z94!+M8~&EXOxMKi2->ew7EK~glsdY6vP;SwZ8 zGpu*(*c>iFQZ&PQkB-gZ5+p@4toQ2J94!}@@Z z&EXOxMKi1q>ew7EK~gls`jC#z;SwZ8GprBm*c>iFQZ&Q*h>p$S5+p@4tdHv094!}^4d&EXOxMKi2V>ew7EK~gls`jn2%;SwZ8GptYR z*c>iFQZ&Q*jE>FW5+p@4tk3G$94!}@}b&EXOx zMKi1~>ew7EK~gls`jU>#;SwZ8GpsM`*c>iFQZ&Q*ijK|U5+p@4tgq_W94!}^Af&EXOxMKi2#>ew7EK~gls`j(E(;SwZ8Gpujx*c>iF zQZ&Q*j*iXY5+p@4tncdB94!}@`a&EXOxMKi1) z>ew7EK~gls`jL*!;SwZ8Gprx$*c>iFQZ&PQK*#2A36i22)=zY74woP)nqmD^$L4Se zlA;;b&va}Kmmn#cVf|dk=5Ps;q8ZjNbZicnASs$*{Zhx~a0!y48P>0KYz~(oDVkyZ zTF2&a36i22)^Bud4woP)nqmD`$L4SelA;;b?{sVqmmn#cVf|jm=5Ps;q8Zj7bZicn zASs$*{ZYr}a0!y48P=b4Yz~(oDVkyZS;yvZ36i22)?ajN4woP)nqmD_$L4SelA;;b z-*jvammn#cVf|gl=5Ps;q8ZjdbZicnASs$*{Zq&0a0!y48P>maYz~(oDVkyZTgT>b z36i22)_-(t4woP)nqmD{$L4SelA;;bgS^hi=5Ps;q8ZkMb!-loASs$*Jw(Uma0!y4 z8P-E}Yz~(oDVkwDOvmPM36i22*28sd4woP)nqfUc$L4SelA;;bBXw*Jmmn#cVLeL6 z=5Ps;q8Zksb!-loASs$*Jx0goa0!y48P;QUYz~(oDVkwDPRHhO36i22*5h?-4woP) znqfUb$L4SelA;;b6LoA3mmn#cVLeI5=5Ps;q8Zkcb!-loASs$*Jw?ana0!y48P-#E zYz~(oDVkwDO~>YN36i22*3)%t4woP)nqfUd$L4SelA;;bGj(hZmmn#cVLeO7=5Ps; zq8Zk+b!-loASs$*Jx9mpa0!y48P;=kYz~(oDVkwDPsiqP36i22*7J324woP)nqj>_ z$L4SelA;;b3w3M`mmn#cVZBJl=5Ps;q8ZkUb!-loASs$*y+p_6a0!y48P-d6Yz~(o zDVkxuOvmPM36i22*2{Hl4woP)nqj>{$L4SelA;;bD|KuRmmn#cVZBPn=5Ps;q8YqO zZeFLujSS{>I-ExTTWufKt95J+mmn#cVZBDj=5Ps;q8Zj}b!-loASs$*y-vsGa0!y4 z8P@A{Yz~(oDVkxuLC5BB36i22)*E$f4woP)nqj?3$L4SelA;;bn{{jsmmn#cVZBAi z=5Ps;q8Zj(b!-loASs$*y-mmFa0!y48P?l%Yz~(oDVkxuL&xTD36i22);o1<4woP) znqj?5$L4SelA;;byLD_1mmn#cVZBGk=5Ps;q8ZkEb!-loASs$*y-&yHa0!y48P@xC zYz~(oDVkw@K*#2A36i22)(3TL4woP)nqhrN$L4SelA;;bhjnZYmmn#cVSPl$=5Ps; zq8Zjlb!-loASs$*eN4yZa0!y48P>;jYz~(oDVkw@LdWKC36i22)+cpr4woP)nqhrP z$L4SelA;;br*&)&mmn#cVSPr&=5Ps;q8Zj_b!-loASs$*eNM;ba0!y48P?}@Yz~(o zDVkw@LC5BB36i22))#eb4woP)nqhrO$L4SelA;;bmvw9ommn#cVSPo%=5Ps;q8Zj# zb!-loASs$*eND&aa0!y48P?ZzYz~(oDVkw@L&xTD36i22);D!*4woP)nqhrQ$L4Se zlA;;bw{>g|mmn#cVSPu(=5Ps;q8ZkAb!-loASs$*eNV^ca0!y48P@l8Yz~(oDVkyZ zK*#2A36i22)(>@T4woP)nqmD&$L4SelA;;bk9BMgmmn#cVLhN@bGQUa(G2S+IyQ$( zkQB|ZeyU@0xCBYj4C`k)Hit`)6wR=Hu48k!1WC~h>lZpUhf9zY&9Hu{V{^C!Nzn}J zS2{L_OOO=Juzsy$bGQUa(G2T1IyQ$(kQB|Zeyd}1xCBYj4C{9~Hit`)6wR=HuVZt# z1WC~h>km3Mhf9zY&9MHcV{^C!Nzn}JPdYY-OOO=Ju>P!LbGQUa(G2S^IyQ$(kQB|Z z{;FehxCBYj4C`+?Hit`)6wR>yu48k!1WC~h>mNEchf9zY&9MHdV{^C!Nzn}JUph92 zOOO=Ju>P%MbGQUa(G2T9IyQ$(kQB|Z{;OkixCBYj4C_H{Ugvc_4woP)nqfUy$L4Se zlA;;bLv(Bommn#cVLepG=5Ps;q8Zl1bZicnASs$*JzU4;a0!y48P+3oYz~(oDVkwD zQpe_S36i22)}wT64woP)nqfU!$L4SelA;;bV{~i|mmn#cVLevI=5Ps;q8ZlXbZicn zASs$*JzmG=a0!y48P*eYYz~(oDVkwDQOD+R36i22){}H>4woP)nqfUz$L4SelA;;b zQ*>+&mmn#cVLesH=5Ps;q8ZlHbZicnASs$*JzdAa0!y48P*GQYz~(oDVkxuP{-zQ36i22){As(4woP)nqj?I$L4SelA;;bOLS}w zmmn#cVZBtx=5Ps;q8Zl9bZicnASs$*y|01u{m6Vq-ciq zW*wWuB}j^9SZ~p>Ib4FIXomGx9h<`?NQ!1yZ_}|kT!N%%hV^zGo5LkYie^~v(6KpO zf~07M^-dj|!zD_E6u{m6Vq-ciqVI7;p zB}j^9SRc``Ib4FIXomGs9h<`?NQ!1yAJefpT!N%%hV^kBo5LkYie^}!(6KpOf~07M z^+_F@!zD}xnu{m6Vq-ciqX&sxxB}j^9SfA0cIb4FIXomG!9h<`?NQ!1ypVP59 zT!N%%hV^+Jo5LkYie^|}(6KpOf~07M^+g?{a+u{m6Vq-ciqWgVNtB}j^9 zSYOexIb4FIXomGw9h<`?NQ!1yU(>NUT!N%%hV^wFo5LkYie^~f(6KpOf~07M^-Ud{ z!zD`Pcu{m6Vq-ciqV;!5rB}j^9SP$sf z94!}^(y&EXOxMKi3Q>)0GFK~gls`h||o;SwZ8 zGpt|g*c>iFQZ&Q*m5$Bf5+p@4tY7Qc|DU6KYSt*&88!Nsvb&RX=jUzPwr$(CZQEv@ zalYyr^Xj>uwerr@VUrZi;WET;bu2bX(Ht&A{7%PWlN8P2GQ{t7EH+8e94#2#6NW`Hc8POE<^lF$6}Kd&EYb{zjZ7& zNzoiGL;Od_Vv`ij;WEU3bu2bX(Ht&A{7=VXlN8P2GQn!{y?2kBUB zlA<|WhIp`!#U?45!)1tv=vZu$qB&fKc&LuWCMlZ3Wr&CASZtD_Ib4Q#xQ@jpDVoD& zh)3vHY?7imT!wh0j>RS^n!{y?N9kB>lA<|WhIq7&#U?45!)1ua=vZu$qB&fKc&v`a zCMlZ3Wr)Y=SZtD_Ib4Q#ypF{tDVoD&h$rY+Y?7imT!wg}j>RS^n!{y?C+S#hlA<|W zhIq1$#U?45!)1u4=vZu$qB&fKc&d)YCMlZ3Wr(NgSZtD_Ib4Q#x{k#rDVoD&h-c_n zY?7imT!wh2j>RS^n!{y?XX#jMlA<|WhIqD)#U?45!)1u)=vZu$qB&fKc&?7cCMlZ3 zWr*kLSZtD_Ib4Q#zK+EvDVoD&h!^NsY?7imT!wg|j>RS^n!{y?7wK4RlA<|WhIp}# z#U?45!)1t<=vZu$qB&fKc&U!XCMlZ3Wr&yQSZtD_Ib4Q#xsJsqDVoD&h*#)XY?7im zT!wh1j>RS^n!{y?SLv{o+`LYQ8yU>&ba)&6--%c2SZtD_Ib4Q#jgG}8DVoD&h}Y^^ zY?7imT!wg^j>RS^n!{y?*XvkplA<|WhIoUH#U?45!)1s!>R4=&qB&fKc$1FBCMlZ3 zWr#QHSZtD_Ib4Q#i;l%6DVoD&h_~ukY?7imT!wg?j>RS^n!{y?x9eDJlA<|WhIogL z#U?45!)1tf>R4=&qB&fKc$bdFCMlZ3Wr%m{SZtD_Ib4Q#kB-GADVoD&i1+GPY?7im zT!wg`j>RS^n!{y?_v=_}lA<|WhWLPv#U?45!)1sM>R4=&qB&fK_>hjpCMlZ3Wrz>! zSZtD_Ib4SLh>pc3DVoD&h>z-6Y?7imT!#3Vj>RS^n!{y?kLy@$lA<|WhWLbz#U?45 z!)1t1>R4=&qB&fK_>_*tCMlZ3Wr$DfSZtD_Ib4SLjE==7DVoD&h|lU+Y?7imT!#3Z zj>RS^n!{y?&+AxhlA<|WhWLVx#U?45!)1ss>R4=&qB&fK_>zvrCMlZ3Wr#29SZtD_ zIb4SLijKu5DVoD&h_C8cY?7imT!#3Xj>RS^n!{y?uj^QBlA<|WhWLh##U?45!)1tX z>R4=&qB&fK_?C{vCMlZ3Wr%ORS^ zn!{y?@9S7>lA<|WhWLSw#U?45!)1sc>R4=&qB&fK_>qpqCMlZ3Wr!c^SZtD_Ib4SL ziH^l4DVoD&h@a|MY?7imT!#3Wj>RS^n!{y?pX*p`lA<|WhWLe!#U?45!)1tH>R4=& zqB&fK_?3>uCMlZ3Wr$zvSZtD_Ib4SLjgG}8DVoD&h~Mg1Y?7imT!#3aj>RS^n!{y? z-|JXxlA<|WhWLYy#U?45!)1s+>R4=&qB&fK_>+#sCMlZ3Wr#oPSZtD_Ib4SLi;l%6 zDVoD&h`;JsY?7imT!#3Yj>RS^n!{y?zw20RlA<|WhWLk$#U?45!)1tn>R4=&qB&fK z_?M2wCMlZ3Wr%<4SZtD_Ib4SLkB-GADVoD&i2v$XY?7imT!#3cj>RS^n!{y?2ga)( zz+#gW&EYb{gLEu5NzoiGLp)f=Vv`ij;WETSbSySW(Ht&AJXFVGlN8P2GQ`7lEH+8e z94#3OVpHc8POE<-$0$6}Kd&EYb{qjW4bNzoiGLp)l?Vv`ij;WETy zbSySW(Ht&AJXXhIlN8P2GQ{I_EH+8e94#1nKZHc8POE<-#~$6}Kd z&EYb{lXNULNzoiGLp)i>Vv`ij;WETibSySW(Ht&AJXObHlN8P2GQ`t#EH+8e94#4~g(Hc8POE<-$1$6}Kd&EYb{vve#rNzoiGLp)o@Vv`ij;WET?bSySW z(Ht&AJXgnJlN8P2GQ{(AEH+8e94#0zvRHc8POE#4B_xHc8POEZ{$z@M>RqzuGTHul6>2 z_5VK)V6jPx=5QI}H98iXq-YM8AzrIvu}O;Na2eutIu@IxXbzVlUaw=ZNs8uh8R88( z7MrAK4woU`sAI87iso<`;!Qdho1|zCmm%J)W3fq!=5QI}EjkvPq-YM8A>OKEu}O;N za2eulIu@IxXbzVl-mYV@Ns8uh8R8u}7MrAK4woU`sbjH8iso<`;$1oxo1|zCmm%J* zW3fq!=5QI}JvtVfq-YM8A>ONFu}O;Na2eu#Iu@IxXbzVl-mhb^Ns8uh8R7#v7MrAK z4woT5sAI87iso<`;zK$Xo1|zCmmxl^W3fq!=5QI}BRUqFq-YM8AwH^Ou}O;Na2eub zIu@IxXbzVlKCWZ2Ns8uh8R8Q<7MrAK4woT5sbjH8iso<`;!`>no1|zCmmxl_W3fq! z=5QI}GddQVq-YM8AwH{Pu}O;Na2eurIu@IxXbzVlKCff3Ns8uh8R82%7MrAK4woUm zsAI87iso<`;!8Rfo1|zCmm$8aW3fq!=5QI}D>@dNq-YM8A-<|(u}O;Na2eujIu@Ix zXbzVlzOG}jNs8uh8R8o{7MrAK4woUmsbjH8iso<`;#)cvo1|zCmm$8bW3fq!=5QI} zJ31Ddq-YM8A-=0)u}O;Na2euzIu@IxXbzVlzOQ4kNs8uh8R7>z7MrAK4woT*sAI87 ziso<`;zv3bo1|zCmmz+vW3fq!=5QI}Cps3Jq-YM8A%3c3u}O;Na2eufIu@IxXbzVl zey(G&Ns8uh8R8c@7MrAK4woT*sbjH8iso<`;#WEro1|zCmmz+wW3fq!=5QI}H#!!Z zq-YM8A%3f4u}O;Na2euvIu@IxXbzVley?M(Ns8uh8R8E*7MrAK4woVRsAI87iso<` z;!ipjo1|zCmm&VFW3fq!=5QI}FFF>Rq-YM8A^xgku}O;Na2eunIu@IxXbzVl{;p%O zNs8uh8R8#07MrAK4woVRsbjH8iso<`;$J!zo1|zCmm&VGW3fq!=5QI}KROnhq-YM8 zA^xjlu}O;Na2eu%Iu@IxXbzVl9{2$Bx(AroJ;1!~0p@kK^U)kGLp(^wVv`ij;WEU7 zbu2bX(Ht&AJVeK0lN8P2GQ>l5EH+8e94#KUzgHc8POE<-#*$6}Kd z&EYb{BXuk`NzoiGLp(~yVv`ij;WEUdbu2bX(Ht&AJVwW2lN8P2GQ?wbEH+8e94#N%}=Hc8POE<-#)$6}Kd&EYb{6Ll;$NzoiGLp({xVv`ij;WEUNbu2bX z(Ht&AJVnQ1lN8P2GQ?ALEH+8e94#M5;wHc8POE<-#+$6}Kd&EYb{ zGj%LBNzoiGLp)2zVv`ij;WEUtbu2bX(Ht&AJV(c3lN8P2GQ@LrEH+8e94#PfA5Hc8POE-DEH+8e94#LIOoHc8POE#Ork|Hc8POE#M^Z&Hc8POE#QSwDHc8POE<=1k$6}Kd&EYb{2X!nqNzoiGLwrcbVv`ij;WEUBbu2bX(Ht&A zd_>1$lN8P2GQ>x9EH+8e94#K(0kHc8POE<=1m$6}Kd&EYb{Cv_|~ zNzoiGLwridVv`ij;WEUhbu2bX(Ht&Ad`8D&lN8P2GQ?+fEH+8e94 z#OHM^Hc8POE<=1l$6}Kd&EYb{7j-N)NzoiGLwrfcVv`ij;WEURbu2bX(Ht&Ad_~7% zlN8P2GQ?MPEH+8e94#MgB!Hc8POE<=1n$6}Kd&EYb{H+3vFNzoiG zLwrleVv`ij;WEUxbu2bX(Ht&Ad`HJ(lN8P2GQ@XvEH+8e94#P@Y9 zHc8POE<^l4$6}Kd&EYb{4|OayNzoiGL;Og`Vv`ij;WEUJbu2bX(Ht&A{6xoMlN8P2 zGQ>}HEH+8e94#LsmsHc8POE<^l6$6}Kd&EYb{FLf+7NzoiGL;Om| zVv`ij;WEUpbu2bX(Ht&A{6@!OlN8P2GQ@9nEH+8e94#P4-1Hc8PO zE<^l5$6}Kd&EYb{A9XA?NzoiGL;Oj{Vv`ij;WEUZbu2bX(Ht&A{6)uNlN8P2GQ?kX zEH+8e94#NTx+Hc8POE<^l7$6}Kd&EYb{KXoiNNzoiGL;Op}Vv`ij z;WEU(bu2bX(Ht&A{71)PlN8P2GQ@v%EH+8e94!~^|h#A1^a&EYb{ zgLEu5NzoiGLp)f=Vv`ij;WETSbSySW(Ht&AJXFVGlN8P2GQ`7lEH+8e94#3OVpHc8POE<-$0$6}Kd&EYb{qjW4bNzoiGLp)l?Vv`ij;WETybSySW(Ht&A zJXXhIlN8P2GQ{I_EH+8e94#1nKZHc8POE<-#~$6}Kd&EYb{lXNUL zNzoiGLp)i>Vv`ij;WETibSySW(Ht&AJXObHlN8P2GQ`t#EH+8e94 z#4~g(Hc8POE<-$1$6}Kd&EYb{vve#rNzoiGLp)o@Vv`ij;WET?bSySW(Ht&AJXgnJ zlN8P2GQ{(AEH+8e94#0zvRHc8POE#4B_x zHc8POE#G7?2Hc8POEM|EH+8e94#JhDYHc8POE z#D{e(Hc8POE<=1o$6}Kd&EYb{M|CVVNzoiGLwrofVv`ij;WEU>bu2bX(Ht&Ad_u=! zlN8P2GQ=l!EH+8e94#HV#EHc8POE<=1q$6}Kd&EYb{XLT$#NzoiG zLwruhVv`ij;WEVMbu2bX(Ht&Ad_l)zlN8P2GQ<~kEH+8e94#Fup} zHc8POE<=1p$6}Kd&EYb{S9L5lNzoiGLwrrgVv`ij;WEV6bu2bX(Ht&Ad_%`#lN8P2 zGQ>A^EH+8e94#J6=UHc8POE<=1r$6}Kd&EYb{cXcc_NzoiGLwrxi zVv`ij;WEVcbu2bX(Ht&A{6NQIlN8P2GQ#E*3>Hc8PO zE<^l8$6}Kd&EYb{PjxIdNzoiGL;Os~Vv`ij;WEU}bu2bX(Ht&A{6fcKlN8P2GQ=-+ zEH+8e94#IJQMHc8POE<^lA$6}Kd&EYb{Z*?p-NzoiGL;Oz1Vv`ij z;WEVUbu2bX(Ht&A{6WWJlN8P2GQ=NsEH+8e94#GiF6Hc8POE<^l9 z$6}Kd&EYb{Uv(@tNzoiGL;Ow0Vv`ij;WEVEbu2bX(Ht&A{6oiLlN8P2GQ>Z1EH+8e z94#J_bcHc8POE<^lB$6}Kd&EYb{e|0Q2NzoiGL;O$2Vv`ij;WESn zeZ|0HlN8P2GQ@*)EH+8e94#6xr}Hc8POE<-$2$6}Kd&EYb{!*nb* zNzoiGLp)r^Vv`ij;WES{bSySW(Ht&AJW|JElN8P2GQ^{FEH+8e94 z#A9?UHc8POE<-$4$6}Kd&EYb{<8&-GNzoiGLp)x`Vv`ij;WES%bSySW(Ht&AJW

#8Y%EHc8POE<-$3$6}Kd&EYb{({wC0NzoiG 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 literal 0 HcmV?d00001 diff --git a/components/tidb_query_datatype/src/codec/collation/collator/gb18030_chinese_ci.data b/components/tidb_query_datatype/src/codec/collation/collator/gb18030_chinese_ci.data new file mode 100644 index 0000000000000000000000000000000000000000..90a8971c213c5f858e3f0e81797466c5998c90fe GIT binary patch literal 4456448 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 z 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

{C4xb>3pE481c;l^;s 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 literal 0 HcmV?d00001 diff --git a/components/tidb_query_datatype/src/codec/collation/collator/gb18030_collation.rs b/components/tidb_query_datatype/src/codec/collation/collator/gb18030_collation.rs new file mode 100644 index 00000000000..ff21559ded6 --- /dev/null +++ b/components/tidb_query_datatype/src/codec/collation/collator/gb18030_collation.rs @@ -0,0 +1,181 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use super::*; + +/// Collator for `gb18030_bin` +#[derive(Debug)] +pub struct CollatorGb18030Bin; + +impl Collator for CollatorGb18030Bin { + type Charset = CharsetGb18030; + type Weight = u32; + const IS_CASE_INSENSITIVE: bool = false; + + #[inline] + fn char_weight(ch: char) -> u32 { + // If the incoming character is not, convert it to '?'. This should not + // happened. + let r = ch as usize; + if r > 0x10FFFF { + return '?' as u32; + } + + (&GB18030_BIN_TABLE[r * 4..r * 4 + 4]) + .read_u32_le() + .unwrap() + } + + #[inline] + fn write_sort_key(writer: &mut W, bstr: &[u8]) -> Result { + let s = str::from_utf8(bstr)?.trim_end_matches(PADDING_SPACE); + let mut n = 0; + for ch in s.chars() { + let weight = Self::char_weight(ch); + if weight > 0xFFFF { + writer.write_u32_be(weight)?; + n += 4; + } else if weight > 0xFF { + writer.write_u16_be(weight as u16)?; + n += 2; + } else { + writer.write_u8(weight as u8)?; + n += 1; + } + } + Ok(n * std::mem::size_of::()) + } + + #[inline] + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = sa.trim_end_matches(PADDING_SPACE); + sb = sb.trim_end_matches(PADDING_SPACE); + } + Ok(sa + .chars() + .map(Self::char_weight) + .cmp(sb.chars().map(Self::char_weight))) + } + + #[inline] + fn sort_hash(state: &mut H, bstr: &[u8]) -> Result<()> { + let s = str::from_utf8(bstr)?.trim_end_matches(PADDING_SPACE); + for ch in s.chars().map(Self::char_weight) { + ch.hash(state); + } + Ok(()) + } +} + +/// Collator for `gb18030_chinese_ci` +#[derive(Debug)] +pub struct CollatorGb18030ChineseCi; + +impl Collator for CollatorGb18030ChineseCi { + type Charset = CharsetGb18030; + type Weight = u32; + const IS_CASE_INSENSITIVE: bool = true; + + #[inline] + fn char_weight(ch: char) -> u32 { + // If the incoming character is not, convert it to '?'. This should not + // happened. + let r = ch as usize; + if r > 0x10FFFF { + return '?' as u32; + } + + (&GB18030_CHINESE_CI_TABLE[r * 4..r * 4 + 4]) + .read_u32_le() + .unwrap() + } + + #[inline] + fn write_sort_key(writer: &mut W, bstr: &[u8]) -> Result { + let s = str::from_utf8(bstr)?.trim_end_matches(PADDING_SPACE); + let mut n = 0; + for ch in s.chars() { + let weight = Self::char_weight(ch); + if weight > 0xFFFF { + writer.write_u32_be(weight)?; + n += 4; + } else if weight > 0xFF { + writer.write_u16_be(weight as u16)?; + n += 2; + } else { + writer.write_u8(weight as u8)?; + n += 1; + } + } + Ok(n * std::mem::size_of::()) + } + + #[inline] + fn sort_compare(a: &[u8], b: &[u8], force_no_pad: bool) -> Result { + let mut sa = str::from_utf8(a)?; + let mut sb = str::from_utf8(b)?; + if !force_no_pad { + sa = sa.trim_end_matches(PADDING_SPACE); + sb = sb.trim_end_matches(PADDING_SPACE); + } + Ok(sa + .chars() + .map(Self::char_weight) + .cmp(sb.chars().map(Self::char_weight))) + } + + #[inline] + fn sort_hash(state: &mut H, bstr: &[u8]) -> Result<()> { + let s = str::from_utf8(bstr)?.trim_end_matches(PADDING_SPACE); + for ch in s.chars().map(Self::char_weight) { + ch.hash(state); + } + Ok(()) + } +} + +const TABLE_SIZE_FOR_GB18030: usize = 4 * (0x10FFFF + 1); + +// GB18030_BIN_TABLE are the encoding tables from Unicode to GB18030 code. +const GB18030_BIN_TABLE: &[u8; TABLE_SIZE_FOR_GB18030] = include_bytes!("gb18030_bin.data"); + +// GB18030_CHINESE_CI_TABLE are the sort key tables for GB18030 codepoint. +const GB18030_CHINESE_CI_TABLE: &[u8; TABLE_SIZE_FOR_GB18030] = + include_bytes!("gb18030_chinese_ci.data"); + +#[cfg(test)] +mod tests { + use crate::codec::collation::{ + collator::{CollatorGb18030Bin, CollatorGb18030ChineseCi}, + Collator, + }; + + #[test] + fn test_weight() { + let cases: Vec<(char, u32, u32)> = vec![ + ('中', 0xFFA09BC1, 0xD6D0), + ('€', 0xA2E3, 0xA2E3), + ('', 0xFF001D21, 0x8135F437), + ('ḿ', 0xFF001D20, 0xA8BC), + ('ǹ', 0xFF000154, 0xA8BF), + ('䦃', 0xFFA09E8A, 0xFE89), + ]; + + for (case, exp_chinese_ci, exp_bin) in cases { + let chinese_ci = CollatorGb18030ChineseCi::char_weight(case); + let bin = CollatorGb18030Bin::char_weight(case); + assert_eq!( + exp_bin, bin, + "{} expected:{:02X?}, but got:{:02X?}", + case, exp_bin, bin + ); + assert_eq!( + exp_chinese_ci, chinese_ci, + "{} expected:{:02X?}, but got:{:02X?}", + case, exp_chinese_ci, chinese_ci + ); + } + } +} diff --git a/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs b/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs index a767ca35bfe..fe71e8e1713 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/gbk_collation.rs @@ -2,9 +2,9 @@ use super::*; -pub trait GbkCollator: 'static + std::marker::Send + std::marker::Sync + std::fmt::Debug { +trait GbkCollator: 'static + Send + Sync + std::fmt::Debug { const IS_CASE_INSENSITIVE: bool; - const WEIGHT_TABLE: &'static [u8; (0xffff + 1) * 2]; + const WEIGHT_TABLE: &'static [u8; TABLE_SIZE_FOR_GBK]; } impl Collator for T { @@ -72,7 +72,7 @@ pub struct CollatorGbkBin; impl GbkCollator for CollatorGbkBin { const IS_CASE_INSENSITIVE: bool = false; - const WEIGHT_TABLE: &'static [u8; (0xffff + 1) * 2] = GBK_BIN_TABLE; + const WEIGHT_TABLE: &'static [u8; TABLE_SIZE_FOR_GBK] = GBK_BIN_TABLE; } /// Collator for `gbk_chinese_ci` collation with padding behavior (trims right @@ -82,15 +82,17 @@ pub struct CollatorGbkChineseCi; impl GbkCollator for CollatorGbkChineseCi { const IS_CASE_INSENSITIVE: bool = true; - const WEIGHT_TABLE: &'static [u8; (0xffff + 1) * 2] = GBK_CHINESE_CI_TABLE; + const WEIGHT_TABLE: &'static [u8; TABLE_SIZE_FOR_GBK] = GBK_CHINESE_CI_TABLE; } +const TABLE_SIZE_FOR_GBK: usize = (0xffff + 1) * 2; + // GBK_BIN_TABLE are the encoding tables from Unicode to GBK code, it is totally // the same with golang's GBK encoding. If there is no mapping code in GBK, use // 0x3F(?) instead. It should not happened. -const GBK_BIN_TABLE: &[u8; (0xffff + 1) * 2] = include_bytes!("gbk_bin.data"); +const GBK_BIN_TABLE: &[u8; TABLE_SIZE_FOR_GBK] = include_bytes!("gbk_bin.data"); // GBK_CHINESE_CI_TABLE are the sort key tables for GBK codepoint. // If there is no mapping code in GBK, use 0x3F(?) instead. It should not // happened. -const GBK_CHINESE_CI_TABLE: &[u8; (0xffff + 1) * 2] = include_bytes!("gbk_chinese_ci.data"); +const GBK_CHINESE_CI_TABLE: &[u8; TABLE_SIZE_FOR_GBK] = include_bytes!("gbk_chinese_ci.data"); diff --git a/components/tidb_query_datatype/src/codec/collation/collator/mod.rs b/components/tidb_query_datatype/src/codec/collation/collator/mod.rs index 4943772e850..4385f83e74b 100644 --- a/components/tidb_query_datatype/src/codec/collation/collator/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/collator/mod.rs @@ -1,6 +1,7 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. mod binary; +mod gb18030_collation; mod gbk_collation; mod latin1_bin; mod utf8mb4_binary; @@ -15,6 +16,7 @@ use std::{ pub use binary::*; use codec::prelude::*; +pub use gb18030_collation::*; pub use gbk_collation::*; pub use latin1_bin::*; pub use utf8mb4_binary::*; @@ -45,6 +47,8 @@ mod tests { (Collation::GbkChineseCi, 6), (Collation::Utf8Mb40900AiCi, 7), (Collation::Utf8Mb40900Bin, 8), + (Collation::Gb18030Bin, 9), + (Collation::Gb18030ChineseCi, 10), ]; let cases = vec![ // (sa, sb, [Utf8Mb4Bin, Utf8Mb4BinNoPadding, Utf8Mb4GeneralCi, Utf8Mb4UnicodeCi, @@ -62,6 +66,8 @@ mod tests { Ordering::Equal, Ordering::Equal, Ordering::Equal, + Ordering::Equal, + Ordering::Equal, ], ), ( @@ -77,6 +83,8 @@ mod tests { Ordering::Equal, Ordering::Less, Ordering::Less, + Ordering::Equal, + Ordering::Equal, ], ), ( @@ -92,6 +100,8 @@ mod tests { Ordering::Equal, Ordering::Less, Ordering::Greater, + Ordering::Greater, + Ordering::Equal, ], ), ( @@ -107,6 +117,8 @@ mod tests { Ordering::Greater, Ordering::Greater, Ordering::Greater, + Ordering::Greater, + Ordering::Greater, ], ), ( @@ -122,6 +134,8 @@ mod tests { Ordering::Less, Ordering::Less, Ordering::Less, + Ordering::Less, + Ordering::Less, ], ), ( @@ -137,6 +151,8 @@ mod tests { Ordering::Less, Ordering::Equal, Ordering::Less, + Ordering::Less, + Ordering::Less, ], ), ( @@ -152,6 +168,8 @@ mod tests { Ordering::Less, Ordering::Greater, Ordering::Less, + Ordering::Less, + Ordering::Less, ], ), ( @@ -167,6 +185,8 @@ mod tests { Ordering::Less, Ordering::Equal, Ordering::Greater, + Ordering::Greater, + Ordering::Greater, ], ), ( @@ -182,6 +202,8 @@ mod tests { Ordering::Greater, Ordering::Less, Ordering::Less, + Ordering::Greater, + Ordering::Greater, ], ), ( @@ -197,6 +219,8 @@ mod tests { Ordering::Less, Ordering::Less, Ordering::Less, + Ordering::Less, + Ordering::Less, ], ), ]; @@ -255,6 +279,8 @@ mod tests { (Collation::GbkChineseCi, 6), (Collation::Utf8Mb40900AiCi, 7), (Collation::Utf8Mb40900Bin, 8), + (Collation::Gb18030Bin, 9), + (Collation::Gb18030ChineseCi, 10), ]; let cases = vec![ // (str, [Utf8Mb4Bin, Utf8Mb4BinNoPadding, Utf8Mb4GeneralCi, Utf8Mb4UnicodeCi, Latin1, @@ -271,6 +297,8 @@ mod tests { vec![0x41], vec![0x1C, 0x47], vec![0x61], + vec![0x61], + vec![0x41], ], ), ( @@ -285,6 +313,8 @@ mod tests { vec![0x41], vec![0x1C, 0x47, 0x2, 0x9], vec![0x41, 0x20], + vec![0x41], + vec![0x41], ], ), ( @@ -299,6 +329,8 @@ mod tests { vec![0x41], vec![0x1C, 0x47], vec![0x41], + vec![0x41], + vec![0x41], ], ), ( @@ -313,6 +345,8 @@ mod tests { vec![0x3F], vec![0x15, 0xFE], vec![0xF0, 0x9F, 0x98, 0x83], + vec![0x94, 0x39, 0xFC, 0x39], + vec![0xFF, 0x03, 0xD8, 0x4B], ], ), ( @@ -364,6 +398,16 @@ mod tests { 0x9D, 0x8C, 0x86, 0x20, 0x62, 0x61, 0x7A, 0x20, 0xE2, 0x98, 0x83, 0x20, 0x71, 0x75, 0x78, ], + vec![ + 0x46, 0x6F, 0x6F, 0x20, 0x81, 0x30, 0x84, 0x38, 0x20, 0x62, 0x61, 0x72, + 0x20, 0x94, 0x32, 0xEF, 0x32, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x81, 0x37, + 0xA3, 0x30, 0x20, 0x71, 0x75, 0x78, + ], + vec![ + 0x46, 0x4F, 0x4F, 0x20, 0xFF, 0x00, 0x00, 0x26, 0x20, 0x42, 0x41, 0x52, + 0x20, 0xFF, 0x03, 0xB5, 0x4E, 0x20, 0x42, 0x41, 0x5A, 0x20, 0xFF, 0x00, + 0x23, 0xC8, 0x20, 0x51, 0x55, 0x58, + ], ], ), ( @@ -384,6 +428,8 @@ mod tests { 0x9C, 0x23, 0xB1, ], vec![0xEF, 0xB7, 0xBB], + vec![0x84, 0x30, 0xFE, 0x35], + vec![0xFF, 0x00, 0x98, 0x8F], ], ), ( @@ -398,6 +444,8 @@ mod tests { vec![0xD3, 0x21, 0xC1, 0xAD], vec![0xFB, 0x40, 0xCE, 0x2D, 0xFB, 0x40, 0xE5, 0x87], vec![0xE4, 0xB8, 0xAD, 0xE6, 0x96, 0x87], + vec![0xD6, 0xD0, 0xCE, 0xC4], + vec![0xFF, 0xA0, 0x9B, 0xC1, 0xFF, 0xA0, 0x78, 0xBD], ], ), ]; diff --git a/components/tidb_query_datatype/src/codec/collation/encoding/gb18030.rs b/components/tidb_query_datatype/src/codec/collation/encoding/gb18030.rs new file mode 100644 index 00000000000..b66512af0f7 --- /dev/null +++ b/components/tidb_query_datatype/src/codec/collation/encoding/gb18030.rs @@ -0,0 +1,434 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use collections::HashMap; +use encoding_rs::GB18030; +use lazy_static::*; + +use self::gb18030_data::GB18030_TO_UNICODE; +use super::*; +use crate::codec::data_type::{BytesGuard, BytesWriter}; + +lazy_static! { + static ref DECODE_MAP: HashMap = GB18030_TO_UNICODE.iter().copied().collect(); + static ref ENCODE_MAP: HashMap> = GB18030_TO_UNICODE + .iter() + .map(|(gb18030, ch)| { + let mut gb18030_bytes = gb18030.to_be_bytes().to_vec(); + let mut pos = 0; + while pos < gb18030_bytes.len() && gb18030_bytes[pos] == 0 { + pos += 1; + } + gb18030_bytes = gb18030_bytes[pos..].to_vec(); + (*ch, gb18030_bytes) + }) + .collect(); +} + +#[derive(Debug)] +pub struct EncodingGb18030 {} + +impl Encoding for EncodingGb18030 { + #[inline] + fn decode(data: BytesRef<'_>) -> Result { + let mut res = Vec::::new(); + let l = data.len(); + if l == 0 { + return Ok(res); + } + let mut base = 0; + while base < l { + // 1. decide the length of next character + let offset; + match data[base] { + ..=0x7f => offset = 1, + 0x81..=0xfe => { + if base + 1 >= l { + return Err(Error::cannot_convert_string( + format_invalid_char(data).as_str(), + "gb18030", + )); + } + if 0x40 <= data[base + 1] && data[base + 1] <= 0xfe && data[base + 1] != 0x7f { + offset = 2; + } else if base + 3 < l + && data[base + 1] >= 0x30 + && data[base + 1] <= 0x39 + && data[base + 2] >= 0x81 + && data[base + 2] <= 0xfe + && data[base + 3] >= 0x30 + && data[base + 3] <= 0x39 + { + offset = 4; + } else { + return Err(Error::cannot_convert_string( + format_invalid_char(data).as_str(), + "gb18030", + )); + } + } + _ => { + return Err(Error::cannot_convert_string( + format_invalid_char(data).as_str(), + "gb18030", + )); + } + } + + // 2. decode next character + let v: u32 = match offset { + 1 => u32::from(data[base]), + 2 => u32::from(data[base]) << 8 | u32::from(data[base + 1]), + 4 => { + u32::from(data[base]) << 24 + | u32::from(data[base + 1]) << 16 + | u32::from(data[base + 2]) << 8 + | u32::from(data[base + 3]) + } + _ => { + return Err(Error::cannot_convert_string( + format_invalid_char(data).as_str(), + "gb18030", + )); + } + }; + if DECODE_MAP.contains_key(&v) { + let mut buffer = [0; 4]; + let utf8_bytes = DECODE_MAP + .get(&v) + .unwrap() + .encode_utf8(&mut buffer) + .as_bytes(); + res.extend(utf8_bytes.to_vec()); + } else { + match GB18030 + .decode_without_bom_handling_and_without_replacement(&data[base..base + offset]) + { + Some(v) => { + res.extend(v.as_bytes()); + } + None => { + return Err(Error::cannot_convert_string( + format_invalid_char(data).as_str(), + "gb18030", + )); + } + } + } + base += offset; + } + + Ok(res) + } + + #[inline] + fn encode(data: BytesRef<'_>) -> Result { + let mut res = Vec::::new(); + let utf8_str = str::from_utf8(data)?; + // encode each character one by one + for ch in utf8_str.chars() { + if ENCODE_MAP.contains_key(&ch) { + res.extend(ENCODE_MAP.get(&ch).unwrap().iter().copied()); + } else { + res.extend(GB18030.encode(&ch.to_string()).0.iter()); + } + } + + Ok(res) + } + + #[inline] + fn lower(s: &str, writer: BytesWriter) -> BytesGuard { + let res = s.chars().flat_map(|ch| { + let c = ch as u32; + match c { + 0xB5 => char::from_u32(c + 775), + 0x3D0 => char::from_u32(c - 30), + 0x3D1 => char::from_u32(c - 25), + 0x3D5 => char::from_u32(c - 15), + 0x3D6 => char::from_u32(c - 22), + 0x3F0 => char::from_u32(c - 54), + 0x3F1 => char::from_u32(c - 48), + 0x3F5 => char::from_u32(c - 64), + 0x1E9B => char::from_u32(c - 58), + 0x1FBE => char::from_u32(c - 7173), + 0x1C5 | 0x1C8 | 0x1CB | 0x1F2 | 0x3C2 => char::from_u32(c + 1), + 0x25C + | 0x261 + | 0x265..=0x266 + | 0x26A + | 0x26C + | 0x282 + | 0x287 + | 0x29D..=0x29E + | 0x37F + | 0x3F3 + | 0x526..=0x52F + | 0x10C7 + | 0x10CD + | 0x10D0..=0x10FA + | 0x10FD..=0x10FF + | 0x13A0..=0x13F5 + | 0x13F8..=0x13FD + | 0x1C80..=0x1C88 + | 0x1C90..=0x1CBA + | 0x1CBD..=0x1CBF + | 0x1D79 + | 0x1D7D + | 0x1D8E + | 0x2CF2..=0x2CF3 + | 0x2D27 + | 0x2D2D + | 0xA660..=0xA661 + | 0xA698..=0xA69B + | 0xA78D + | 0xA790..=0xA794 + | 0xA796..=0xA7AE + | 0xA7B0..=0xA7BF + | 0xA7C2..=0xA7CA + | 0xA7F5..=0xA7F6 + | 0xAB53 + | 0xAB70..=0xABBF + | 0x104B0..=0x104D3 + | 0x104D8..=0x104FB + | 0x10C80..=0x10CB2 + | 0x10CC0..=0x10CF2 + | 0x118A0..=0x118DF + | 0x16E40..=0x16E7F + | 0x1E900..=0x1E943 => char::from_u32(c), + _ => unicode_to_lower(ch), + } + }); + writer.write_from_char_iter(res) + } + + #[inline] + fn upper(s: &str, writer: BytesWriter) -> BytesGuard { + let res = s.chars().flat_map(|ch| { + let c = ch as u32; + match c { + 0xB5 + | 0x1C5 + | 0x1C8 + | 0x1CB + | 0x1F2 + | 0x25C + | 0x261 + | 0x265..=0x266 + | 0x26A + | 0x26C + | 0x282 + | 0x287 + | 0x29D..=0x29E + | 0x37F + | 0x3C2 + | 0x3D0 + | 0x3D1 + | 0x3D5 + | 0x3D6 + | 0x3F0 + | 0x3F1 + | 0x3F3 + | 0x3F5 + | 0x526..=0x52F + | 0x10C7 + | 0x10CD + | 0x10D0..=0x10FA + | 0x10FD..=0x10FF + | 0x13A0..=0x13F5 + | 0x13F8..=0x13FD + | 0x1C80..=0x1C88 + | 0x1C90..=0x1CBA + | 0x1CBD..=0x1CBF + | 0x1D79 + | 0x1D7D + | 0x1D8E + | 0x1E9B + | 0x1FBE + | 0x2CF2..=0x2CF3 + | 0x2D27 + | 0x2D2D + | 0xA660..=0xA661 + | 0xA698..=0xA69B + | 0xA78D + | 0xA790..=0xA794 + | 0xA796..=0xA7AE + | 0xA7B0..=0xA7BF + | 0xA7C2..=0xA7CA + | 0xA7F5..=0xA7F6 + | 0xAB53 + | 0xAB70..=0xABBF + | 0x104B0..=0x104D3 + | 0x104D8..=0x104FB + | 0x10C80..=0x10CB2 + | 0x10CC0..=0x10CF2 + | 0x118A0..=0x118DF + | 0x16E40..=0x16E7F + | 0x1E900..=0x1E943 => char::from_u32(c), + _ => unicode_to_upper(ch), + } + }); + writer.write_from_char_iter(res) + } +} + +#[cfg(test)] +mod tests { + use bstr::ByteSlice; + + use crate::codec::collation::{encoding::EncodingGb18030, Encoding}; + + #[test] + fn test_encode() { + let cases = vec![ + ("中文", vec![0xD6, 0xD0, 0xCE, 0xC4]), + ("€", vec![0xA2, 0xE3]), + ("ḿ", vec![0xA8, 0xBC]), + ("", vec![0x81, 0x35, 0xF4, 0x37]), + ("€ḿ", vec![0xA2, 0xE3, 0xA8, 0xBC]), + ("😃", vec![0x94, 0x39, 0xFC, 0x39]), + ( + "Foo © bar 𝌆 baz ☃ qux", + vec![ + 0x46, 0x6F, 0x6F, 0x20, 0x81, 0x30, 0x84, 0x38, 0x20, 0x62, 0x61, 0x72, 0x20, + 0x94, 0x32, 0xEF, 0x32, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x81, 0x37, 0xA3, 0x30, + 0x20, 0x71, 0x75, 0x78, + ], + ), + ("ﷻ", vec![0x84, 0x30, 0xFE, 0x35]), + // GB18030-2005 + ( + "〾⿰⿱⿲⿳⿴⿵⿶⿷⿸⿹⿺⿻", + vec![ + 0xA9, 0x89, 0xA9, 0x8A, 0xA9, 0x8B, 0xA9, 0x8C, 0xA9, 0x8D, 0xA9, 0x8E, 0xA9, + 0x8F, 0xA9, 0x90, 0xA9, 0x91, 0xA9, 0x92, 0xA9, 0x93, 0xA9, 0x94, 0xA9, 0x95, + ], + ), + ("ǹ", vec![0xA8, 0xBF]), + ( + "⺁㧟㩳㧐", + vec![0xFE, 0x50, 0xFE, 0x63, 0xFE, 0x64, 0xFE, 0x65], + ), + ("䦃", vec![0xFE, 0x89]), + ("︐", vec![0xA6, 0xD9]), + ("𠂇𠂉", vec![0x95, 0x32, 0x90, 0x31, 0x95, 0x32, 0x90, 0x33]), + ("\u{e816}\u{e855}", vec![0xFE, 0x51, 0xFE, 0x91]), + // GB18038-2022 + ("\u{f9f1}", vec![0xFD, 0xA0]), + ( + "\u{fa0c}\u{fa0d}\u{fa0e}", + vec![0xFE, 0x40, 0xFE, 0x41, 0xFE, 0x42], + ), + ( + "\u{2e81}\u{e816}\u{e817}\u{e818}\u{2e84}", + vec![0xFE, 0x50, 0xFE, 0x51, 0xFE, 0x52, 0xFE, 0x53, 0xFE, 0x54], + ), + ( + "\u{e831}\u{9fb8}\u{2eaa}\u{4056}", + vec![0xFE, 0x6C, 0xFE, 0x6D, 0xFE, 0x6E, 0xFE, 0x6F], + ), + ( + "\u{f92c}\u{f979}\u{f995}\u{f9e7}\u{f9f1}\u{fa0c}\u{fa0d}\u{fa18}\u{fa20}", + vec![ + 0xFD, 0x9C, 0xFD, 0x9D, 0xFD, 0x9E, 0xFD, 0x9F, 0xFD, 0xA0, 0xFE, 0x40, 0xFE, + 0x41, 0xFE, 0x47, 0xFE, 0x49, + ], + ), + ("\u{e5e5}\u{e000}", vec![0xA3, 0xA0, 0xAA, 0xA1]), + ]; + for (case, expected) in cases { + let res = EncodingGb18030::encode(case.to_string().as_bytes()); + match res { + Ok(bytes) => { + assert_eq!( + expected, bytes, + "{} expected:{:02X?}, but got:{:02X?}", + case, expected, bytes + ); + } + _ => panic!("Should succeed to encode"), + } + } + } + + #[test] + fn test_decode() { + let cases: Vec<(Vec, &str)> = vec![ + (vec![0xD6, 0xD0, 0xCE, 0xC4], "中文"), + (vec![0xA2, 0xE3], "€"), + (vec![0xA8, 0xBC], "ḿ"), + (vec![0x81, 0x35, 0xF4, 0x37], ""), + (vec![0xA2, 0xE3, 0xA8, 0xBC], "€ḿ"), + (vec![0x94, 0x39, 0xFC, 0x39], "😃"), + ( + vec![ + 0x46, 0x6F, 0x6F, 0x20, 0x81, 0x30, 0x84, 0x38, 0x20, 0x62, 0x61, 0x72, 0x20, + 0x94, 0x32, 0xEF, 0x32, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x81, 0x37, 0xA3, 0x30, + 0x20, 0x71, 0x75, 0x78, + ], + "Foo © bar 𝌆 baz ☃ qux", + ), + (vec![0x84, 0x30, 0xFE, 0x35], "ﷻ"), + // GB18030-2005 + ( + vec![ + 0xA9, 0x89, 0xA9, 0x8A, 0xA9, 0x8B, 0xA9, 0x8C, 0xA9, 0x8D, 0xA9, 0x8E, 0xA9, + 0x8F, 0xA9, 0x90, 0xA9, 0x91, 0xA9, 0x92, 0xA9, 0x93, 0xA9, 0x94, 0xA9, 0x95, + ], + "〾⿰⿱⿲⿳⿴⿵⿶⿷⿸⿹⿺⿻", + ), + (vec![0xA8, 0xBF], "ǹ"), + ( + vec![ + 0xFE, 0x50, 0xFE, 0x54, 0xFE, 0x55, 0xFE, 0x56, 0xFE, 0x57, 0xFE, 0x58, 0xFE, + 0x5A, 0xFE, 0x5B, 0xFE, 0x5C, 0xFE, 0x5D, 0xFE, 0x5E, 0xFE, 0x5F, 0xFE, 0x60, + 0xFE, 0x62, 0xFE, 0x63, 0xFE, 0x64, 0xFE, 0x65, 0xFE, 0x68, 0xFE, 0x69, 0xFE, + 0x6A, 0xFE, 0x6B, 0xFE, 0x6E, 0xFE, 0x6F, + ], + "⺁⺄㑳㑇⺈⺋㖞㘚㘎⺌⺗㥮㤘㧏㧟㩳㧐㭎㱮㳠⺧⺪䁖", + ), + (vec![0xFE, 0x76], "\u{e83b}"), + (vec![0xFE, 0x89], "䦃"), + (vec![0xA6, 0xD9], "︐"), + (vec![0x95, 0x32, 0x90, 0x31, 0x95, 0x32, 0x90, 0x33], "𠂇𠂉"), + (vec![0xFE, 0x51, 0xFE, 0x91], "\u{e816}\u{e855}"), + // GB18030-2022 + (vec![0xFD, 0xA0], "\u{f9f1}"), + ( + vec![0xFE, 0x40, 0xFE, 0x41, 0xFE, 0x42], + "\u{fa0c}\u{fa0d}\u{fa0e}", + ), + ( + vec![0xFE, 0x50, 0xFE, 0x51, 0xFE, 0x52, 0xFE, 0x53, 0xFE, 0x54], + "\u{2e81}\u{e816}\u{e817}\u{e818}\u{2e84}", + ), + ( + vec![0xFE, 0x6C, 0xFE, 0x6D, 0xFE, 0x6E, 0xFE, 0x6F], + "\u{e831}\u{9fb8}\u{2eaa}\u{4056}", + ), + ( + vec![ + 0xFD, 0x9C, 0xFD, 0x9D, 0xFD, 0x9E, 0xFD, 0x9F, 0xFD, 0xA0, 0xFE, 0x40, 0xFE, + 0x41, 0xFE, 0x47, 0xFE, 0x49, + ], + "\u{f92c}\u{f979}\u{f995}\u{f9e7}\u{f9f1}\u{fa0c}\u{fa0d}\u{fa18}\u{fa20}", + ), + (vec![0xA3, 0xA0, 0xAA, 0xA1], "\u{e5e5}\u{e000}"), + ]; + for (case, expected) in cases { + let res = EncodingGb18030::decode(case.as_bytes()); + match res { + Ok(bytes) => { + let s = bytes.to_str().unwrap(); + assert_eq!( + expected, s, + "{:02X?} expected:{}, but got:{}", + case, expected, s + ) + } + Err(e) => { + panic!("Should succeed to decode;\n{}", e); + } + } + } + } +} diff --git a/components/tidb_query_datatype/src/codec/collation/encoding/gb18030_data.rs b/components/tidb_query_datatype/src/codec/collation/encoding/gb18030_data.rs new file mode 100644 index 00000000000..e720fbd3fd0 --- /dev/null +++ b/components/tidb_query_datatype/src/codec/collation/encoding/gb18030_data.rs @@ -0,0 +1,2107 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +pub const GB18030_TO_UNICODE: &[(u32, char)] = &[ + (0xA140, '\u{e4c6}'), + (0xA141, '\u{e4c7}'), + (0xA142, '\u{e4c8}'), + (0xA143, '\u{e4c9}'), + (0xA144, '\u{e4ca}'), + (0xA145, '\u{e4cb}'), + (0xA146, '\u{e4cc}'), + (0xA147, '\u{e4cd}'), + (0xA148, '\u{e4ce}'), + (0xA149, '\u{e4cf}'), + (0xA14A, '\u{e4d0}'), + (0xA14B, '\u{e4d1}'), + (0xA14C, '\u{e4d2}'), + (0xA14D, '\u{e4d3}'), + (0xA14E, '\u{e4d4}'), + (0xA14F, '\u{e4d5}'), + (0xA150, '\u{e4d6}'), + (0xA151, '\u{e4d7}'), + (0xA152, '\u{e4d8}'), + (0xA153, '\u{e4d9}'), + (0xA154, '\u{e4da}'), + (0xA155, '\u{e4db}'), + (0xA156, '\u{e4dc}'), + (0xA157, '\u{e4dd}'), + (0xA158, '\u{e4de}'), + (0xA159, '\u{e4df}'), + (0xA15A, '\u{e4e0}'), + (0xA15B, '\u{e4e1}'), + (0xA15C, '\u{e4e2}'), + (0xA15D, '\u{e4e3}'), + (0xA15E, '\u{e4e4}'), + (0xA15F, '\u{e4e5}'), + (0xA160, '\u{e4e6}'), + (0xA161, '\u{e4e7}'), + (0xA162, '\u{e4e8}'), + (0xA163, '\u{e4e9}'), + (0xA164, '\u{e4ea}'), + (0xA165, '\u{e4eb}'), + (0xA166, '\u{e4ec}'), + (0xA167, '\u{e4ed}'), + (0xA168, '\u{e4ee}'), + (0xA169, '\u{e4ef}'), + (0xA16A, '\u{e4f0}'), + (0xA16B, '\u{e4f1}'), + (0xA16C, '\u{e4f2}'), + (0xA16D, '\u{e4f3}'), + (0xA16E, '\u{e4f4}'), + (0xA16F, '\u{e4f5}'), + (0xA170, '\u{e4f6}'), + (0xA171, '\u{e4f7}'), + (0xA172, '\u{e4f8}'), + (0xA173, '\u{e4f9}'), + (0xA174, '\u{e4fa}'), + (0xA175, '\u{e4fb}'), + (0xA176, '\u{e4fc}'), + (0xA177, '\u{e4fd}'), + (0xA178, '\u{e4fe}'), + (0xA179, '\u{e4ff}'), + (0xA17A, '\u{e500}'), + (0xA17B, '\u{e501}'), + (0xA17C, '\u{e502}'), + (0xA17D, '\u{e503}'), + (0xA17E, '\u{e504}'), + (0xA180, '\u{e505}'), + (0xA181, '\u{e506}'), + (0xA182, '\u{e507}'), + (0xA183, '\u{e508}'), + (0xA184, '\u{e509}'), + (0xA185, '\u{e50a}'), + (0xA186, '\u{e50b}'), + (0xA187, '\u{e50c}'), + (0xA188, '\u{e50d}'), + (0xA189, '\u{e50e}'), + (0xA18A, '\u{e50f}'), + (0xA18B, '\u{e510}'), + (0xA18C, '\u{e511}'), + (0xA18D, '\u{e512}'), + (0xA18E, '\u{e513}'), + (0xA18F, '\u{e514}'), + (0xA190, '\u{e515}'), + (0xA191, '\u{e516}'), + (0xA192, '\u{e517}'), + (0xA193, '\u{e518}'), + (0xA194, '\u{e519}'), + (0xA195, '\u{e51a}'), + (0xA196, '\u{e51b}'), + (0xA197, '\u{e51c}'), + (0xA198, '\u{e51d}'), + (0xA199, '\u{e51e}'), + (0xA19A, '\u{e51f}'), + (0xA19B, '\u{e520}'), + (0xA19C, '\u{e521}'), + (0xA19D, '\u{e522}'), + (0xA19E, '\u{e523}'), + (0xA19F, '\u{e524}'), + (0xA1A0, '\u{e525}'), + (0xA240, '\u{e526}'), + (0xA241, '\u{e527}'), + (0xA242, '\u{e528}'), + (0xA243, '\u{e529}'), + (0xA244, '\u{e52a}'), + (0xA245, '\u{e52b}'), + (0xA246, '\u{e52c}'), + (0xA247, '\u{e52d}'), + (0xA248, '\u{e52e}'), + (0xA249, '\u{e52f}'), + (0xA24A, '\u{e530}'), + (0xA24B, '\u{e531}'), + (0xA24C, '\u{e532}'), + (0xA24D, '\u{e533}'), + (0xA24E, '\u{e534}'), + (0xA24F, '\u{e535}'), + (0xA250, '\u{e536}'), + (0xA251, '\u{e537}'), + (0xA252, '\u{e538}'), + (0xA253, '\u{e539}'), + (0xA254, '\u{e53a}'), + (0xA255, '\u{e53b}'), + (0xA256, '\u{e53c}'), + (0xA257, '\u{e53d}'), + (0xA258, '\u{e53e}'), + (0xA259, '\u{e53f}'), + (0xA25A, '\u{e540}'), + (0xA25B, '\u{e541}'), + (0xA25C, '\u{e542}'), + (0xA25D, '\u{e543}'), + (0xA25E, '\u{e544}'), + (0xA25F, '\u{e545}'), + (0xA260, '\u{e546}'), + (0xA261, '\u{e547}'), + (0xA262, '\u{e548}'), + (0xA263, '\u{e549}'), + (0xA264, '\u{e54a}'), + (0xA265, '\u{e54b}'), + (0xA266, '\u{e54c}'), + (0xA267, '\u{e54d}'), + (0xA268, '\u{e54e}'), + (0xA269, '\u{e54f}'), + (0xA26A, '\u{e550}'), + (0xA26B, '\u{e551}'), + (0xA26C, '\u{e552}'), + (0xA26D, '\u{e553}'), + (0xA26E, '\u{e554}'), + (0xA26F, '\u{e555}'), + (0xA270, '\u{e556}'), + (0xA271, '\u{e557}'), + (0xA272, '\u{e558}'), + (0xA273, '\u{e559}'), + (0xA274, '\u{e55a}'), + (0xA275, '\u{e55b}'), + (0xA276, '\u{e55c}'), + (0xA277, '\u{e55d}'), + (0xA278, '\u{e55e}'), + (0xA279, '\u{e55f}'), + (0xA27A, '\u{e560}'), + (0xA27B, '\u{e561}'), + (0xA27C, '\u{e562}'), + (0xA27D, '\u{e563}'), + (0xA27E, '\u{e564}'), + (0xA280, '\u{e565}'), + (0xA281, '\u{e566}'), + (0xA282, '\u{e567}'), + (0xA283, '\u{e568}'), + (0xA284, '\u{e569}'), + (0xA285, '\u{e56a}'), + (0xA286, '\u{e56b}'), + (0xA287, '\u{e56c}'), + (0xA288, '\u{e56d}'), + (0xA289, '\u{e56e}'), + (0xA28A, '\u{e56f}'), + (0xA28B, '\u{e570}'), + (0xA28C, '\u{e571}'), + (0xA28D, '\u{e572}'), + (0xA28E, '\u{e573}'), + (0xA28F, '\u{e574}'), + (0xA290, '\u{e575}'), + (0xA291, '\u{e576}'), + (0xA292, '\u{e577}'), + (0xA293, '\u{e578}'), + (0xA294, '\u{e579}'), + (0xA295, '\u{e57a}'), + (0xA296, '\u{e57b}'), + (0xA297, '\u{e57c}'), + (0xA298, '\u{e57d}'), + (0xA299, '\u{e57e}'), + (0xA29A, '\u{e57f}'), + (0xA29B, '\u{e580}'), + (0xA29C, '\u{e581}'), + (0xA29D, '\u{e582}'), + (0xA29E, '\u{e583}'), + (0xA29F, '\u{e584}'), + (0xA2A0, '\u{e585}'), + (0xA2AB, '\u{e766}'), + (0xA2AC, '\u{e767}'), + (0xA2AD, '\u{e768}'), + (0xA2AE, '\u{e769}'), + (0xA2AF, '\u{e76a}'), + (0xA2B0, '\u{e76b}'), + (0xA2E3, '\u{20ac}'), + (0xA2E4, '\u{e76d}'), + (0xA2EF, '\u{e76e}'), + (0xA2F0, '\u{e76f}'), + (0xA2FD, '\u{e770}'), + (0xA2FE, '\u{e771}'), + (0xA340, '\u{e586}'), + (0xA341, '\u{e587}'), + (0xA342, '\u{e588}'), + (0xA343, '\u{e589}'), + (0xA344, '\u{e58a}'), + (0xA345, '\u{e58b}'), + (0xA346, '\u{e58c}'), + (0xA347, '\u{e58d}'), + (0xA348, '\u{e58e}'), + (0xA349, '\u{e58f}'), + (0xA34A, '\u{e590}'), + (0xA34B, '\u{e591}'), + (0xA34C, '\u{e592}'), + (0xA34D, '\u{e593}'), + (0xA34E, '\u{e594}'), + (0xA34F, '\u{e595}'), + (0xA350, '\u{e596}'), + (0xA351, '\u{e597}'), + (0xA352, '\u{e598}'), + (0xA353, '\u{e599}'), + (0xA354, '\u{e59a}'), + (0xA355, '\u{e59b}'), + (0xA356, '\u{e59c}'), + (0xA357, '\u{e59d}'), + (0xA358, '\u{e59e}'), + (0xA359, '\u{e59f}'), + (0xA35A, '\u{e5a0}'), + (0xA35B, '\u{e5a1}'), + (0xA35C, '\u{e5a2}'), + (0xA35D, '\u{e5a3}'), + (0xA35E, '\u{e5a4}'), + (0xA35F, '\u{e5a5}'), + (0xA360, '\u{e5a6}'), + (0xA361, '\u{e5a7}'), + (0xA362, '\u{e5a8}'), + (0xA363, '\u{e5a9}'), + (0xA364, '\u{e5aa}'), + (0xA365, '\u{e5ab}'), + (0xA366, '\u{e5ac}'), + (0xA367, '\u{e5ad}'), + (0xA368, '\u{e5ae}'), + (0xA369, '\u{e5af}'), + (0xA36A, '\u{e5b0}'), + (0xA36B, '\u{e5b1}'), + (0xA36C, '\u{e5b2}'), + (0xA36D, '\u{e5b3}'), + (0xA36E, '\u{e5b4}'), + (0xA36F, '\u{e5b5}'), + (0xA370, '\u{e5b6}'), + (0xA371, '\u{e5b7}'), + (0xA372, '\u{e5b8}'), + (0xA373, '\u{e5b9}'), + (0xA374, '\u{e5ba}'), + (0xA375, '\u{e5bb}'), + (0xA376, '\u{e5bc}'), + (0xA377, '\u{e5bd}'), + (0xA378, '\u{e5be}'), + (0xA379, '\u{e5bf}'), + (0xA37A, '\u{e5c0}'), + (0xA37B, '\u{e5c1}'), + (0xA37C, '\u{e5c2}'), + (0xA37D, '\u{e5c3}'), + (0xA37E, '\u{e5c4}'), + (0xA380, '\u{e5c5}'), + (0xA381, '\u{e5c6}'), + (0xA382, '\u{e5c7}'), + (0xA383, '\u{e5c8}'), + (0xA384, '\u{e5c9}'), + (0xA385, '\u{e5ca}'), + (0xA386, '\u{e5cb}'), + (0xA387, '\u{e5cc}'), + (0xA388, '\u{e5cd}'), + (0xA389, '\u{e5ce}'), + (0xA38A, '\u{e5cf}'), + (0xA38B, '\u{e5d0}'), + (0xA38C, '\u{e5d1}'), + (0xA38D, '\u{e5d2}'), + (0xA38E, '\u{e5d3}'), + (0xA38F, '\u{e5d4}'), + (0xA390, '\u{e5d5}'), + (0xA391, '\u{e5d6}'), + (0xA392, '\u{e5d7}'), + (0xA393, '\u{e5d8}'), + (0xA394, '\u{e5d9}'), + (0xA395, '\u{e5da}'), + (0xA396, '\u{e5db}'), + (0xA397, '\u{e5dc}'), + (0xA398, '\u{e5dd}'), + (0xA399, '\u{e5de}'), + (0xA39A, '\u{e5df}'), + (0xA39B, '\u{e5e0}'), + (0xA39C, '\u{e5e1}'), + (0xA39D, '\u{e5e2}'), + (0xA39E, '\u{e5e3}'), + (0xA39F, '\u{e5e4}'), + (0xA3A0, '\u{e5e5}'), + (0xA440, '\u{e5e6}'), + (0xA441, '\u{e5e7}'), + (0xA442, '\u{e5e8}'), + (0xA443, '\u{e5e9}'), + (0xA444, '\u{e5ea}'), + (0xA445, '\u{e5eb}'), + (0xA446, '\u{e5ec}'), + (0xA447, '\u{e5ed}'), + (0xA448, '\u{e5ee}'), + (0xA449, '\u{e5ef}'), + (0xA44A, '\u{e5f0}'), + (0xA44B, '\u{e5f1}'), + (0xA44C, '\u{e5f2}'), + (0xA44D, '\u{e5f3}'), + (0xA44E, '\u{e5f4}'), + (0xA44F, '\u{e5f5}'), + (0xA450, '\u{e5f6}'), + (0xA451, '\u{e5f7}'), + (0xA452, '\u{e5f8}'), + (0xA453, '\u{e5f9}'), + (0xA454, '\u{e5fa}'), + (0xA455, '\u{e5fb}'), + (0xA456, '\u{e5fc}'), + (0xA457, '\u{e5fd}'), + (0xA458, '\u{e5fe}'), + (0xA459, '\u{e5ff}'), + (0xA45A, '\u{e600}'), + (0xA45B, '\u{e601}'), + (0xA45C, '\u{e602}'), + (0xA45D, '\u{e603}'), + (0xA45E, '\u{e604}'), + (0xA45F, '\u{e605}'), + (0xA460, '\u{e606}'), + (0xA461, '\u{e607}'), + (0xA462, '\u{e608}'), + (0xA463, '\u{e609}'), + (0xA464, '\u{e60a}'), + (0xA465, '\u{e60b}'), + (0xA466, '\u{e60c}'), + (0xA467, '\u{e60d}'), + (0xA468, '\u{e60e}'), + (0xA469, '\u{e60f}'), + (0xA46A, '\u{e610}'), + (0xA46B, '\u{e611}'), + (0xA46C, '\u{e612}'), + (0xA46D, '\u{e613}'), + (0xA46E, '\u{e614}'), + (0xA46F, '\u{e615}'), + (0xA470, '\u{e616}'), + (0xA471, '\u{e617}'), + (0xA472, '\u{e618}'), + (0xA473, '\u{e619}'), + (0xA474, '\u{e61a}'), + (0xA475, '\u{e61b}'), + (0xA476, '\u{e61c}'), + (0xA477, '\u{e61d}'), + (0xA478, '\u{e61e}'), + (0xA479, '\u{e61f}'), + (0xA47A, '\u{e620}'), + (0xA47B, '\u{e621}'), + (0xA47C, '\u{e622}'), + (0xA47D, '\u{e623}'), + (0xA47E, '\u{e624}'), + (0xA480, '\u{e625}'), + (0xA481, '\u{e626}'), + (0xA482, '\u{e627}'), + (0xA483, '\u{e628}'), + (0xA484, '\u{e629}'), + (0xA485, '\u{e62a}'), + (0xA486, '\u{e62b}'), + (0xA487, '\u{e62c}'), + (0xA488, '\u{e62d}'), + (0xA489, '\u{e62e}'), + (0xA48A, '\u{e62f}'), + (0xA48B, '\u{e630}'), + (0xA48C, '\u{e631}'), + (0xA48D, '\u{e632}'), + (0xA48E, '\u{e633}'), + (0xA48F, '\u{e634}'), + (0xA490, '\u{e635}'), + (0xA491, '\u{e636}'), + (0xA492, '\u{e637}'), + (0xA493, '\u{e638}'), + (0xA494, '\u{e639}'), + (0xA495, '\u{e63a}'), + (0xA496, '\u{e63b}'), + (0xA497, '\u{e63c}'), + (0xA498, '\u{e63d}'), + (0xA499, '\u{e63e}'), + (0xA49A, '\u{e63f}'), + (0xA49B, '\u{e640}'), + (0xA49C, '\u{e641}'), + (0xA49D, '\u{e642}'), + (0xA49E, '\u{e643}'), + (0xA49F, '\u{e644}'), + (0xA4A0, '\u{e645}'), + (0xA4F4, '\u{e772}'), + (0xA4F5, '\u{e773}'), + (0xA4F6, '\u{e774}'), + (0xA4F7, '\u{e775}'), + (0xA4F8, '\u{e776}'), + (0xA4F9, '\u{e777}'), + (0xA4FA, '\u{e778}'), + (0xA4FB, '\u{e779}'), + (0xA4FC, '\u{e77a}'), + (0xA4FD, '\u{e77b}'), + (0xA4FE, '\u{e77c}'), + (0xA540, '\u{e646}'), + (0xA541, '\u{e647}'), + (0xA542, '\u{e648}'), + (0xA543, '\u{e649}'), + (0xA544, '\u{e64a}'), + (0xA545, '\u{e64b}'), + (0xA546, '\u{e64c}'), + (0xA547, '\u{e64d}'), + (0xA548, '\u{e64e}'), + (0xA549, '\u{e64f}'), + (0xA54A, '\u{e650}'), + (0xA54B, '\u{e651}'), + (0xA54C, '\u{e652}'), + (0xA54D, '\u{e653}'), + (0xA54E, '\u{e654}'), + (0xA54F, '\u{e655}'), + (0xA550, '\u{e656}'), + (0xA551, '\u{e657}'), + (0xA552, '\u{e658}'), + (0xA553, '\u{e659}'), + (0xA554, '\u{e65a}'), + (0xA555, '\u{e65b}'), + (0xA556, '\u{e65c}'), + (0xA557, '\u{e65d}'), + (0xA558, '\u{e65e}'), + (0xA559, '\u{e65f}'), + (0xA55A, '\u{e660}'), + (0xA55B, '\u{e661}'), + (0xA55C, '\u{e662}'), + (0xA55D, '\u{e663}'), + (0xA55E, '\u{e664}'), + (0xA55F, '\u{e665}'), + (0xA560, '\u{e666}'), + (0xA561, '\u{e667}'), + (0xA562, '\u{e668}'), + (0xA563, '\u{e669}'), + (0xA564, '\u{e66a}'), + (0xA565, '\u{e66b}'), + (0xA566, '\u{e66c}'), + (0xA567, '\u{e66d}'), + (0xA568, '\u{e66e}'), + (0xA569, '\u{e66f}'), + (0xA56A, '\u{e670}'), + (0xA56B, '\u{e671}'), + (0xA56C, '\u{e672}'), + (0xA56D, '\u{e673}'), + (0xA56E, '\u{e674}'), + (0xA56F, '\u{e675}'), + (0xA570, '\u{e676}'), + (0xA571, '\u{e677}'), + (0xA572, '\u{e678}'), + (0xA573, '\u{e679}'), + (0xA574, '\u{e67a}'), + (0xA575, '\u{e67b}'), + (0xA576, '\u{e67c}'), + (0xA577, '\u{e67d}'), + (0xA578, '\u{e67e}'), + (0xA579, '\u{e67f}'), + (0xA57A, '\u{e680}'), + (0xA57B, '\u{e681}'), + (0xA57C, '\u{e682}'), + (0xA57D, '\u{e683}'), + (0xA57E, '\u{e684}'), + (0xA580, '\u{e685}'), + (0xA581, '\u{e686}'), + (0xA582, '\u{e687}'), + (0xA583, '\u{e688}'), + (0xA584, '\u{e689}'), + (0xA585, '\u{e68a}'), + (0xA586, '\u{e68b}'), + (0xA587, '\u{e68c}'), + (0xA588, '\u{e68d}'), + (0xA589, '\u{e68e}'), + (0xA58A, '\u{e68f}'), + (0xA58B, '\u{e690}'), + (0xA58C, '\u{e691}'), + (0xA58D, '\u{e692}'), + (0xA58E, '\u{e693}'), + (0xA58F, '\u{e694}'), + (0xA590, '\u{e695}'), + (0xA591, '\u{e696}'), + (0xA592, '\u{e697}'), + (0xA593, '\u{e698}'), + (0xA594, '\u{e699}'), + (0xA595, '\u{e69a}'), + (0xA596, '\u{e69b}'), + (0xA597, '\u{e69c}'), + (0xA598, '\u{e69d}'), + (0xA599, '\u{e69e}'), + (0xA59A, '\u{e69f}'), + (0xA59B, '\u{e6a0}'), + (0xA59C, '\u{e6a1}'), + (0xA59D, '\u{e6a2}'), + (0xA59E, '\u{e6a3}'), + (0xA59F, '\u{e6a4}'), + (0xA5A0, '\u{e6a5}'), + (0xA5F7, '\u{e77d}'), + (0xA5F8, '\u{e77e}'), + (0xA5F9, '\u{e77f}'), + (0xA5FA, '\u{e780}'), + (0xA5FB, '\u{e781}'), + (0xA5FC, '\u{e782}'), + (0xA5FD, '\u{e783}'), + (0xA5FE, '\u{e784}'), + (0xA640, '\u{e6a6}'), + (0xA641, '\u{e6a7}'), + (0xA642, '\u{e6a8}'), + (0xA643, '\u{e6a9}'), + (0xA644, '\u{e6aa}'), + (0xA645, '\u{e6ab}'), + (0xA646, '\u{e6ac}'), + (0xA647, '\u{e6ad}'), + (0xA648, '\u{e6ae}'), + (0xA649, '\u{e6af}'), + (0xA64A, '\u{e6b0}'), + (0xA64B, '\u{e6b1}'), + (0xA64C, '\u{e6b2}'), + (0xA64D, '\u{e6b3}'), + (0xA64E, '\u{e6b4}'), + (0xA64F, '\u{e6b5}'), + (0xA650, '\u{e6b6}'), + (0xA651, '\u{e6b7}'), + (0xA652, '\u{e6b8}'), + (0xA653, '\u{e6b9}'), + (0xA654, '\u{e6ba}'), + (0xA655, '\u{e6bb}'), + (0xA656, '\u{e6bc}'), + (0xA657, '\u{e6bd}'), + (0xA658, '\u{e6be}'), + (0xA659, '\u{e6bf}'), + (0xA65A, '\u{e6c0}'), + (0xA65B, '\u{e6c1}'), + (0xA65C, '\u{e6c2}'), + (0xA65D, '\u{e6c3}'), + (0xA65E, '\u{e6c4}'), + (0xA65F, '\u{e6c5}'), + (0xA660, '\u{e6c6}'), + (0xA661, '\u{e6c7}'), + (0xA662, '\u{e6c8}'), + (0xA663, '\u{e6c9}'), + (0xA664, '\u{e6ca}'), + (0xA665, '\u{e6cb}'), + (0xA666, '\u{e6cc}'), + (0xA667, '\u{e6cd}'), + (0xA668, '\u{e6ce}'), + (0xA669, '\u{e6cf}'), + (0xA66A, '\u{e6d0}'), + (0xA66B, '\u{e6d1}'), + (0xA66C, '\u{e6d2}'), + (0xA66D, '\u{e6d3}'), + (0xA66E, '\u{e6d4}'), + (0xA66F, '\u{e6d5}'), + (0xA670, '\u{e6d6}'), + (0xA671, '\u{e6d7}'), + (0xA672, '\u{e6d8}'), + (0xA673, '\u{e6d9}'), + (0xA674, '\u{e6da}'), + (0xA675, '\u{e6db}'), + (0xA676, '\u{e6dc}'), + (0xA677, '\u{e6dd}'), + (0xA678, '\u{e6de}'), + (0xA679, '\u{e6df}'), + (0xA67A, '\u{e6e0}'), + (0xA67B, '\u{e6e1}'), + (0xA67C, '\u{e6e2}'), + (0xA67D, '\u{e6e3}'), + (0xA67E, '\u{e6e4}'), + (0xA680, '\u{e6e5}'), + (0xA681, '\u{e6e6}'), + (0xA682, '\u{e6e7}'), + (0xA683, '\u{e6e8}'), + (0xA684, '\u{e6e9}'), + (0xA685, '\u{e6ea}'), + (0xA686, '\u{e6eb}'), + (0xA687, '\u{e6ec}'), + (0xA688, '\u{e6ed}'), + (0xA689, '\u{e6ee}'), + (0xA68A, '\u{e6ef}'), + (0xA68B, '\u{e6f0}'), + (0xA68C, '\u{e6f1}'), + (0xA68D, '\u{e6f2}'), + (0xA68E, '\u{e6f3}'), + (0xA68F, '\u{e6f4}'), + (0xA690, '\u{e6f5}'), + (0xA691, '\u{e6f6}'), + (0xA692, '\u{e6f7}'), + (0xA693, '\u{e6f8}'), + (0xA694, '\u{e6f9}'), + (0xA695, '\u{e6fa}'), + (0xA696, '\u{e6fb}'), + (0xA697, '\u{e6fc}'), + (0xA698, '\u{e6fd}'), + (0xA699, '\u{e6fe}'), + (0xA69A, '\u{e6ff}'), + (0xA69B, '\u{e700}'), + (0xA69C, '\u{e701}'), + (0xA69D, '\u{e702}'), + (0xA69E, '\u{e703}'), + (0xA69F, '\u{e704}'), + (0xA6A0, '\u{e705}'), + (0xA6B9, '\u{e785}'), + (0xA6BA, '\u{e786}'), + (0xA6BB, '\u{e787}'), + (0xA6BC, '\u{e788}'), + (0xA6BD, '\u{e789}'), + (0xA6BE, '\u{e78a}'), + (0xA6BF, '\u{e78b}'), + (0xA6C0, '\u{e78c}'), + (0xA6D9, '\u{fe10}'), + (0xA6DA, '\u{fe12}'), + (0xA6DB, '\u{fe11}'), + (0xA6DC, '\u{fe13}'), + (0xA6DD, '\u{fe14}'), + (0xA6DE, '\u{fe15}'), + (0xA6DF, '\u{fe16}'), + (0xA6EC, '\u{fe17}'), + (0xA6ED, '\u{fe18}'), + (0xA6F3, '\u{fe19}'), + (0xA6F6, '\u{e797}'), + (0xA6F7, '\u{e798}'), + (0xA6F8, '\u{e799}'), + (0xA6F9, '\u{e79a}'), + (0xA6FA, '\u{e79b}'), + (0xA6FB, '\u{e79c}'), + (0xA6FC, '\u{e79d}'), + (0xA6FD, '\u{e79e}'), + (0xA6FE, '\u{e79f}'), + (0xA740, '\u{e706}'), + (0xA741, '\u{e707}'), + (0xA742, '\u{e708}'), + (0xA743, '\u{e709}'), + (0xA744, '\u{e70a}'), + (0xA745, '\u{e70b}'), + (0xA746, '\u{e70c}'), + (0xA747, '\u{e70d}'), + (0xA748, '\u{e70e}'), + (0xA749, '\u{e70f}'), + (0xA74A, '\u{e710}'), + (0xA74B, '\u{e711}'), + (0xA74C, '\u{e712}'), + (0xA74D, '\u{e713}'), + (0xA74E, '\u{e714}'), + (0xA74F, '\u{e715}'), + (0xA750, '\u{e716}'), + (0xA751, '\u{e717}'), + (0xA752, '\u{e718}'), + (0xA753, '\u{e719}'), + (0xA754, '\u{e71a}'), + (0xA755, '\u{e71b}'), + (0xA756, '\u{e71c}'), + (0xA757, '\u{e71d}'), + (0xA758, '\u{e71e}'), + (0xA759, '\u{e71f}'), + (0xA75A, '\u{e720}'), + (0xA75B, '\u{e721}'), + (0xA75C, '\u{e722}'), + (0xA75D, '\u{e723}'), + (0xA75E, '\u{e724}'), + (0xA75F, '\u{e725}'), + (0xA760, '\u{e726}'), + (0xA761, '\u{e727}'), + (0xA762, '\u{e728}'), + (0xA763, '\u{e729}'), + (0xA764, '\u{e72a}'), + (0xA765, '\u{e72b}'), + (0xA766, '\u{e72c}'), + (0xA767, '\u{e72d}'), + (0xA768, '\u{e72e}'), + (0xA769, '\u{e72f}'), + (0xA76A, '\u{e730}'), + (0xA76B, '\u{e731}'), + (0xA76C, '\u{e732}'), + (0xA76D, '\u{e733}'), + (0xA76E, '\u{e734}'), + (0xA76F, '\u{e735}'), + (0xA770, '\u{e736}'), + (0xA771, '\u{e737}'), + (0xA772, '\u{e738}'), + (0xA773, '\u{e739}'), + (0xA774, '\u{e73a}'), + (0xA775, '\u{e73b}'), + (0xA776, '\u{e73c}'), + (0xA777, '\u{e73d}'), + (0xA778, '\u{e73e}'), + (0xA779, '\u{e73f}'), + (0xA77A, '\u{e740}'), + (0xA77B, '\u{e741}'), + (0xA77C, '\u{e742}'), + (0xA77D, '\u{e743}'), + (0xA77E, '\u{e744}'), + (0xA780, '\u{e745}'), + (0xA781, '\u{e746}'), + (0xA782, '\u{e747}'), + (0xA783, '\u{e748}'), + (0xA784, '\u{e749}'), + (0xA785, '\u{e74a}'), + (0xA786, '\u{e74b}'), + (0xA787, '\u{e74c}'), + (0xA788, '\u{e74d}'), + (0xA789, '\u{e74e}'), + (0xA78A, '\u{e74f}'), + (0xA78B, '\u{e750}'), + (0xA78C, '\u{e751}'), + (0xA78D, '\u{e752}'), + (0xA78E, '\u{e753}'), + (0xA78F, '\u{e754}'), + (0xA790, '\u{e755}'), + (0xA791, '\u{e756}'), + (0xA792, '\u{e757}'), + (0xA793, '\u{e758}'), + (0xA794, '\u{e759}'), + (0xA795, '\u{e75a}'), + (0xA796, '\u{e75b}'), + (0xA797, '\u{e75c}'), + (0xA798, '\u{e75d}'), + (0xA799, '\u{e75e}'), + (0xA79A, '\u{e75f}'), + (0xA79B, '\u{e760}'), + (0xA79C, '\u{e761}'), + (0xA79D, '\u{e762}'), + (0xA79E, '\u{e763}'), + (0xA79F, '\u{e764}'), + (0xA7A0, '\u{e765}'), + (0xA7C2, '\u{e7a0}'), + (0xA7C3, '\u{e7a1}'), + (0xA7C4, '\u{e7a2}'), + (0xA7C5, '\u{e7a3}'), + (0xA7C6, '\u{e7a4}'), + (0xA7C7, '\u{e7a5}'), + (0xA7C8, '\u{e7a6}'), + (0xA7C9, '\u{e7a7}'), + (0xA7CA, '\u{e7a8}'), + (0xA7CB, '\u{e7a9}'), + (0xA7CC, '\u{e7aa}'), + (0xA7CD, '\u{e7ab}'), + (0xA7CE, '\u{e7ac}'), + (0xA7CF, '\u{e7ad}'), + (0xA7D0, '\u{e7ae}'), + (0xA7F2, '\u{e7af}'), + (0xA7F3, '\u{e7b0}'), + (0xA7F4, '\u{e7b1}'), + (0xA7F5, '\u{e7b2}'), + (0xA7F6, '\u{e7b3}'), + (0xA7F7, '\u{e7b4}'), + (0xA7F8, '\u{e7b5}'), + (0xA7F9, '\u{e7b6}'), + (0xA7FA, '\u{e7b7}'), + (0xA7FB, '\u{e7b8}'), + (0xA7FC, '\u{e7b9}'), + (0xA7FD, '\u{e7ba}'), + (0xA7FE, '\u{e7bb}'), + (0xA896, '\u{e7bc}'), + (0xA897, '\u{e7bd}'), + (0xA898, '\u{e7be}'), + (0xA899, '\u{e7bf}'), + (0xA89A, '\u{e7c0}'), + (0xA89B, '\u{e7c1}'), + (0xA89C, '\u{e7c2}'), + (0xA89D, '\u{e7c3}'), + (0xA89E, '\u{e7c4}'), + (0xA89F, '\u{e7c5}'), + (0xA8A0, '\u{e7c6}'), + (0xA8BC, '\u{1e3f}'), + (0xA8C1, '\u{e7c9}'), + (0xA8C2, '\u{e7ca}'), + (0xA8C3, '\u{e7cb}'), + (0xA8C4, '\u{e7cc}'), + (0xA8EA, '\u{e7cd}'), + (0xA8EB, '\u{e7ce}'), + (0xA8EC, '\u{e7cf}'), + (0xA8ED, '\u{e7d0}'), + (0xA8EE, '\u{e7d1}'), + (0xA8EF, '\u{e7d2}'), + (0xA8F0, '\u{e7d3}'), + (0xA8F1, '\u{e7d4}'), + (0xA8F2, '\u{e7d5}'), + (0xA8F3, '\u{e7d6}'), + (0xA8F4, '\u{e7d7}'), + (0xA8F5, '\u{e7d8}'), + (0xA8F6, '\u{e7d9}'), + (0xA8F7, '\u{e7da}'), + (0xA8F8, '\u{e7db}'), + (0xA8F9, '\u{e7dc}'), + (0xA8FA, '\u{e7dd}'), + (0xA8FB, '\u{e7de}'), + (0xA8FC, '\u{e7df}'), + (0xA8FD, '\u{e7e0}'), + (0xA8FE, '\u{e7e1}'), + (0xA958, '\u{e7e2}'), + (0xA95B, '\u{e7e3}'), + (0xA95D, '\u{e7e4}'), + (0xA95E, '\u{e7e5}'), + (0xA95F, '\u{e7e6}'), + (0xA997, '\u{e7f4}'), + (0xA998, '\u{e7f5}'), + (0xA999, '\u{e7f6}'), + (0xA99A, '\u{e7f7}'), + (0xA99B, '\u{e7f8}'), + (0xA99C, '\u{e7f9}'), + (0xA99D, '\u{e7fa}'), + (0xA99E, '\u{e7fb}'), + (0xA99F, '\u{e7fc}'), + (0xA9A0, '\u{e7fd}'), + (0xA9A1, '\u{e7fe}'), + (0xA9A2, '\u{e7ff}'), + (0xA9A3, '\u{e800}'), + (0xA9F0, '\u{e801}'), + (0xA9F1, '\u{e802}'), + (0xA9F2, '\u{e803}'), + (0xA9F3, '\u{e804}'), + (0xA9F4, '\u{e805}'), + (0xA9F5, '\u{e806}'), + (0xA9F6, '\u{e807}'), + (0xA9F7, '\u{e808}'), + (0xA9F8, '\u{e809}'), + (0xA9F9, '\u{e80a}'), + (0xA9FA, '\u{e80b}'), + (0xA9FB, '\u{e80c}'), + (0xA9FC, '\u{e80d}'), + (0xA9FD, '\u{e80e}'), + (0xA9FE, '\u{e80f}'), + (0xAAA1, '\u{e000}'), + (0xAAA2, '\u{e001}'), + (0xAAA3, '\u{e002}'), + (0xAAA4, '\u{e003}'), + (0xAAA5, '\u{e004}'), + (0xAAA6, '\u{e005}'), + (0xAAA7, '\u{e006}'), + (0xAAA8, '\u{e007}'), + (0xAAA9, '\u{e008}'), + (0xAAAA, '\u{e009}'), + (0xAAAB, '\u{e00a}'), + (0xAAAC, '\u{e00b}'), + (0xAAAD, '\u{e00c}'), + (0xAAAE, '\u{e00d}'), + (0xAAAF, '\u{e00e}'), + (0xAAB0, '\u{e00f}'), + (0xAAB1, '\u{e010}'), + (0xAAB2, '\u{e011}'), + (0xAAB3, '\u{e012}'), + (0xAAB4, '\u{e013}'), + (0xAAB5, '\u{e014}'), + (0xAAB6, '\u{e015}'), + (0xAAB7, '\u{e016}'), + (0xAAB8, '\u{e017}'), + (0xAAB9, '\u{e018}'), + (0xAABA, '\u{e019}'), + (0xAABB, '\u{e01a}'), + (0xAABC, '\u{e01b}'), + (0xAABD, '\u{e01c}'), + (0xAABE, '\u{e01d}'), + (0xAABF, '\u{e01e}'), + (0xAAC0, '\u{e01f}'), + (0xAAC1, '\u{e020}'), + (0xAAC2, '\u{e021}'), + (0xAAC3, '\u{e022}'), + (0xAAC4, '\u{e023}'), + (0xAAC5, '\u{e024}'), + (0xAAC6, '\u{e025}'), + (0xAAC7, '\u{e026}'), + (0xAAC8, '\u{e027}'), + (0xAAC9, '\u{e028}'), + (0xAACA, '\u{e029}'), + (0xAACB, '\u{e02a}'), + (0xAACC, '\u{e02b}'), + (0xAACD, '\u{e02c}'), + (0xAACE, '\u{e02d}'), + (0xAACF, '\u{e02e}'), + (0xAAD0, '\u{e02f}'), + (0xAAD1, '\u{e030}'), + (0xAAD2, '\u{e031}'), + (0xAAD3, '\u{e032}'), + (0xAAD4, '\u{e033}'), + (0xAAD5, '\u{e034}'), + (0xAAD6, '\u{e035}'), + (0xAAD7, '\u{e036}'), + (0xAAD8, '\u{e037}'), + (0xAAD9, '\u{e038}'), + (0xAADA, '\u{e039}'), + (0xAADB, '\u{e03a}'), + (0xAADC, '\u{e03b}'), + (0xAADD, '\u{e03c}'), + (0xAADE, '\u{e03d}'), + (0xAADF, '\u{e03e}'), + (0xAAE0, '\u{e03f}'), + (0xAAE1, '\u{e040}'), + (0xAAE2, '\u{e041}'), + (0xAAE3, '\u{e042}'), + (0xAAE4, '\u{e043}'), + (0xAAE5, '\u{e044}'), + (0xAAE6, '\u{e045}'), + (0xAAE7, '\u{e046}'), + (0xAAE8, '\u{e047}'), + (0xAAE9, '\u{e048}'), + (0xAAEA, '\u{e049}'), + (0xAAEB, '\u{e04a}'), + (0xAAEC, '\u{e04b}'), + (0xAAED, '\u{e04c}'), + (0xAAEE, '\u{e04d}'), + (0xAAEF, '\u{e04e}'), + (0xAAF0, '\u{e04f}'), + (0xAAF1, '\u{e050}'), + (0xAAF2, '\u{e051}'), + (0xAAF3, '\u{e052}'), + (0xAAF4, '\u{e053}'), + (0xAAF5, '\u{e054}'), + (0xAAF6, '\u{e055}'), + (0xAAF7, '\u{e056}'), + (0xAAF8, '\u{e057}'), + (0xAAF9, '\u{e058}'), + (0xAAFA, '\u{e059}'), + (0xAAFB, '\u{e05a}'), + (0xAAFC, '\u{e05b}'), + (0xAAFD, '\u{e05c}'), + (0xAAFE, '\u{e05d}'), + (0xABA1, '\u{e05e}'), + (0xABA2, '\u{e05f}'), + (0xABA3, '\u{e060}'), + (0xABA4, '\u{e061}'), + (0xABA5, '\u{e062}'), + (0xABA6, '\u{e063}'), + (0xABA7, '\u{e064}'), + (0xABA8, '\u{e065}'), + (0xABA9, '\u{e066}'), + (0xABAA, '\u{e067}'), + (0xABAB, '\u{e068}'), + (0xABAC, '\u{e069}'), + (0xABAD, '\u{e06a}'), + (0xABAE, '\u{e06b}'), + (0xABAF, '\u{e06c}'), + (0xABB0, '\u{e06d}'), + (0xABB1, '\u{e06e}'), + (0xABB2, '\u{e06f}'), + (0xABB3, '\u{e070}'), + (0xABB4, '\u{e071}'), + (0xABB5, '\u{e072}'), + (0xABB6, '\u{e073}'), + (0xABB7, '\u{e074}'), + (0xABB8, '\u{e075}'), + (0xABB9, '\u{e076}'), + (0xABBA, '\u{e077}'), + (0xABBB, '\u{e078}'), + (0xABBC, '\u{e079}'), + (0xABBD, '\u{e07a}'), + (0xABBE, '\u{e07b}'), + (0xABBF, '\u{e07c}'), + (0xABC0, '\u{e07d}'), + (0xABC1, '\u{e07e}'), + (0xABC2, '\u{e07f}'), + (0xABC3, '\u{e080}'), + (0xABC4, '\u{e081}'), + (0xABC5, '\u{e082}'), + (0xABC6, '\u{e083}'), + (0xABC7, '\u{e084}'), + (0xABC8, '\u{e085}'), + (0xABC9, '\u{e086}'), + (0xABCA, '\u{e087}'), + (0xABCB, '\u{e088}'), + (0xABCC, '\u{e089}'), + (0xABCD, '\u{e08a}'), + (0xABCE, '\u{e08b}'), + (0xABCF, '\u{e08c}'), + (0xABD0, '\u{e08d}'), + (0xABD1, '\u{e08e}'), + (0xABD2, '\u{e08f}'), + (0xABD3, '\u{e090}'), + (0xABD4, '\u{e091}'), + (0xABD5, '\u{e092}'), + (0xABD6, '\u{e093}'), + (0xABD7, '\u{e094}'), + (0xABD8, '\u{e095}'), + (0xABD9, '\u{e096}'), + (0xABDA, '\u{e097}'), + (0xABDB, '\u{e098}'), + (0xABDC, '\u{e099}'), + (0xABDD, '\u{e09a}'), + (0xABDE, '\u{e09b}'), + (0xABDF, '\u{e09c}'), + (0xABE0, '\u{e09d}'), + (0xABE1, '\u{e09e}'), + (0xABE2, '\u{e09f}'), + (0xABE3, '\u{e0a0}'), + (0xABE4, '\u{e0a1}'), + (0xABE5, '\u{e0a2}'), + (0xABE6, '\u{e0a3}'), + (0xABE7, '\u{e0a4}'), + (0xABE8, '\u{e0a5}'), + (0xABE9, '\u{e0a6}'), + (0xABEA, '\u{e0a7}'), + (0xABEB, '\u{e0a8}'), + (0xABEC, '\u{e0a9}'), + (0xABED, '\u{e0aa}'), + (0xABEE, '\u{e0ab}'), + (0xABEF, '\u{e0ac}'), + (0xABF0, '\u{e0ad}'), + (0xABF1, '\u{e0ae}'), + (0xABF2, '\u{e0af}'), + (0xABF3, '\u{e0b0}'), + (0xABF4, '\u{e0b1}'), + (0xABF5, '\u{e0b2}'), + (0xABF6, '\u{e0b3}'), + (0xABF7, '\u{e0b4}'), + (0xABF8, '\u{e0b5}'), + (0xABF9, '\u{e0b6}'), + (0xABFA, '\u{e0b7}'), + (0xABFB, '\u{e0b8}'), + (0xABFC, '\u{e0b9}'), + (0xABFD, '\u{e0ba}'), + (0xABFE, '\u{e0bb}'), + (0xACA1, '\u{e0bc}'), + (0xACA2, '\u{e0bd}'), + (0xACA3, '\u{e0be}'), + (0xACA4, '\u{e0bf}'), + (0xACA5, '\u{e0c0}'), + (0xACA6, '\u{e0c1}'), + (0xACA7, '\u{e0c2}'), + (0xACA8, '\u{e0c3}'), + (0xACA9, '\u{e0c4}'), + (0xACAA, '\u{e0c5}'), + (0xACAB, '\u{e0c6}'), + (0xACAC, '\u{e0c7}'), + (0xACAD, '\u{e0c8}'), + (0xACAE, '\u{e0c9}'), + (0xACAF, '\u{e0ca}'), + (0xACB0, '\u{e0cb}'), + (0xACB1, '\u{e0cc}'), + (0xACB2, '\u{e0cd}'), + (0xACB3, '\u{e0ce}'), + (0xACB4, '\u{e0cf}'), + (0xACB5, '\u{e0d0}'), + (0xACB6, '\u{e0d1}'), + (0xACB7, '\u{e0d2}'), + (0xACB8, '\u{e0d3}'), + (0xACB9, '\u{e0d4}'), + (0xACBA, '\u{e0d5}'), + (0xACBB, '\u{e0d6}'), + (0xACBC, '\u{e0d7}'), + (0xACBD, '\u{e0d8}'), + (0xACBE, '\u{e0d9}'), + (0xACBF, '\u{e0da}'), + (0xACC0, '\u{e0db}'), + (0xACC1, '\u{e0dc}'), + (0xACC2, '\u{e0dd}'), + (0xACC3, '\u{e0de}'), + (0xACC4, '\u{e0df}'), + (0xACC5, '\u{e0e0}'), + (0xACC6, '\u{e0e1}'), + (0xACC7, '\u{e0e2}'), + (0xACC8, '\u{e0e3}'), + (0xACC9, '\u{e0e4}'), + (0xACCA, '\u{e0e5}'), + (0xACCB, '\u{e0e6}'), + (0xACCC, '\u{e0e7}'), + (0xACCD, '\u{e0e8}'), + (0xACCE, '\u{e0e9}'), + (0xACCF, '\u{e0ea}'), + (0xACD0, '\u{e0eb}'), + (0xACD1, '\u{e0ec}'), + (0xACD2, '\u{e0ed}'), + (0xACD3, '\u{e0ee}'), + (0xACD4, '\u{e0ef}'), + (0xACD5, '\u{e0f0}'), + (0xACD6, '\u{e0f1}'), + (0xACD7, '\u{e0f2}'), + (0xACD8, '\u{e0f3}'), + (0xACD9, '\u{e0f4}'), + (0xACDA, '\u{e0f5}'), + (0xACDB, '\u{e0f6}'), + (0xACDC, '\u{e0f7}'), + (0xACDD, '\u{e0f8}'), + (0xACDE, '\u{e0f9}'), + (0xACDF, '\u{e0fa}'), + (0xACE0, '\u{e0fb}'), + (0xACE1, '\u{e0fc}'), + (0xACE2, '\u{e0fd}'), + (0xACE3, '\u{e0fe}'), + (0xACE4, '\u{e0ff}'), + (0xACE5, '\u{e100}'), + (0xACE6, '\u{e101}'), + (0xACE7, '\u{e102}'), + (0xACE8, '\u{e103}'), + (0xACE9, '\u{e104}'), + (0xACEA, '\u{e105}'), + (0xACEB, '\u{e106}'), + (0xACEC, '\u{e107}'), + (0xACED, '\u{e108}'), + (0xACEE, '\u{e109}'), + (0xACEF, '\u{e10a}'), + (0xACF0, '\u{e10b}'), + (0xACF1, '\u{e10c}'), + (0xACF2, '\u{e10d}'), + (0xACF3, '\u{e10e}'), + (0xACF4, '\u{e10f}'), + (0xACF5, '\u{e110}'), + (0xACF6, '\u{e111}'), + (0xACF7, '\u{e112}'), + (0xACF8, '\u{e113}'), + (0xACF9, '\u{e114}'), + (0xACFA, '\u{e115}'), + (0xACFB, '\u{e116}'), + (0xACFC, '\u{e117}'), + (0xACFD, '\u{e118}'), + (0xACFE, '\u{e119}'), + (0xADA1, '\u{e11a}'), + (0xADA2, '\u{e11b}'), + (0xADA3, '\u{e11c}'), + (0xADA4, '\u{e11d}'), + (0xADA5, '\u{e11e}'), + (0xADA6, '\u{e11f}'), + (0xADA7, '\u{e120}'), + (0xADA8, '\u{e121}'), + (0xADA9, '\u{e122}'), + (0xADAA, '\u{e123}'), + (0xADAB, '\u{e124}'), + (0xADAC, '\u{e125}'), + (0xADAD, '\u{e126}'), + (0xADAE, '\u{e127}'), + (0xADAF, '\u{e128}'), + (0xADB0, '\u{e129}'), + (0xADB1, '\u{e12a}'), + (0xADB2, '\u{e12b}'), + (0xADB3, '\u{e12c}'), + (0xADB4, '\u{e12d}'), + (0xADB5, '\u{e12e}'), + (0xADB6, '\u{e12f}'), + (0xADB7, '\u{e130}'), + (0xADB8, '\u{e131}'), + (0xADB9, '\u{e132}'), + (0xADBA, '\u{e133}'), + (0xADBB, '\u{e134}'), + (0xADBC, '\u{e135}'), + (0xADBD, '\u{e136}'), + (0xADBE, '\u{e137}'), + (0xADBF, '\u{e138}'), + (0xADC0, '\u{e139}'), + (0xADC1, '\u{e13a}'), + (0xADC2, '\u{e13b}'), + (0xADC3, '\u{e13c}'), + (0xADC4, '\u{e13d}'), + (0xADC5, '\u{e13e}'), + (0xADC6, '\u{e13f}'), + (0xADC7, '\u{e140}'), + (0xADC8, '\u{e141}'), + (0xADC9, '\u{e142}'), + (0xADCA, '\u{e143}'), + (0xADCB, '\u{e144}'), + (0xADCC, '\u{e145}'), + (0xADCD, '\u{e146}'), + (0xADCE, '\u{e147}'), + (0xADCF, '\u{e148}'), + (0xADD0, '\u{e149}'), + (0xADD1, '\u{e14a}'), + (0xADD2, '\u{e14b}'), + (0xADD3, '\u{e14c}'), + (0xADD4, '\u{e14d}'), + (0xADD5, '\u{e14e}'), + (0xADD6, '\u{e14f}'), + (0xADD7, '\u{e150}'), + (0xADD8, '\u{e151}'), + (0xADD9, '\u{e152}'), + (0xADDA, '\u{e153}'), + (0xADDB, '\u{e154}'), + (0xADDC, '\u{e155}'), + (0xADDD, '\u{e156}'), + (0xADDE, '\u{e157}'), + (0xADDF, '\u{e158}'), + (0xADE0, '\u{e159}'), + (0xADE1, '\u{e15a}'), + (0xADE2, '\u{e15b}'), + (0xADE3, '\u{e15c}'), + (0xADE4, '\u{e15d}'), + (0xADE5, '\u{e15e}'), + (0xADE6, '\u{e15f}'), + (0xADE7, '\u{e160}'), + (0xADE8, '\u{e161}'), + (0xADE9, '\u{e162}'), + (0xADEA, '\u{e163}'), + (0xADEB, '\u{e164}'), + (0xADEC, '\u{e165}'), + (0xADED, '\u{e166}'), + (0xADEE, '\u{e167}'), + (0xADEF, '\u{e168}'), + (0xADF0, '\u{e169}'), + (0xADF1, '\u{e16a}'), + (0xADF2, '\u{e16b}'), + (0xADF3, '\u{e16c}'), + (0xADF4, '\u{e16d}'), + (0xADF5, '\u{e16e}'), + (0xADF6, '\u{e16f}'), + (0xADF7, '\u{e170}'), + (0xADF8, '\u{e171}'), + (0xADF9, '\u{e172}'), + (0xADFA, '\u{e173}'), + (0xADFB, '\u{e174}'), + (0xADFC, '\u{e175}'), + (0xADFD, '\u{e176}'), + (0xADFE, '\u{e177}'), + (0xAEA1, '\u{e178}'), + (0xAEA2, '\u{e179}'), + (0xAEA3, '\u{e17a}'), + (0xAEA4, '\u{e17b}'), + (0xAEA5, '\u{e17c}'), + (0xAEA6, '\u{e17d}'), + (0xAEA7, '\u{e17e}'), + (0xAEA8, '\u{e17f}'), + (0xAEA9, '\u{e180}'), + (0xAEAA, '\u{e181}'), + (0xAEAB, '\u{e182}'), + (0xAEAC, '\u{e183}'), + (0xAEAD, '\u{e184}'), + (0xAEAE, '\u{e185}'), + (0xAEAF, '\u{e186}'), + (0xAEB0, '\u{e187}'), + (0xAEB1, '\u{e188}'), + (0xAEB2, '\u{e189}'), + (0xAEB3, '\u{e18a}'), + (0xAEB4, '\u{e18b}'), + (0xAEB5, '\u{e18c}'), + (0xAEB6, '\u{e18d}'), + (0xAEB7, '\u{e18e}'), + (0xAEB8, '\u{e18f}'), + (0xAEB9, '\u{e190}'), + (0xAEBA, '\u{e191}'), + (0xAEBB, '\u{e192}'), + (0xAEBC, '\u{e193}'), + (0xAEBD, '\u{e194}'), + (0xAEBE, '\u{e195}'), + (0xAEBF, '\u{e196}'), + (0xAEC0, '\u{e197}'), + (0xAEC1, '\u{e198}'), + (0xAEC2, '\u{e199}'), + (0xAEC3, '\u{e19a}'), + (0xAEC4, '\u{e19b}'), + (0xAEC5, '\u{e19c}'), + (0xAEC6, '\u{e19d}'), + (0xAEC7, '\u{e19e}'), + (0xAEC8, '\u{e19f}'), + (0xAEC9, '\u{e1a0}'), + (0xAECA, '\u{e1a1}'), + (0xAECB, '\u{e1a2}'), + (0xAECC, '\u{e1a3}'), + (0xAECD, '\u{e1a4}'), + (0xAECE, '\u{e1a5}'), + (0xAECF, '\u{e1a6}'), + (0xAED0, '\u{e1a7}'), + (0xAED1, '\u{e1a8}'), + (0xAED2, '\u{e1a9}'), + (0xAED3, '\u{e1aa}'), + (0xAED4, '\u{e1ab}'), + (0xAED5, '\u{e1ac}'), + (0xAED6, '\u{e1ad}'), + (0xAED7, '\u{e1ae}'), + (0xAED8, '\u{e1af}'), + (0xAED9, '\u{e1b0}'), + (0xAEDA, '\u{e1b1}'), + (0xAEDB, '\u{e1b2}'), + (0xAEDC, '\u{e1b3}'), + (0xAEDD, '\u{e1b4}'), + (0xAEDE, '\u{e1b5}'), + (0xAEDF, '\u{e1b6}'), + (0xAEE0, '\u{e1b7}'), + (0xAEE1, '\u{e1b8}'), + (0xAEE2, '\u{e1b9}'), + (0xAEE3, '\u{e1ba}'), + (0xAEE4, '\u{e1bb}'), + (0xAEE5, '\u{e1bc}'), + (0xAEE6, '\u{e1bd}'), + (0xAEE7, '\u{e1be}'), + (0xAEE8, '\u{e1bf}'), + (0xAEE9, '\u{e1c0}'), + (0xAEEA, '\u{e1c1}'), + (0xAEEB, '\u{e1c2}'), + (0xAEEC, '\u{e1c3}'), + (0xAEED, '\u{e1c4}'), + (0xAEEE, '\u{e1c5}'), + (0xAEEF, '\u{e1c6}'), + (0xAEF0, '\u{e1c7}'), + (0xAEF1, '\u{e1c8}'), + (0xAEF2, '\u{e1c9}'), + (0xAEF3, '\u{e1ca}'), + (0xAEF4, '\u{e1cb}'), + (0xAEF5, '\u{e1cc}'), + (0xAEF6, '\u{e1cd}'), + (0xAEF7, '\u{e1ce}'), + (0xAEF8, '\u{e1cf}'), + (0xAEF9, '\u{e1d0}'), + (0xAEFA, '\u{e1d1}'), + (0xAEFB, '\u{e1d2}'), + (0xAEFC, '\u{e1d3}'), + (0xAEFD, '\u{e1d4}'), + (0xAEFE, '\u{e1d5}'), + (0xAFA1, '\u{e1d6}'), + (0xAFA2, '\u{e1d7}'), + (0xAFA3, '\u{e1d8}'), + (0xAFA4, '\u{e1d9}'), + (0xAFA5, '\u{e1da}'), + (0xAFA6, '\u{e1db}'), + (0xAFA7, '\u{e1dc}'), + (0xAFA8, '\u{e1dd}'), + (0xAFA9, '\u{e1de}'), + (0xAFAA, '\u{e1df}'), + (0xAFAB, '\u{e1e0}'), + (0xAFAC, '\u{e1e1}'), + (0xAFAD, '\u{e1e2}'), + (0xAFAE, '\u{e1e3}'), + (0xAFAF, '\u{e1e4}'), + (0xAFB0, '\u{e1e5}'), + (0xAFB1, '\u{e1e6}'), + (0xAFB2, '\u{e1e7}'), + (0xAFB3, '\u{e1e8}'), + (0xAFB4, '\u{e1e9}'), + (0xAFB5, '\u{e1ea}'), + (0xAFB6, '\u{e1eb}'), + (0xAFB7, '\u{e1ec}'), + (0xAFB8, '\u{e1ed}'), + (0xAFB9, '\u{e1ee}'), + (0xAFBA, '\u{e1ef}'), + (0xAFBB, '\u{e1f0}'), + (0xAFBC, '\u{e1f1}'), + (0xAFBD, '\u{e1f2}'), + (0xAFBE, '\u{e1f3}'), + (0xAFBF, '\u{e1f4}'), + (0xAFC0, '\u{e1f5}'), + (0xAFC1, '\u{e1f6}'), + (0xAFC2, '\u{e1f7}'), + (0xAFC3, '\u{e1f8}'), + (0xAFC4, '\u{e1f9}'), + (0xAFC5, '\u{e1fa}'), + (0xAFC6, '\u{e1fb}'), + (0xAFC7, '\u{e1fc}'), + (0xAFC8, '\u{e1fd}'), + (0xAFC9, '\u{e1fe}'), + (0xAFCA, '\u{e1ff}'), + (0xAFCB, '\u{e200}'), + (0xAFCC, '\u{e201}'), + (0xAFCD, '\u{e202}'), + (0xAFCE, '\u{e203}'), + (0xAFCF, '\u{e204}'), + (0xAFD0, '\u{e205}'), + (0xAFD1, '\u{e206}'), + (0xAFD2, '\u{e207}'), + (0xAFD3, '\u{e208}'), + (0xAFD4, '\u{e209}'), + (0xAFD5, '\u{e20a}'), + (0xAFD6, '\u{e20b}'), + (0xAFD7, '\u{e20c}'), + (0xAFD8, '\u{e20d}'), + (0xAFD9, '\u{e20e}'), + (0xAFDA, '\u{e20f}'), + (0xAFDB, '\u{e210}'), + (0xAFDC, '\u{e211}'), + (0xAFDD, '\u{e212}'), + (0xAFDE, '\u{e213}'), + (0xAFDF, '\u{e214}'), + (0xAFE0, '\u{e215}'), + (0xAFE1, '\u{e216}'), + (0xAFE2, '\u{e217}'), + (0xAFE3, '\u{e218}'), + (0xAFE4, '\u{e219}'), + (0xAFE5, '\u{e21a}'), + (0xAFE6, '\u{e21b}'), + (0xAFE7, '\u{e21c}'), + (0xAFE8, '\u{e21d}'), + (0xAFE9, '\u{e21e}'), + (0xAFEA, '\u{e21f}'), + (0xAFEB, '\u{e220}'), + (0xAFEC, '\u{e221}'), + (0xAFED, '\u{e222}'), + (0xAFEE, '\u{e223}'), + (0xAFEF, '\u{e224}'), + (0xAFF0, '\u{e225}'), + (0xAFF1, '\u{e226}'), + (0xAFF2, '\u{e227}'), + (0xAFF3, '\u{e228}'), + (0xAFF4, '\u{e229}'), + (0xAFF5, '\u{e22a}'), + (0xAFF6, '\u{e22b}'), + (0xAFF7, '\u{e22c}'), + (0xAFF8, '\u{e22d}'), + (0xAFF9, '\u{e22e}'), + (0xAFFA, '\u{e22f}'), + (0xAFFB, '\u{e230}'), + (0xAFFC, '\u{e231}'), + (0xAFFD, '\u{e232}'), + (0xAFFE, '\u{e233}'), + (0xD7FA, '\u{e810}'), + (0xD7FB, '\u{e811}'), + (0xD7FC, '\u{e812}'), + (0xD7FD, '\u{e813}'), + (0xD7FE, '\u{e814}'), + (0xF8A1, '\u{e234}'), + (0xF8A2, '\u{e235}'), + (0xF8A3, '\u{e236}'), + (0xF8A4, '\u{e237}'), + (0xF8A5, '\u{e238}'), + (0xF8A6, '\u{e239}'), + (0xF8A7, '\u{e23a}'), + (0xF8A8, '\u{e23b}'), + (0xF8A9, '\u{e23c}'), + (0xF8AA, '\u{e23d}'), + (0xF8AB, '\u{e23e}'), + (0xF8AC, '\u{e23f}'), + (0xF8AD, '\u{e240}'), + (0xF8AE, '\u{e241}'), + (0xF8AF, '\u{e242}'), + (0xF8B0, '\u{e243}'), + (0xF8B1, '\u{e244}'), + (0xF8B2, '\u{e245}'), + (0xF8B3, '\u{e246}'), + (0xF8B4, '\u{e247}'), + (0xF8B5, '\u{e248}'), + (0xF8B6, '\u{e249}'), + (0xF8B7, '\u{e24a}'), + (0xF8B8, '\u{e24b}'), + (0xF8B9, '\u{e24c}'), + (0xF8BA, '\u{e24d}'), + (0xF8BB, '\u{e24e}'), + (0xF8BC, '\u{e24f}'), + (0xF8BD, '\u{e250}'), + (0xF8BE, '\u{e251}'), + (0xF8BF, '\u{e252}'), + (0xF8C0, '\u{e253}'), + (0xF8C1, '\u{e254}'), + (0xF8C2, '\u{e255}'), + (0xF8C3, '\u{e256}'), + (0xF8C4, '\u{e257}'), + (0xF8C5, '\u{e258}'), + (0xF8C6, '\u{e259}'), + (0xF8C7, '\u{e25a}'), + (0xF8C8, '\u{e25b}'), + (0xF8C9, '\u{e25c}'), + (0xF8CA, '\u{e25d}'), + (0xF8CB, '\u{e25e}'), + (0xF8CC, '\u{e25f}'), + (0xF8CD, '\u{e260}'), + (0xF8CE, '\u{e261}'), + (0xF8CF, '\u{e262}'), + (0xF8D0, '\u{e263}'), + (0xF8D1, '\u{e264}'), + (0xF8D2, '\u{e265}'), + (0xF8D3, '\u{e266}'), + (0xF8D4, '\u{e267}'), + (0xF8D5, '\u{e268}'), + (0xF8D6, '\u{e269}'), + (0xF8D7, '\u{e26a}'), + (0xF8D8, '\u{e26b}'), + (0xF8D9, '\u{e26c}'), + (0xF8DA, '\u{e26d}'), + (0xF8DB, '\u{e26e}'), + (0xF8DC, '\u{e26f}'), + (0xF8DD, '\u{e270}'), + (0xF8DE, '\u{e271}'), + (0xF8DF, '\u{e272}'), + (0xF8E0, '\u{e273}'), + (0xF8E1, '\u{e274}'), + (0xF8E2, '\u{e275}'), + (0xF8E3, '\u{e276}'), + (0xF8E4, '\u{e277}'), + (0xF8E5, '\u{e278}'), + (0xF8E6, '\u{e279}'), + (0xF8E7, '\u{e27a}'), + (0xF8E8, '\u{e27b}'), + (0xF8E9, '\u{e27c}'), + (0xF8EA, '\u{e27d}'), + (0xF8EB, '\u{e27e}'), + (0xF8EC, '\u{e27f}'), + (0xF8ED, '\u{e280}'), + (0xF8EE, '\u{e281}'), + (0xF8EF, '\u{e282}'), + (0xF8F0, '\u{e283}'), + (0xF8F1, '\u{e284}'), + (0xF8F2, '\u{e285}'), + (0xF8F3, '\u{e286}'), + (0xF8F4, '\u{e287}'), + (0xF8F5, '\u{e288}'), + (0xF8F6, '\u{e289}'), + (0xF8F7, '\u{e28a}'), + (0xF8F8, '\u{e28b}'), + (0xF8F9, '\u{e28c}'), + (0xF8FA, '\u{e28d}'), + (0xF8FB, '\u{e28e}'), + (0xF8FC, '\u{e28f}'), + (0xF8FD, '\u{e290}'), + (0xF8FE, '\u{e291}'), + (0xF9A1, '\u{e292}'), + (0xF9A2, '\u{e293}'), + (0xF9A3, '\u{e294}'), + (0xF9A4, '\u{e295}'), + (0xF9A5, '\u{e296}'), + (0xF9A6, '\u{e297}'), + (0xF9A7, '\u{e298}'), + (0xF9A8, '\u{e299}'), + (0xF9A9, '\u{e29a}'), + (0xF9AA, '\u{e29b}'), + (0xF9AB, '\u{e29c}'), + (0xF9AC, '\u{e29d}'), + (0xF9AD, '\u{e29e}'), + (0xF9AE, '\u{e29f}'), + (0xF9AF, '\u{e2a0}'), + (0xF9B0, '\u{e2a1}'), + (0xF9B1, '\u{e2a2}'), + (0xF9B2, '\u{e2a3}'), + (0xF9B3, '\u{e2a4}'), + (0xF9B4, '\u{e2a5}'), + (0xF9B5, '\u{e2a6}'), + (0xF9B6, '\u{e2a7}'), + (0xF9B7, '\u{e2a8}'), + (0xF9B8, '\u{e2a9}'), + (0xF9B9, '\u{e2aa}'), + (0xF9BA, '\u{e2ab}'), + (0xF9BB, '\u{e2ac}'), + (0xF9BC, '\u{e2ad}'), + (0xF9BD, '\u{e2ae}'), + (0xF9BE, '\u{e2af}'), + (0xF9BF, '\u{e2b0}'), + (0xF9C0, '\u{e2b1}'), + (0xF9C1, '\u{e2b2}'), + (0xF9C2, '\u{e2b3}'), + (0xF9C3, '\u{e2b4}'), + (0xF9C4, '\u{e2b5}'), + (0xF9C5, '\u{e2b6}'), + (0xF9C6, '\u{e2b7}'), + (0xF9C7, '\u{e2b8}'), + (0xF9C8, '\u{e2b9}'), + (0xF9C9, '\u{e2ba}'), + (0xF9CA, '\u{e2bb}'), + (0xF9CB, '\u{e2bc}'), + (0xF9CC, '\u{e2bd}'), + (0xF9CD, '\u{e2be}'), + (0xF9CE, '\u{e2bf}'), + (0xF9CF, '\u{e2c0}'), + (0xF9D0, '\u{e2c1}'), + (0xF9D1, '\u{e2c2}'), + (0xF9D2, '\u{e2c3}'), + (0xF9D3, '\u{e2c4}'), + (0xF9D4, '\u{e2c5}'), + (0xF9D5, '\u{e2c6}'), + (0xF9D6, '\u{e2c7}'), + (0xF9D7, '\u{e2c8}'), + (0xF9D8, '\u{e2c9}'), + (0xF9D9, '\u{e2ca}'), + (0xF9DA, '\u{e2cb}'), + (0xF9DB, '\u{e2cc}'), + (0xF9DC, '\u{e2cd}'), + (0xF9DD, '\u{e2ce}'), + (0xF9DE, '\u{e2cf}'), + (0xF9DF, '\u{e2d0}'), + (0xF9E0, '\u{e2d1}'), + (0xF9E1, '\u{e2d2}'), + (0xF9E2, '\u{e2d3}'), + (0xF9E3, '\u{e2d4}'), + (0xF9E4, '\u{e2d5}'), + (0xF9E5, '\u{e2d6}'), + (0xF9E6, '\u{e2d7}'), + (0xF9E7, '\u{e2d8}'), + (0xF9E8, '\u{e2d9}'), + (0xF9E9, '\u{e2da}'), + (0xF9EA, '\u{e2db}'), + (0xF9EB, '\u{e2dc}'), + (0xF9EC, '\u{e2dd}'), + (0xF9ED, '\u{e2de}'), + (0xF9EE, '\u{e2df}'), + (0xF9EF, '\u{e2e0}'), + (0xF9F0, '\u{e2e1}'), + (0xF9F1, '\u{e2e2}'), + (0xF9F2, '\u{e2e3}'), + (0xF9F3, '\u{e2e4}'), + (0xF9F4, '\u{e2e5}'), + (0xF9F5, '\u{e2e6}'), + (0xF9F6, '\u{e2e7}'), + (0xF9F7, '\u{e2e8}'), + (0xF9F8, '\u{e2e9}'), + (0xF9F9, '\u{e2ea}'), + (0xF9FA, '\u{e2eb}'), + (0xF9FB, '\u{e2ec}'), + (0xF9FC, '\u{e2ed}'), + (0xF9FD, '\u{e2ee}'), + (0xF9FE, '\u{e2ef}'), + (0xFAA1, '\u{e2f0}'), + (0xFAA2, '\u{e2f1}'), + (0xFAA3, '\u{e2f2}'), + (0xFAA4, '\u{e2f3}'), + (0xFAA5, '\u{e2f4}'), + (0xFAA6, '\u{e2f5}'), + (0xFAA7, '\u{e2f6}'), + (0xFAA8, '\u{e2f7}'), + (0xFAA9, '\u{e2f8}'), + (0xFAAA, '\u{e2f9}'), + (0xFAAB, '\u{e2fa}'), + (0xFAAC, '\u{e2fb}'), + (0xFAAD, '\u{e2fc}'), + (0xFAAE, '\u{e2fd}'), + (0xFAAF, '\u{e2fe}'), + (0xFAB0, '\u{e2ff}'), + (0xFAB1, '\u{e300}'), + (0xFAB2, '\u{e301}'), + (0xFAB3, '\u{e302}'), + (0xFAB4, '\u{e303}'), + (0xFAB5, '\u{e304}'), + (0xFAB6, '\u{e305}'), + (0xFAB7, '\u{e306}'), + (0xFAB8, '\u{e307}'), + (0xFAB9, '\u{e308}'), + (0xFABA, '\u{e309}'), + (0xFABB, '\u{e30a}'), + (0xFABC, '\u{e30b}'), + (0xFABD, '\u{e30c}'), + (0xFABE, '\u{e30d}'), + (0xFABF, '\u{e30e}'), + (0xFAC0, '\u{e30f}'), + (0xFAC1, '\u{e310}'), + (0xFAC2, '\u{e311}'), + (0xFAC3, '\u{e312}'), + (0xFAC4, '\u{e313}'), + (0xFAC5, '\u{e314}'), + (0xFAC6, '\u{e315}'), + (0xFAC7, '\u{e316}'), + (0xFAC8, '\u{e317}'), + (0xFAC9, '\u{e318}'), + (0xFACA, '\u{e319}'), + (0xFACB, '\u{e31a}'), + (0xFACC, '\u{e31b}'), + (0xFACD, '\u{e31c}'), + (0xFACE, '\u{e31d}'), + (0xFACF, '\u{e31e}'), + (0xFAD0, '\u{e31f}'), + (0xFAD1, '\u{e320}'), + (0xFAD2, '\u{e321}'), + (0xFAD3, '\u{e322}'), + (0xFAD4, '\u{e323}'), + (0xFAD5, '\u{e324}'), + (0xFAD6, '\u{e325}'), + (0xFAD7, '\u{e326}'), + (0xFAD8, '\u{e327}'), + (0xFAD9, '\u{e328}'), + (0xFADA, '\u{e329}'), + (0xFADB, '\u{e32a}'), + (0xFADC, '\u{e32b}'), + (0xFADD, '\u{e32c}'), + (0xFADE, '\u{e32d}'), + (0xFADF, '\u{e32e}'), + (0xFAE0, '\u{e32f}'), + (0xFAE1, '\u{e330}'), + (0xFAE2, '\u{e331}'), + (0xFAE3, '\u{e332}'), + (0xFAE4, '\u{e333}'), + (0xFAE5, '\u{e334}'), + (0xFAE6, '\u{e335}'), + (0xFAE7, '\u{e336}'), + (0xFAE8, '\u{e337}'), + (0xFAE9, '\u{e338}'), + (0xFAEA, '\u{e339}'), + (0xFAEB, '\u{e33a}'), + (0xFAEC, '\u{e33b}'), + (0xFAED, '\u{e33c}'), + (0xFAEE, '\u{e33d}'), + (0xFAEF, '\u{e33e}'), + (0xFAF0, '\u{e33f}'), + (0xFAF1, '\u{e340}'), + (0xFAF2, '\u{e341}'), + (0xFAF3, '\u{e342}'), + (0xFAF4, '\u{e343}'), + (0xFAF5, '\u{e344}'), + (0xFAF6, '\u{e345}'), + (0xFAF7, '\u{e346}'), + (0xFAF8, '\u{e347}'), + (0xFAF9, '\u{e348}'), + (0xFAFA, '\u{e349}'), + (0xFAFB, '\u{e34a}'), + (0xFAFC, '\u{e34b}'), + (0xFAFD, '\u{e34c}'), + (0xFAFE, '\u{e34d}'), + (0xFBA1, '\u{e34e}'), + (0xFBA2, '\u{e34f}'), + (0xFBA3, '\u{e350}'), + (0xFBA4, '\u{e351}'), + (0xFBA5, '\u{e352}'), + (0xFBA6, '\u{e353}'), + (0xFBA7, '\u{e354}'), + (0xFBA8, '\u{e355}'), + (0xFBA9, '\u{e356}'), + (0xFBAA, '\u{e357}'), + (0xFBAB, '\u{e358}'), + (0xFBAC, '\u{e359}'), + (0xFBAD, '\u{e35a}'), + (0xFBAE, '\u{e35b}'), + (0xFBAF, '\u{e35c}'), + (0xFBB0, '\u{e35d}'), + (0xFBB1, '\u{e35e}'), + (0xFBB2, '\u{e35f}'), + (0xFBB3, '\u{e360}'), + (0xFBB4, '\u{e361}'), + (0xFBB5, '\u{e362}'), + (0xFBB6, '\u{e363}'), + (0xFBB7, '\u{e364}'), + (0xFBB8, '\u{e365}'), + (0xFBB9, '\u{e366}'), + (0xFBBA, '\u{e367}'), + (0xFBBB, '\u{e368}'), + (0xFBBC, '\u{e369}'), + (0xFBBD, '\u{e36a}'), + (0xFBBE, '\u{e36b}'), + (0xFBBF, '\u{e36c}'), + (0xFBC0, '\u{e36d}'), + (0xFBC1, '\u{e36e}'), + (0xFBC2, '\u{e36f}'), + (0xFBC3, '\u{e370}'), + (0xFBC4, '\u{e371}'), + (0xFBC5, '\u{e372}'), + (0xFBC6, '\u{e373}'), + (0xFBC7, '\u{e374}'), + (0xFBC8, '\u{e375}'), + (0xFBC9, '\u{e376}'), + (0xFBCA, '\u{e377}'), + (0xFBCB, '\u{e378}'), + (0xFBCC, '\u{e379}'), + (0xFBCD, '\u{e37a}'), + (0xFBCE, '\u{e37b}'), + (0xFBCF, '\u{e37c}'), + (0xFBD0, '\u{e37d}'), + (0xFBD1, '\u{e37e}'), + (0xFBD2, '\u{e37f}'), + (0xFBD3, '\u{e380}'), + (0xFBD4, '\u{e381}'), + (0xFBD5, '\u{e382}'), + (0xFBD6, '\u{e383}'), + (0xFBD7, '\u{e384}'), + (0xFBD8, '\u{e385}'), + (0xFBD9, '\u{e386}'), + (0xFBDA, '\u{e387}'), + (0xFBDB, '\u{e388}'), + (0xFBDC, '\u{e389}'), + (0xFBDD, '\u{e38a}'), + (0xFBDE, '\u{e38b}'), + (0xFBDF, '\u{e38c}'), + (0xFBE0, '\u{e38d}'), + (0xFBE1, '\u{e38e}'), + (0xFBE2, '\u{e38f}'), + (0xFBE3, '\u{e390}'), + (0xFBE4, '\u{e391}'), + (0xFBE5, '\u{e392}'), + (0xFBE6, '\u{e393}'), + (0xFBE7, '\u{e394}'), + (0xFBE8, '\u{e395}'), + (0xFBE9, '\u{e396}'), + (0xFBEA, '\u{e397}'), + (0xFBEB, '\u{e398}'), + (0xFBEC, '\u{e399}'), + (0xFBED, '\u{e39a}'), + (0xFBEE, '\u{e39b}'), + (0xFBEF, '\u{e39c}'), + (0xFBF0, '\u{e39d}'), + (0xFBF1, '\u{e39e}'), + (0xFBF2, '\u{e39f}'), + (0xFBF3, '\u{e3a0}'), + (0xFBF4, '\u{e3a1}'), + (0xFBF5, '\u{e3a2}'), + (0xFBF6, '\u{e3a3}'), + (0xFBF7, '\u{e3a4}'), + (0xFBF8, '\u{e3a5}'), + (0xFBF9, '\u{e3a6}'), + (0xFBFA, '\u{e3a7}'), + (0xFBFB, '\u{e3a8}'), + (0xFBFC, '\u{e3a9}'), + (0xFBFD, '\u{e3aa}'), + (0xFBFE, '\u{e3ab}'), + (0xFCA1, '\u{e3ac}'), + (0xFCA2, '\u{e3ad}'), + (0xFCA3, '\u{e3ae}'), + (0xFCA4, '\u{e3af}'), + (0xFCA5, '\u{e3b0}'), + (0xFCA6, '\u{e3b1}'), + (0xFCA7, '\u{e3b2}'), + (0xFCA8, '\u{e3b3}'), + (0xFCA9, '\u{e3b4}'), + (0xFCAA, '\u{e3b5}'), + (0xFCAB, '\u{e3b6}'), + (0xFCAC, '\u{e3b7}'), + (0xFCAD, '\u{e3b8}'), + (0xFCAE, '\u{e3b9}'), + (0xFCAF, '\u{e3ba}'), + (0xFCB0, '\u{e3bb}'), + (0xFCB1, '\u{e3bc}'), + (0xFCB2, '\u{e3bd}'), + (0xFCB3, '\u{e3be}'), + (0xFCB4, '\u{e3bf}'), + (0xFCB5, '\u{e3c0}'), + (0xFCB6, '\u{e3c1}'), + (0xFCB7, '\u{e3c2}'), + (0xFCB8, '\u{e3c3}'), + (0xFCB9, '\u{e3c4}'), + (0xFCBA, '\u{e3c5}'), + (0xFCBB, '\u{e3c6}'), + (0xFCBC, '\u{e3c7}'), + (0xFCBD, '\u{e3c8}'), + (0xFCBE, '\u{e3c9}'), + (0xFCBF, '\u{e3ca}'), + (0xFCC0, '\u{e3cb}'), + (0xFCC1, '\u{e3cc}'), + (0xFCC2, '\u{e3cd}'), + (0xFCC3, '\u{e3ce}'), + (0xFCC4, '\u{e3cf}'), + (0xFCC5, '\u{e3d0}'), + (0xFCC6, '\u{e3d1}'), + (0xFCC7, '\u{e3d2}'), + (0xFCC8, '\u{e3d3}'), + (0xFCC9, '\u{e3d4}'), + (0xFCCA, '\u{e3d5}'), + (0xFCCB, '\u{e3d6}'), + (0xFCCC, '\u{e3d7}'), + (0xFCCD, '\u{e3d8}'), + (0xFCCE, '\u{e3d9}'), + (0xFCCF, '\u{e3da}'), + (0xFCD0, '\u{e3db}'), + (0xFCD1, '\u{e3dc}'), + (0xFCD2, '\u{e3dd}'), + (0xFCD3, '\u{e3de}'), + (0xFCD4, '\u{e3df}'), + (0xFCD5, '\u{e3e0}'), + (0xFCD6, '\u{e3e1}'), + (0xFCD7, '\u{e3e2}'), + (0xFCD8, '\u{e3e3}'), + (0xFCD9, '\u{e3e4}'), + (0xFCDA, '\u{e3e5}'), + (0xFCDB, '\u{e3e6}'), + (0xFCDC, '\u{e3e7}'), + (0xFCDD, '\u{e3e8}'), + (0xFCDE, '\u{e3e9}'), + (0xFCDF, '\u{e3ea}'), + (0xFCE0, '\u{e3eb}'), + (0xFCE1, '\u{e3ec}'), + (0xFCE2, '\u{e3ed}'), + (0xFCE3, '\u{e3ee}'), + (0xFCE4, '\u{e3ef}'), + (0xFCE5, '\u{e3f0}'), + (0xFCE6, '\u{e3f1}'), + (0xFCE7, '\u{e3f2}'), + (0xFCE8, '\u{e3f3}'), + (0xFCE9, '\u{e3f4}'), + (0xFCEA, '\u{e3f5}'), + (0xFCEB, '\u{e3f6}'), + (0xFCEC, '\u{e3f7}'), + (0xFCED, '\u{e3f8}'), + (0xFCEE, '\u{e3f9}'), + (0xFCEF, '\u{e3fa}'), + (0xFCF0, '\u{e3fb}'), + (0xFCF1, '\u{e3fc}'), + (0xFCF2, '\u{e3fd}'), + (0xFCF3, '\u{e3fe}'), + (0xFCF4, '\u{e3ff}'), + (0xFCF5, '\u{e400}'), + (0xFCF6, '\u{e401}'), + (0xFCF7, '\u{e402}'), + (0xFCF8, '\u{e403}'), + (0xFCF9, '\u{e404}'), + (0xFCFA, '\u{e405}'), + (0xFCFB, '\u{e406}'), + (0xFCFC, '\u{e407}'), + (0xFCFD, '\u{e408}'), + (0xFCFE, '\u{e409}'), + (0xFD9C, '\u{f92c}'), + (0xFD9D, '\u{f979}'), + (0xFD9E, '\u{f995}'), + (0xFD9F, '\u{f9e7}'), + (0xFDA0, '\u{f9f1}'), + (0xFDA1, '\u{e40a}'), + (0xFDA2, '\u{e40b}'), + (0xFDA3, '\u{e40c}'), + (0xFDA4, '\u{e40d}'), + (0xFDA5, '\u{e40e}'), + (0xFDA6, '\u{e40f}'), + (0xFDA7, '\u{e410}'), + (0xFDA8, '\u{e411}'), + (0xFDA9, '\u{e412}'), + (0xFDAA, '\u{e413}'), + (0xFDAB, '\u{e414}'), + (0xFDAC, '\u{e415}'), + (0xFDAD, '\u{e416}'), + (0xFDAE, '\u{e417}'), + (0xFDAF, '\u{e418}'), + (0xFDB0, '\u{e419}'), + (0xFDB1, '\u{e41a}'), + (0xFDB2, '\u{e41b}'), + (0xFDB3, '\u{e41c}'), + (0xFDB4, '\u{e41d}'), + (0xFDB5, '\u{e41e}'), + (0xFDB6, '\u{e41f}'), + (0xFDB7, '\u{e420}'), + (0xFDB8, '\u{e421}'), + (0xFDB9, '\u{e422}'), + (0xFDBA, '\u{e423}'), + (0xFDBB, '\u{e424}'), + (0xFDBC, '\u{e425}'), + (0xFDBD, '\u{e426}'), + (0xFDBE, '\u{e427}'), + (0xFDBF, '\u{e428}'), + (0xFDC0, '\u{e429}'), + (0xFDC1, '\u{e42a}'), + (0xFDC2, '\u{e42b}'), + (0xFDC3, '\u{e42c}'), + (0xFDC4, '\u{e42d}'), + (0xFDC5, '\u{e42e}'), + (0xFDC6, '\u{e42f}'), + (0xFDC7, '\u{e430}'), + (0xFDC8, '\u{e431}'), + (0xFDC9, '\u{e432}'), + (0xFDCA, '\u{e433}'), + (0xFDCB, '\u{e434}'), + (0xFDCC, '\u{e435}'), + (0xFDCD, '\u{e436}'), + (0xFDCE, '\u{e437}'), + (0xFDCF, '\u{e438}'), + (0xFDD0, '\u{e439}'), + (0xFDD1, '\u{e43a}'), + (0xFDD2, '\u{e43b}'), + (0xFDD3, '\u{e43c}'), + (0xFDD4, '\u{e43d}'), + (0xFDD5, '\u{e43e}'), + (0xFDD6, '\u{e43f}'), + (0xFDD7, '\u{e440}'), + (0xFDD8, '\u{e441}'), + (0xFDD9, '\u{e442}'), + (0xFDDA, '\u{e443}'), + (0xFDDB, '\u{e444}'), + (0xFDDC, '\u{e445}'), + (0xFDDD, '\u{e446}'), + (0xFDDE, '\u{e447}'), + (0xFDDF, '\u{e448}'), + (0xFDE0, '\u{e449}'), + (0xFDE1, '\u{e44a}'), + (0xFDE2, '\u{e44b}'), + (0xFDE3, '\u{e44c}'), + (0xFDE4, '\u{e44d}'), + (0xFDE5, '\u{e44e}'), + (0xFDE6, '\u{e44f}'), + (0xFDE7, '\u{e450}'), + (0xFDE8, '\u{e451}'), + (0xFDE9, '\u{e452}'), + (0xFDEA, '\u{e453}'), + (0xFDEB, '\u{e454}'), + (0xFDEC, '\u{e455}'), + (0xFDED, '\u{e456}'), + (0xFDEE, '\u{e457}'), + (0xFDEF, '\u{e458}'), + (0xFDF0, '\u{e459}'), + (0xFDF1, '\u{e45a}'), + (0xFDF2, '\u{e45b}'), + (0xFDF3, '\u{e45c}'), + (0xFDF4, '\u{e45d}'), + (0xFDF5, '\u{e45e}'), + (0xFDF6, '\u{e45f}'), + (0xFDF7, '\u{e460}'), + (0xFDF8, '\u{e461}'), + (0xFDF9, '\u{e462}'), + (0xFDFA, '\u{e463}'), + (0xFDFB, '\u{e464}'), + (0xFDFC, '\u{e465}'), + (0xFDFD, '\u{e466}'), + (0xFDFE, '\u{e467}'), + (0xFE40, '\u{fa0c}'), + (0xFE41, '\u{fa0d}'), + (0xFE47, '\u{fa18}'), + (0xFE49, '\u{fa20}'), + (0xFE51, '\u{e816}'), + (0xFE52, '\u{e817}'), + (0xFE53, '\u{e818}'), + (0xFE59, '\u{9fb4}'), + (0xFE61, '\u{9fb5}'), + (0xFE66, '\u{9fb6}'), + (0xFE67, '\u{9fb7}'), + (0xFE6C, '\u{e831}'), + (0xFE6D, '\u{9fb8}'), + (0xFE76, '\u{e83b}'), + (0xFE7E, '\u{9fb9}'), + (0xFE90, '\u{9fba}'), + (0xFE91, '\u{e855}'), + (0xFEA0, '\u{9fbb}'), + (0xFEA1, '\u{e468}'), + (0xFEA2, '\u{e469}'), + (0xFEA3, '\u{e46a}'), + (0xFEA4, '\u{e46b}'), + (0xFEA5, '\u{e46c}'), + (0xFEA6, '\u{e46d}'), + (0xFEA7, '\u{e46e}'), + (0xFEA8, '\u{e46f}'), + (0xFEA9, '\u{e470}'), + (0xFEAA, '\u{e471}'), + (0xFEAB, '\u{e472}'), + (0xFEAC, '\u{e473}'), + (0xFEAD, '\u{e474}'), + (0xFEAE, '\u{e475}'), + (0xFEAF, '\u{e476}'), + (0xFEB0, '\u{e477}'), + (0xFEB1, '\u{e478}'), + (0xFEB2, '\u{e479}'), + (0xFEB3, '\u{e47a}'), + (0xFEB4, '\u{e47b}'), + (0xFEB5, '\u{e47c}'), + (0xFEB6, '\u{e47d}'), + (0xFEB7, '\u{e47e}'), + (0xFEB8, '\u{e47f}'), + (0xFEB9, '\u{e480}'), + (0xFEBA, '\u{e481}'), + (0xFEBB, '\u{e482}'), + (0xFEBC, '\u{e483}'), + (0xFEBD, '\u{e484}'), + (0xFEBE, '\u{e485}'), + (0xFEBF, '\u{e486}'), + (0xFEC0, '\u{e487}'), + (0xFEC1, '\u{e488}'), + (0xFEC2, '\u{e489}'), + (0xFEC3, '\u{e48a}'), + (0xFEC4, '\u{e48b}'), + (0xFEC5, '\u{e48c}'), + (0xFEC6, '\u{e48d}'), + (0xFEC7, '\u{e48e}'), + (0xFEC8, '\u{e48f}'), + (0xFEC9, '\u{e490}'), + (0xFECA, '\u{e491}'), + (0xFECB, '\u{e492}'), + (0xFECC, '\u{e493}'), + (0xFECD, '\u{e494}'), + (0xFECE, '\u{e495}'), + (0xFECF, '\u{e496}'), + (0xFED0, '\u{e497}'), + (0xFED1, '\u{e498}'), + (0xFED2, '\u{e499}'), + (0xFED3, '\u{e49a}'), + (0xFED4, '\u{e49b}'), + (0xFED5, '\u{e49c}'), + (0xFED6, '\u{e49d}'), + (0xFED7, '\u{e49e}'), + (0xFED8, '\u{e49f}'), + (0xFED9, '\u{e4a0}'), + (0xFEDA, '\u{e4a1}'), + (0xFEDB, '\u{e4a2}'), + (0xFEDC, '\u{e4a3}'), + (0xFEDD, '\u{e4a4}'), + (0xFEDE, '\u{e4a5}'), + (0xFEDF, '\u{e4a6}'), + (0xFEE0, '\u{e4a7}'), + (0xFEE1, '\u{e4a8}'), + (0xFEE2, '\u{e4a9}'), + (0xFEE3, '\u{e4aa}'), + (0xFEE4, '\u{e4ab}'), + (0xFEE5, '\u{e4ac}'), + (0xFEE6, '\u{e4ad}'), + (0xFEE7, '\u{e4ae}'), + (0xFEE8, '\u{e4af}'), + (0xFEE9, '\u{e4b0}'), + (0xFEEA, '\u{e4b1}'), + (0xFEEB, '\u{e4b2}'), + (0xFEEC, '\u{e4b3}'), + (0xFEED, '\u{e4b4}'), + (0xFEEE, '\u{e4b5}'), + (0xFEEF, '\u{e4b6}'), + (0xFEF0, '\u{e4b7}'), + (0xFEF1, '\u{e4b8}'), + (0xFEF2, '\u{e4b9}'), + (0xFEF3, '\u{e4ba}'), + (0xFEF4, '\u{e4bb}'), + (0xFEF5, '\u{e4bc}'), + (0xFEF6, '\u{e4bd}'), + (0xFEF7, '\u{e4be}'), + (0xFEF8, '\u{e4bf}'), + (0xFEF9, '\u{e4c0}'), + (0xFEFA, '\u{e4c1}'), + (0xFEFB, '\u{e4c2}'), + (0xFEFC, '\u{e4c3}'), + (0xFEFD, '\u{e4c4}'), + (0xFEFE, '\u{e4c5}'), + (0x8135F437, '\u{e7c7}'), + (0x82359037, '\u{e81e}'), + (0x82359038, '\u{e826}'), + (0x82359039, '\u{e82b}'), + (0x82359130, '\u{e82c}'), + (0x82359131, '\u{e832}'), + (0x82359132, '\u{e843}'), + (0x82359133, '\u{e854}'), + (0x82359134, '\u{e864}'), + (0x84318236, '\u{e78d}'), + (0x84318237, '\u{e78f}'), + (0x84318238, '\u{e78e}'), + (0x84318239, '\u{e790}'), + (0x84318330, '\u{e791}'), + (0x84318331, '\u{e792}'), + (0x84318332, '\u{e793}'), + (0x84318333, '\u{e794}'), + (0x84318334, '\u{e795}'), + (0x84318335, '\u{e796}'), + (0x95329031, '\u{20087}'), + (0x95329033, '\u{20089}'), + (0x95329730, '\u{200cc}'), + (0x9536B937, '\u{215d7}'), + (0x9630BA35, '\u{2298f}'), + (0x9635B630, '\u{241fe}'), +]; diff --git a/components/tidb_query_datatype/src/codec/collation/encoding/mod.rs b/components/tidb_query_datatype/src/codec/collation/encoding/mod.rs index 268b11aad41..ba7d5d75ec2 100644 --- a/components/tidb_query_datatype/src/codec/collation/encoding/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/encoding/mod.rs @@ -1,6 +1,8 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. mod ascii; +mod gb18030; +mod gb18030_data; mod gbk; mod unicode_letter; mod utf8; @@ -8,6 +10,7 @@ mod utf8; use std::str; pub use ascii::*; +pub use gb18030::*; pub use gbk::*; pub use unicode_letter::*; pub use utf8::*; diff --git a/components/tidb_query_datatype/src/codec/collation/mod.rs b/components/tidb_query_datatype/src/codec/collation/mod.rs index fe72a674e0b..98284ac5463 100644 --- a/components/tidb_query_datatype/src/codec/collation/mod.rs +++ b/components/tidb_query_datatype/src/codec/collation/mod.rs @@ -37,6 +37,8 @@ macro_rules! match_template_collator { Latin1Bin => CollatorLatin1Bin, GbkBin => CollatorGbkBin, GbkChineseCi => CollatorGbkChineseCi, + Gb18030Bin => CollatorGb18030Bin, + Gb18030ChineseCi => CollatorGb18030ChineseCi, ], $($tail)* } @@ -81,6 +83,7 @@ macro_rules! match_template_charset { Utf8Mb4 => EncodingUtf8Mb4, Latin1 => EncodingLatin1, Gbk => EncodingGbk, + Gb18030 => EncodingGb18030, Binary => EncodingBinary, Ascii => EncodingAscii, ], diff --git a/components/tidb_query_datatype/src/codec/mysql/charset.rs b/components/tidb_query_datatype/src/codec/mysql/charset.rs index 0ac2655c619..cbdd5a01315 100644 --- a/components/tidb_query_datatype/src/codec/mysql/charset.rs +++ b/components/tidb_query_datatype/src/codec/mysql/charset.rs @@ -13,6 +13,8 @@ pub const CHARSET_ASCII: &str = "ascii"; pub const CHARSET_LATIN1: &str = "latin1"; /// `CHARSET_GBK` is Chinese character set. pub const CHARSET_GBK: &str = "gbk"; +/// `CHARSET_GB18030` is another Chinese character set containing GBK. +pub const CHARSET_GB18030: &str = "gb18030"; /// All utf8 charsets. pub const UTF8_CHARSETS: &[&str] = &[CHARSET_UTF8, CHARSET_UTF8MB4, CHARSET_ASCII]; diff --git a/components/tidb_query_datatype/src/def/field_type.rs b/components/tidb_query_datatype/src/def/field_type.rs index ad76a8e339c..5210d368dd3 100644 --- a/components/tidb_query_datatype/src/def/field_type.rs +++ b/components/tidb_query_datatype/src/def/field_type.rs @@ -117,6 +117,8 @@ pub enum Collation { Latin1Bin = -47, GbkBin = -87, GbkChineseCi = -28, + Gb18030ChineseCi = -248, + Gb18030Bin = -249, } impl Collation { @@ -134,6 +136,8 @@ impl Collation { -224 | -192 => Ok(Collation::Utf8Mb4UnicodeCi), -87 => Ok(Collation::GbkBin), -28 => Ok(Collation::GbkChineseCi), + -248 => Ok(Collation::Gb18030ChineseCi), + -249 => Ok(Collation::Gb18030Bin), -255 => Ok(Collation::Utf8Mb40900AiCi), -309 => Ok(Collation::Utf8Mb40900Bin), n if n >= 0 => Ok(Collation::Utf8Mb4BinNoPadding), @@ -163,6 +167,7 @@ pub enum Charset { Gbk, Binary, Ascii, + Gb18030, } impl Charset { @@ -174,6 +179,7 @@ impl Charset { "gbk" => Ok(Charset::Gbk), "binary" => Ok(Charset::Binary), "ascii" => Ok(Charset::Ascii), + "gb18030" => Ok(Charset::Gb18030), _ => Err(DataTypeError::UnsupportedCharset { name: String::from(name), }), @@ -552,6 +558,8 @@ mod tests { (-224, Some(Collation::Utf8Mb4UnicodeCi)), (-28, Some(Collation::GbkChineseCi)), (-87, Some(Collation::GbkBin)), + (-248, Some(Collation::Gb18030ChineseCi)), + (-249, Some(Collation::Gb18030Bin)), ]; for (collate, expected) in cases { @@ -577,6 +585,7 @@ mod tests { ("binary", Some(Charset::Binary)), ("latin1", Some(Charset::Latin1)), ("ascii", Some(Charset::Ascii)), + ("gb18030", Some(Charset::Gb18030)), ("somethingwrong", None), ]; diff --git a/components/tidb_query_expr/src/impl_cast.rs b/components/tidb_query_expr/src/impl_cast.rs index b55f441a2a1..ff15cfb05cc 100644 --- a/components/tidb_query_expr/src/impl_cast.rs +++ b/components/tidb_query_expr/src/impl_cast.rs @@ -4487,6 +4487,8 @@ mod tests { Some(vec![0xe4, 0xb8, 0x80]), ), ("一".as_bytes().to_vec(), "gbk", Some(vec![0xd2, 0xbb])), + ("一".as_bytes().to_vec(), "gb18030", Some(vec![0xd2, 0xbb])), + ("€".as_bytes().to_vec(), "gb18030", Some(vec![0xa2, 0xe3])), ]; for (v, charset, expected) in cases { @@ -4515,6 +4517,8 @@ mod tests { Some("一".as_bytes().to_vec()), ), (vec![0xd2, 0xbb], "gbk", Some("一".as_bytes().to_vec())), + (vec![0xd2, 0xbb], "gb18030", Some("一".as_bytes().to_vec())), + (vec![0xa2, 0xe3], "gb18030", Some("€".as_bytes().to_vec())), ]; for (v, charset, expected) in cases { diff --git a/components/tidb_query_expr/src/impl_string.rs b/components/tidb_query_expr/src/impl_string.rs index d0aeb1a9b1e..9727ee98355 100644 --- a/components/tidb_query_expr/src/impl_string.rs +++ b/components/tidb_query_expr/src/impl_string.rs @@ -1132,7 +1132,7 @@ mod tests { use tidb_query_datatype::{ builder::FieldTypeBuilder, - codec::mysql::charset::{CHARSET_GBK, CHARSET_UTF8MB4}, + codec::mysql::charset::{CHARSET_GB18030, CHARSET_GBK, CHARSET_UTF8MB4}, }; use tipb::ScalarFuncSig; @@ -2884,6 +2884,7 @@ mod tests { #[test] fn test_upper() { + // Test binary string case let cases = vec![ (Some(b"hello".to_vec()), Some(b"hello".to_vec())), (Some(b"123".to_vec()), Some(b"123".to_vec())), @@ -2912,7 +2913,7 @@ mod tests { arg.clone(), FieldTypeBuilder::new() .tp(FieldTypeTp::VarString) - .charset(CHARSET_UTF8MB4) + .collation(Collation::Binary) .build(), ) .evaluate(ScalarFuncSig::Upper) @@ -2961,6 +2962,70 @@ mod tests { } } + #[test] + fn test_gb18030_lower_upper() { + // Test GB18030 string case + let raw_upper_lower: Vec<(&str, &str, &str)> = vec![ + ("µ", "µ", "μ"), // "B5" "B5" "3BC" + ("DžLjNj", "DžLjNj", "džljnj"), // "1C5" "1C8" "1CB" + ("DŽLJNJ", "DŽLJNJ", "džljnj"), // "1C4" "1C7" "1CA" + ("džljnj", "DŽLJNJ", "džljnj"), // "1C6" "1C9" "1CC" + ( + "ɥɪჾᏸᏻᏽᵽꮕàáèéêìíòóùúüāēěīńňōūǎǐǒǔǖǘǚǜⅪⅫ", + "ɥɪჾᏸᏻᏽᵽꮕÀÁÈÉÊÌÍÒÓÙÚÜĀĒĚĪŃŇŌŪǍǏǑǓǕǗǙǛⅪⅫ", + "ɥɪჾᏸᏻᏽᵽꮕàáèéêìíòóùúüāēěīńňōūǎǐǒǔǖǘǚǜⅺⅻ", + ), + ("Dzɜɡ", "Dzɜɡ", "dzɜɡ"), // "1F2" "25C" "261" + ( + "𐒰𐓘𐲀𐳀𑢠𖹀𞤀", // "104B0 104D8 10C80 10CC0 118A0 16E40 1E900" + "𐒰𐓘𐲀𐳀𑢠𖹀𞤀", + "𐒰𐓘𐲀𐳀𑢠𖹀𞤀", + ), + ( + "ẛι", // 1E9B 1FBE + "ẛι", "ṡι", + ), + ]; + + for (i, test_case) in raw_upper_lower.iter().enumerate() { + let output = RpnFnScalarEvaluator::new() + .push_param_with_field_type( + Some((test_case.0).as_bytes().to_vec()).clone(), + FieldTypeBuilder::new() + .tp(FieldTypeTp::VarString) + .charset(CHARSET_GB18030) + .build(), + ) + .evaluate(ScalarFuncSig::UpperUtf8) + .unwrap(); + assert_eq!( + output, + Some((test_case.1).as_bytes().to_vec()), + "error in upper cases #{} ({})", + i + 1, + (test_case.0) + ); + + let output = RpnFnScalarEvaluator::new() + .push_param_with_field_type( + Some((test_case.0).as_bytes().to_vec()).clone(), + FieldTypeBuilder::new() + .tp(FieldTypeTp::VarString) + .charset(CHARSET_GB18030) + .build(), + ) + .evaluate(ScalarFuncSig::LowerUtf8) + .unwrap(); + assert_eq!( + output, + Some((test_case.2).as_bytes().to_vec()), + "error in lower cases #{} ({})", + i + 1, + (test_case.0) + ); + } + } + #[test] fn test_lower() { // Test binary string case From 9e2e5bf5601819f19f1b224388e5bc1a49a19942 Mon Sep 17 00:00:00 2001 From: glorv Date: Tue, 24 Sep 2024 14:41:16 +0800 Subject: [PATCH 081/144] resource_control: support setting resource usage limit for background tasks (#17532) close tikv/tikv#17531 Use the background task setting `UTILIZATION_LIMIT` from the default resource group to limit the percent of resource(CPU/IO) that background tasks can consume. Signed-off-by: glorv --- components/resource_control/src/metrics.rs | 6 +++ .../resource_control/src/resource_group.rs | 5 +-- components/resource_control/src/worker.rs | 39 +++++++++++++++++-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/components/resource_control/src/metrics.rs b/components/resource_control/src/metrics.rs index 45723063492..da40021659f 100644 --- a/components/resource_control/src/metrics.rs +++ b/components/resource_control/src/metrics.rs @@ -28,6 +28,12 @@ lazy_static! { &["priority"] ) .unwrap(); + pub static ref BACKGROUND_TASK_RESOURCE_UTILITATION_VEC: IntGaugeVec = register_int_gauge_vec!( + "tikv_resource_control_bg_resource_utilitation", + "The total resource utilization percentage of background tasks", + &["type"] + ) + .unwrap(); } pub fn deregister_metrics(name: &str) { diff --git a/components/resource_control/src/resource_group.rs b/components/resource_control/src/resource_group.rs index 85730e60481..c78179c4a51 100644 --- a/components/resource_control/src/resource_group.rs +++ b/components/resource_control/src/resource_group.rs @@ -12,9 +12,7 @@ use std::{ }; use collections::HashMap; -#[cfg(test)] -use dashmap::mapref::one::Ref; -use dashmap::DashMap; +use dashmap::{mapref::one::Ref, DashMap}; use fail::fail_point; use kvproto::{ kvrpcpb::{CommandPri, ResourceControlContext}, @@ -217,7 +215,6 @@ impl ResourceGroupManager { } } - #[cfg(test)] pub(crate) fn get_resource_group(&self, name: &str) -> Option> { self.resource_groups.get(&name.to_ascii_lowercase()) } diff --git a/components/resource_control/src/worker.rs b/components/resource_control/src/worker.rs index 4957ee1aa3f..ae4b6b51b47 100644 --- a/components/resource_control/src/worker.rs +++ b/components/resource_control/src/worker.rs @@ -13,7 +13,7 @@ use prometheus::Histogram; use strum::EnumCount; use tikv_util::{ debug, - resource_control::TaskPriority, + resource_control::{TaskPriority, DEFAULT_RESOURCE_GROUP_NAME}, sys::{cpu_time::ProcessStat, SysQuota}, time::Instant, warn, @@ -137,6 +137,20 @@ impl GroupQuotaAdjustWorker { } self.last_adjust_time = now; + let mut background_util_limit = self + .resource_ctl + .get_resource_group(DEFAULT_RESOURCE_GROUP_NAME) + .map_or(0, |r| { + r.group.get_background_settings().get_utilization_limit() + }); + if background_util_limit == 0 { + background_util_limit = 100; + } + + BACKGROUND_TASK_RESOURCE_UTILITATION_VEC + .with_label_values(&["limit"]) + .set(background_util_limit as i64); + let mut background_groups: Vec<_> = self .resource_ctl .resource_groups @@ -156,8 +170,18 @@ impl GroupQuotaAdjustWorker { return; } - self.do_adjust(ResourceType::Cpu, dur_secs, &mut background_groups); - self.do_adjust(ResourceType::Io, dur_secs, &mut background_groups); + self.do_adjust( + ResourceType::Cpu, + dur_secs, + background_util_limit, + &mut background_groups, + ); + self.do_adjust( + ResourceType::Io, + dur_secs, + background_util_limit, + &mut background_groups, + ); // clean up deleted group stats if self.prev_stats_by_group[0].len() != background_groups.len() { @@ -173,6 +197,7 @@ impl GroupQuotaAdjustWorker { &mut self, resource_type: ResourceType, dur_secs: f64, + utilization_limit: u64, bg_group_stats: &mut [GroupStats], ) { let resource_stats = match self.resource_quota_getter.get_current_stats(resource_type) { @@ -219,6 +244,12 @@ impl GroupQuotaAdjustWorker { } } + let background_util = + (background_consumed_total / resource_stats.total_quota * 100.0) as u64; + BACKGROUND_TASK_RESOURCE_UTILITATION_VEC + .with_label_values(&[resource_type.as_str()]) + .set(background_util as i64); + // fast path if process cpu is low let is_low_load = resource_stats.current_used <= (resource_stats.total_quota * 0.1); if is_low_load && !has_wait && self.is_last_time_low_load[resource_type as usize] { @@ -226,6 +257,7 @@ impl GroupQuotaAdjustWorker { } self.is_last_time_low_load[resource_type as usize] = is_low_load; + let util_limit_percent = (utilization_limit as f64 / 100.0).min(1.0); // the available resource for background tasks is defined as: // (total_resource_quota - foreground_task_used). foreground_task_used // resource is calculated by: (resource_current_total_used - @@ -235,6 +267,7 @@ impl GroupQuotaAdjustWorker { - resource_stats.current_used + background_consumed_total) * 0.8) + .min(resource_stats.total_quota * util_limit_percent) .max(resource_stats.total_quota * 0.1); let mut total_expected_cost = 0.0; for g in bg_group_stats.iter_mut() { From f070033c093ecb21acd77065b02d4d1db6231bf9 Mon Sep 17 00:00:00 2001 From: Spade A <71589810+SpadeA-Tang@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:03:56 +0800 Subject: [PATCH 082/144] In-memory engine: add cross check task for data consistency verification (#17241) ref tikv/tikv#16141 add cross check task for data consistency verification Signed-off-by: SpadeA-Tang Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- .../src/background.rs | 31 +- .../src/cross_check.rs | 1466 +++++++++++++++++ .../range_cache_memory_engine/src/engine.rs | 24 + .../range_cache_memory_engine/src/lib.rs | 16 + .../src/memory_controller.rs | 1 + .../range_cache_memory_engine/src/read.rs | 13 +- components/server/src/common.rs | 5 +- 7 files changed, 1548 insertions(+), 8 deletions(-) create mode 100644 components/range_cache_memory_engine/src/cross_check.rs diff --git a/components/range_cache_memory_engine/src/background.rs b/components/range_cache_memory_engine/src/background.rs index 1357490ffa4..42c4a9e03cb 100644 --- a/components/range_cache_memory_engine/src/background.rs +++ b/components/range_cache_memory_engine/src/background.rs @@ -29,6 +29,7 @@ use txn_types::{Key, TimeStamp, WriteRef, WriteType}; use yatp::Remote; use crate::{ + cross_check::CrossChecker, engine::{RangeCacheMemoryEngineCore, SkiplistHandle}, keys::{ decode_key, encode_key, encode_key_for_boundary_with_mvcc, encoding_for_filter, @@ -45,7 +46,7 @@ use crate::{ LabelRule, RegionLabelChangedCallback, RegionLabelRulesManager, RegionLabelServiceBuilder, }, write_batch::RangeCacheWriteBatchEntry, - RangeCacheEngineConfig, + RangeCacheEngineConfig, RangeCacheMemoryEngine, }; // 5 seconds should be long enough for getting a TSO from PD. @@ -54,7 +55,7 @@ const TIMTOUT_FOR_TSO: Duration = Duration::from_secs(5); /// Try to extract the key and `u64` timestamp from `encoded_key`. /// /// See also: [`txn_types::Key::split_on_ts_for`] -fn split_ts(key: &[u8]) -> Result<(&[u8], u64), String> { +pub(crate) fn split_ts(key: &[u8]) -> Result<(&[u8], u64), String> { match Key::split_on_ts_for(key) { Ok((key, ts)) => Ok((key, ts.into_inner())), Err(_) => Err(format!( @@ -64,7 +65,7 @@ fn split_ts(key: &[u8]) -> Result<(&[u8], u64), String> { } } -fn parse_write(value: &[u8]) -> Result, String> { +pub(crate) fn parse_write(value: &[u8]) -> Result, String> { match WriteRef::parse(value) { Ok(write) => Ok(write), Err(_) => Err(format!( @@ -74,7 +75,6 @@ fn parse_write(value: &[u8]) -> Result, String> { } } -#[derive(Debug)] pub enum BackgroundTask { Gc(GcTask), LoadRegion(CacheRegion, Arc), @@ -82,6 +82,14 @@ pub enum BackgroundTask { DeleteRegions(Vec), TopRegionsLoadEvict, CleanLockTombstone(u64), + TurnOnCrossCheck( + ( + RangeCacheMemoryEngine, + RocksEngine, + Arc, + Duration, + ), + ), SetRocksEngine(RocksEngine), } @@ -99,6 +107,7 @@ impl Display for BackgroundTask { .debug_struct("CleanLockTombstone") .field("seqno", r) .finish(), + BackgroundTask::TurnOnCrossCheck(_) => f.debug_struct("TurnOnCrossCheck").finish(), BackgroundTask::SetRocksEngine(_) => f.debug_struct("SetDiskEngine").finish(), } } @@ -745,6 +754,8 @@ pub struct BackgroundRunner { lock_cleanup_remote: Remote, lock_cleanup_worker: Worker, + cross_check_worker: Option, + // The last sequence number for the lock cf tombstone cleanup last_seqno: u64, // RocksEngine is used to get the oldest snapshot sequence number. @@ -758,6 +769,9 @@ impl Drop for BackgroundRunner { self.gc_range_worker.stop(); self.load_evict_worker.stop(); self.lock_cleanup_worker.stop(); + if let Some(cross_check_worker) = self.cross_check_worker.take() { + cross_check_worker.stop() + }; } } @@ -823,6 +837,7 @@ impl BackgroundRunner { load_evict_remote, lock_cleanup_remote, lock_cleanup_worker, + cross_check_worker: None, last_seqno: 0, rocks_engine: None, }, @@ -1179,6 +1194,14 @@ impl Runnable for BackgroundRunner { self.lock_cleanup_remote.spawn(f); } + BackgroundTask::TurnOnCrossCheck((engine, rocks_engine, pd_client, check_interval)) => { + let cross_check_worker = Worker::new("cross-check-worker"); + let cross_check_runner = + CrossChecker::new(pd_client, engine, rocks_engine, check_interval); + let _ = + cross_check_worker.start_with_timer("cross-check-runner", cross_check_runner); + self.cross_check_worker = Some(cross_check_worker); + } } } } diff --git a/components/range_cache_memory_engine/src/cross_check.rs b/components/range_cache_memory_engine/src/cross_check.rs new file mode 100644 index 00000000000..f7c460b5148 --- /dev/null +++ b/components/range_cache_memory_engine/src/cross_check.rs @@ -0,0 +1,1466 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::{fmt::Display, sync::Arc, time::Duration}; + +use engine_rocks::{RocksEngine, RocksEngineIterator, RocksSnapshot}; +use engine_traits::{ + iter_option, CacheRegion, Iterable, Iterator, KvEngine, Peekable, RangeCacheEngine, + SnapshotMiscExt, CF_LOCK, CF_WRITE, +}; +use pd_client::PdClient; +use slog_global::{error, info, warn}; +use tikv_util::{ + future::block_on_timeout, + time::Instant, + worker::{Runnable, RunnableWithTimer}, +}; +use txn_types::{Key, TimeStamp, WriteRef, WriteType}; + +use crate::{ + background::{parse_write, split_ts}, + read::{RangeCacheIterator, RangeCacheSnapshot}, + RangeCacheMemoryEngine, RegionState, +}; + +#[derive(Debug)] +pub(crate) enum CrossCheckTask { + CrossCheck, +} + +impl Display for CrossCheckTask { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CrossCheckTask::CrossCheck => f.debug_struct("CrossCheck").finish(), + } + } +} + +// Checks the data consistency in the mvcc snapshot semantics between in-memory +// engine and rocksdb. It compares keys one by one in the in-memory engine +// with keys in the rocksdb and for those keys that are missed or redundant +// in the in-memory engine, check the validity. +pub(crate) struct CrossChecker { + pd_client: Arc, + memory_engine: RangeCacheMemoryEngine, + rocks_engine: RocksEngine, + interval: Duration, +} + +impl CrossChecker { + pub(crate) fn new( + pd_client: Arc, + memory_engine: RangeCacheMemoryEngine, + rocks_engine: RocksEngine, + interval: Duration, + ) -> CrossChecker { + CrossChecker { + pd_client, + memory_engine, + rocks_engine, + interval, + } + } + + fn cross_check_range(&self, range_snap: &RangeCacheSnapshot, rocks_snap: &RocksSnapshot) { + info!( + "cross check region"; + "region" => ?range_snap.snapshot_meta().region, + ); + let opts = iter_option( + &range_snap.snapshot_meta().region.start, + &range_snap.snapshot_meta().region.end, + false, + ); + let mut safe_point = { + let region_maps = self + .memory_engine + .core() + .region_manager() + .regions_map() + .read(); + let Some(s) = region_maps.region_meta(range_snap.snapshot_meta().region.id) else { + return; + }; + s.safe_point() + }; + + for cf in &[CF_LOCK, CF_WRITE] { + let mut mem_iter = range_snap.iterator_opt(cf, opts.clone()).unwrap(); + let mut disk_iter = rocks_snap.iterator_opt(cf, opts.clone()).unwrap(); + + let mem_valid = mem_iter.seek_to_first().unwrap(); + let disk_valid = disk_iter.seek_to_first().unwrap(); + if !mem_valid { + // There's no key in IME, we should check whether the rocks engine has no key + // visible to user with read_ts `safe_point`. + let mut last_disk_user_key = vec![]; + let mut last_disk_user_key_delete = false; + let mut prev_key_info = KeyCheckingInfo::default(); + if !CrossChecker::check_remain_disk_key( + cf, + &range_snap.snapshot_meta().region, + &mut safe_point, + &mem_iter, + &mut disk_iter, + &mut prev_key_info, + &mut last_disk_user_key, + &mut last_disk_user_key_delete, + &self.memory_engine, + ) { + return; + } + continue; + } + + if !disk_valid { + panic!( + "cross check fail(key should not exist): {:?} cf not match when seek_to_first; + cache_region={:?}; cache_key={:?}; sequence_numer={};", + cf, + range_snap.snapshot_meta().region, + log_wrappers::Value(mem_iter.key()), + mem_iter.sequence_number, + ); + } + + let check_default = |iter: &RangeCacheIterator| { + let write = WriteRef::parse(iter.value()).unwrap(); + if write.write_type == WriteType::Put && write.short_value.is_none() { + let start_ts = write.start_ts; + let (user_key, _) = split_ts(iter.key()).unwrap(); + let default_key = Key::from_encoded(user_key.to_vec()).append_ts(start_ts); + if let Ok(Some(_)) = range_snap.get_value(default_key.as_encoded()) { + } else { + // check again + if let Ok(Some(_)) = range_snap.get_value_cf(CF_WRITE, iter.key()) { + panic!( + "cross check fail(key should exist): default not found; + cache_region={:?}; default_key={:?}, write_key={:?}, start_ts={}; sequence_numer={};", + range_snap.snapshot_meta().region, + log_wrappers::Value(default_key.as_encoded()), + log_wrappers::Value(iter.key()), + start_ts, + iter.sequence_number, + ); + } + } + } + }; + + let mut last_disk_user_key = vec![]; + // We can have this state: + // Safe point: 6 + // IME: [k2-7] + // Rocks: k1-5-delete, [k1-3], k2-7 + // where k1-5-delete and k1-3 are filtered which is legal as k1-5 is a delete + // type. At some time, rocksdb iterator points to k1-3 while IME iterator points + // to k2-7 and we need last_disk_user_key_delete being true to verify the + // legality. + let mut last_disk_user_key_delete = false; + + let mut cur_key_info = KeyCheckingInfo { + user_key: vec![], + // Used to record mvcc versions of same user keys. So if safe point changed, we + // can found the last_mvcc_before_safe_point_of_cur_user_key and + // last_mvcc_before_safe_point_of_last_user_key + mvcc_recordings: vec![], + // We can have intermediate state: + // Safe point: 6 + // IME: k1-7, k1-5, k1-2 + // Rocks: k1-7, k1-5, k1-3, k1-2 + // where k1-3 is GCed but k1-2 is not. It's safe because safe point is 6 and we + // have k1-5 so both k1-3 and k1-2 are not visible. + // So we record last_mvcc_before_safe_point_of_cur_user_key = 5 and we reject + // any version of this user key with mvcc between 5 and safe point 6. + last_mvcc_version_before_safe_point: 0, + }; + + let mut prev_key_info = KeyCheckingInfo { + user_key: vec![], + mvcc_recordings: vec![], + // We can have this sate: + // Safe point: 6 + // IME: k1-7, k1-5, [k2-7] + // Rocks: k1-7, k1-5, [k1-3], k1-2, k2-7 + // where k1-3 and k1-2 are filtered which is valid. At some time, rocksdb + // iterator points to k1-3 and IME iterator points to k2-7. We need + // to record last_mvcc_before_safe_point_of_last_user_key = 5 and + // reject any version of user key k1 (which is the last user key of + // IME) with mvcc between 5 and 6. + last_mvcc_version_before_safe_point: 0, + }; + + if *cf == CF_WRITE { + let write = match parse_write(mem_iter.value()) { + Ok(write) => write, + Err(e) => { + panic!( + "cross check fail(parse error); + cache_region={:?}; cache_key={:?}, cache_val={:?}; sequence_numer={}; Error={:?}", + range_snap.snapshot_meta().region, + log_wrappers::Value(mem_iter.key()), + log_wrappers::Value(mem_iter.value()), + mem_iter.sequence_number, + e, + ); + } + }; + let (user_key, ts) = split_ts(mem_iter.key()).unwrap(); + + if write.write_type != WriteType::Lock && write.write_type != WriteType::Rollback { + cur_key_info.mvcc_recordings.push(ts); + } + + cur_key_info.user_key = user_key.to_vec(); + } + + CrossChecker::check_with_key_in_disk_iter( + cf, + &mem_iter, + &mut disk_iter, + false, + &mut safe_point, + &self.memory_engine, + &range_snap.snapshot_meta().region, + &mut prev_key_info, + &mut cur_key_info, + &mut last_disk_user_key_delete, + &mut last_disk_user_key, + ); + + if *cf == CF_WRITE { + check_default(&mem_iter); + } + + while mem_iter.next().unwrap() { + if *cf == CF_WRITE { + let (user_key, ts) = split_ts(mem_iter.key()).unwrap(); + let write = match parse_write(mem_iter.value()) { + Ok(write) => write, + Err(e) => { + panic!( + "cross check fail(parse error); + cache_region={:?}; cache_key={:?}, cache_val={:?}; sequence_numer={}; Error={:?}", + range_snap.snapshot_meta().region, + log_wrappers::Value(mem_iter.key()), + log_wrappers::Value(mem_iter.value()), + mem_iter.sequence_number, + e, + ); + } + }; + + if cur_key_info.user_key != user_key { + prev_key_info = cur_key_info; + cur_key_info = KeyCheckingInfo { + user_key: user_key.to_vec(), + mvcc_recordings: vec![], + last_mvcc_version_before_safe_point: 0, + }; + } + + if write.write_type != WriteType::Lock + && write.write_type != WriteType::Rollback + { + cur_key_info.mvcc_recordings.push(ts); + } + } + + CrossChecker::check_with_key_in_disk_iter( + cf, + &mem_iter, + &mut disk_iter, + true, + &mut safe_point, + &self.memory_engine, + &range_snap.snapshot_meta().region, + &mut prev_key_info, + &mut cur_key_info, + &mut last_disk_user_key_delete, + &mut last_disk_user_key, + ); + + if *cf == CF_WRITE { + check_default(&mem_iter); + } + } + prev_key_info = cur_key_info; + disk_iter.next().unwrap(); + if !CrossChecker::check_remain_disk_key( + cf, + &range_snap.snapshot_meta().region, + &mut safe_point, + &mem_iter, + &mut disk_iter, + &mut prev_key_info, + &mut last_disk_user_key, + &mut last_disk_user_key_delete, + &self.memory_engine, + ) { + return; + } + } + + info!( + "cross check range done"; + "region" => ?range_snap.snapshot_meta().region, + ); + } + + // In-memory engine may have GCed some versions, so we should call next of + // disk_iter for some times to get aligned with mem_iter. + // After each call of disk_iter, we will check whether the key missed in the + // in-memory engine will not make it compromise data consistency. + // `next_first` denotes whether disk_iter should call next before comparison. + #[allow(clippy::collapsible_if)] + fn check_with_key_in_disk_iter( + cf: &str, + mem_iter: &RangeCacheIterator, + disk_iter: &mut RocksEngineIterator, + next_fisrt: bool, + safe_point: &mut u64, + engine: &RangeCacheMemoryEngine, + cached_region: &CacheRegion, + prev_key_info: &mut KeyCheckingInfo, + cur_key_info: &mut KeyCheckingInfo, + last_disk_user_key_delete: &mut bool, + last_disk_user_key: &mut Vec, + ) -> bool { + let read_ts = mem_iter.snapshot_read_ts; + let mem_key = mem_iter.key(); + if next_fisrt && !disk_iter.next().unwrap() { + panic!( + "cross check fail(key should not exist): disk iterator next failed; + cache_region={:?}; cache_key={:?}; sequence_numer={}; cf={:?}", + cached_region, + log_wrappers::Value(mem_key), + mem_iter.sequence_number, + cf, + ); + } + + loop { + let disk_key = disk_iter.key(); + if cf == CF_LOCK { + // CF_LOCK should always have the same view + if disk_key != mem_key { + panic!( + "cross check fail(key not equal): lock cf not match; + cache_region={:?}; cache_key={:?}, disk_key={:?}; sequence_numer={};", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + ); + } + if mem_iter.value() != disk_iter.value() { + panic!( + "cross check fail(value not equal): lock cf not match; + cache_region={:?}; key={:?}, mem_value={:?} disk_key={:?};", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(mem_iter.value()), + log_wrappers::Value(disk_iter.value()), + ); + } + break; + } + + if disk_key == mem_key { + if mem_iter.value() != disk_iter.value() { + panic!( + "cross check fail(value not equal): write cf not match; + cache_region={:?}; key={:?}, mem_value={:?} disk_key={:?};", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(mem_iter.value()), + log_wrappers::Value(disk_iter.value()), + ); + } + break; + } + + let (mem_user_key, mem_mvcc) = split_ts(mem_key).unwrap(); + let (disk_user_key, disk_mvcc) = split_ts(disk_key).unwrap(); + + let write = match parse_write(disk_iter.value()) { + Ok(write) => write, + Err(e) => { + panic!( + "cross check fail(parse error); + cache_region={:?}; cache_key={:?}, cache_val={:?}; sequence_numer={}; Error={:?}", + cached_region, + log_wrappers::Value(mem_iter.key()), + log_wrappers::Value(mem_iter.value()), + mem_iter.sequence_number, + e, + ); + } + }; + + if mem_user_key == disk_user_key { + if disk_mvcc > mem_mvcc { + if write.write_type == WriteType::Rollback + || write.write_type == WriteType::Lock + { + info!( + "cross check: meet gced rollback or lock"; + "cache_key" => log_wrappers::Value(mem_key), + "disk_key" => log_wrappers::Value(disk_key), + "cache_region" => ?cached_region, + "seqno" => mem_iter.sequence_number, + "cf" => ?cf, + ); + } else { + // [k1-10, k1-8, k1-5(mvcc delete), k1-4, k1-3] + // safe_point: 6 + // If we gc this range, we will filter k-5, k1-4, and + // k1-3 but with k1-5 deleted at last, so we may see an + // intermediate state: + // [k1-10, k1-8, k1-5(mvcc delete), k1-3] where k1-4 is + // filtered so we have a lower mvcc + // key k1-3 and a higher mvcc key k1-5. So we should use + // the safe_point to compare the mvcc version. + + if disk_mvcc >= *safe_point { + if disk_mvcc < read_ts { + // get safe point again as it may be updated + *safe_point = { + let region_maps = + engine.core().region_manager().regions_map().read(); + let meta = region_maps.region_meta(cached_region.id).unwrap(); + // region might have split + if meta.get_region() != cached_region { + return false; + } + assert!(meta.safe_point() >= *safe_point); + meta.safe_point() + }; + } + // check again + if disk_mvcc >= *safe_point { + if write.write_type == WriteType::Put || disk_mvcc > *safe_point { + panic!( + "cross check fail(key should exist): miss valid mvcc version(larger than safe point); + cache_region={:?}; cache_key={:?}, disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}; cur_key_info={:?}", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + read_ts, + *safe_point, + cur_key_info, + ); + } + } + } + + cur_key_info.update_last_mvcc_version_before_safe_point(*safe_point); + // We record the largest mvcc version below safe_point for each user_key -- + // and there should not be any version between it and safe_point + // So, for [k1-10, k1-8, k1-5, k1-4, k1-3] + // safe_point: 6 + // If we see [k1-10, k1-8, k1-4, k1-3] in the in-memory engine, and we + // record the last_mvcc_version_before_safe_point be 4. When we see k1-5 + // in rocksdb, we have this version 5 which is between 6 and 4 which + // denotes we have GCed a version that should not be GCed. + if disk_mvcc < *safe_point + && disk_mvcc > cur_key_info.last_mvcc_version_before_safe_point + && (write.write_type != WriteType::Rollback + && write.write_type != WriteType::Lock) + { + panic!( + "cross check fail(key should exist): miss valid mvcc version(less than safe point); + cache_region={:?}; cache_key={:?}, disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}; cur_key_info={:?}", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + read_ts, + *safe_point, + cur_key_info, + ); + } + } + } + } else { + if disk_mvcc > *safe_point { + *safe_point = { + let region_maps = engine.core().region_manager().regions_map().read(); + let meta = region_maps.region_meta(cached_region.id).unwrap(); + // region might have split + if meta.get_region() != cached_region { + return false; + } + assert!(meta.safe_point() >= *safe_point); + meta.safe_point() + }; + if disk_mvcc > *safe_point { + panic!( + "cross check fail(key should exist): keys newer than safe_point have been gced; + cache_region={:?}; disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}", + cached_region, + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + read_ts, + *safe_point, + ); + } + } + + if !CrossChecker::check_duplicated_mvcc_version_for_last_user_key( + cf, + cached_region, + mem_iter, + &write, + safe_point, + disk_key, + disk_mvcc, + disk_user_key, + prev_key_info, + last_disk_user_key, + last_disk_user_key_delete, + engine, + ) { + return false; + } + } + + if disk_key > mem_key { + panic!( + "cross check fail(key should not exist): write cf not match; + cache_region={:?}; cache_key={:?}, disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}", + cached_region, + log_wrappers::Value(mem_key), + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + read_ts, + *safe_point, + ); + } + + assert!(disk_iter.next().unwrap()); + } + + true + } + + // IME iterator has reached to end, now check the validity of the remaining keys + // in rocksdb iterator. + // Return false means the range has been evicted, and for simplicity, stop the + // check. + fn check_remain_disk_key( + cf: &&str, + cached_region: &CacheRegion, + safe_point: &mut u64, + mem_iter: &RangeCacheIterator, + disk_iter: &mut RocksEngineIterator, + prev_key_info: &mut KeyCheckingInfo, + last_disk_user_key: &mut Vec, + last_disk_user_key_delete: &mut bool, + engine: &RangeCacheMemoryEngine, + ) -> bool { + while disk_iter.valid().unwrap() { + // IME and rocks enigne should have the same data view for CF_LOCK + if *cf == CF_LOCK { + panic!( + "cross check fail(key should exist): lock cf not match; + cache_region={:?}; disk_key={:?}; sequence_numer={};", + cached_region, + log_wrappers::Value(disk_iter.key()), + mem_iter.sequence_number, + ); + } + + let (disk_user_key, disk_mvcc) = split_ts(disk_iter.key()).unwrap(); + // We cannot miss any types of write if the mvcc version is larger + // than `safe_point` of the relevant region. But the safe + // point can be updated during the cross check. Fetch it + // and check again. + if disk_mvcc > *safe_point { + *safe_point = { + let region_maps = engine.core().region_manager().regions_map().read(); + let meta = region_maps.region_meta(cached_region.id).unwrap(); + // region might have split + if meta.get_region() != cached_region { + return false; + } + assert!(meta.safe_point() >= *safe_point); + meta.safe_point() + }; + if disk_mvcc > *safe_point { + panic!( + "cross check fail(key should exist): write cf not match; + cache_region={:?}; disk_key={:?}, disk_mvcc={}; sequence_numer={}; prev_key_info={:?}", + cached_region, + log_wrappers::Value(disk_iter.key()), + disk_mvcc, + mem_iter.sequence_number, + prev_key_info, + ); + } + } + let write = match parse_write(disk_iter.value()) { + Ok(write) => write, + Err(e) => { + panic!( + "cross check fail(parse error); + cache_region={:?}; cache_key={:?}, cache_val={:?}; sequence_numer={}; Error={:?}", + cached_region, + log_wrappers::Value(mem_iter.key()), + log_wrappers::Value(mem_iter.value()), + mem_iter.sequence_number, + e, + ); + } + }; + + if !CrossChecker::check_duplicated_mvcc_version_for_last_user_key( + cf, + cached_region, + mem_iter, + &write, + safe_point, + disk_iter.key(), + disk_mvcc, + disk_user_key, + prev_key_info, + last_disk_user_key, + last_disk_user_key_delete, + engine, + ) { + return false; + }; + + disk_iter.next().unwrap(); + } + + true + } + + // mem_iter has pointed to the next user key whereas disk_iter still has some + // versions. + #[allow(clippy::collapsible_else_if)] + fn check_duplicated_mvcc_version_for_last_user_key( + cf: &str, + cached_region: &CacheRegion, + mem_iter: &RangeCacheIterator, + write: &WriteRef<'_>, + safe_point: &mut u64, + disk_key: &[u8], + disk_mvcc: u64, + disk_user_key: &[u8], + prev_key_info: &mut KeyCheckingInfo, + last_disk_user_key: &mut Vec, + last_disk_user_key_delete: &mut bool, + engine: &RangeCacheMemoryEngine, + ) -> bool { + if write.write_type == WriteType::Rollback || write.write_type == WriteType::Lock { + info!( + "meet gced rollback or lock"; + "disk_key" => log_wrappers::Value(disk_key), + "cache_region" => ?cached_region, + "seqno" => mem_iter.sequence_number, + "cf" => ?cf, + ); + return true; + } + + if disk_user_key == prev_key_info.user_key { + prev_key_info.update_last_mvcc_version_before_safe_point(*safe_point); + // It means all versions below safe point are GCed which means the + // latest write below safe point is mvcc delete. + // IME: k1-9, [k2-9] + // Rocks:k1-9, k1-5, [k1-3], k2-9 + // Safe point: 6 + // In this case, k1-5 must be MVCC delete. + // So when disk points to k1-5 we set last_disk_user_key_delete be + // true so that when we check k1-3 we can know it is deleted + // legally. + if prev_key_info.last_mvcc_version_before_safe_point == 0 { + *safe_point = { + let region_maps = engine.core().region_manager().regions_map().read(); + let meta = region_maps.region_meta(cached_region.id).unwrap(); + // region might have split + if meta.get_region() != cached_region { + return false; + } + assert!(meta.safe_point() >= *safe_point); + meta.safe_point() + }; + prev_key_info.update_last_mvcc_version_before_safe_point(*safe_point); + } + if prev_key_info.last_mvcc_version_before_safe_point == 0 { + if disk_user_key != last_disk_user_key { + *last_disk_user_key = disk_user_key.to_vec(); + *last_disk_user_key_delete = false; + } + if !*last_disk_user_key_delete { + if write.write_type == WriteType::Delete { + *last_disk_user_key_delete = true; + } else { + panic!( + "cross check fail(key should exist): miss valid mvcc version; + cache_region={:?}; disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}; prev_key_info={:?}", + cached_region, + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + mem_iter.snapshot_read_ts, + safe_point, + prev_key_info, + ); + } + } + } else { + if disk_mvcc > prev_key_info.last_mvcc_version_before_safe_point { + if write.write_type == WriteType::Rollback + || write.write_type == WriteType::Lock + { + info!( + "meet gced rollback or lock"; + "disk_key" => log_wrappers::Value(disk_key), + "cache_region" => ?cached_region, + "seqno" => mem_iter.sequence_number, + "cf" => ?cf, + ); + } else { + panic!( + "cross check fail(key should exist): miss valid mvcc version; + cache_region={:?}; disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}", + cached_region, + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + mem_iter.snapshot_read_ts, + safe_point, + ); + } + } else { + // It's ok + } + } + } else { + // IME: k2-9 + // Rocks: k1-5, k1-3, k2-9 + // Safe point: 6 + // In this case, k1-5 must be MVCC delete. + // So when disk points to k1-5 we set last_disk_user_key_delete be true so that + // when we check k1-3 we can know it is deleted legally. + if disk_user_key != last_disk_user_key { + *last_disk_user_key = disk_user_key.to_vec(); + *last_disk_user_key_delete = false; + } + if !*last_disk_user_key_delete { + if write.write_type == WriteType::Delete { + *last_disk_user_key_delete = true; + } else { + panic!( + "cross check fail(key should exist): miss valid mvcc version; + cache_region={:?}; disk_key={:?}; sequence_numer={}; read_ts={}, safe_point={}", + cached_region, + log_wrappers::Value(disk_key), + mem_iter.sequence_number, + mem_iter.snapshot_read_ts, + safe_point, + ); + } + } + } + + true + } +} + +impl Runnable for CrossChecker { + type Task = CrossCheckTask; + + fn run(&mut self, _: Self::Task) { + let active_regions: Vec<_> = { + let regions_map = self + .memory_engine + .core() + .region_manager() + .regions_map() + .read(); + regions_map + .regions() + .iter() + .filter_map(|(_, meta)| { + if meta.get_state() == RegionState::Active { + Some(meta.get_region().clone()) + } else { + None + } + }) + .collect() + }; + + let snap = self.rocks_engine.snapshot(); + + let tso_timeout = Duration::from_secs(5); + let now = match block_on_timeout(self.pd_client.get_tso(), tso_timeout) { + Ok(Ok(ts)) => ts, + err => { + error!( + "schedule range cache engine gc failed "; + "timeout_duration" => ?tso_timeout, + "error" => ?err, + ); + return; + } + }; + + // Check the snapshot with read_ts one minute ago + let read_ts = now.physical() - Duration::from_secs(60).as_millis() as u64; + let read_ts = TimeStamp::compose(read_ts, 0).into_inner(); + + let ranges_to_audit: Vec<_> = active_regions + .iter() + .filter_map(|range| { + match self + .memory_engine + .snapshot(range.clone(), read_ts, snap.sequence_number()) + { + Ok(range_snap) => Some(range_snap), + Err(_) => { + warn!( + "failed to get snap in cross check"; + "range" => ?range, + ); + None + } + } + }) + .collect(); + + if ranges_to_audit.is_empty() { + return; + } + + let now = Instant::now(); + + ranges_to_audit + .into_iter() + .for_each(|r| self.cross_check_range(&r, &snap)); + info!( + "cross check finished"; + "duration" => ?now.saturating_elapsed(), + ); + } +} + +impl RunnableWithTimer for CrossChecker { + fn get_interval(&self) -> Duration { + self.interval + } + + fn on_timeout(&mut self) { + self.run(CrossCheckTask::CrossCheck); + } +} + +#[derive(Default)] +struct KeyCheckingInfo { + user_key: Vec, + mvcc_recordings: Vec, + last_mvcc_version_before_safe_point: u64, +} + +impl KeyCheckingInfo { + fn update_last_mvcc_version_before_safe_point(&mut self, safe_point: u64) { + self.last_mvcc_version_before_safe_point = *self + .mvcc_recordings + .iter() + .find(|&mvcc| mvcc <= &safe_point) + .unwrap_or(&0); + } +} + +impl std::fmt::Debug for KeyCheckingInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("KeyCheckingInfo") + .field("user_key", &log_wrappers::Value(&self.user_key)) + .field("mvcc_recordings", &self.mvcc_recordings) + .field( + "last_mvcc_version_before_safe_point", + &self.last_mvcc_version_before_safe_point, + ) + .finish() + } +} + +#[cfg(test)] +mod tests { + use std::{sync::Arc, time::Duration}; + + use engine_rocks::{util::new_engine_opt, RocksDbOptions, RocksWriteBatchVec}; + use engine_traits::{ + CacheRegion, KvEngine, Mutable, RangeCacheEngine, WriteBatch, WriteBatchExt, CF_DEFAULT, + CF_LOCK, CF_WRITE, + }; + use futures::future::ready; + use keys::data_key; + use kvproto::metapb::{Region, RegionEpoch}; + use pd_client::PdClient; + use raftstore::{ + coprocessor::{RegionInfoCallback, RegionInfoProvider}, + RegionInfo, SeekRegionCallback, + }; + use tempfile::Builder; + use tikv_util::{config::VersionTrack, store::new_peer}; + use txn_types::{Key, TimeStamp, Write, WriteType}; + + use crate::{ + cross_check::CrossChecker, RangeCacheEngineConfig, RangeCacheEngineContext, + RangeCacheMemoryEngine, RangeCacheWriteBatch, + }; + + #[derive(Clone)] + struct MockRegionInfoProvider; + impl RegionInfoProvider for MockRegionInfoProvider { + fn seek_region( + &self, + _: &[u8], + _: SeekRegionCallback, + ) -> raftstore::coprocessor::Result<()> { + Ok(()) + } + fn find_region_by_id( + &self, + _: u64, + _: RegionInfoCallback>, + ) -> raftstore::coprocessor::Result<()> { + Ok(()) + } + fn get_regions_in_range( + &self, + _start_key: &[u8], + _end_key: &[u8], + ) -> raftstore::coprocessor::Result> { + Ok(vec![]) + } + } + + fn cross_check(prepare_data: F) + where + F: FnOnce(&mut RangeCacheWriteBatch, &mut RocksWriteBatchVec), + { + let mut engine = RangeCacheMemoryEngine::with_region_info_provider( + RangeCacheEngineContext::new_for_tests(Arc::new(VersionTrack::new( + RangeCacheEngineConfig::config_for_test(), + ))), + Some(Arc::new(MockRegionInfoProvider {})), + ); + let mut region = Region::default(); + region.set_peers(vec![new_peer(1, 1)].into()); + region.set_id(1); + region.set_end_key(b"z".to_vec()); + let mut epoch = RegionEpoch::default(); + epoch.conf_ver = 1; + epoch.version = 1; + region.set_region_epoch(epoch); + let cache_region = CacheRegion::from_region(®ion); + engine.new_region(region.clone()); + + let path = Builder::new().prefix("temp").tempdir().unwrap(); + let db_opts = RocksDbOptions::default(); + let cf_opts = [CF_DEFAULT, CF_LOCK, CF_WRITE] + .iter() + .map(|name| (*name, Default::default())) + .collect(); + let rocks_engine = new_engine_opt(path.path().to_str().unwrap(), db_opts, cf_opts).unwrap(); + + engine.set_disk_engine(rocks_engine.clone()); + engine + .core() + .region_manager() + .regions_map() + .write() + .mut_region_meta(region.id) + .unwrap() + .set_safe_point(6); + + struct MockPdClient {} + impl PdClient for MockPdClient { + fn get_tso(&self) -> pd_client::PdFuture { + Box::pin(ready(Ok(TimeStamp::compose(TimeStamp::physical_now(), 0)))) + } + } + + let cross_checker = CrossChecker::new( + Arc::new(MockPdClient {}), + engine.clone(), + rocks_engine.clone(), + Duration::from_secs(100000), + ); + + { + let mut wb = engine.write_batch(); + wb.prepare_for_region(cache_region.clone()); + let mut disk_wb = rocks_engine.write_batch(); + + prepare_data(&mut wb, &mut disk_wb); + + wb.set_sequence_number(1000).unwrap(); + wb.write().unwrap(); + disk_wb.write().unwrap(); + + let snap = engine.snapshot(cache_region.clone(), 10, 10000).unwrap(); + let disk_snap = rocks_engine.snapshot(); + + cross_checker.cross_check_range(&snap, &disk_snap); + } + } + + fn write_key(k: &[u8], ts: u64, ty: WriteType) -> (Vec, Vec) { + let data_key = data_key(k); + let raw_write_k = Key::from_raw(&data_key).append_ts(ts.into()); + let val = Write::new(ty, ts.into(), Some(vec![])).as_ref().to_bytes(); + (raw_write_k.into_encoded(), val) + } + + #[test] + fn test_cross_check() { + // Safe point: 6 + // IME: + // Disk: k1-4-r, + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Rollback); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: + // Disk: k1-4-d, + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: + // Disk: k1-4-d, k1-3 + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: + // Disk: k1-5-r, k1-4-d, k1-3 + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 5, WriteType::Rollback); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k1-5, + // Disk: k1-9, k1-5, k1-4, k1-2 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k2-5, + // Disk: k2-5, k2-4, k2-2 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-2", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-5, k2-4, k3-4, k4-4 + // Disk: k1-5, k1-3, k2-4, k2-2, k3-4, k3-2, k4-4, k4-2 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 4, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-3", 4, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-3", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-4", 4, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-4", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k1-5, k2-7 + // Disk: k1-9, k1-5, k1-4, k1-2, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Temporary state in GC: k1-4 is filtered + // Safe point: 6 + // IME: k1-9, k1-5-d, k1-2 k2-7 + // Disk: k1-9, k1-5-d, k1-4, k1-2, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Delete); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k2-7 + // Disk: k1-9, k1-5-d, k1-4, k1-2, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k1-5, k3-7 + // Disk: k1-9, k1-5, k1-4, k1-2, k2-4-d, k2-3, k3-7 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 4, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-3", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k2-4-d k2-1 k3-7 + // Disk: k1-9, k1-5-d, k1-4, k1-2, k2-4-d, k2-3, k2-1 k3-7 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 4, WriteType::Delete); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 2, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-3", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + + // Safe point: 6 + // IME: k1-9, k3-7 + // Disk: k1-9, k1-5-d, k1-4, k1-2, k2-4-d, k2-3, k3-7 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 4, WriteType::Delete); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-3", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic1() { + // Safe point: 6 + // IME: k1-9, k1-5-r, k2-7 + // Disk: k1-9, k1-5-r, k1-4, k1-2, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Rollback); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic2() { + // Safe point: 6 + // IME: k1-9, k1-4, k2-7 + // Disk: k1-9, k1-5, k1-4, k1-2, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic2_2() { + // Safe point: 6 + // IME: k1-9, + // Disk: k1-9, k1-5, k1-4, k1-2, k-2-7 + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 5, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 2, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic3_1() { + // Safe point: 6 + // IME: k2-7 + // Disk: k1-9, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic3_2() { + // Safe point: 6 + // IME: + // Disk: k1-9, + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic3_3() { + // Safe point: 6 + // IME: + // Disk: k1-4, + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic3_4() { + // Safe point: 6 + // IME: + // Disk: k1-4-r, k1-3 + cross_check(|_wb, disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Rollback); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-1", 3, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic4_1() { + // Safe point: 6 + // IME: k1-4 + // Disk: + cross_check(|wb, _disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Rollback); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic4_2() { + // Safe point: 6 + // IME: k1-7, k2-4 + // Disk: k1-7 + cross_check(|wb, _disk_wb| { + let (k, v) = write_key(b"k-1", 4, WriteType::Rollback); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } + + #[test] + #[should_panic] + fn test_cross_check_panic5() { + // Safe point: 6 + // IME: k2-7 + // Disk: k1-9, k2-7, + cross_check(|wb, disk_wb| { + let (k, v) = write_key(b"k-1", 9, WriteType::Put); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + + let (k, v) = write_key(b"k-2", 7, WriteType::Put); + wb.put_cf(CF_WRITE, &k, &v).unwrap(); + disk_wb.put_cf(CF_WRITE, &k, &v).unwrap(); + }); + } +} diff --git a/components/range_cache_memory_engine/src/engine.rs b/components/range_cache_memory_engine/src/engine.rs index 44dd00aa3a0..84fe0e5f452 100644 --- a/components/range_cache_memory_engine/src/engine.rs +++ b/components/range_cache_memory_engine/src/engine.rs @@ -18,6 +18,7 @@ use engine_traits::{ RangeCacheEngineExt, RegionEvent, Result, CF_DEFAULT, CF_LOCK, CF_WRITE, DATA_CFS, }; use kvproto::metapb::Region; +use pd_client::PdClient; use raftstore::coprocessor::RegionInfoProvider; use slog_global::error; use tikv_util::{config::VersionTrack, info, warn}; @@ -427,6 +428,27 @@ impl RangeCacheMemoryEngine { pub fn statistics(&self) -> Arc { self.statistics.clone() } + + pub fn start_cross_check(&self, rocks_engine: RocksEngine, pd_client: Arc) { + let cross_check_interval = self.config.value().cross_check_interval; + if !cross_check_interval.is_zero() { + if let Err(e) = + self.bg_worker_manager() + .schedule_task(BackgroundTask::TurnOnCrossCheck(( + self.clone(), + rocks_engine, + pd_client, + cross_check_interval.0, + ))) + { + error!( + "schedule TurnOnCrossCheck failed"; + "err" => ?e, + ); + assert!(tikv_util::thread_group::is_shutdown(!cfg!(test))); + } + } + } } impl RangeCacheMemoryEngine { @@ -650,6 +672,7 @@ pub mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), + cross_check_interval: Default::default(), mvcc_amplification_threshold: 10, })); let mem_controller = Arc::new(MemoryController::new(config.clone(), skiplist.clone())); @@ -707,6 +730,7 @@ pub mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Some(ReadableSize::mb(20)), + cross_check_interval: Default::default(), mvcc_amplification_threshold: 10, })); let mem_controller = Arc::new(MemoryController::new(config.clone(), skiplist.clone())); diff --git a/components/range_cache_memory_engine/src/lib.rs b/components/range_cache_memory_engine/src/lib.rs index e3724d573f3..5f90e6e2a82 100644 --- a/components/range_cache_memory_engine/src/lib.rs +++ b/components/range_cache_memory_engine/src/lib.rs @@ -18,6 +18,7 @@ use tikv_util::config::{ReadableDuration, ReadableSize, VersionTrack}; mod background; pub mod config; +mod cross_check; mod engine; mod keys; mod memory_controller; @@ -68,6 +69,10 @@ pub struct RangeCacheEngineConfig { // used in getting top regions to filter those with less mvcc amplification. Here, we define // mvcc amplification to be '(next + prev) / processed_keys'. pub mvcc_amplification_threshold: usize, + // Cross check is only for test usage and should not be turned on in production + // environment. Interval 0 means it is turned off, which is the default value. + #[online_config(skip)] + pub cross_check_interval: ReadableDuration, } impl Default for RangeCacheEngineConfig { @@ -82,6 +87,7 @@ impl Default for RangeCacheEngineConfig { hard_limit_threshold: None, expected_region_size: None, mvcc_amplification_threshold: 100, + cross_check_interval: ReadableDuration(Duration::from_secs(0)), } } } @@ -159,10 +165,12 @@ impl RangeCacheEngineConfig { hard_limit_threshold: Some(ReadableSize::gb(2)), expected_region_size: Some(ReadableSize::mb(20)), mvcc_amplification_threshold: 10, + cross_check_interval: ReadableDuration(Duration::from_secs(0)), } } } +#[derive(Clone)] pub struct RangeCacheEngineContext { config: Arc>, statistics: Arc, @@ -197,6 +205,14 @@ impl RangeCacheEngineContext { } } + pub fn pd_client(&self) -> Arc { + self.pd_client.clone() + } + + pub fn config(&self) -> &Arc> { + &self.config + } + pub fn statistics(&self) -> Arc { self.statistics.clone() } diff --git a/components/range_cache_memory_engine/src/memory_controller.rs b/components/range_cache_memory_engine/src/memory_controller.rs index 3411996c9c0..749d9fcc688 100644 --- a/components/range_cache_memory_engine/src/memory_controller.rs +++ b/components/range_cache_memory_engine/src/memory_controller.rs @@ -132,6 +132,7 @@ mod tests { soft_limit_threshold: Some(ReadableSize(300)), hard_limit_threshold: Some(ReadableSize(500)), expected_region_size: Default::default(), + cross_check_interval: Default::default(), mvcc_amplification_threshold: 10, })); let mc = MemoryController::new(config, skiplist_engine.clone()); diff --git a/components/range_cache_memory_engine/src/read.rs b/components/range_cache_memory_engine/src/read.rs index fd0c4b31264..ba6892bfea4 100644 --- a/components/range_cache_memory_engine/src/read.rs +++ b/components/range_cache_memory_engine/src/read.rs @@ -84,6 +84,10 @@ impl RangeCacheSnapshot { engine: engine.clone(), }) } + + pub(crate) fn snapshot_meta(&self) -> &RangeCacheSnapshotMeta { + &self.snapshot_meta + } } impl Drop for RangeCacheSnapshot { @@ -155,6 +159,7 @@ impl Iterable for RangeCacheSnapshot { prefix_extractor, local_stats: LocalStatistics::default(), seek_duration: IN_MEMORY_ENGINE_SEEK_DURATION.local(), + snapshot_read_ts: self.snapshot_meta.snapshot_ts, }) } } @@ -225,11 +230,11 @@ pub struct RangeCacheIterator { iter: OwnedIter>, InternalBytes, InternalBytes>, // The lower bound is inclusive while the upper bound is exclusive if set // Note: bounds (region boundaries) have no mvcc versions - lower_bound: Vec, - upper_bound: Vec, + pub(crate) lower_bound: Vec, + pub(crate) upper_bound: Vec, // A snapshot sequence number passed from RocksEngine Snapshot to guarantee suitable // visibility. - sequence_number: u64, + pub(crate) sequence_number: u64, saved_user_key: Vec, // This is only used by backwawrd iteration where the value we want may not be pointed by the @@ -246,6 +251,8 @@ pub struct RangeCacheIterator { statistics: Arc, local_stats: LocalStatistics, seek_duration: LocalHistogram, + + pub(crate) snapshot_read_ts: u64, } impl Drop for RangeCacheIterator { diff --git a/components/server/src/common.rs b/components/server/src/common.rs index d8ebded71ed..e979bb777c4 100644 --- a/components/server/src/common.rs +++ b/components/server/src/common.rs @@ -703,7 +703,7 @@ pub fn build_hybrid_engine( ) -> HybridEngine { // todo(SpadeA): add config for it let mut memory_engine = RangeCacheMemoryEngine::with_region_info_provider( - range_cache_engine_context, + range_cache_engine_context.clone(), region_info_provider, ); memory_engine.set_disk_engine(disk_engine.clone()); @@ -712,6 +712,9 @@ pub fn build_hybrid_engine( ::RangeHintService::from(pd_client.clone()), ) } + + memory_engine.start_cross_check(disk_engine.clone(), range_cache_engine_context.pd_client()); + HybridEngine::new(disk_engine, memory_engine) } From ddd5da88f064700f940056458a9709846675919c Mon Sep 17 00:00:00 2001 From: ekexium Date: Tue, 24 Sep 2024 15:34:36 +0800 Subject: [PATCH 083/144] txn: introduce large_txn_cache in txn_status_cache (#17460) ref tikv/tikv#17459 Introduce large_txn_status in txn_status_cache. Signed-off-by: ekexium Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/tikv_util/src/lru.rs | 5 + src/storage/mod.rs | 31 +- src/storage/txn/commands/prewrite.rs | 5 +- src/storage/txn/scheduler.rs | 4 +- src/storage/txn/txn_status_cache.rs | 903 +++++++++++++++++++++------ 5 files changed, 739 insertions(+), 209 deletions(-) diff --git a/components/tikv_util/src/lru.rs b/components/tikv_util/src/lru.rs index e2ea1e8c64b..c69be44da40 100644 --- a/components/tikv_util/src/lru.rs +++ b/components/tikv_util/src/lru.rs @@ -405,6 +405,11 @@ where self.map.get(key).map(|v| &v.value) } + #[inline] + pub fn contains_key(&self, key: &K) -> bool { + self.get_no_promote(key).is_some() + } + #[inline] pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { match self.map.get_mut(key) { diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 57be6099a17..da2a1db51b9 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -11427,7 +11427,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(10.into()) + .get_committed_no_promote(10.into()) .unwrap(), 21.into() ); @@ -11515,7 +11515,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(10.into()) + .get_committed_no_promote(10.into()) .is_none() ); @@ -11535,7 +11535,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(10.into()) + .get_committed_no_promote(10.into()) .unwrap(), 20.into() ); @@ -11557,7 +11557,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(30.into()) + .get_committed_no_promote(30.into()) .is_none() ); @@ -11591,7 +11591,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(50.into()) + .get_committed_no_promote(50.into()) .unwrap(), 60.into() ); @@ -11636,7 +11636,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(70.into()) + .get_committed_no_promote(70.into()) .unwrap(), 80.into() ); @@ -11679,7 +11679,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(90.into()) + .get_committed_no_promote(90.into()) .unwrap(), 100.into() ); @@ -11706,12 +11706,15 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(9.into()) + .get_committed_no_promote(9.into()) .is_none() ); // CheckTxnStatus: committed transaction - storage.sched.get_txn_status_cache().remove(10.into()); + storage + .sched + .get_txn_status_cache() + .remove_normal(10.into()); storage .sched_txn_command( commands::CheckTxnStatus::new( @@ -11733,7 +11736,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(10.into()) + .get_committed_no_promote(10.into()) .unwrap(), 20.into() ); @@ -11776,7 +11779,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(120.into()) + .get_committed_no_promote(120.into()) .is_none() ); @@ -11796,7 +11799,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(120.into()) + .get_committed_no_promote(120.into()) .is_none() ); @@ -11841,7 +11844,7 @@ mod tests { storage .sched .get_txn_status_cache() - .remove(130.into()) + .remove_normal(130.into()) .unwrap(), 140.into() ); @@ -11861,7 +11864,7 @@ mod tests { storage .sched .get_txn_status_cache() - .get_no_promote(130.into()) + .get_committed_no_promote(130.into()) .unwrap(), 140.into() ); diff --git a/src/storage/txn/commands/prewrite.rs b/src/storage/txn/commands/prewrite.rs index e5c9ec4f755..38b22f24960 100644 --- a/src/storage/txn/commands/prewrite.rs +++ b/src/storage/txn/commands/prewrite.rs @@ -502,7 +502,10 @@ impl Prewriter { // Handle special cases about retried prewrite requests for pessimistic // transactions. if let TransactionKind::Pessimistic(_) = self.kind.txn_kind() { - if let Some(commit_ts) = context.txn_status_cache.get_no_promote(self.start_ts) { + if let Some(commit_ts) = context + .txn_status_cache + .get_committed_no_promote(self.start_ts) + { fail_point!("before_prewrite_txn_status_cache_hit"); if self.ctx.is_retry_request { MVCC_PREWRITE_REQUEST_AFTER_COMMIT_COUNTER_VEC diff --git a/src/storage/txn/scheduler.rs b/src/storage/txn/scheduler.rs index 25ec5723104..b82a84c55d1 100644 --- a/src/storage/txn/scheduler.rs +++ b/src/storage/txn/scheduler.rs @@ -899,7 +899,9 @@ impl TxnScheduler { // remain not updated after receiving signal from the callback. let now = std::time::SystemTime::now(); for (start_ts, commit_ts) in known_txn_status { - self.inner.txn_status_cache.insert(start_ts, commit_ts, now); + self.inner + .txn_status_cache + .insert_committed(start_ts, commit_ts, now); } } diff --git a/src/storage/txn/txn_status_cache.rs b/src/storage/txn/txn_status_cache.rs index ab50bd0412e..4edff6bc7a8 100644 --- a/src/storage/txn/txn_status_cache.rs +++ b/src/storage/txn/txn_status_cache.rs @@ -104,7 +104,32 @@ //! lock; and for write requests, if it finds the transaction of that lock is //! already committed, it can merge together the resolve-lock-committing and the //! write operation that the request needs to perform. - +//! +//! ## Design Update-1: Dual-Cache System +//! +//! Goal: maximize all TiKV nodes' awareness of large pipelined transactions +//! during their lifetime, i.e. from their first writes to all locks being +//! committed. This is crucial to resolved-ts resolver to handle locks belonging +//! to large transactions. +//! +//! The txn_status_cache is then split into two independent parts. +//! 1. `normal_cache`: For most transactions, including committed and rolled +//! back transactions. +//! 2. `large_txn_cache`: Specifically for ongoing large transactions. +//! +//! ### Key characteristics: +//! +//! - Large Transaction Identification: Large transactions are identified if +//! their `start_ts` and `min_commit_ts` differ. Non-large transactions which +//! request to be cached in the cache can also be treated as large +//! transactions, as they imply their min_commit_ts are useful. +//! +//! - Prioritized Caching: The `large_txn_cache` has a higher priority when +//! upserting and retrieving transaction status. +//! +//! This dual-cache design allows for more efficient handling of both normal and +//! large transactions, preventing either type from dominating the cache and +//! evicting information about transactions of the other type. use std::{ sync::{atomic::AtomicU64, Arc}, time::{Duration, SystemTime, UNIX_EPOCH}, @@ -122,18 +147,35 @@ use crate::storage::metrics::*; const TXN_STATUS_CACHE_SLOTS: usize = 128; -/// An cache item should be kept for at least this time. +/// A cache item should be kept for at least this time. /// Actually this should be guaranteed only for committed transactions. See /// [this section](# /// for-filtering-out-unwanted-late-arrived-stale-prewrite-requests) for details /// about why this is needed. const CACHE_ITEMS_REQUIRED_KEEP_TIME: Duration = Duration::from_secs(30); +const CACHE_ITEMS_REQUIRED_KEEP_TIME_FOR_LARGE_TXNS: Duration = Duration::from_secs(30); -struct CacheEntry { - commit_ts: TimeStamp, +pub struct CacheEntry { + state: TxnState, /// The system timestamp in milliseconds when the entry is inserted to the /// cache. - insert_time: u64, + update_time: u64, +} + +impl CacheEntry { + pub(crate) fn commit_ts(&self) -> Option { + match self.state { + TxnState::Committed { commit_ts } => Some(commit_ts), + _ => None, + } + } +} + +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum TxnState { + Ongoing { min_commit_ts: TimeStamp }, + Committed { commit_ts: TimeStamp }, + RolledBack, } /// Defines the policy to evict expired entries from the cache. @@ -192,7 +234,7 @@ impl lru::EvictPolicy for TxnStatusCacheEvictPolicy { // If it's long enough, remove it. if let Some((_, v)) = get_tail_entry.get_tail_entry() { if self.now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64 - > self.required_keep_time_millis + v.insert_time + > self.required_keep_time_millis + v.update_time { return true; } @@ -219,7 +261,12 @@ type TxnStatusCacheSlot = /// Note that the `TxnStatusCache` updates metrics in some operations assuming /// there's at most one instance of `TxnStatusCache` in a process. pub struct TxnStatusCache { - slots: Vec>>, + // default cache for committed txns + normal_cache: Vec>>, + // for large txns, or any txn whose min_commit_ts needs to be cached + // It is isolated from the normal cache to prevents large transactions from being evicted due + // to normal transactions. This is how this module "prioritizes" large transactions. + large_txn_cache: Vec>>, is_enabled: bool, } @@ -229,24 +276,28 @@ impl TxnStatusCache { fn new_impl( slots: usize, required_keep_time: Duration, + large_txn_required_keep_time: Duration, capacity: usize, + large_txn_capacity: usize, simulated_system_time: Option>, ) -> Self { if capacity == 0 { return Self { - slots: vec![], + normal_cache: vec![], + large_txn_cache: vec![], is_enabled: false, }; } // The limit of the LruCache of each slot. let allowed_capacity_per_slot = capacity / slots; + let capacity_per_slot_for_large_txns = large_txn_capacity / slots; // The total memory allocated initially by the LruCache's internal data // structure for all slots. let mut initial_allocated_capacity_total = 0; let res = Self { - slots: (0..slots) + normal_cache: (0..slots) .map(|_| { let cache = LruCache::new( allowed_capacity_per_slot, @@ -262,6 +313,22 @@ impl TxnStatusCache { Mutex::new(cache).into() }) .collect(), + large_txn_cache: (0..slots) + .map(|_| { + let cache = LruCache::new( + capacity_per_slot_for_large_txns, + 0, + lru::CountTracker::default(), + TxnStatusCacheEvictPolicy::new( + large_txn_required_keep_time, + simulated_system_time.clone(), + ), + ); + let allocated_capacity = cache.internal_allocated_capacity(); + initial_allocated_capacity_total += allocated_capacity; + Mutex::new(cache).into() + }) + .collect(), is_enabled: true, }; SCHED_TXN_STATUS_CACHE_SIZE @@ -274,6 +341,7 @@ impl TxnStatusCache { Self::with_slots_and_time_limit( TXN_STATUS_CACHE_SLOTS, CACHE_ITEMS_REQUIRED_KEEP_TIME, + CACHE_ITEMS_REQUIRED_KEEP_TIME_FOR_LARGE_TXNS, capacity, ) } @@ -281,15 +349,28 @@ impl TxnStatusCache { #[cfg(test)] pub fn new_for_test() -> Self { // 1M capacity should be enough for tests. - Self::with_slots_and_time_limit(16, CACHE_ITEMS_REQUIRED_KEEP_TIME, 1 << 20) + Self::with_slots_and_time_limit( + 16, + CACHE_ITEMS_REQUIRED_KEEP_TIME, + CACHE_ITEMS_REQUIRED_KEEP_TIME_FOR_LARGE_TXNS, + 1 << 20, + ) } pub fn with_slots_and_time_limit( slots: usize, required_keep_time: Duration, + large_txn_required_keep_time: Duration, capacity: usize, ) -> Self { - Self::new_impl(slots, required_keep_time, capacity, None) + Self::new_impl( + slots, + required_keep_time, + large_txn_required_keep_time, + capacity, + capacity, + None, + ) } /// Create a `TxnStatusCache` instance for test purpose, with simulating @@ -301,13 +382,15 @@ impl TxnStatusCache { #[cfg(test)] fn with_simulated_system_time( slots: usize, - requried_keep_time: Duration, + required_keep_time: Duration, capacity: usize, ) -> (Self, Arc) { let system_time = Arc::new(AtomicU64::new(0)); let res = Self::new_impl( slots, - requried_keep_time, + required_keep_time, + CACHE_ITEMS_REQUIRED_KEEP_TIME_FOR_LARGE_TXNS, + capacity, capacity, Some(system_time.clone()), ); @@ -315,79 +398,177 @@ impl TxnStatusCache { } fn slot_index(&self, start_ts: TimeStamp) -> usize { - fxhash::hash(&start_ts) % self.slots.len() + fxhash::hash(&start_ts) % self.normal_cache.len() } - /// Insert a transaction status into the cache. The current system time - /// should be passed from outside to avoid getting system time repeatedly - /// when multiple items is being inserted. - /// - /// If the transaction's information is already in the cache, it will - /// **NOT** be promoted to the most-recent place of the internal LRU. - pub fn insert(&self, start_ts: TimeStamp, commit_ts: TimeStamp, now: SystemTime) { + /// Insert a transaction status into the cache, or update it. The current + /// system time should be passed from outside to avoid getting system time + /// repeatedly when multiple items are being inserted. + pub fn upsert(&self, start_ts: TimeStamp, state: TxnState, now: SystemTime) { if !self.is_enabled { return; } - let insert_time = now.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64; - let mut slot = self.slots[self.slot_index(start_ts)].lock(); - let previous_size = slot.size(); - let previous_allocated = slot.internal_allocated_capacity(); - slot.insert_if_not_exist( - start_ts, - CacheEntry { - commit_ts, - insert_time, - }, - ); - let size = slot.size(); - let allocated = slot.internal_allocated_capacity(); + let update_time = now.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64; + let entry = CacheEntry { state, update_time }; + let slot_index = self.slot_index(start_ts); + + let previous_size; + let after_size; + let previous_allocated; + let after_allocated; + match &state { + // large cache path + TxnState::Ongoing { min_commit_ts } if *min_commit_ts > start_ts => { + // The large_txn_cache takes precedence over the normal_cache in the retrieval + // process. + // This case implies that min_commit_ts would be useful, thus the entry is put + // in the large cache. + let mut large_txn_cache = self.large_txn_cache[slot_index].lock(); + previous_size = large_txn_cache.size(); + previous_allocated = large_txn_cache.internal_allocated_capacity(); + if let Some(existing_entry) = large_txn_cache.get_mut(&start_ts) { + // don't update committed or rolled back txns. + if let TxnState::Ongoing { + min_commit_ts: existing_min_commit_ts, + } = existing_entry.state + { + if *min_commit_ts > existing_min_commit_ts { + existing_entry.state = state; + existing_entry.update_time = update_time; + } + } + } else { + large_txn_cache.insert(start_ts, entry); + } + after_size = large_txn_cache.size(); + after_allocated = large_txn_cache.internal_allocated_capacity(); + } + // normal cache path + _ => { + let mut normal_cache = self.normal_cache[slot_index].lock(); + previous_size = normal_cache.size(); + previous_allocated = normal_cache.internal_allocated_capacity(); + if let Some(existing_entry) = normal_cache.get_mut(&start_ts) { + // don't update committed or rolled back txns. + if let TxnState::Ongoing { min_commit_ts } = existing_entry.state { + if let TxnState::Committed { commit_ts } = state { + assert!(min_commit_ts <= commit_ts); + } + existing_entry.state = state; + existing_entry.update_time = update_time; + } + } else { + normal_cache.insert(start_ts, entry); + } + after_size = normal_cache.size(); + after_allocated = normal_cache.internal_allocated_capacity(); + + let mut large_cache = self.large_txn_cache[slot_index].lock(); + if let Some(existing_entry) = large_cache.get_mut(&start_ts) { + // don't update committed or rolled back txns. + if let TxnState::Ongoing { min_commit_ts } = existing_entry.state { + if let TxnState::Committed { commit_ts } = state { + assert!(min_commit_ts <= commit_ts); + } + existing_entry.state = state; + existing_entry.update_time = update_time; + } + } + } + } // Update statistics. // CAUTION: Assuming that only one TxnStatusCache instance is in a TiKV process. SCHED_TXN_STATUS_CACHE_SIZE .used - .add(size as i64 - previous_size as i64); + .add(after_size as i64 - previous_size as i64); SCHED_TXN_STATUS_CACHE_SIZE .allocated - .add(allocated as i64 - previous_allocated as i64); + .add(after_allocated as i64 - previous_allocated as i64); + } + + /// Insert a committed txn into the normal cache. + pub fn insert_committed(&self, start_ts: TimeStamp, commit_ts: TimeStamp, now: SystemTime) { + let state = TxnState::Committed { commit_ts }; + self.upsert(start_ts, state, now); + } + + pub fn get(&self, start_ts: TimeStamp) -> Option { + if !self.is_enabled { + return None; + } + + let slot_index = self.slot_index(start_ts); + + // large txn cache should be queried first, because it has a higher priority + // when upserting. It's possible for a start_ts to exist in both caches. + // The one in large_txn_cache is more up-to-date. + let mut large_txn_cache = self.large_txn_cache[slot_index].lock(); + if let Some(entry) = large_txn_cache.get(&start_ts) { + return Some(entry.state); + } + + let mut normal_cache = self.normal_cache[slot_index].lock(); + if let Some(entry) = normal_cache.get(&start_ts) { + return Some(entry.state); + } + + None } - /// Try to get an item from the cache, without promoting the item (if - /// exists) to the most recent place. - pub fn get_no_promote(&self, start_ts: TimeStamp) -> Option { + /// Try to get the committed txn from the normal cache, without promoting + /// the item (if exists) to the most recent place. + /// If the txn is ongoing or rolled back, returns None. + pub fn get_committed_no_promote(&self, start_ts: TimeStamp) -> Option { if !self.is_enabled { return None; } - let slot = self.slots[self.slot_index(start_ts)].lock(); - slot.get_no_promote(&start_ts).map(|entry| entry.commit_ts) + let slot = self.normal_cache[self.slot_index(start_ts)].lock(); + slot.get_no_promote(&start_ts) + .and_then(|entry| entry.commit_ts()) } - pub fn get(&self, start_ts: TimeStamp) -> Option { + /// Try to get the committed txn from the normal cache. + /// If the txn is ongoing or rolled back, returns None. + pub fn get_committed(&self, start_ts: TimeStamp) -> Option { if !self.is_enabled { return None; } - let mut slot = self.slots[self.slot_index(start_ts)].lock(); - slot.get(&start_ts).map(|entry| entry.commit_ts) + let mut slot = self.normal_cache[self.slot_index(start_ts)].lock(); + slot.get(&start_ts).and_then(|entry| entry.commit_ts()) } - /// Remove an entry from the cache. We usually don't need to remove anything - /// from the `TxnStatusCache`, but it's useful in tests to construct cache- - /// miss cases. + /// Removes a txn from the normal cache. We usually don't need to + /// remove anything from the normal cache, but it's useful in tests + /// to construct cache-miss cases. + /// Return its commit_ts if it's committed; return None otherwise. #[cfg(test)] - pub fn remove(&self, start_ts: TimeStamp) -> Option { + pub fn remove_normal(&self, start_ts: TimeStamp) -> Option { if !self.is_enabled { return None; } let res = { - let mut slot = self.slots[self.slot_index(start_ts)].lock(); - slot.remove(&start_ts).map(|e| e.commit_ts) + let mut slot = self.normal_cache[self.slot_index(start_ts)].lock(); + slot.remove(&start_ts).and_then(|e| e.commit_ts()) }; - debug_assert!(self.get_no_promote(start_ts).is_none()); + debug_assert!(self.get_committed_no_promote(start_ts).is_none()); res } + + /// Remove a txn from the large-txn cache. + /// This could happen when the large txn finishes its + /// secondary commit phase, i.e. all locks have been cleared. There is no + /// need to keep this txn in cache any longer. + pub fn remove_large_txn(&self, start_ts: TimeStamp) -> Option { + if !self.is_enabled { + return None; + } + let mut slot = self.large_txn_cache[self.slot_index(start_ts)].lock(); + slot.remove(&start_ts) + } } #[cfg(test)] @@ -414,7 +595,7 @@ mod tests { // Spread these items evenly in a specific time limit, so that every time // a new item is inserted, an item will be popped out. for i in 1..=init_size { - c.insert( + c.insert_committed( (i as u64).into(), (i as u64 + 1).into(), start_time + Duration::from_millis(i as u64), @@ -431,7 +612,7 @@ mod tests { .as_millis() as u64, Ordering::Release, ); - c.insert( + c.insert_committed( current_time_shift.into(), (current_time_shift + 1).into(), simulated_now, @@ -445,11 +626,12 @@ mod tests { let c = TxnStatusCache::with_slots_and_time_limit( TXN_STATUS_CACHE_SLOTS, CACHE_ITEMS_REQUIRED_KEEP_TIME, + CACHE_ITEMS_REQUIRED_KEEP_TIME_FOR_LARGE_TXNS, 1 << 20, ); let now = SystemTime::now(); for i in 1..=init_size { - c.insert( + c.insert_committed( (i as u64).into(), (i as u64 + 1).into(), now + Duration::from_millis(i as u64), @@ -458,7 +640,7 @@ mod tests { let rand_range = if init_size == 0 { 10000 } else { init_size } as u64; b.iter(|| { let ts = rand::thread_rng().gen_range(0u64, rand_range); - let res = c.get_no_promote(ts.into()); + let res = c.get_committed_no_promote(ts.into()); test::black_box(&res); }) } @@ -633,7 +815,7 @@ mod tests { ); let start_time = SystemTime::now(); for i in 1..=init_size { - c.insert( + c.insert_committed( (i as u64).into(), (i as u64 + 1).into(), start_time + Duration::from_millis(i as u64), @@ -665,9 +847,9 @@ mod tests { ); if get_before_insert { - test::black_box(c.get_no_promote(time_shift.into())); + test::black_box(c.get_committed_no_promote(time_shift.into())); } - c.insert(time_shift.into(), (time_shift + 1).into(), now); + c.insert_committed(time_shift.into(), (time_shift + 1).into(), now); test::black_box(&c); }); } @@ -696,31 +878,25 @@ mod tests { #[test] fn test_insert_and_get() { let c = TxnStatusCache::new_for_test(); - assert!(c.get_no_promote(1.into()).is_none()); + assert!(c.get_committed_no_promote(1.into()).is_none()); let now = SystemTime::now(); - c.insert(1.into(), 2.into(), now); - assert_eq!(c.get_no_promote(1.into()).unwrap(), 2.into()); - c.insert(3.into(), 4.into(), now); - assert_eq!(c.get_no_promote(3.into()).unwrap(), 4.into()); - - // This won't actually happen, since a transaction will never have commit info - // with two different commit_ts. We just use this to check replacing - // won't happen. - c.insert(1.into(), 4.into(), now); - assert_eq!(c.get_no_promote(1.into()).unwrap(), 2.into()); + c.insert_committed(1.into(), 2.into(), now); + assert_eq!(c.get_committed_no_promote(1.into()).unwrap(), 2.into()); + c.insert_committed(3.into(), 4.into(), now); + assert_eq!(c.get_committed_no_promote(3.into()).unwrap(), 4.into()); let mut start_ts_list: Vec<_> = (1..100).step_by(2).map(TimeStamp::from).collect(); start_ts_list.shuffle(&mut rand::thread_rng()); for &start_ts in &start_ts_list { let commit_ts = start_ts.next(); - c.insert(start_ts, commit_ts, now); + c.insert_committed(start_ts, commit_ts, now); } start_ts_list.shuffle(&mut rand::thread_rng()); for &start_ts in &start_ts_list { let commit_ts = start_ts.next(); - assert_eq!(c.get_no_promote(start_ts).unwrap(), commit_ts); + assert_eq!(c.get_committed_no_promote(start_ts).unwrap(), commit_ts); } } @@ -743,106 +919,93 @@ mod tests { Duration::from_millis(1) ); - c.insert(1.into(), 2.into(), now()); + c.insert_committed(1.into(), 2.into(), now()); set_time(1); - c.insert(3.into(), 4.into(), now()); + c.insert_committed(3.into(), 4.into(), now()); set_time(2); - c.insert(5.into(), 6.into(), now()); + c.insert_committed(5.into(), 6.into(), now()); // Size should be calculated by count. - assert_eq!(c.slots[0].lock().size(), 3); - - // Insert entry 1 again. So if entry 1 is the first one to be popped out, it - // verifies that inserting an existing key won't promote it. - c.insert(1.into(), 2.into(), now()); + assert_eq!(c.normal_cache[0].lock().size(), 3); // All the 3 entries are kept - assert_eq!(c.get_no_promote(1.into()).unwrap(), 2.into()); - assert_eq!(c.get_no_promote(3.into()).unwrap(), 4.into()); - assert_eq!(c.get_no_promote(5.into()).unwrap(), 6.into()); + assert_eq!(c.get_committed_no_promote(1.into()).unwrap(), 2.into()); + assert_eq!(c.get_committed_no_promote(3.into()).unwrap(), 4.into()); + assert_eq!(c.get_committed_no_promote(5.into()).unwrap(), 6.into()); set_time(1001); - c.insert(7.into(), 8.into(), now()); + c.insert_committed(7.into(), 8.into(), now()); // Entry 1 will be popped out. - assert!(c.get_no_promote(1.into()).is_none()); - assert_eq!(c.get_no_promote(3.into()).unwrap(), 4.into()); - assert_eq!(c.get_no_promote(5.into()).unwrap(), 6.into()); + assert!(c.get_committed_no_promote(1.into()).is_none()); + assert_eq!(c.get_committed_no_promote(3.into()).unwrap(), 4.into()); + assert_eq!(c.get_committed_no_promote(5.into()).unwrap(), 6.into()); set_time(1004); - c.insert(9.into(), 10.into(), now()); - // It pops more than 1 entries if there are many expired items at the tail. + c.insert_committed(9.into(), 10.into(), now()); + // It pops more than 1 entry if there are many expired items at the tail. // Entry 3 and 5 will be popped out. - assert!(c.get_no_promote(1.into()).is_none()); - assert!(c.get_no_promote(3.into()).is_none()); - assert!(c.get_no_promote(5.into()).is_none()); - assert_eq!(c.get_no_promote(7.into()).unwrap(), 8.into()); - assert_eq!(c.get_no_promote(9.into()).unwrap(), 10.into()); + assert!(c.get_committed_no_promote(1.into()).is_none()); + assert!(c.get_committed_no_promote(3.into()).is_none()); + assert!(c.get_committed_no_promote(5.into()).is_none()); + assert_eq!(c.get_committed_no_promote(7.into()).unwrap(), 8.into()); + assert_eq!(c.get_committed_no_promote(9.into()).unwrap(), 10.into()); // Now the cache's contents are: // 7@1001, 9@1004 // Test `get` promotes an entry and entries are not in order on insert time. - assert_eq!(c.get(7.into()).unwrap(), 8.into()); + assert_eq!(c.get_committed(7.into()).unwrap(), 8.into()); set_time(2003); - c.insert(11.into(), 12.into(), now()); - assert_eq!(c.get_no_promote(7.into()).unwrap(), 8.into()); - assert_eq!(c.get_no_promote(9.into()).unwrap(), 10.into()); - assert_eq!(c.get_no_promote(11.into()).unwrap(), 12.into()); + c.insert_committed(11.into(), 12.into(), now()); + assert_eq!(c.get_committed_no_promote(7.into()).unwrap(), 8.into()); + assert_eq!(c.get_committed_no_promote(9.into()).unwrap(), 10.into()); + assert_eq!(c.get_committed_no_promote(11.into()).unwrap(), 12.into()); set_time(2005); - c.insert(13.into(), 14.into(), now()); - assert!(c.get_no_promote(7.into()).is_none()); - assert!(c.get_no_promote(9.into()).is_none()); - assert_eq!(c.get_no_promote(11.into()).unwrap(), 12.into()); + c.insert_committed(13.into(), 14.into(), now()); + assert!(c.get_committed_no_promote(7.into()).is_none()); + assert!(c.get_committed_no_promote(9.into()).is_none()); + assert_eq!(c.get_committed_no_promote(11.into()).unwrap(), 12.into()); // Now the cache's contents are: // 11@2003, 13@2005 - // Test inserting existed entries. - // According to the implementation of LruCache, though it won't do any update to - // the content, it still check the tail to see if anything can be - // evicted. set_time(3004); - c.insert(13.into(), 14.into(), now()); - assert!(c.get_no_promote(11.into()).is_none()); - assert_eq!(c.get_no_promote(13.into()).unwrap(), 14.into()); + c.insert_committed(14.into(), 14.into(), now()); + assert!(c.get_committed_no_promote(11.into()).is_none()); + assert_eq!(c.get_committed_no_promote(13.into()).unwrap(), 14.into()); set_time(3006); - c.insert(13.into(), 14.into(), now()); - assert!(c.get_no_promote(13.into()).is_none()); + c.remove_normal(13.into()); // Now the cache is empty. - c.insert(15.into(), 16.into(), now()); + c.insert_committed(15.into(), 16.into(), now()); set_time(3008); - c.insert(17.into(), 18.into(), now()); - // Test inserting existed entry doesn't promote it. - // Re-insert 15. - set_time(3009); - c.insert(15.into(), 16.into(), now()); + c.insert_committed(17.into(), 18.into(), now()); set_time(4007); - c.insert(19.into(), 20.into(), now()); + c.insert_committed(19.into(), 20.into(), now()); // 15's insert time is not updated, and is at the tail of the LRU, so it should // be popped. - assert!(c.get_no_promote(15.into()).is_none()); - assert_eq!(c.get_no_promote(17.into()).unwrap(), 18.into()); + assert!(c.get_committed_no_promote(15.into()).is_none()); + assert_eq!(c.get_committed_no_promote(17.into()).unwrap(), 18.into()); // Now the cache's contents are: // 17@3008, 19@4007 // Test system time being changed, which can lead to current time being less // than entries' insert time. set_time(2000); - c.insert(21.into(), 22.into(), now()); - assert_eq!(c.get_no_promote(17.into()).unwrap(), 18.into()); - assert_eq!(c.get_no_promote(19.into()).unwrap(), 20.into()); - assert_eq!(c.get_no_promote(21.into()).unwrap(), 22.into()); + c.insert_committed(21.into(), 22.into(), now()); + assert_eq!(c.get_committed_no_promote(17.into()).unwrap(), 18.into()); + assert_eq!(c.get_committed_no_promote(19.into()).unwrap(), 20.into()); + assert_eq!(c.get_committed_no_promote(21.into()).unwrap(), 22.into()); set_time(3500); - c.insert(23.into(), 24.into(), now()); - assert_eq!(c.get_no_promote(21.into()).unwrap(), 22.into()); - assert_eq!(c.get(17.into()).unwrap(), 18.into()); - assert_eq!(c.get(19.into()).unwrap(), 20.into()); - assert_eq!(c.get(23.into()).unwrap(), 24.into()); + c.insert_committed(23.into(), 24.into(), now()); + assert_eq!(c.get_committed_no_promote(21.into()).unwrap(), 22.into()); + assert_eq!(c.get_committed(17.into()).unwrap(), 18.into()); + assert_eq!(c.get_committed(19.into()).unwrap(), 20.into()); + assert_eq!(c.get_committed(23.into()).unwrap(), 24.into()); // `get` promotes the entries, and entry 21 is put to the tail. - c.insert(23.into(), 24.into(), now()); - assert_eq!(c.get_no_promote(17.into()).unwrap(), 18.into()); - assert_eq!(c.get_no_promote(19.into()).unwrap(), 20.into()); - assert!(c.get_no_promote(21.into()).is_none()); - assert_eq!(c.get_no_promote(23.into()).unwrap(), 24.into()); + c.insert_committed(24.into(), 24.into(), now()); + assert_eq!(c.get_committed_no_promote(17.into()).unwrap(), 18.into()); + assert_eq!(c.get_committed_no_promote(19.into()).unwrap(), 20.into()); + assert!(c.get_committed_no_promote(21.into()).is_none()); + assert_eq!(c.get_committed_no_promote(23.into()).unwrap(), 24.into()); // Now the cache's contents are: // 17@3008, 19@4007, 23@3500 @@ -850,28 +1013,28 @@ mod tests { // the `TxnStatusCacheEvictPolicy` as they are fetched at different time. set_time(4009); // Insert with time 4007, but check with time 4009 - c.insert(25.into(), 26.into(), now() - Duration::from_millis(2)); - assert!(c.get_no_promote(17.into()).is_none()); - assert_eq!(c.get_no_promote(19.into()).unwrap(), 20.into()); + c.insert_committed(25.into(), 26.into(), now() - Duration::from_millis(2)); + assert!(c.get_committed_no_promote(17.into()).is_none()); + assert_eq!(c.get_committed_no_promote(19.into()).unwrap(), 20.into()); // The cache's contents: // 19@4007, 23@3500, 25@4007 set_time(4010); - c.insert(27.into(), 28.into(), now()); + c.insert_committed(27.into(), 28.into(), now()); // The cache's contents: // 19@4007, 23@3500, 25@4007, 27@4010 // It's also possible to check with a lower time considering that system time // may be changed. Insert with time 5018, but check with time 5008 set_time(5008); - c.insert(29.into(), 30.into(), now() + Duration::from_millis(10)); - assert!(c.get_no_promote(19.into()).is_none()); - assert!(c.get_no_promote(23.into()).is_none()); - assert!(c.get_no_promote(25.into()).is_none()); - assert_eq!(c.get_no_promote(27.into()).unwrap(), 28.into()); - assert_eq!(c.get_no_promote(29.into()).unwrap(), 30.into()); - - // Now the the cache's contents are: + c.insert_committed(29.into(), 30.into(), now() + Duration::from_millis(10)); + assert!(c.get_committed_no_promote(19.into()).is_none()); + assert!(c.get_committed_no_promote(23.into()).is_none()); + assert!(c.get_committed_no_promote(25.into()).is_none()); + assert_eq!(c.get_committed_no_promote(27.into()).unwrap(), 28.into()); + assert_eq!(c.get_committed_no_promote(29.into()).unwrap(), 30.into()); + + // Now the cache's contents are: // 27@4010, 29@5018 // Considering the case that system time is being changed, it's even // possible that the entry being inserted is already expired @@ -879,29 +1042,43 @@ mod tests { // entry will be dropped immediately or not. We just ensure it won't // trigger more troubles. set_time(7000); - c.insert(31.into(), 32.into(), now() - Duration::from_millis(1001)); - assert!(c.get_no_promote(27.into()).is_none()); - assert!(c.get_no_promote(29.into()).is_none()); - assert!(c.get_no_promote(31.into()).is_none()); - assert_eq!(c.slots[0].lock().size(), 0); + c.insert_committed(31.into(), 32.into(), now() - Duration::from_millis(1001)); + assert!(c.get_committed_no_promote(27.into()).is_none()); + assert!(c.get_committed_no_promote(29.into()).is_none()); + assert!(c.get_committed_no_promote(31.into()).is_none()); + assert_eq!(c.normal_cache[0].lock().size(), 0); } #[test] fn test_setting_capacity() { - let c = TxnStatusCache::new_impl(2, Duration::from_millis(1000), 10, None); + let c = TxnStatusCache::new_impl( + 2, + Duration::from_millis(1000), + Duration::from_millis(1000), + 10, + 10, + None, + ); assert!(c.is_enabled); - assert_eq!(c.slots.len(), 2); - assert_eq!(c.slots[0].lock().capacity(), 5); - assert_eq!(c.slots[1].lock().capacity(), 5); - - let c = TxnStatusCache::new_impl(2, Duration::from_millis(1000), 0, None); + assert_eq!(c.normal_cache.len(), 2); + assert_eq!(c.normal_cache[0].lock().capacity(), 5); + assert_eq!(c.normal_cache[1].lock().capacity(), 5); + + let c = TxnStatusCache::new_impl( + 2, + Duration::from_millis(1000), + Duration::from_millis(1000), + 0, + 0, + None, + ); assert!(!c.is_enabled); - assert_eq!(c.slots.len(), 0); + assert_eq!(c.normal_cache.len(), 0); // All operations are noops and won't cause panic or return any incorrect // result. - c.insert(1.into(), 2.into(), SystemTime::now()); - assert!(c.get_no_promote(1.into()).is_none()); - assert!(c.get(1.into()).is_none()); + c.insert_committed(1.into(), 2.into(), SystemTime::now()); + assert!(c.get_committed_no_promote(1.into()).is_none()); + assert!(c.get_committed(1.into()).is_none()); } #[test] @@ -918,61 +1095,401 @@ mod tests { let now = || UNIX_EPOCH + Duration::from_millis(time.load(Ordering::Acquire)); set_time(0); - c.insert(1.into(), 2.into(), now()); + c.insert_committed(1.into(), 2.into(), now()); set_time(2); - c.insert(3.into(), 4.into(), now()); + c.insert_committed(3.into(), 4.into(), now()); set_time(4); - c.insert(5.into(), 6.into(), now()); + c.insert_committed(5.into(), 6.into(), now()); set_time(6); - c.insert(7.into(), 8.into(), now()); + c.insert_committed(7.into(), 8.into(), now()); // The cache can keep at most 5 entries. set_time(8); - c.insert(9.into(), 10.into(), now()); + c.insert_committed(9.into(), 10.into(), now()); // Entry 1 not evicted. 5 entries in the cache currently - assert_eq!(c.slots[0].lock().len(), 5); - assert_eq!(c.get_no_promote(1.into()).unwrap(), 2.into()); + assert_eq!(c.normal_cache[0].lock().len(), 5); + assert_eq!(c.get_committed_no_promote(1.into()).unwrap(), 2.into()); set_time(10); - c.insert(11.into(), 12.into(), now()); + c.insert_committed(11.into(), 12.into(), now()); // Entry 1 evicted. Still 5 entries in the cache. - assert_eq!(c.slots[0].lock().len(), 5); - assert!(c.get_no_promote(1.into()).is_none()); - assert_eq!(c.get_no_promote(3.into()).unwrap(), 4.into()); + assert_eq!(c.normal_cache[0].lock().len(), 5); + assert!(c.get_committed_no_promote(1.into()).is_none()); + assert_eq!(c.get_committed_no_promote(3.into()).unwrap(), 4.into()); // Nothing will be evicted after trying to insert an existing key. - c.insert(11.into(), 12.into(), now()); - assert_eq!(c.slots[0].lock().len(), 5); - assert_eq!(c.get_no_promote(3.into()).unwrap(), 4.into()); + c.insert_committed(11.into(), 12.into(), now()); + assert_eq!(c.normal_cache[0].lock().len(), 5); + assert_eq!(c.get_committed_no_promote(3.into()).unwrap(), 4.into()); // Current contents (key@time): // 3@2, 5@4, 7@6. 9@8, 11@10 // Evicting by time works as well. set_time(1005); - c.insert(13.into(), 14.into(), now()); - assert_eq!(c.slots[0].lock().len(), 4); - assert!(c.get_no_promote(3.into()).is_none()); - assert!(c.get_no_promote(5.into()).is_none()); - assert_eq!(c.get_no_promote(7.into()).unwrap(), 8.into()); + c.insert_committed(13.into(), 14.into(), now()); + assert_eq!(c.normal_cache[0].lock().len(), 4); + assert!(c.get_committed_no_promote(3.into()).is_none()); + assert!(c.get_committed_no_promote(5.into()).is_none()); + assert_eq!(c.get_committed_no_promote(7.into()).unwrap(), 8.into()); // Reorder the entries by `get` to prepare for testing the next case. - assert_eq!(c.get(7.into()).unwrap(), 8.into()); - assert_eq!(c.get(9.into()).unwrap(), 10.into()); - assert_eq!(c.get(11.into()).unwrap(), 12.into()); + assert_eq!(c.get_committed(7.into()).unwrap(), 8.into()); + assert_eq!(c.get_committed(9.into()).unwrap(), 10.into()); + assert_eq!(c.get_committed(11.into()).unwrap(), 12.into()); - c.insert(15.into(), 16.into(), now()); + c.insert_committed(15.into(), 16.into(), now()); // Current contents: // 13@1005, 7@6. 9@8, 11@10, 15@1005 - assert_eq!(c.slots[0].lock().len(), 5); + assert_eq!(c.normal_cache[0].lock().len(), 5); // Expired entries that are not the tail can be evicted after the tail // is evicted due to capacity exceeded. set_time(1011); - c.insert(17.into(), 18.into(), now()); - assert_eq!(c.slots[0].lock().len(), 2); - assert!(c.get_no_promote(13.into()).is_none()); - assert!(c.get_no_promote(7.into()).is_none()); - assert!(c.get_no_promote(9.into()).is_none()); - assert!(c.get_no_promote(11.into()).is_none()); - assert_eq!(c.get(15.into()).unwrap(), 16.into()); - assert_eq!(c.get(17.into()).unwrap(), 18.into()); + c.insert_committed(17.into(), 18.into(), now()); + assert_eq!(c.normal_cache[0].lock().len(), 2); + assert!(c.get_committed_no_promote(13.into()).is_none()); + assert!(c.get_committed_no_promote(7.into()).is_none()); + assert!(c.get_committed_no_promote(9.into()).is_none()); + assert!(c.get_committed_no_promote(11.into()).is_none()); + assert_eq!(c.get_committed(15.into()).unwrap(), 16.into()); + assert_eq!(c.get_committed(17.into()).unwrap(), 18.into()); + } + + fn setup_cache() -> TxnStatusCache { + TxnStatusCache::with_slots_and_time_limit( + 16, + Duration::from_secs(30), + Duration::from_secs(60), + 1000, + ) + } + + #[test] + fn test_upsert_and_get_normal_txn() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 2.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 2.into() + }) + ); + + cache.upsert( + 1.into(), + TxnState::Committed { + commit_ts: 3.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Committed { + commit_ts: 3.into() + }) + ); + } + + #[test] + fn test_upsert_and_get_large_txn() { + let cache = setup_cache(); + let now = SystemTime::now(); + let large_ts = 10000.into(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: large_ts, + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: large_ts + }) + ); + + cache.upsert( + 1.into(), + TxnState::Committed { + commit_ts: large_ts, + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Committed { + commit_ts: large_ts + }) + ); + } + + #[test] + fn test_update_ongoing_txn() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 2.into(), + }, + now, + ); + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 3.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 3.into() + }) + ); + } + + #[test] + fn test_update_committed_txn() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Committed { + commit_ts: 2.into(), + }, + now, + ); + cache.upsert(1.into(), TxnState::RolledBack, now); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Committed { + commit_ts: 2.into() + }) + ); + } + + #[test] + fn test_normal_to_large_txn_transition() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 1.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 1.into() + }) + ); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 2.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 2.into() + }) + ); + } + + #[test] + fn test_large_to_normal_txn_transition() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 10000.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 10000.into() + }) + ); + + cache.upsert( + 1.into(), + TxnState::Committed { + commit_ts: 10001.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Committed { + commit_ts: 10001.into() + }) + ); + } + + #[test] + fn test_eviction_normal_txn() { + let (cache, time) = + TxnStatusCache::with_simulated_system_time(1, Duration::from_secs(30), 1); + + time.store(0, Ordering::SeqCst); + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 2.into(), + }, + SystemTime::now(), + ); + + time.store(31 * 1000, Ordering::SeqCst); // 31 seconds later + cache.upsert( + 3.into(), + TxnState::Ongoing { + min_commit_ts: 4.into(), + }, + SystemTime::now(), + ); + assert_eq!(cache.get(1.into()), None); + assert_eq!( + cache.get(3.into()), + Some(TxnState::Ongoing { + min_commit_ts: 4.into() + }) + ); + } + + #[test] + fn test_eviction_large_txn() { + let (cache, time) = + TxnStatusCache::with_simulated_system_time(1, Duration::from_secs(60), 1); + + time.store(0, Ordering::SeqCst); + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 10000.into(), + }, + SystemTime::now(), + ); + + time.store(61 * 1000, Ordering::SeqCst); // 61 seconds later + cache.upsert( + 2.into(), + TxnState::Ongoing { + min_commit_ts: 20000.into(), + }, + SystemTime::now(), + ); + assert_eq!(cache.get(1.into()), None); + assert_eq!( + cache.get(2.into()), + Some(TxnState::Ongoing { + min_commit_ts: 20000.into() + }) + ); + } + + #[test] + fn test_capacity_limit() { + let cache = TxnStatusCache::with_slots_and_time_limit( + 1, + Duration::from_secs(30), + Duration::from_secs(60), + 5, + ); + let now = SystemTime::now(); + + for i in 1..=5 { + cache.upsert( + i.into(), + TxnState::Ongoing { + min_commit_ts: (i + 1).into(), + }, + now, + ); + } + + cache.upsert( + 6.into(), + TxnState::Ongoing { + min_commit_ts: 7.into(), + }, + now, + ); + assert_eq!(cache.get(1.into()), None); + assert_eq!( + cache.get(6.into()), + Some(TxnState::Ongoing { + min_commit_ts: 7.into() + }) + ); + } + + #[test] + fn test_get_committed() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Committed { + commit_ts: 2.into(), + }, + now, + ); + cache.upsert( + 3.into(), + TxnState::Ongoing { + min_commit_ts: 4.into(), + }, + now, + ); + + assert_eq!(cache.get_committed(1.into()), Some(2.into())); + assert_eq!(cache.get_committed(3.into()), None); + } + + #[test] + fn test_remove_large_txn() { + let cache = setup_cache(); + let now = SystemTime::now(); + + cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 10000.into(), + }, + now, + ); + assert_eq!( + cache.get(1.into()), + Some(TxnState::Ongoing { + min_commit_ts: 10000.into() + }) + ); + + let removed = cache.remove_large_txn(1.into()); + assert!(removed.is_some()); + assert_eq!(cache.get(1.into()), None); } } From 5fa16eeecb2c18290447215e1ea16745928f02a7 Mon Sep 17 00:00:00 2001 From: hhwyt Date: Tue, 24 Sep 2024 17:15:20 +0800 Subject: [PATCH 084/144] raftstore: optimize entry cache eviction to prevent append rejections under memory pressure (#17488) close tikv/tikv#17392 This PR addresses the issue where, under memory pressure, a follower directly rejects append requests instead of first attempting to free up memory by evicting the entry cache. One potential solution is for the follower, before rejecting append requests, to notify other peers on the same node (including leaders and followers) to evict their entry caches. This would require a global module that coordinates peers. When many followers on the same node receive append requests under memory pressure, they would notify the module, which would then send messages to a sufficient number of peers to trigger entry cache eviction and report the results back to the followers. This module could also be triggered by a leader on the same node when it's receiving write requests under memory pressure. However, this solution is a bit complex and has a low ROI. A more practical solution is to optimize the conditions for triggering entry cache eviction, so it occurs earlier, avoiding append rejection. Why doesn't the current version trigger cache eviction earlier? Currently, entry cache eviction is checked either by the `raft_log_gc_tick_interval` (default 3 seconds) or during `handle_raft_committed_entries`. The trigger conditions for eviction are: 1. Total memory usage has reached the high water mark. 2. Entry cache memory usage has reached the `evict_cache_on_memory_ratio` (default 0.1, not visible to the customer). On the other hand, append rejection is triggered when: 1. Total memory usage has reached the high water mark. 2. The total memory usage of the entry cache, raft messages, and applying entries has reached the `reject_messages_on_memory_ratio` (default 0.2). The issue is that when the first condition is met, the second condition for append rejection may be triggered earlier. The solution proposed in this PR is to modify the first condition for cache eviction. Instead of waiting for memory usage to fully reach the high water mark, eviction will be triggered when memory usage is **near** the high water mark. This change should not introduce significant performance overhead because eviction is only triggered when memory usage is near the high water mark, and it helps prevent the more disruptive append rejections. Signed-off-by: hhwyt Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- components/raftstore/src/store/config.rs | 2 +- .../raftstore/src/store/entry_storage.rs | 26 +-- components/raftstore/src/store/memory.rs | 24 ++- components/tikv_util/src/sys/mod.rs | 87 ++++++++- src/server/service/kv.rs | 5 +- .../cases/test_memory_usage_limit.rs | 178 ++++++++++++++---- 6 files changed, 241 insertions(+), 81 deletions(-) diff --git a/components/raftstore/src/store/config.rs b/components/raftstore/src/store/config.rs index 0e10b467faf..005896ef6de 100644 --- a/components/raftstore/src/store/config.rs +++ b/components/raftstore/src/store/config.rs @@ -303,7 +303,7 @@ pub struct Config { #[doc(hidden)] #[online_config(skip)] /// Disable this feature by set to 0, logic will be removed in other pr. - /// When TiKV memory usage reaches `memory_usage_high_water` it will try to + /// When TiKV memory usage is near `memory_usage_high_water` it will try to /// limit memory increasing. For raftstore layer entries will be evicted /// from entry cache, if they utilize memory more than /// `evict_cache_on_memory_ratio` * total. diff --git a/components/raftstore/src/store/entry_storage.rs b/components/raftstore/src/store/entry_storage.rs index 1c261e3b238..a09c3475e1a 100644 --- a/components/raftstore/src/store/entry_storage.rs +++ b/components/raftstore/src/store/entry_storage.rs @@ -335,26 +335,8 @@ impl EntryCache { fn trace_cached_entries(&mut self, entries: CachedEntries) { let dangle_size = { let mut guard = entries.entries.lock().unwrap(); - - let last_idx = guard.0.last().map(|e| e.index).unwrap(); - let cache_front = match self.cache.front().map(|e| e.index) { - Some(i) => i, - None => u64::MAX, - }; - - let dangle_range = if last_idx < cache_front { - // All entries are not in entry cache. - 0..guard.0.len() - } else if let Ok(i) = guard.0.binary_search_by(|e| e.index.cmp(&cache_front)) { - // Some entries are in entry cache. - 0..i - } else { - // All entries are in entry cache. - 0..0 - }; - let mut size = 0; - for e in &guard.0[dangle_range] { + for e in &guard.0 { size += bytes_capacity(&e.data) + bytes_capacity(&e.context); } guard.1 = size; @@ -1272,6 +1254,8 @@ impl EntryStorage { /// Evict entries from the cache. pub fn evict_entry_cache(&mut self, half: bool) { + fail_point!("mock_evict_entry_cache", |_| {}); + if !self.is_entry_cache_empty() { let cache = &mut self.cache; let cache_len = cache.cache.len(); @@ -1408,7 +1392,7 @@ pub mod tests { // Test trace an entry which is still in cache. let cached_entries = CachedEntries::new(vec![new_padded_entry(102, 3, 5)]); cache.trace_cached_entries(cached_entries); - check_mem_size_change(0); + check_mem_size_change(5); // Test compare `cached_last` with `trunc_to_idx` in `EntryCache::append_impl`. cache.append(0, 0, &[new_padded_entry(103, 4, 7)]); @@ -1422,7 +1406,7 @@ pub mod tests { // Test compact the last traced dangle entry. cache.persisted = 102; cache.compact_to(103); - check_mem_size_change(-5); + check_mem_size_change(-10); // Test compact all entries. cache.persisted = 103; diff --git a/components/raftstore/src/store/memory.rs b/components/raftstore/src/store/memory.rs index b1f40d93715..c1ad65392a8 100644 --- a/components/raftstore/src/store/memory.rs +++ b/components/raftstore/src/store/memory.rs @@ -9,7 +9,7 @@ use tikv_alloc::{ mem_trace, trace::{Id, MemoryTrace}, }; -use tikv_util::sys::memory_usage_reaches_high_water; +use tikv_util::sys::memory_usage_reaches_near_high_water; lazy_static! { pub static ref MEMTRACE_ROOT: Arc = mem_trace!( @@ -57,18 +57,28 @@ lazy_static! { MEMTRACE_ROOT.sub_trace(Id::Name("raft_entries")); } +pub fn get_memory_usage_entry_cache() -> u64 { + (|| { + fail_point!("mock_memory_usage_entry_cache", |t| { + t.unwrap().parse::().unwrap() + }); + MEMTRACE_ENTRY_CACHE.sum() as u64 + })() +} + pub fn needs_evict_entry_cache(evict_cache_on_memory_ratio: f64) -> bool { fail_point!("needs_evict_entry_cache", |_| true); + if evict_cache_on_memory_ratio < f64::EPSILON { return false; } let mut usage = 0; - if memory_usage_reaches_high_water(&mut usage) { - let ec_usage = MEMTRACE_ENTRY_CACHE.sum() as u64; - if ec_usage as f64 > usage as f64 * evict_cache_on_memory_ratio { - return true; - } + let is_near = memory_usage_reaches_near_high_water(&mut usage); + if !is_near { + return false; } - false + + let ec_usage = get_memory_usage_entry_cache(); + ec_usage as f64 > usage as f64 * evict_cache_on_memory_ratio } diff --git a/components/tikv_util/src/sys/mod.rs b/components/tikv_util/src/sys/mod.rs index 028a70ce181..7acbb7f28ea 100644 --- a/components/tikv_util/src/sys/mod.rs +++ b/components/tikv_util/src/sys/mod.rs @@ -1,13 +1,5 @@ // Copyright 2017 TiKV Project Authors. Licensed under Apache-2.0. -#[cfg(target_os = "linux")] -mod cgroup; -pub mod cpu_time; -pub mod disk; -pub mod inspector; -pub mod ioload; -pub mod thread; - // re-export some traits for ease of use use std::{ path::Path, @@ -22,12 +14,27 @@ pub use sysinfo::{CpuExt, DiskExt, NetworkExt, ProcessExt, SystemExt}; use crate::config::ReadableSize; +#[cfg(target_os = "linux")] +mod cgroup; +pub mod cpu_time; +pub mod disk; +pub mod inspector; +pub mod ioload; +pub mod thread; + pub const HIGH_PRI: i32 = -1; const CPU_CORES_QUOTA_ENV_VAR_KEY: &str = "TIKV_CPU_CORES_QUOTA"; static GLOBAL_MEMORY_USAGE: AtomicU64 = AtomicU64::new(0); static MEMORY_USAGE_HIGH_WATER: AtomicU64 = AtomicU64::new(u64::MAX); +// MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT is used to decide whether to use a fixed +// margin or a percentage-based margin, ensuring a reasonable margin value on +// both large and small memory machines. +const MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT: u64 = 10 * 1024 * 1024 * 1024; // 10GB +const MEMORY_HIGH_WATER_FIXED_MARGIN: u64 = 1024 * 1024 * 1024; // 1GB +const MEMORY_HIGH_WATER_PERCENTAGE_MARGIN: f64 = 0.9; // Empirical value. + #[cfg(target_os = "linux")] lazy_static! { static ref SELF_CGROUP: cgroup::CGroupSys = cgroup::CGroupSys::new().unwrap_or_default(); @@ -138,6 +145,9 @@ impl SysQuota { /// Get the current global memory usage in bytes. Users need to call /// `record_global_memory_usage` to refresh it periodically. pub fn get_global_memory_usage() -> u64 { + fail_point!("mock_memory_usage", |t| { + t.unwrap().parse::().unwrap() + }); GLOBAL_MEMORY_USAGE.load(Ordering::Acquire) } @@ -160,10 +170,36 @@ pub fn register_memory_usage_high_water(mark: u64) { MEMORY_USAGE_HIGH_WATER.store(mark, Ordering::Release); } +fn get_memory_usage_high_water() -> u64 { + fail_point!("mock_memory_usage_high_water", |t| { + t.unwrap().parse::().unwrap() + }); + MEMORY_USAGE_HIGH_WATER.load(Ordering::Acquire) +} + pub fn memory_usage_reaches_high_water(usage: &mut u64) -> bool { fail_point!("memory_usage_reaches_high_water", |_| true); + *usage = get_global_memory_usage(); - *usage >= MEMORY_USAGE_HIGH_WATER.load(Ordering::Acquire) + let high_water = get_memory_usage_high_water(); + + *usage >= high_water +} + +pub fn memory_usage_reaches_near_high_water(usage: &mut u64) -> bool { + *usage = get_global_memory_usage(); + let high_water = get_memory_usage_high_water(); + + memory_usage_reaches_near_high_water_internal(*usage, high_water) +} + +// Internal function for easier testing. +fn memory_usage_reaches_near_high_water_internal(usage: u64, high_water: u64) -> bool { + if usage > MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT { + usage >= high_water - MEMORY_HIGH_WATER_FIXED_MARGIN + } else { + (usage as f64) >= (high_water as f64) * MEMORY_HIGH_WATER_PERCENTAGE_MARGIN + } } fn limit_cpu_cores_quota_by_env_var(quota: f64) -> f64 { @@ -360,4 +396,37 @@ mqueue /dev/mqueue mqueue rw,relatime 0 0 disk::get_disk_space_stats("/non-exist-path").unwrap_err(); } + #[test] + fn test_near_high_water() { + // Below MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT. + let is_near = memory_usage_reaches_near_high_water_internal( + 8500 * 1024 * 1024, + 9 * 1024 * 1024 * 1024, + ); + assert!(is_near); + + // Above MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT. + let is_near = memory_usage_reaches_near_high_water_internal( + 11 * 1024 * 1024 * 1024, + 12 * 1024 * 1024 * 1024, + ); + assert!(is_near); + } + + #[test] + fn test_not_near_high_water() { + // Below MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT. + let is_near = memory_usage_reaches_near_high_water_internal( + 8 * 1024 * 1024 * 1024, + 9 * 1024 * 1024 * 1024, + ); + assert!(!is_near); + + // Above MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT. + let is_near = memory_usage_reaches_near_high_water_internal( + 10 * 1024 * 1024 * 1024, + 12 * 1024 * 1024 * 1024, + ); + assert!(!is_near); + } } diff --git a/src/server/service/kv.rs b/src/server/service/kv.rs index d67aa14d109..6a93e3f52b8 100644 --- a/src/server/service/kv.rs +++ b/src/server/service/kv.rs @@ -28,8 +28,9 @@ use protobuf::RepeatedField; use raft::eraftpb::MessageType; use raftstore::{ store::{ + get_memory_usage_entry_cache, memory::{MEMTRACE_APPLYS, MEMTRACE_RAFT_ENTRIES, MEMTRACE_RAFT_MESSAGES}, - metrics::{MESSAGE_RECV_BY_STORE, RAFT_ENTRIES_CACHES_GAUGE}, + metrics::MESSAGE_RECV_BY_STORE, CheckLeaderTask, }, Error as RaftStoreError, Result as RaftStoreResult, @@ -2567,7 +2568,7 @@ fn needs_reject_raft_append(reject_messages_on_memory_ratio: f64) -> bool { let mut usage = 0; if memory_usage_reaches_high_water(&mut usage) { let raft_msg_usage = (MEMTRACE_RAFT_ENTRIES.sum() + MEMTRACE_RAFT_MESSAGES.sum()) as u64; - let cached_entries = RAFT_ENTRIES_CACHES_GAUGE.get() as u64; + let cached_entries = get_memory_usage_entry_cache(); let applying_entries = MEMTRACE_APPLYS.sum() as u64; if (raft_msg_usage + cached_entries + applying_entries) as f64 > usage as f64 * reject_messages_on_memory_ratio diff --git a/tests/failpoints/cases/test_memory_usage_limit.rs b/tests/failpoints/cases/test_memory_usage_limit.rs index 82aa9d5148d..ee408ac6d4f 100644 --- a/tests/failpoints/cases/test_memory_usage_limit.rs +++ b/tests/failpoints/cases/test_memory_usage_limit.rs @@ -8,6 +8,7 @@ use std::{ time::{Duration, Instant}, }; +use more_asserts::assert_ge; use raft::eraftpb::MessageType; use raftstore::store::MEMTRACE_ENTRY_CACHE; use test_raftstore::*; @@ -77,59 +78,154 @@ fn test_evict_entry_cache() { fail::cfg("on_entry_cache_evict_tick", "off").unwrap(); } -// Test Raft leader will pause a follower if it meets memory full. -#[test] -fn test_memory_full_cause_of_raft_message() { +fn setup_server_cluster() -> Cluster { let mut cluster = new_server_cluster(0, 2); let pd_client = cluster.pd_client.clone(); cluster.pd_client.disable_default_operator(); - - let r1 = cluster.run_conf_change(); - cluster.must_put(b"k1", b"v1"); - pd_client.must_add_peer(r1, new_learner_peer(2, 2)); - must_get_equal(&cluster.get_engine(2), b"k1", b"v1"); + cluster.run_conf_change(); + pd_client.must_add_peer(1, new_learner_peer(2, 2)); cluster.must_transfer_leader(1, new_peer(1, 1)); + cluster +} - let append_to_2 = Arc::new(AtomicUsize::new(0)); - let append_to_2_ = append_to_2.clone(); - cluster.add_send_filter(CloneFilterFactory( - RegionPacketFilter::new(r1, 2) - .direction(Direction::Recv) - .msg_type(MessageType::MsgAppend) - .allow(usize::MAX) - .set_msg_callback(Arc::new(move |_m| { - append_to_2_.fetch_add(1, Ordering::SeqCst); - })), - )); +fn put_n_entries(cluster: &mut Cluster, num_entries: usize, value_size: usize) { + let value = vec![b'x'; value_size]; + (0..num_entries).for_each(|_| cluster.must_put(b"k1", &value)); +} - let response_to_1 = Arc::new(AtomicUsize::new(0)); - let response_to_1_ = response_to_1.clone(); +fn add_message_filter( + cluster: &mut Cluster, + region_id: u64, + peer_id: u64, + msg_type: MessageType, + counter: Arc, +) { cluster.add_send_filter(CloneFilterFactory( - RegionPacketFilter::new(r1, 1) + RegionPacketFilter::new(region_id, peer_id) .direction(Direction::Recv) - .msg_type(MessageType::MsgUnreachable) + .msg_type(msg_type) .allow(usize::MAX) - .set_msg_callback(Arc::new(move |_m| { - response_to_1_.fetch_add(1, Ordering::SeqCst); - })), + .set_msg_callback({ + let counter = Arc::clone(&counter); + Arc::new(move |_m| { + counter.fetch_add(1, Ordering::SeqCst); + }) + }), )); +} - // A MsgHeartbeatResponse will trigger one MsgAppend. - fail::cfg("needs_reject_raft_append", "return").unwrap(); - (0..10).for_each(|_| cluster.must_put(b"k1", b"v1")); - let now = Instant::now(); - while now.elapsed() < Duration::from_secs(2) { - sleep_ms(100); - let appends = append_to_2.load(Ordering::SeqCst); - if appends < 10 { - continue; +fn add_filter_append_and_unreachable( + cluster: &mut Cluster, + append_to_2: Arc, + response_to_1: Arc, +) { + add_message_filter( + cluster, + 1, + 2, + MessageType::MsgAppend, + Arc::clone(&append_to_2), + ); + add_message_filter( + cluster, + 1, + 1, + MessageType::MsgUnreachable, + Arc::clone(&response_to_1), + ); +} + +fn wait_msg_counter( + append_counter: Arc, + unreachable_counter: Arc, + num_appends: usize, + num_unreachable: usize, +) { + let timeout = Instant::now() + Duration::from_secs(2); + loop { + if Instant::now() > timeout { + break; } - let responses = response_to_1.load(Ordering::SeqCst); - if responses < 10 { - continue; + + let appends = append_counter.load(Ordering::SeqCst); + let responses = unreachable_counter.load(Ordering::SeqCst); + + if appends >= num_appends && responses >= num_unreachable { + break; } - fail::cfg("needs_delay_raft_append", "off").unwrap(); - return; + sleep_ms(50); } - panic!("must have 10 MsgAppend and 10 MsgUnreachable"); +} + +// Test Raft leader will pause a follower if it meets memory full. +#[test] +fn test_memory_full_cause_of_raft_message() { + let mut cluster = setup_server_cluster(); + + let append_to_2 = Arc::new(AtomicUsize::new(0)); + let unreachable_to_2 = Arc::new(AtomicUsize::new(0)); + add_filter_append_and_unreachable(&mut cluster, append_to_2.clone(), unreachable_to_2.clone()); + + fail::cfg("needs_reject_raft_append", "return").unwrap(); + put_n_entries(&mut cluster, 10, 1024); + wait_msg_counter(append_to_2.clone(), unreachable_to_2.clone(), 10, 10); + assert_ge!(append_to_2.load(Ordering::SeqCst), 10); + assert_ge!(unreachable_to_2.load(Ordering::SeqCst), 10); +} + +#[test] +fn test_evict_early_avoids_reject() { + let mut cluster = setup_server_cluster(); + // Set a long lifetime to avoid clearing the entry cache based on time. + cluster.cfg.raft_store.raft_entry_cache_life_time = ReadableDuration::secs(1000); + + fail::cfg("on_raft_gc_log_tick", "return").unwrap(); + fail::cfg("on_entry_cache_evict_tick", "return").unwrap(); + + // Initially disable `evict_entry_cache` to prevent eviction during the first + // round of insertions. + fail::cfg("mock_evict_entry_cache", "return").unwrap(); + // Insert a batch of entries and verify that the entry cache size increases as + // expected. + put_n_entries(&mut cluster, 10, 1024); + let entry_cache_size_before = MEMTRACE_ENTRY_CACHE.sum(); + assert!( + entry_cache_size_before > 10 * 1024, + "Entry cache should not have been evicted during the first roundd" + ); + // Remove the failpoint to allow `evict_entry_cache` for subsequent operations. + fail::remove("mock_evict_entry_cache"); + + // Track MsgAppend and MsgUnreachable. + let append_to_2 = Arc::new(AtomicUsize::new(0)); + let unreachable_to_2 = Arc::new(AtomicUsize::new(0)); + add_filter_append_and_unreachable(&mut cluster, append_to_2.clone(), unreachable_to_2.clone()); + + // Simulate high memory usage conditions. + // The memory usage is set to 9216, which is close to the high water mark of + // 10240. We use 9216 since 9216 < MEMORY_HIGH_WATER_MARGIN_SPLIT_POINT, and + // 10240 * MEMORY_HIGH_WATER_MARGIN_RATIO = 9216. + fail::cfg("mock_memory_usage", "return(9216)").unwrap(); + fail::cfg("mock_memory_usage_high_water", "return(10240)").unwrap(); + fail::cfg("mock_memory_usage_entry_cache", "return(10240)").unwrap(); + + // Insert another batch of entries and ensure that no `MsgUnreachable` messages + // are sent, indicating no rejection occurred during the append + // process. + put_n_entries(&mut cluster, 10, 1024); + wait_msg_counter(append_to_2.clone(), unreachable_to_2.clone(), 10, 0); + assert!( + append_to_2.load(Ordering::SeqCst) == 10 || + // This value could be 11 if a no-op entry. + append_to_2.load(Ordering::SeqCst) == 11 + ); + assert_eq!(unreachable_to_2.load(Ordering::SeqCst), 0); + + // Verify that `evict_entry_cache` was triggered by checking that the entry + // cache size has decreased. + let entry_cache_size_after = MEMTRACE_ENTRY_CACHE.sum(); + assert!( + entry_cache_size_after < entry_cache_size_before, + "Entry cache should be evicted after the second round of insertions" + ); } From 5d2b5cef54e3badc71884d55463187d073bab2e3 Mon Sep 17 00:00:00 2001 From: Wenqi Mou Date: Tue, 24 Sep 2024 17:33:47 -0400 Subject: [PATCH 085/144] br : add encryption support for log/stream backup and restore (#17387) close tikv/tikv#17495 Added support for local encryption for log backup and restore. Added MultiMasterBackend for future extension of having multiple master keys to achieve high availability. Added BackupEncryptionManager in router to encapsulate local temp file encryption using DataKeyManager and MultiMasterBackend. User can also specify plaintext data key if setting up master key not an option. But not recommended as plaintext data key will be store in the PD due to the BR architecture. Signed-off-by: Wenqi Mou --- Cargo.lock | 24 +- components/backup-stream/Cargo.toml | 3 +- components/backup-stream/src/endpoint.rs | 11 +- components/backup-stream/src/router.rs | 808 +++++++++++++++--- .../backup-stream/src/subscription_manager.rs | 7 +- components/backup-stream/src/tempfiles.rs | 76 +- components/backup-stream/tests/suite.rs | 9 +- components/cloud/aws/src/kms.rs | 40 +- components/cloud/aws/src/util.rs | 2 +- components/cloud/azure/src/kms.rs | 2 + components/cloud/gcp/src/kms.rs | 2 + components/cloud/src/kms.rs | 8 + components/encryption/Cargo.toml | 2 + components/encryption/export/examples/ecli.rs | 8 +- components/encryption/export/src/lib.rs | 65 +- .../src/backup/backup_encryption.rs | 83 ++ components/encryption/src/backup/mod.rs | 2 + components/encryption/src/config.rs | 385 +++++++-- components/encryption/src/lib.rs | 8 +- components/encryption/src/manager/mod.rs | 13 + components/encryption/src/master_key/file.rs | 34 +- components/encryption/src/master_key/kms.rs | 72 +- components/encryption/src/master_key/mod.rs | 313 ++++++- components/encryption/src/test_utils.rs | 18 + components/external_storage/Cargo.toml | 2 +- components/external_storage/src/export.rs | 33 +- components/external_storage/src/lib.rs | 197 +++-- components/file_system/src/lib.rs | 31 + components/server/src/lib.rs | 1 + components/server/src/server.rs | 9 +- components/server/src/server2.rs | 8 +- components/server/src/utils.rs | 19 + components/sst_importer/Cargo.toml | 3 + components/sst_importer/src/service.rs | 31 - components/sst_importer/src/sst_importer.rs | 698 ++++++++++++--- src/import/sst_service.rs | 15 +- 36 files changed, 2474 insertions(+), 568 deletions(-) create mode 100644 components/encryption/src/backup/backup_encryption.rs create mode 100644 components/encryption/src/backup/mod.rs create mode 100644 components/encryption/src/test_utils.rs create mode 100644 components/server/src/utils.rs delete mode 100644 components/sst_importer/src/service.rs diff --git a/Cargo.lock b/Cargo.lock index c90df74def1..7c991802f94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.3.14" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "futures-core", "futures-io", @@ -486,6 +486,7 @@ dependencies = [ "crossbeam-channel", "dashmap", "encryption", + "encryption_export", "engine_panic", "engine_rocks", "engine_test", @@ -1488,6 +1489,7 @@ dependencies = [ "openssl", "prometheus", "protobuf", + "rand 0.8.5", "serde", "serde_derive", "slog", @@ -5579,10 +5581,12 @@ name = "sst_importer" version = "0.1.0" dependencies = [ "api_version", + "async-compression", "collections", "crc32fast", "dashmap", "encryption", + "encryption_export", "engine_rocks", "engine_test", "engine_traits", @@ -5612,6 +5616,7 @@ dependencies = [ "tikv_alloc", "tikv_util", "tokio", + "tokio-util", "txn_types", "uuid 0.8.2", ] @@ -7769,29 +7774,28 @@ dependencies = [ [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ - "libc 0.2.151", "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", - "libc 0.2.151", + "pkg-config", ] diff --git a/components/backup-stream/Cargo.toml b/components/backup-stream/Cargo.toml index 3aa319db92e..025fcb36f04 100644 --- a/components/backup-stream/Cargo.toml +++ b/components/backup-stream/Cargo.toml @@ -26,7 +26,7 @@ test = true harness = true [dependencies] -async-compression = { version = "0.3.14", features = ["tokio", "zstd"] } +async-compression = { version = "0.4.12", features = ["tokio", "zstd"] } async-trait = { version = "0.1" } bytes = "1" chrono = { workspace = true } @@ -35,6 +35,7 @@ crossbeam = { workspace = true } crossbeam-channel = { workspace = true } dashmap = "5" encryption = { workspace = true } +encryption_export = { workspace = true } engine_rocks = { workspace = true } engine_traits = { workspace = true } error_code = { workspace = true } diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index a40fb06c71c..67742ab58c5 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -10,7 +10,7 @@ use std::{ }; use concurrency_manager::ConcurrencyManager; -use encryption::DataKeyManager; +use encryption::BackupEncryptionManager; use engine_traits::KvEngine; use error_code::ErrorCodeExt; use futures::{stream::AbortHandle, FutureExt, TryFutureExt}; @@ -91,8 +91,6 @@ pub struct Endpoint { pool: Runtime, region_operator: Sender, failover_time: Option, - // We holds the config before, even it is useless for now, - // however probably it would be useful in the future. config: BackupStreamConfig, pub checkpoint_mgr: CheckpointManager, @@ -123,16 +121,15 @@ where pd_client: Arc, concurrency_manager: ConcurrencyManager, resolver: BackupStreamResolver, - data_key_manager: Option>, + backup_encryption_manager: BackupEncryptionManager, ) -> Self { crate::metrics::STREAM_ENABLED.inc(); let pool = create_tokio_runtime((config.num_threads / 2).max(1), "backup-stream") .expect("failed to create tokio runtime for backup stream worker."); let meta_client = MetadataClient::new(store, store_id); - let mut conf = router::Config::from(config.clone()); - conf.data_key_manager = data_key_manager; - let range_router = Router::new(scheduler.clone(), conf); + let conf = router::Config::from(config.clone()); + let range_router = Router::new(scheduler.clone(), conf, backup_encryption_manager.clone()); // spawn a worker to watch task changes from etcd periodically. let meta_client_clone = meta_client.clone(); diff --git a/components/backup-stream/src/router.rs b/components/backup-stream/src/router.rs index fbdd3158057..55e693c2b89 100644 --- a/components/backup-stream/src/router.rs +++ b/components/backup-stream/src/router.rs @@ -14,15 +14,18 @@ use std::{ }; use dashmap::DashMap; -use encryption::DataKeyManager; +use encryption::{BackupEncryptionManager, EncrypterReader, Iv, MultiMasterKeyBackend}; +use encryption_export::create_async_backend; use engine_traits::{CfName, CF_DEFAULT, CF_LOCK, CF_WRITE}; use external_storage::{create_storage, BackendConfig, ExternalStorage, UnpinReader}; +use file_system::Sha256Reader; use futures::io::Cursor; use kvproto::{ brpb::{ CompressionType, DataFileGroup, DataFileInfo, FileType, MetaVersion, Metadata, - StreamBackupTaskInfo, + StreamBackupTaskInfo, StreamBackupTaskSecurityConfig_oneof_encryption, }, + encryptionpb::{EncryptionMethod, FileEncryptionInfo, MasterKeyBased, PlainTextDataKey}, raft_cmdpb::CmdType, }; use openssl::hash::{Hasher, MessageDigest}; @@ -45,7 +48,7 @@ use tokio::{ io::AsyncWriteExt, sync::{Mutex, RwLock}, }; -use tokio_util::compat::TokioAsyncReadCompatExt; +use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use tracing::instrument; use tracing_active_tree::frame; use txn_types::{Key, Lock, TimeStamp, WriteRef}; @@ -58,7 +61,7 @@ use crate::{ metadata::StreamTask, metrics::{HANDLE_KV_HISTOGRAM, SKIP_KV_COUNTER}, subscription_track::TwoPhaseResolver, - tempfiles::{self, TempFilePool}, + tempfiles::{self, ForRead, TempFilePool}, try_send, utils::{self, CompressionWriter, FilesReader, SegmentMap, SlotMap, StopWatch}, }; @@ -133,7 +136,7 @@ impl<'a> TaskSelectorRef<'a> { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ApplyEvent { pub key: Vec, pub value: Vec, @@ -141,7 +144,7 @@ pub struct ApplyEvent { pub cmd_type: CmdType, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ApplyEvents { events: Vec, region_id: u64, @@ -327,7 +330,6 @@ pub struct Config { pub temp_file_size_limit: u64, pub temp_file_memory_quota: u64, pub max_flush_interval: Duration, - pub data_key_manager: Option>, } impl From for Config { @@ -341,15 +343,22 @@ impl From for Config { temp_file_size_limit, temp_file_memory_quota, max_flush_interval, - data_key_manager: None, } } } impl Router { /// Create a new router with the temporary folder. - pub fn new(scheduler: Scheduler, config: Config) -> Self { - Self(Arc::new(RouterInner::new(scheduler, config))) + pub fn new( + scheduler: Scheduler, + config: Config, + backup_encryption_manager: BackupEncryptionManager, + ) -> Self { + Self(Arc::new(RouterInner::new( + scheduler, + config, + backup_encryption_manager, + ))) } } @@ -388,7 +397,9 @@ pub struct RouterInner { temp_file_memory_quota: AtomicU64, /// The max duration the local data can be pending. max_flush_interval: SyncRwLock, - data_key_manager: Option>, + + /// Backup encryption manager + backup_encryption_manager: BackupEncryptionManager, } impl std::fmt::Debug for RouterInner { @@ -402,7 +413,11 @@ impl std::fmt::Debug for RouterInner { } impl RouterInner { - pub fn new(scheduler: Scheduler, config: Config) -> Self { + pub fn new( + scheduler: Scheduler, + config: Config, + backup_encryption_manager: BackupEncryptionManager, + ) -> Self { RouterInner { ranges: SyncRwLock::new(SegmentMap::default()), tasks: DashMap::new(), @@ -411,7 +426,7 @@ impl RouterInner { temp_file_size_limit: AtomicU64::new(config.temp_file_size_limit), temp_file_memory_quota: AtomicU64::new(config.temp_file_memory_quota), max_flush_interval: SyncRwLock::new(config.max_flush_interval), - data_key_manager: config.data_key_manager, + backup_encryption_manager, } } @@ -480,13 +495,19 @@ impl RouterInner { merged_file_size_limit: u64, ) -> Result<()> { let task_name = task.info.get_name().to_owned(); - // register task info let cfg = self.tempfile_config_for_task(&task); - let stream_task_handler = - StreamTaskHandler::new(task, ranges.clone(), merged_file_size_limit, cfg).await?; - self.tasks - .insert(task_name.clone(), Arc::new(stream_task_handler)); + let backup_encryption_manager = + self.build_backup_encryption_manager_for_task(&task).await?; + let stream_task = StreamTaskHandler::new( + task, + ranges.clone(), + merged_file_size_limit, + cfg, + backup_encryption_manager, + ) + .await?; + self.tasks.insert(task_name.clone(), Arc::new(stream_task)); // register ranges self.register_ranges(&task_name, ranges); @@ -494,6 +515,67 @@ impl RouterInner { Ok(()) } + async fn build_backup_encryption_manager_for_task( + &self, + task: &StreamTask, + ) -> Result { + if let Some(config) = task.info.security_config.as_ref() { + if let Some(encryption) = config.encryption.as_ref() { + match encryption { + StreamBackupTaskSecurityConfig_oneof_encryption::PlaintextDataKey(key) => { + // sanity check key is valid + let opt_key = if !key.cipher_key.is_empty() + && (key.cipher_type != EncryptionMethod::Plaintext + && key.cipher_type != EncryptionMethod::Unknown) + { + Some(key.clone()) + } else { + None + }; + Ok(BackupEncryptionManager::new( + opt_key, + self.backup_encryption_manager + .master_key_based_file_encryption_method, + self.backup_encryption_manager + .multi_master_key_backend + .clone(), + self.backup_encryption_manager.tikv_data_key_manager.clone(), + )) + } + StreamBackupTaskSecurityConfig_oneof_encryption::MasterKeyConfig(config) => { + let multi_master_key_backend = if !config.master_keys.is_empty() { + let multi_master_key_backend = MultiMasterKeyBackend::new(); + multi_master_key_backend + .update_from_proto_if_needed( + config.master_keys.to_vec(), + create_async_backend, + ) + .await?; + multi_master_key_backend + } else { + error!( + "receive master key config but does not find master key inside, fall back to default" + ); + self.backup_encryption_manager + .multi_master_key_backend + .clone() + }; + Ok(BackupEncryptionManager::new( + None, + config.encryption_type, + multi_master_key_backend, + self.backup_encryption_manager.tikv_data_key_manager.clone(), + )) + } + } + } else { + Ok(self.backup_encryption_manager.clone()) + } + } else { + Ok(self.backup_encryption_manager.clone()) + } + } + fn tempfile_config_for_task(&self, task: &StreamTask) -> tempfiles::Config { // Note: the scope of this config is per-task. That means, when there are // multi tasks, we may need to share the pool over tasks, or at least share the @@ -507,7 +589,6 @@ impl RouterInner { content_compression: task.info.get_compression_type(), minimal_swap_out_file_size: ReadableSize::mb(1).0 as _, write_buffer_size: ReadableSize::kb(4).0 as _, - encryption: self.data_key_manager.clone(), } } @@ -834,6 +915,9 @@ pub struct StreamTaskHandler { pub(crate) storage: Arc, /// The listening range of the task. ranges: Vec<(Vec, Vec)>, + // Note: acquiring locks on files, flushing_files, flushing_meta_files at the same time might + // introduce deadlocks if ordering is not carefully maintained. Better think of another way + // to make it risk-free. /// The temporary file index. Both meta (m prefixed keys) and data (t /// prefixed keys). files: SlotMap, @@ -862,6 +946,9 @@ pub struct StreamTaskHandler { merged_file_size_limit: u64, /// The pool for holding the temporary files. temp_file_pool: Arc, + /// encryption manager to encrypt backup files uploaded + /// to external storage and local temp files. + backup_encryption_manager: BackupEncryptionManager, } impl Drop for StreamTaskHandler { @@ -904,6 +991,7 @@ impl StreamTaskHandler { ranges: Vec<(Vec, Vec)>, merged_file_size_limit: u64, temp_pool_cfg: tempfiles::Config, + backup_encryption_manager: BackupEncryptionManager, ) -> Result { let temp_dir = &temp_pool_cfg.swap_files; tokio::fs::create_dir_all(temp_dir).await?; @@ -926,7 +1014,40 @@ impl StreamTaskHandler { flush_fail_count: AtomicUsize::new(0), global_checkpoint_ts: AtomicU64::new(start_ts), merged_file_size_limit, - temp_file_pool: Arc::new(TempFilePool::new(temp_pool_cfg)?), + temp_file_pool: Arc::new(TempFilePool::new( + temp_pool_cfg, + backup_encryption_manager.clone(), + )?), + backup_encryption_manager, + }) + } + + #[cfg(test)] + pub fn new_test_only( + task: StreamTask, + ranges: Vec<(Vec, Vec)>, + merged_file_size_limit: u64, + external_storage: Arc, + pool: Arc, + backup_encryption_manager: BackupEncryptionManager, + ) -> Result { + let start_ts = task.info.get_start_ts(); + Ok(Self { + task, + storage: external_storage, + ranges, + min_resolved_ts: TimeStamp::max(), + files: SlotMap::default(), + flushing_files: RwLock::default(), + flushing_meta_files: RwLock::default(), + last_flush_time: AtomicPtr::new(Box::into_raw(Box::new(Instant::now()))), + total_size: AtomicUsize::new(0), + flushing: AtomicBool::new(false), + flush_fail_count: AtomicUsize::new(0), + global_checkpoint_ts: AtomicU64::new(start_ts), + merged_file_size_limit, + temp_file_pool: pool, + backup_encryption_manager, }) } @@ -992,7 +1113,7 @@ impl StreamTaskHandler { /// Flush all template files and generate corresponding metadata. #[instrument(skip_all)] - pub async fn generate_metadata(&self, store_id: u64) -> Result { + pub async fn generate_backup_metadata(&self, store_id: u64) -> Result { let mut w = self.flushing_files.write().await; let mut wm = self.flushing_meta_files.write().await; // Let's flush all files first... @@ -1094,11 +1215,10 @@ impl StreamTaskHandler { #[instrument(skip_all)] async fn merge_and_flush_log_files_to( - storage: Arc, + &self, files: &mut [(TempFileKey, DataFile, DataFileInfo)], metadata: &mut MetadataInfo, is_meta: bool, - shared_pool: Arc, ) -> Result<()> { let mut data_files_open = Vec::new(); let mut data_file_infos = Vec::new(); @@ -1113,16 +1233,19 @@ impl StreamTaskHandler { // and push it into merged_file_info(DataFileGroup). file_info_clone.set_range_offset(stat_length); data_files_open.push({ - let file = shared_pool + // the file content is compressed. + let file_reader = self + .temp_file_pool .open_raw_for_read(data_file.inner.path()) .context(format_args!( "failed to open read file {:?}", data_file.inner.path() ))?; - let compress_length = file.len().await?; + let compress_length = file_reader.len().await?; stat_length += compress_length; file_info_clone.set_range_length(compress_length); - file + + file_reader }); data_file_infos.push(file_info_clone); @@ -1144,16 +1267,17 @@ impl StreamTaskHandler { merged_file_info.set_max_ts(max_ts); merged_file_info.set_min_ts(min_ts); merged_file_info.set_min_resolved_ts(min_resolved_ts.unwrap_or_default()); + let (unpin_reader, file_encryption_info_vec, hasher_vec) = self + .build_unpin_reader_with_encryption_if_needed(data_files_open) + .await?; - // to do: limiter to storage - let limiter = Limiter::builder(std::f64::INFINITY).build(); - - let files_reader = FilesReader::new(data_files_open); - - let reader = UnpinReader(Box::new(limiter.limit(files_reader.compat()))); let filepath = &merged_file_info.path; - let ret = storage.write(filepath, reader, stat_length).await; + // flush to external storage + let ret = self + .storage + .write(filepath, unpin_reader, stat_length) + .await; match ret { Ok(_) => { @@ -1172,43 +1296,46 @@ impl StreamTaskHandler { } } + // update data file metadata with encryption info and calculated file checksum + self.update_data_file_metadata( + &mut merged_file_info, + hasher_vec, + file_encryption_info_vec, + )?; + // push merged file into metadata metadata.push(merged_file_info); Ok(()) } #[instrument(skip_all)] - pub async fn flush_log(&self, metadata: &mut MetadataInfo) -> Result<()> { - let storage = self.storage.clone(); - self.merge_log(metadata, storage.clone(), &self.flushing_files, false) + pub async fn flush_log(&self, backup_metadata: &mut MetadataInfo) -> Result<()> { + self.merge_and_flush_log(backup_metadata, &self.flushing_files, false) .await?; - self.merge_log(metadata, storage.clone(), &self.flushing_meta_files, true) + self.merge_and_flush_log(backup_metadata, &self.flushing_meta_files, true) .await?; Ok(()) } #[instrument(skip_all)] - async fn merge_log( + async fn merge_and_flush_log( &self, metadata: &mut MetadataInfo, - storage: Arc, - files_lock: &RwLock>, - is_meta: bool, + files: &RwLock>, + is_tikv_meta_file: bool, ) -> Result<()> { - let mut files = files_lock.write().await; + let mut files_guard = files.write().await; let mut batch_size = 0; // file[batch_begin_index, i) is a batch let mut batch_begin_index = 0; // TODO: upload the merged file concurrently, // then collect merged_file_infos and push them into `metadata`. - for i in 0..files.len() { + for i in 0..files_guard.len() { if batch_size >= self.merged_file_size_limit { - Self::merge_and_flush_log_files_to( - storage.clone(), - &mut files[batch_begin_index..i], + self.merge_and_flush_log_files_to( + &mut files_guard[batch_begin_index..i], metadata, - is_meta, - self.temp_file_pool.clone(), + is_tikv_meta_file, ) .await?; @@ -1216,15 +1343,13 @@ impl StreamTaskHandler { batch_size = 0; } - batch_size += files[i].2.length; + batch_size += files_guard[i].2.length; } - if batch_begin_index < files.len() { - Self::merge_and_flush_log_files_to( - storage.clone(), - &mut files[batch_begin_index..], + if batch_begin_index < files_guard.len() { + self.merge_and_flush_log_files_to( + &mut files_guard[batch_begin_index..], metadata, - is_meta, - self.temp_file_pool.clone(), + is_tikv_meta_file, ) .await?; } @@ -1233,7 +1358,7 @@ impl StreamTaskHandler { } #[instrument(skip_all)] - pub async fn flush_meta(&self, metadata_info: MetadataInfo) -> Result<()> { + pub async fn flush_backup_metadata(&self, metadata_info: MetadataInfo) -> Result<()> { if !metadata_info.file_groups.is_empty() { let meta_path = metadata_info.path_to_meta(); let meta_buff = metadata_info.marshal_to()?; @@ -1275,11 +1400,11 @@ impl StreamTaskHandler { let begin = Instant::now_coarse(); let mut sw = StopWatch::by_now(); - // generate meta data and prepare to flush to storage - let mut metadata_info = self + // generate backup meta data and prepare to flush to storage + let mut backup_metadata = self .move_to_flushing_files() .await? - .generate_metadata(store_id) + .generate_backup_metadata(store_id) .await?; fail::fail_point!("after_moving_to_flushing_files"); @@ -1288,22 +1413,23 @@ impl StreamTaskHandler { .observe(sw.lap().as_secs_f64()); // flush log file to storage. - self.flush_log(&mut metadata_info).await?; + self.flush_log(&mut backup_metadata).await?; // the field `min_resolved_ts` of metadata will be updated // only after flush is done. - metadata_info.min_resolved_ts = metadata_info + backup_metadata.min_resolved_ts = backup_metadata .min_resolved_ts .max(Some(resolved_ts_provided.into_inner())); - let rts = metadata_info.min_resolved_ts; + let rts = backup_metadata.min_resolved_ts; // compress length - let file_size_vec = metadata_info + let file_size_vec = backup_metadata .file_groups .iter() .map(|d| (d.length, d.data_files_info.len())) .collect::>(); - // flush meta file to storage. - self.flush_meta(metadata_info).await?; + + // flush backup metadata to external storage. + self.flush_backup_metadata(backup_metadata).await?; crate::metrics::FLUSH_DURATION .with_label_values(&["save_files"]) .observe(sw.lap().as_secs_f64()); @@ -1372,6 +1498,169 @@ impl StreamTaskHandler { } Ok(false) } + + async fn build_unpin_reader_with_encryption_if_needed( + &self, + mut data_file_readers: Vec, + ) -> Result<( + UnpinReader, + Vec, + Vec>>, + )> { + // to do: limiter to storage + let limiter = Limiter::builder(f64::INFINITY).build(); + + // prioritize plaintext key passed from the user, it will override the default + // master key config if there is any + // + if let Some(cipher_info) = self.backup_encryption_manager.plaintext_data_key.as_ref() { + let mut encrypted_hashing_readers = Vec::new(); + let mut hasher_vec = Vec::new(); + let mut encryption_info_vec = Vec::new(); + + let data_key = &cipher_info.cipher_key; + for data_file_reader in data_file_readers.drain(..) { + let file_iv = Iv::new_ctr().map_err(|e| { + Error::Other(box_err!( + "failed to create IV for plaintext data key: {:?}", + e + )) + })?; + let encrypter_reader = EncrypterReader::new( + data_file_reader.compat(), + cipher_info.cipher_type, + &data_key[..], + file_iv, + ) + .map_err(|e| { + Error::Other(box_err!( + "failed to create encrypted reader for plaintext data key: {:?}", + e + )) + })?; + let (sha256_reader, hasher) = Sha256Reader::new(encrypter_reader.compat()) + .map_err(|e| { + Error::Other(box_err!( + "failed to create sha256 reader for plaintext data key: {:?}", + e + )) + })?; + + let mut encryption_info = FileEncryptionInfo::new(); + encryption_info.set_file_iv(file_iv.as_slice().to_vec()); + encryption_info.set_encryption_method(cipher_info.cipher_type); + encryption_info.set_plain_text_data_key(PlainTextDataKey::new()); + + encryption_info_vec.push(encryption_info); + hasher_vec.push(hasher); + encrypted_hashing_readers.push(sha256_reader); + } + + let files_reader = FilesReader::new(encrypted_hashing_readers); + let unpin_reader = UnpinReader(Box::new(limiter.limit(files_reader.compat()))); + Ok((unpin_reader, encryption_info_vec, hasher_vec)) + } else if self + .backup_encryption_manager + .is_master_key_backend_initialized() + .await + { + let mut encrypted_hashing_readers = Vec::new(); + let mut hasher_vec = Vec::new(); + let mut encryption_info_vec = Vec::new(); + + let data_key = self + .backup_encryption_manager + .generate_data_key() + .map_err(|e| Error::Other(box_err!("failed to generate data key: {:?}", e)))?; + + let encrypted_data_key = self + .backup_encryption_manager + .encrypt_data_key(&data_key) + .await + .map_err(|e| Error::Other(box_err!("failed to encrypt data key: {:?}", e)))?; + + // iterate data files readers and wrap with encryption + hashing + // + for data_file_reader in data_file_readers.drain(..) { + let file_iv = Iv::new_ctr().map_err(|e| { + Error::Other(box_err!( + "failed to create IV for master key based data key: {:?}", + e + )) + })?; + let encrypter_reader = EncrypterReader::new( + data_file_reader.compat(), + self.backup_encryption_manager + .master_key_based_file_encryption_method, + &data_key, + file_iv, + ) + .map_err(|e| { + Error::Other(box_err!( + "failed to create encrypted reader for master key based data key: {:?}", + e + )) + })?; + let (sha256_reader, hasher) = Sha256Reader::new(encrypter_reader.compat()) + .map_err(|e| { + Error::Other(box_err!( + "failed to create sha256 reader for master key based data key: {:?}", + e + )) + })?; + + let mut master_key_based_info = MasterKeyBased::new(); + master_key_based_info + .set_data_key_encrypted_content(vec![encrypted_data_key.clone()].into()); + + let mut encryption_info = FileEncryptionInfo::new(); + encryption_info.set_master_key_based(master_key_based_info); + encryption_info.set_file_iv(file_iv.as_slice().to_vec()); + encryption_info.set_encryption_method( + self.backup_encryption_manager + .master_key_based_file_encryption_method, + ); + + encryption_info_vec.push(encryption_info); + hasher_vec.push(hasher); + encrypted_hashing_readers.push(sha256_reader); + } + + let files_reader = FilesReader::new(encrypted_hashing_readers); + let unpin_reader = UnpinReader(Box::new(limiter.limit(files_reader.compat()))); + Ok((unpin_reader, encryption_info_vec, hasher_vec)) + } else { + // no encryption + let files_reader = FilesReader::new(data_file_readers); + let unpin_reader = UnpinReader(Box::new(limiter.limit(files_reader.compat()))); + Ok((unpin_reader, vec![], vec![])) + } + } + + fn update_data_file_metadata( + &self, + data_file_meta: &mut DataFileGroup, + hasher_vec: Vec>>, + encryption_info_vec: Vec, + ) -> Result<()> { + // Iterate over the vectors and update the data_file_meta + for ((meta, hasher), mut encryption_info) in data_file_meta + .data_files_info + .iter_mut() + .zip(hasher_vec.into_iter()) + .zip(encryption_info_vec.into_iter()) + { + let checksum = hasher + .lock() + .unwrap() + .finish() + .map(|digest| digest.to_vec()) + .map_err(|e| Error::Other(box_err!("calculate checksum error: {:?}", e)))?; + encryption_info.set_checksum(checksum); + meta.set_file_encryption_info(encryption_info); + } + Ok(()) + } } /// A opened log file with some metadata. @@ -1380,6 +1669,7 @@ struct DataFile { max_ts: TimeStamp, resolved_ts: TimeStamp, min_begin_ts: Option, + // checksum of plaintext kv file , calculated before compression sha256: Hasher, // TODO: use lz4 with async feature inner: tempfiles::ForWrite, @@ -1584,6 +1874,7 @@ impl std::fmt::Debug for DataFile { .field("min_ts", &self.min_ts) .field("max_ts", &self.max_ts) .field("resolved_ts", &self.resolved_ts) + .field("file_size", &self.file_size) .finish() } } @@ -1600,18 +1891,28 @@ struct TaskRange { #[cfg(test)] mod tests { - use std::{ffi::OsStr, io, time::Duration}; + use std::{ffi::OsStr, io, io::Cursor, time::Duration}; + use async_compression::tokio::bufread::ZstdDecoder; + use encryption::{DecrypterReader, FileConfig, MasterKeyConfig, MultiMasterKeyBackend}; use external_storage::{ExternalData, NoopStorage}; use futures::AsyncReadExt; - use kvproto::brpb::{Local, Noop, StorageBackend, StreamBackupTaskInfo}; + use kvproto::{ + brpb::{CipherInfo, Noop, StorageBackend, StreamBackupTaskInfo}, + encryptionpb::EncryptionMethod, + }; use online_config::{ConfigManager, OnlineConfig}; + use rand::Rng; use tempfile::TempDir; use tikv_util::{ - codec::number::NumberEncoder, + codec::{ + number::NumberEncoder, + stream_event::{EventIterator, Iterator}, + }, config::ReadableDuration, worker::{dummy_scheduler, ReceiverWrapper}, }; + use tokio::{fs::File, io::BufReader}; use txn_types::{Write, WriteType}; use super::*; @@ -1629,7 +1930,6 @@ mod tests { content_compression: CompressionType::Zstd, minimal_swap_out_file_size: 0, write_buffer_size: 0, - encryption: None, } } @@ -1727,8 +2027,8 @@ mod tests { temp_file_size_limit: 1024, temp_file_memory_quota: 1024 * 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), ); // -----t1.start-----t1.end-----t2.start-----t2.end------ // --|------------|----------|------------|-----------|-- @@ -1753,15 +2053,6 @@ mod tests { result } - fn create_local_storage_backend(path: String) -> StorageBackend { - let mut local = Local::default(); - local.set_path(path); - - let mut sb = StorageBackend::default(); - sb.set_local(local); - sb - } - fn create_noop_storage_backend() -> StorageBackend { let nop = Noop::new(); let mut backend = StorageBackend::default(); @@ -1774,10 +2065,7 @@ mod tests { stream_task.set_name(name); let storage_path = std::env::temp_dir().join(format!("{}", uuid::Uuid::new_v4())); tokio::fs::create_dir_all(&storage_path).await?; - println!("storage={:?}", storage_path); - stream_task.set_storage(create_local_storage_backend( - storage_path.to_str().unwrap().to_string(), - )); + stream_task.set_storage(external_storage::make_local_backend(storage_path.as_path())); Ok((stream_task, storage_path)) } @@ -1838,8 +2126,8 @@ mod tests { temp_file_size_limit: 32, temp_file_memory_quota: 32 * 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), ); let (stream_task, storage_path) = task("dummy".to_owned()).await.unwrap(); must_register_table(&router, stream_task, 1).await; @@ -1848,12 +2136,12 @@ mod tests { tokio::time::sleep(Duration::from_millis(200)).await; let end_ts = TimeStamp::physical_now(); - let files = router.tasks.get("dummy").unwrap().clone(); - let mut meta = files + let task_handler = router.tasks.get("dummy").unwrap().clone(); + let mut meta = task_handler .move_to_flushing_files() .await .unwrap() - .generate_metadata(1) + .generate_backup_metadata(1) .await .unwrap(); @@ -1873,16 +2161,16 @@ mod tests { // in some case when flush failed to write files to storage. // we may run `generate_metadata` again with same files. - let mut another_meta = files + let mut another_meta = task_handler .move_to_flushing_files() .await .unwrap() - .generate_metadata(1) + .generate_backup_metadata(1) .await .unwrap(); - files.flush_log(&mut meta).await.unwrap(); - files.flush_log(&mut another_meta).await.unwrap(); + task_handler.flush_log(&mut meta).await.unwrap(); + task_handler.flush_log(&mut another_meta).await.unwrap(); // meta updated let files_num = meta .file_groups @@ -1903,8 +2191,8 @@ mod tests { } } - files.flush_meta(meta).await.unwrap(); - files.clear_flushing_files().await; + task_handler.flush_backup_metadata(meta).await.unwrap(); + task_handler.clear_flushing_files().await; drop(router); let cmds = collect_recv(rx); @@ -1919,7 +2207,6 @@ mod tests { for entry in walkdir::WalkDir::new(storage_path) { let entry = entry.unwrap(); let filename = entry.file_name(); - println!("walking {}", entry.path().display()); if entry.path().extension() == Some(OsStr::new("meta")) { meta_count += 1; } else if entry.path().extension() == Some(OsStr::new("log")) { @@ -1966,6 +2253,7 @@ mod tests { vec![(vec![], vec![])], merged_file_size_limit, make_tempfiles_cfg(tmp_dir.path()), + BackupEncryptionManager::default(), ) .await .unwrap(); @@ -1984,18 +2272,7 @@ mod tests { assert_eq!(task_handler.flushing_files.read().await.is_empty(), true); // assert backup log files - let mut meta_count = 0; - let mut log_count = 0; - for entry in walkdir::WalkDir::new(tmp_dir.path()) { - let entry = entry.unwrap(); - if entry.path().extension() == Some(OsStr::new("meta")) { - meta_count += 1; - } else if entry.path().extension() == Some(OsStr::new("log")) { - log_count += 1; - } - } - assert_eq!(meta_count, 1); - assert_eq!(log_count, 2); + verify_on_disk_file(tmp_dir.path(), 2, 1); } struct ErrorStorage { @@ -2088,8 +2365,8 @@ mod tests { temp_file_size_limit: 1, temp_file_memory_quota: 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), )); let (task, _path) = task("error_prone".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; @@ -2125,8 +2402,8 @@ mod tests { temp_file_size_limit: 32, temp_file_memory_quota: 32 * 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), ); let mut stream_task = StreamBackupTaskInfo::default(); stream_task.set_name("nothing".to_string()); @@ -2161,8 +2438,8 @@ mod tests { temp_file_size_limit: 1, temp_file_memory_quota: 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), )); let (task, _path) = task("cleanup_test".to_owned()).await?; must_register_table(&router, task, 1).await; @@ -2216,8 +2493,8 @@ mod tests { temp_file_size_limit: 1, temp_file_memory_quota: 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), )); let (task, _path) = task("flush_failure".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; @@ -2337,7 +2614,7 @@ mod tests { // create local storage let tmp_dir = tempfile::tempdir().unwrap(); let backend = external_storage::make_local_backend(tmp_dir.path()); - + let backup_encryption_manager = BackupEncryptionManager::default(); // build a StreamTaskInfo let mut task_info = StreamBackupTaskInfo::default(); task_info.set_storage(backend); @@ -2350,6 +2627,7 @@ mod tests { vec![(vec![], vec![])], 0x100000, make_tempfiles_cfg(tmp_dir.path()), + backup_encryption_manager, ) .await .unwrap(); @@ -2395,7 +2673,7 @@ mod tests { } struct MockCheckContentStorage { - s: NoopStorage, + s: Box, } #[async_trait::async_trait] @@ -2428,11 +2706,11 @@ mod tests { } } - fn read(&self, name: &str) -> external_storage::ExternalData<'_> { + fn read(&self, name: &str) -> ExternalData<'_> { self.s.read(name) } - fn read_part(&self, name: &str, off: u64, len: u64) -> external_storage::ExternalData<'_> { + fn read_part(&self, name: &str, off: u64, len: u64) -> ExternalData<'_> { self.s.read_part(name, off, len) } } @@ -2440,13 +2718,16 @@ mod tests { #[tokio::test] async fn test_est_len_in_flush() -> Result<()> { let noop_s = NoopStorage::default(); - let ms = MockCheckContentStorage { s: noop_s }; + let mock_external_storage = Arc::new(MockCheckContentStorage { + s: Box::new(noop_s), + }); let file_name = format!("{}", uuid::Uuid::new_v4()); let file_path = Path::new(&file_name); let tempfile = TempDir::new().unwrap(); let cfg = make_tempfiles_cfg(tempfile.path()); - let pool = Arc::new(TempFilePool::new(cfg).unwrap()); + let backup_encryption_manager = BackupEncryptionManager::default(); + let pool = Arc::new(TempFilePool::new(cfg, backup_encryption_manager.clone()).unwrap()); let mut f = pool.open_for_write(file_path).unwrap(); f.write_all(b"test-data").await?; f.done().await?; @@ -2458,14 +2739,24 @@ mod tests { let tmp_key = TempFileKey::of(&kv_event.events[0], 1); data_file.inner.done().await?; let mut files = vec![(tmp_key, data_file, info)]; - let result = StreamTaskHandler::merge_and_flush_log_files_to( - Arc::new(ms), - &mut files[0..], - &mut meta, - false, + + let stream_task = StreamTask { + info: StreamBackupTaskInfo::default(), + is_paused: false, + }; + let stream_task_handler = StreamTaskHandler::new_test_only( + stream_task, + vec![(vec![], vec![])], + 0x100000, + mock_external_storage, pool.clone(), + backup_encryption_manager, ) - .await; + .unwrap(); + + let result = stream_task_handler + .merge_and_flush_log_files_to(&mut files[0..], &mut meta, false) + .await; result.unwrap(); Ok(()) } @@ -2481,8 +2772,8 @@ mod tests { temp_file_size_limit: 1, temp_file_memory_quota: 2, max_flush_interval: cfg.max_flush_interval.0, - data_key_manager: None, }, + BackupEncryptionManager::default(), )); let mut cfg_manager = BackupStreamConfigManager::new(sched, cfg.clone()); @@ -2511,7 +2802,7 @@ mod tests { } #[test] - fn test_udpate_invalid_config() { + fn test_update_invalid_config() { let cfg = BackupStreamConfig::default(); let (sched, _) = dummy_scheduler(); let mut cfg_manager = BackupStreamConfigManager::new(sched, cfg.clone()); @@ -2538,8 +2829,8 @@ mod tests { temp_file_size_limit: 1000, temp_file_memory_quota: 2, max_flush_interval: Duration::from_secs(300), - data_key_manager: None, }, + BackupEncryptionManager::default(), )); let (task, _path) = task("race".to_owned()).await?; @@ -2611,4 +2902,271 @@ mod tests { assert_eq!(t.files.read().await.len(), 0,); Ok(()) } + + #[tokio::test] + async fn test_encryption_not_set() -> Result<()> { + test_encryption(BackupEncryptionManager::default()).await + } + + #[tokio::test] + async fn test_encryption_plaintext_data_key() -> Result<()> { + // set up plaintext data key + // + let data_key: [u8; 32] = rand::thread_rng().gen(); + let mut cipher = CipherInfo::new(); + cipher.set_cipher_key(data_key.to_vec()); + cipher.set_cipher_type(EncryptionMethod::Aes256Ctr); + + let multi_master_key_backends = MultiMasterKeyBackend::new(); + let backup_encryption_manager = BackupEncryptionManager::new( + Some(cipher), + EncryptionMethod::Aes256Ctr, + multi_master_key_backends, + None, + ); + + test_encryption(backup_encryption_manager).await + } + #[tokio::test] + async fn test_encryption_master_key_based() -> Result<()> { + // set up file backed master key + // + let hex_bytes = encryption::test_utils::generate_random_master_key(); + let (path, _dir) = encryption::test_utils::create_master_key_file_test_only(&hex_bytes); + let master_key_config = MasterKeyConfig::File { + config: FileConfig { + path: path.to_string_lossy().into_owned(), + }, + }; + let multi_master_key_backends = MultiMasterKeyBackend::new(); + multi_master_key_backends + .update_from_config_if_needed(vec![master_key_config], create_async_backend) + .await?; + + let backup_encryption_manager = BackupEncryptionManager::new( + None, + EncryptionMethod::Aes256Ctr, + multi_master_key_backends, + None, + ); + + test_encryption(backup_encryption_manager).await + } + + async fn test_encryption(backup_encryption_manager: BackupEncryptionManager) -> Result<()> { + // set up local file backend for external storage + // + let local_backend_file_path = tempfile::tempdir().unwrap(); + let backend = external_storage::make_local_backend(local_backend_file_path.path()); + let mut task_info = StreamBackupTaskInfo::default(); + task_info.set_storage(backend); + let stream_task = StreamTask { + info: task_info, + is_paused: false, + }; + let merged_file_size_limit = 0x10000000; + + // configure task handler with optional encryption + // + let task_handler = StreamTaskHandler::new( + stream_task, + vec![(vec![], vec![])], + merged_file_size_limit, + make_tempfiles_cfg(tempfile::tempdir().unwrap().path()), + backup_encryption_manager.clone(), + ) + .await + .unwrap(); + + // write some kv into the handler and flush it + // + let kv_events = build_kv_event(0, 1000000); + task_handler.on_events(kv_events.clone()).await?; + task_handler.set_flushing_status(true); + let start = Instant::now(); + task_handler.do_flush(1, TimeStamp::new(1)).await?; + let duration = start.saturating_elapsed(); + println!("Time taken for do_flush: {:?}", duration); + + // verify_on_disk_file(local_backend_file_path.path(), 1, 1); + + // read meta file first to figure out the data file offset + // + let meta_file_paths = meta_file_names(local_backend_file_path.path()); + assert_eq!(meta_file_paths.len(), 1); + + let meta_vec = read_and_parse_meta_files(meta_file_paths); + assert_eq!(meta_vec.len(), 1); + + let meta = meta_vec.first().unwrap(); + let file_group = meta.file_groups.first().unwrap(); + + // read log file and parse to kv pairs + // + let log_file_paths = log_file_names(local_backend_file_path.path()); + assert_eq!(log_file_paths.len(), 1); + + let mut read_out_kv_pairs = read_and_parse_log_file( + log_file_paths.first().unwrap(), + file_group, + backup_encryption_manager, + ) + .await; + + // check whether kv pair matches + // + let mut expected_kv_pairs = events_to_kv_pair(&kv_events); + read_out_kv_pairs.sort(); + expected_kv_pairs.sort(); + assert_eq!(read_out_kv_pairs, expected_kv_pairs); + Ok(()) + } + + fn verify_on_disk_file(path: &Path, num_log: i32, num_backup_meta: i32) { + let mut meta_count = 0; + let mut log_count = 0; + for entry in walkdir::WalkDir::new(path) { + let entry = entry.unwrap(); + + if entry.path().extension() == Some(OsStr::new("meta")) { + meta_count += 1; + } else if entry.path().extension() == Some(OsStr::new("log")) { + log_count += 1; + } + } + assert_eq!(meta_count, num_backup_meta); + assert_eq!(log_count, num_log); + } + + fn log_file_names(path: &Path) -> Vec { + let mut log_files = Vec::new(); + for entry in walkdir::WalkDir::new(path) { + let entry = entry.unwrap(); + if entry.path().extension() == Some(OsStr::new("log")) { + log_files.push(entry.path().to_path_buf()); + } + } + log_files + } + + fn meta_file_names(path: &Path) -> Vec { + let mut meta_files = Vec::new(); + for entry in walkdir::WalkDir::new(path) { + let entry = entry.unwrap(); + if entry.path().extension() == Some(OsStr::new("meta")) { + meta_files.push(entry.path().to_path_buf()); + } + } + meta_files + } + + fn read_and_parse_meta_files(paths: Vec) -> Vec { + let mut meta_vec = Vec::new(); + for path in paths { + let content = std::fs::read(path).unwrap(); + let metadata = protobuf::parse_from_bytes::(&content).unwrap(); + meta_vec.push(metadata); + } + meta_vec + } + + async fn read_and_parse_log_file( + path: &Path, + file_group_meta: &DataFileGroup, + backup_encryption_manager: BackupEncryptionManager, + ) -> Vec<(Vec, Vec)> { + use tokio::io::AsyncReadExt; + + let mut log_file_bytes = Vec::new(); + + // read out the entire disk + // + let mut bytes_buf = Vec::new(); + BufReader::new(File::open(path).await.unwrap()) + .read_to_end(&mut bytes_buf) + .await + .unwrap(); + // find each file length and read it and append to the result + // + assert!(!file_group_meta.get_data_files_info().is_empty()); + for file_info in file_group_meta.get_data_files_info() { + let slice = &bytes_buf[file_info.range_offset as usize + ..(file_info.range_offset + file_info.range_length) as usize]; + let mut file_buf = Vec::new(); + if let Some(cipher_info) = backup_encryption_manager.plaintext_data_key.as_ref() { + let iv = Iv::from_slice(&file_info.file_encryption_info.as_ref().unwrap().file_iv) + .unwrap(); + let mut decrypter = DecrypterReader::new( + BufReader::new(Cursor::new(slice)).compat(), + file_info + .file_encryption_info + .as_ref() + .unwrap() + .encryption_method, + &cipher_info.cipher_key, + iv, + ) + .unwrap(); + let mut decrypted_buf = Vec::new(); + decrypter.read_to_end(&mut decrypted_buf).await.unwrap(); + let mut decoder = ZstdDecoder::new(BufReader::new(Cursor::new(decrypted_buf))); + decoder.read_to_end(&mut file_buf).await.unwrap(); + } else if backup_encryption_manager + .is_master_key_backend_initialized() + .await + { + let iv = Iv::from_slice(&file_info.file_encryption_info.as_ref().unwrap().file_iv) + .unwrap(); + let cipher_data_key = file_info + .file_encryption_info + .as_ref() + .unwrap() + .get_master_key_based() + .data_key_encrypted_content + .first() + .unwrap(); + let plaintext_data_key = backup_encryption_manager + .decrypt_data_key(cipher_data_key) + .await + .unwrap(); + let mut decrypter = DecrypterReader::new( + BufReader::new(Cursor::new(slice)).compat(), + file_info + .file_encryption_info + .as_ref() + .unwrap() + .encryption_method, + &plaintext_data_key, + iv, + ) + .unwrap(); + let mut decrypted_buf = Vec::new(); + decrypter.read_to_end(&mut decrypted_buf).await.unwrap(); + let mut decoder = ZstdDecoder::new(BufReader::new(Cursor::new(decrypted_buf))); + decoder.read_to_end(&mut file_buf).await.unwrap(); + } else { + let mut decode_reader = ZstdDecoder::new(BufReader::new(Cursor::new(slice))); + decode_reader.read_to_end(&mut file_buf).await.unwrap(); + } + + // parse to kv pair + // + let mut event_iter = EventIterator::new(&file_buf); + while event_iter.valid() { + event_iter.next().unwrap(); + let key = event_iter.key(); + let val = event_iter.value(); + log_file_bytes.push((key.to_vec(), val.to_vec())) + } + } + log_file_bytes + } + + fn events_to_kv_pair(apply_events: &ApplyEvents) -> Vec<(Vec, Vec)> { + let mut kv_pairs = Vec::new(); + for apply_event in &apply_events.events { + kv_pairs.push((apply_event.key.clone(), apply_event.value.clone())); + } + kv_pairs + } } diff --git a/components/backup-stream/src/subscription_manager.rs b/components/backup-stream/src/subscription_manager.rs index 7e8d2c89de2..26838b6cd57 100644 --- a/components/backup-stream/src/subscription_manager.rs +++ b/components/backup-stream/src/subscription_manager.rs @@ -835,6 +835,7 @@ mod test { time::Duration, }; + use encryption::BackupEncryptionManager; use engine_test::{kv::KvTestEngine, raft::RaftTestEngine}; use kvproto::{ brpb::{Noop, StorageBackend, StreamBackupTaskInfo}, @@ -1037,7 +1038,11 @@ mod test { let subs = SubscriptionTracer::default(); let memory_manager = Arc::new(MemoryQuota::new(1024)); let (tx, mut rx) = tokio::sync::mpsc::channel(8); - let router = RouterInner::new(scheduler.clone(), BackupStreamConfig::default().into()); + let router = RouterInner::new( + scheduler.clone(), + BackupStreamConfig::default().into(), + BackupEncryptionManager::default(), + ); let mut task = StreamBackupTaskInfo::new(); task.set_name(task_name.to_owned()); task.set_storage({ diff --git a/components/backup-stream/src/tempfiles.rs b/components/backup-stream/src/tempfiles.rs index 21a07798cea..4e1e82676b6 100644 --- a/components/backup-stream/src/tempfiles.rs +++ b/components/backup-stream/src/tempfiles.rs @@ -28,7 +28,7 @@ use std::{ task::{ready, Context, Poll}, }; -use encryption::{DataKeyManager, DecrypterReader, EncrypterWriter, Iv}; +use encryption::{BackupEncryptionManager, DecrypterReader, EncrypterWriter, Iv}; use futures::{AsyncWriteExt, TryFutureExt}; use kvproto::{brpb::CompressionType, encryptionpb::EncryptionMethod}; use tikv_util::warn; @@ -64,9 +64,6 @@ pub struct Config { /// those content would be kept in memory before they reach a threshold. /// This would help us to reduce the I/O system calls. pub write_buffer_size: usize, - /// The encryption applied to swapped out files. - /// The in-memory content will be plaintext always. - pub encryption: Option>, } impl std::fmt::Debug for Config { @@ -80,10 +77,6 @@ impl std::fmt::Debug for Config { &self.minimal_swap_out_file_size, ) .field("write_buffer_size", &self.write_buffer_size) - .field( - "encryption", - &self.encryption.as_ref().map(|enc| enc.encryption_method()), - ) .finish() } } @@ -98,6 +91,7 @@ pub struct TempFilePool { cfg: Config, current: AtomicUsize, files: BlockMutex, + backup_encryption_manager: BackupEncryptionManager, #[cfg(test)] override_swapout: Option< @@ -201,10 +195,10 @@ struct FileSet { } impl TempFilePool { - pub fn new(cfg: Config) -> Result { + pub fn new(cfg: Config, backup_encryption_manager: BackupEncryptionManager) -> Result { if let Ok(true) = std::fs::metadata(&cfg.swap_files).map(|x| x.is_dir()) { warn!("find content in the swap file directory node. truncating them."; "dir" => %cfg.swap_files.display()); - if let Some(enc) = &cfg.encryption { + if let Some(enc) = backup_encryption_manager.opt_data_key_manager() { enc.remove_dir(&cfg.swap_files, None)?; } std::fs::remove_dir_all(&cfg.swap_files)?; @@ -215,6 +209,7 @@ impl TempFilePool { cfg, current: AtomicUsize::new(0usize), files: BlockMutex::default(), + backup_encryption_manager, #[cfg(test)] override_swapout: None, @@ -262,13 +257,14 @@ impl TempFilePool { } } - /// Open a file reference for reading. - /// Please notice that once a compression applied, this would yield the - /// compressed content (won't decompress them.) -- that is what "raw" - /// implies. - /// "But why there isn't a `open_for_read` which decompresses the content?" - /// "Because in our use case, we only need the raw content -- we just send - /// it to external storage." + /// Opens a file for reading in its raw format. + /// + /// This method returns the file content as-is, including any applied + /// compression. It does not perform decompression. + /// + /// Note: We don't provide an `open_for_read` method that decompresses the + /// content because our primary use case is to send the raw (potentially + /// compressed) data directly to external storage. pub fn open_raw_for_read(&self, p: &Path) -> Result { use std::io::{Error as IoErr, ErrorKind}; @@ -314,7 +310,7 @@ impl TempFilePool { } /// Remove a file from the pool. - /// If there are still some reference to the file, the deletion may be + /// If there is still some reference to the file, the deletion may be /// delayed until all reference to the file drop. pub fn remove(&self, p: &Path) -> bool { let mut files = self.files.lock().unwrap(); @@ -335,7 +331,7 @@ impl TempFilePool { } /// Create a file for writing. - /// This function is synchronous so we can call it easier in the polling + /// This function is synchronous, so we can call it easier in the polling /// context. (Anyway, it is really hard to call an async function in the /// polling context.) fn create_relative(&self, p: &Path) -> std::io::Result { @@ -346,7 +342,8 @@ impl TempFilePool { None => {} } let file = OsFile::from_std(SyncOsFile::create(&abs_path)?); - let pfile = match &self.cfg.encryption { + + let pfile = match &self.backup_encryption_manager.opt_data_key_manager() { Some(enc) => SwappedOut::Encrypted( enc.open_file_with_writer(&abs_path, file.compat(), true) .map_err(Self::convert_encrypt_error_to_io)? @@ -365,7 +362,7 @@ impl TempFilePool { let abs_path = self.cfg.swap_files.join(p); let file = SyncOsFile::open(&abs_path)?; let async_file = OsFile::from_std(file).compat(); - let decrypted_file = match &self.cfg.encryption { + let decrypted_file = match &self.backup_encryption_manager.opt_data_key_manager() { Some(enc) => enc .open_file_with_reader(&abs_path, async_file) .map_err(Self::convert_encrypt_error_to_io)? @@ -379,7 +376,7 @@ impl TempFilePool { fn delete_relative(&self, p: &Path) -> std::io::Result<()> { let abs_path = self.cfg.swap_files.join(p); - if let Some(enc) = &self.cfg.encryption { + if let Some(enc) = &self.backup_encryption_manager.opt_data_key_manager() { enc.delete_file(&abs_path.to_string_lossy(), None)?; } std::fs::remove_file(&abs_path)?; @@ -791,7 +788,7 @@ mod test { }; use async_compression::tokio::bufread::ZstdDecoder; - use encryption::DataKeyManager; + use encryption::{BackupEncryptionManager, DataKeyManager, MultiMasterKeyBackend}; use kvproto::{brpb::CompressionType, encryptionpb::EncryptionMethod}; use tempfile::{tempdir, TempDir}; use test_util::new_test_key_manager; @@ -831,12 +828,11 @@ mod test { content_compression: CompressionType::Unknown, minimal_swap_out_file_size: 8192, write_buffer_size: 4096, - encryption: None, }; m(&mut cfg); TestPool { tmpdir: Arc::new(tmp), - pool: Arc::new(TempFilePool::new(cfg).unwrap()), + pool: Arc::new(TempFilePool::new(cfg, BackupEncryptionManager::default()).unwrap()), } } @@ -1122,12 +1118,30 @@ mod test { fn test_encryption(enc: DataKeyManager) { let method = enc.encryption_method(); - let pool = test_pool_with_modify(|cfg| { - cfg.encryption = Some(Arc::new(enc)); - cfg.minimal_swap_out_file_size = 15; - cfg.write_buffer_size = 15; - cfg.cache_size = AtomicUsize::new(15); - }); + let tmp = tempdir().unwrap(); + let cfg = Config { + cache_size: AtomicUsize::new(15), + swap_files: tmp.path().to_owned(), + content_compression: CompressionType::Unknown, + minimal_swap_out_file_size: 15, + write_buffer_size: 15, + }; + let pool = TestPool { + tmpdir: Arc::new(tmp), + pool: Arc::new( + TempFilePool::new( + cfg, + BackupEncryptionManager::new( + None, + EncryptionMethod::Plaintext, + MultiMasterKeyBackend::default(), + Some(Arc::new(enc)), + ), + ) + .unwrap(), + ), + }; + let rt = rt_for_test(); let content_to_write: [&[u8]; 4] = [ b"Now let's test the encryption.", diff --git a/components/backup-stream/tests/suite.rs b/components/backup-stream/tests/suite.rs index 843bc5e4c9a..2c75abaeaf5 100644 --- a/components/backup-stream/tests/suite.rs +++ b/components/backup-stream/tests/suite.rs @@ -21,10 +21,12 @@ use backup_stream::{ utils, BackupStreamGrpcService, BackupStreamResolver, Endpoint, GetCheckpointResult, RegionCheckpointOperation, RegionSet, Task, }; +use encryption::{BackupEncryptionManager, MultiMasterKeyBackend}; use futures::{executor::block_on, AsyncWriteExt, Future, Stream, StreamExt}; use grpcio::{ChannelBuilder, Server, ServerBuilder}; use kvproto::{ brpb::{CompressionType, Local, Metadata, StorageBackend}, + encryptionpb::EncryptionMethod, kvrpcpb::*, logbackuppb::{SubscribeFlushEventRequest, SubscribeFlushEventResponse}, logbackuppb_grpc::{create_log_backup, LogBackupClient}, @@ -404,7 +406,12 @@ impl Suite { cluster.pd_client.clone(), cm, BackupStreamResolver::V1(resolver), - sim.encryption.clone(), + BackupEncryptionManager::new( + None, + EncryptionMethod::Plaintext, + MultiMasterKeyBackend::default(), + sim.encryption.clone(), + ), ); worker.start(endpoint); } diff --git a/components/cloud/aws/src/kms.rs b/components/cloud/aws/src/kms.rs index 87b4c48d568..560a27ed0b7 100644 --- a/components/cloud/aws/src/kms.rs +++ b/components/cloud/aws/src/kms.rs @@ -8,7 +8,7 @@ use cloud::{ kms::{Config, CryptographyType, DataKeyPair, EncryptedKey, KeyId, KmsProvider, PlainKey}, }; use rusoto_core::{request::DispatchSignedRequest, RusotoError}; -use rusoto_credential::ProvideAwsCredentials; +use rusoto_credential::{AwsCredentials, ProvideAwsCredentials, StaticProvider}; use rusoto_kms::{ DecryptError, DecryptRequest, GenerateDataKeyError, GenerateDataKeyRequest, Kms, KmsClient, }; @@ -62,17 +62,35 @@ impl AwsKms { }) } - fn new_with_dispatcher(config: Config, dispatcher: D) -> Result - where - D: DispatchSignedRequest + Send + Sync + 'static, - { - let credentials_provider = util::CredentialsProvider::new()?; - Self::new_with_creds_dispatcher(config, dispatcher, credentials_provider) - } - pub fn new(config: Config) -> Result { let dispatcher = util::new_http_client()?; - Self::new_with_dispatcher(config, dispatcher) + match config.aws.as_ref() { + Some(aws_config) => { + if let (Some(access_key), Some(secret_access_key)) = ( + aws_config.access_key.clone(), + aws_config.secret_access_key.clone(), + ) { + // Use provided AWS credentials + let credentials = AwsCredentials::new( + access_key, + secret_access_key, + None, // session token + None, // expiration + ); + let static_provider = StaticProvider::from(credentials); + Self::new_with_creds_dispatcher(config, dispatcher, static_provider) + } else { + // Fall back to default credentials provider + let provider = util::CredentialsProvider::new()?; + Self::new_with_creds_dispatcher(config, dispatcher, provider) + } + } + None => { + // No AWS config provided, use default credentials provider + let provider = util::CredentialsProvider::new()?; + Self::new_with_creds_dispatcher(config, dispatcher, provider) + } + } } } @@ -226,6 +244,7 @@ mod tests { }, azure: None, gcp: None, + aws: None, }; let dispatcher = @@ -271,6 +290,7 @@ mod tests { }, azure: None, gcp: None, + aws: None, }; // IncorrectKeyException diff --git a/components/cloud/aws/src/util.rs b/components/cloud/aws/src/util.rs index a2dc1ca8c76..6ee27bb0c42 100644 --- a/components/cloud/aws/src/util.rs +++ b/components/cloud/aws/src/util.rs @@ -87,7 +87,7 @@ where retry_ext( action, RetryExt::default().with_fail_hook(move |err: &E| { - warn!("aws request meet error."; "err" => %err, "retry?" => %err.is_retryable(), "context" => %name, "uuid" => %id); + warn!("aws request fails"; "err" => %err, "retry?" => %err.is_retryable(), "context" => %name, "uuid" => %id); metrics::CLOUD_ERROR_VEC.with_label_values(&["aws", name]).inc(); }), ).await diff --git a/components/cloud/azure/src/kms.rs b/components/cloud/azure/src/kms.rs index f1afd021c1f..a7d72c2afa4 100644 --- a/components/cloud/azure/src/kms.rs +++ b/components/cloud/azure/src/kms.rs @@ -282,6 +282,7 @@ mod tests { }, azure: Some(err_azure_cfg.clone()), gcp: None, + aws: None, }; AzureKms::new(err_config.clone()).unwrap_err(); let azure_cfg = SubConfigAzure { @@ -326,6 +327,7 @@ mod tests { }, azure: Some(azure_cfg), gcp: None, + aws: None, }; if config.vendor != STORAGE_VENDOR_NAME_AZURE { AzureKms::new(config).unwrap(); diff --git a/components/cloud/gcp/src/kms.rs b/components/cloud/gcp/src/kms.rs index ec1c689adcd..3d4c84d06a1 100644 --- a/components/cloud/gcp/src/kms.rs +++ b/components/cloud/gcp/src/kms.rs @@ -358,6 +358,7 @@ mod tests { gcp: Some(SubConfigGcp { credential_file_path: None, }), + aws: None, }; _ = GcpKms::new(cfg).unwrap_err(); @@ -378,6 +379,7 @@ mod tests { gcp: Some(SubConfigGcp { credential_file_path: None, }), + aws: None, }; let res = GcpKms::new(cfg).unwrap(); diff --git a/components/cloud/src/kms.rs b/components/cloud/src/kms.rs index c5d41c96ea0..e87220ab867 100644 --- a/components/cloud/src/kms.rs +++ b/components/cloud/src/kms.rs @@ -41,6 +41,12 @@ pub struct SubConfigGcp { pub credential_file_path: Option, } +#[derive(Debug, Default, Clone)] +pub struct SubConfigAws { + pub access_key: Option, + pub secret_access_key: Option, +} + #[derive(Debug, Clone)] pub struct Config { pub key_id: KeyId, @@ -48,6 +54,7 @@ pub struct Config { pub vendor: String, pub azure: Option, pub gcp: Option, + pub aws: Option, } impl Config { @@ -61,6 +68,7 @@ impl Config { vendor: mk.vendor, azure: None, gcp: None, + aws: None, }) } diff --git a/components/encryption/Cargo.toml b/components/encryption/Cargo.toml index 2968ea4be30..c5e4f527c00 100644 --- a/components/encryption/Cargo.toml +++ b/components/encryption/Cargo.toml @@ -33,6 +33,7 @@ online_config = { workspace = true } openssl = { workspace = true } prometheus = { version = "0.13", features = ["nightly"] } protobuf = { version = "2.8", features = ["bytes"] } +rand = "0.8.0" # For simplicity and compliance with FIPS 140 requirements for random number # generation, do not use the 'rand' crate in encryption-related code. # rand = "*" @@ -41,6 +42,7 @@ serde_derive = "1.0" slog = { workspace = true } # better to not use slog-global, but pass in the logger slog-global = { workspace = true } +tempfile = "3.1" thiserror = "1.0" tikv_alloc = { workspace = true } tikv_util = { workspace = true } diff --git a/components/encryption/export/examples/ecli.rs b/components/encryption/export/examples/ecli.rs index 140b69c06aa..106b22ded75 100644 --- a/components/encryption/export/examples/ecli.rs +++ b/components/encryption/export/examples/ecli.rs @@ -4,7 +4,7 @@ use std::io::{Read, Write}; use azure::STORAGE_VENDOR_NAME_AZURE; pub use cloud::kms::Config as CloudConfig; -use encryption::GcpConfig; +use encryption::{GcpConfig, KmsBackend}; use encryption_export::{create_cloud_backend, AzureConfig, Backend, Error, KmsConfig, Result}; use file_system::{File, OpenOptions}; use gcp::STORAGE_VENDOR_NAME_GCP; @@ -99,7 +99,7 @@ struct SubCommandGcp { fn create_aws_backend( cmd: &SubCommandAws, credential_file: Option<&String>, -) -> Result> { +) -> Result> { let mut config = KmsConfig::default(); if let Some(credential_file) = credential_file { @@ -122,7 +122,7 @@ fn create_aws_backend( fn create_azure_backend( cmd: &SubCommandAzure, credential_file: Option<&String>, -) -> Result> { +) -> Result> { let mut config = KmsConfig::default(); config.vendor = STORAGE_VENDOR_NAME_AZURE.to_owned(); @@ -146,7 +146,7 @@ fn create_azure_backend( fn create_gcp_backend( cmd: &SubCommandGcp, credential_file: Option<&String>, -) -> Result> { +) -> Result> { let mut config = KmsConfig::default(); config.gcp = Some(GcpConfig { credential_file_path: credential_file diff --git a/components/encryption/export/src/lib.rs b/components/encryption/export/src/lib.rs index 365714063e6..1b7d23d5042 100644 --- a/components/encryption/export/src/lib.rs +++ b/components/encryption/export/src/lib.rs @@ -3,11 +3,10 @@ use std::path::Path; use aws::{AwsKms, STORAGE_VENDOR_NAME_AWS}; use azure::{AzureKms, STORAGE_VENDOR_NAME_AZURE}; -use cloud::kms::Config as CloudConfig; pub use encryption::{ - clean_up_dir, clean_up_trash, trash_dir_all, AzureConfig, Backend, DataKeyImporter, - DataKeyManager, DataKeyManagerArgs, DecrypterReader, EncryptionConfig, Error, FileConfig, Iv, - KmsBackend, KmsConfig, MasterKeyConfig, Result, + clean_up_dir, clean_up_trash, trash_dir_all, AsyncBackend, AzureConfig, Backend, + DataKeyImporter, DataKeyManager, DataKeyManagerArgs, DecrypterReader, EncryptionConfig, Error, + FileConfig, Iv, KmsBackend, KmsConfig, MasterKeyConfig, Result, }; use encryption::{cloud_convert_error, FileBackend, PlaintextBackend}; use gcp::{GcpKms, STORAGE_VENDOR_NAME_GCP}; @@ -27,6 +26,15 @@ pub fn data_key_manager_from_config( DataKeyManager::new(master_key, previous_master_key, args) } +pub fn create_async_backend(config: &MasterKeyConfig) -> Result> { + let result = create_async_backend_inner(config); + if let Err(e) = result { + error!("failed to access master key, {}", e); + return Err(e); + }; + result +} + pub fn create_backend(config: &MasterKeyConfig) -> Result> { let result = create_backend_inner(config); if let Err(e) = result { @@ -36,41 +44,41 @@ pub fn create_backend(config: &MasterKeyConfig) -> Result> { result } -pub fn create_cloud_backend(config: &KmsConfig) -> Result> { - info!("Encryption init aws backend"; +pub fn create_cloud_backend(config: &KmsConfig) -> Result> { + info!("Encryption init KMS backend"; "region" => &config.region, "endpoint" => &config.endpoint, "key_id" => &config.key_id, "vendor" => &config.vendor, ); + let cloud_config = config.to_cloud_config()?; match config.vendor.as_str() { STORAGE_VENDOR_NAME_AWS | "" => { - let conf = CloudConfig::from_proto(config.clone().into_proto()) - .map_err(cloud_convert_error("aws from proto".to_owned()))?; - let kms_provider = - Box::new(AwsKms::new(conf).map_err(cloud_convert_error("new AWS KMS".to_owned()))?); - Ok(Box::new(KmsBackend::new(kms_provider)?) as Box) + let kms_provider = Box::new( + AwsKms::new(cloud_config).map_err(cloud_convert_error("new AWS KMS".to_owned()))?, + ); + Ok(Box::new(KmsBackend::new(kms_provider)?)) } STORAGE_VENDOR_NAME_AZURE => { - if config.azure.is_none() { + // sanity check + if cloud_config.azure.is_none() { return Err(Error::Other(box_err!( "invalid configurations for Azure KMS" ))); } - let (mk, azure_kms_cfg) = config.clone().convert_to_azure_kms_config(); - let conf = CloudConfig::from_azure_kms_config(mk, azure_kms_cfg) - .map_err(cloud_convert_error("azure from proto".to_owned()))?; - let keyvault_provider = Box::new( - AzureKms::new(conf).map_err(cloud_convert_error("new Azure KMS".to_owned()))?, + let kms_provider = Box::new( + AzureKms::new(cloud_config) + .map_err(cloud_convert_error("new Azure KMS".to_owned()))?, ); - Ok(Box::new(KmsBackend::new(keyvault_provider)?)) + Ok(Box::new(KmsBackend::new(kms_provider)?)) } STORAGE_VENDOR_NAME_GCP => { - let (mk, gcp_cfg) = config.clone().convert_to_gcp_config(); - let conf = CloudConfig::from_gcp_kms_config(mk, gcp_cfg) - .map_err(cloud_convert_error("gcp from proto".to_owned()))?; + // sanity check + if cloud_config.gcp.is_none() { + return Err(Error::Other(box_err!("invalid configurations for GCP KMS"))); + } let kms_provider = - GcpKms::new(conf).map_err(cloud_convert_error("new GCP KMS".to_owned()))?; + GcpKms::new(cloud_config).map_err(cloud_convert_error("new GCP KMS".to_owned()))?; Ok(Box::new(KmsBackend::new(Box::new(kms_provider))?)) } provider => Err(Error::Other(box_err!("provider not found {}", provider))), @@ -83,7 +91,17 @@ fn create_backend_inner(config: &MasterKeyConfig) -> Result> { MasterKeyConfig::File { config } => { Box::new(FileBackend::new(Path::new(&config.path))?) as _ } - MasterKeyConfig::Kms { config } => return create_cloud_backend(config), + MasterKeyConfig::Kms { config } => create_cloud_backend(config)? as Box, + }) +} + +fn create_async_backend_inner(config: &MasterKeyConfig) -> Result> { + Ok(match config { + MasterKeyConfig::Plaintext => Box::new(PlaintextBackend {}) as _, + MasterKeyConfig::File { config } => { + Box::new(FileBackend::new(Path::new(&config.path))?) as _ + } + MasterKeyConfig::Kms { config } => create_cloud_backend(config)? as Box, }) } @@ -108,6 +126,7 @@ mod tests { ..AzureConfig::default() }), gcp: None, + aws: None, }; let invalid_config = KmsConfig { azure: None, diff --git a/components/encryption/src/backup/backup_encryption.rs b/components/encryption/src/backup/backup_encryption.rs new file mode 100644 index 00000000000..fc2a53654ea --- /dev/null +++ b/components/encryption/src/backup/backup_encryption.rs @@ -0,0 +1,83 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::sync::Arc; + +use kvproto::{ + brpb::CipherInfo, + encryptionpb::{EncryptedContent, EncryptionMethod}, +}; + +use crate::{DataKeyManager, Error, MultiMasterKeyBackend}; + +/// BackupEncryptionManager handles encryption operations for backup processes. +#[derive(Clone)] +pub struct BackupEncryptionManager { + // Plaintext data key directly passed from user in stream back request, + // only used to encrypt log backup files uploaded to external storage, + // Not recommended in production. + pub plaintext_data_key: Option, + // encryption method used to encrypt log backup files for master key based approach + pub master_key_based_file_encryption_method: EncryptionMethod, + // backend that can contain multiple master keys, initialized as zero key inside + pub multi_master_key_backend: MultiMasterKeyBackend, + // used to encrypt local temp files, configured by TiKV + pub tikv_data_key_manager: Option>, +} +impl BackupEncryptionManager { + pub fn new( + plaintext_data_key: Option, + master_key_based_file_encryption_method: EncryptionMethod, + multi_master_key_backend: MultiMasterKeyBackend, + tikv_data_key_manager: Option>, + ) -> Self { + BackupEncryptionManager { + plaintext_data_key, + master_key_based_file_encryption_method, + multi_master_key_backend, + tikv_data_key_manager, + } + } + + pub fn default() -> Self { + BackupEncryptionManager { + plaintext_data_key: None, + master_key_based_file_encryption_method: EncryptionMethod::default(), + multi_master_key_backend: MultiMasterKeyBackend::new(), + tikv_data_key_manager: None, + } + } + + pub fn opt_data_key_manager(&self) -> Option> { + self.tikv_data_key_manager.clone() + } + + pub async fn encrypt_data_key( + &self, + plaintext_data_key: &[u8], + ) -> Result { + self.multi_master_key_backend + .encrypt(plaintext_data_key) + .await + } + + pub async fn decrypt_data_key( + &self, + encrypted_content: &EncryptedContent, + ) -> Result, Error> { + self.multi_master_key_backend + .decrypt(encrypted_content) + .await + } + + // check if master key backend ready to encrypt and decrypt keys. + pub async fn is_master_key_backend_initialized(&self) -> bool { + self.master_key_based_file_encryption_method != EncryptionMethod::Unknown + && self.master_key_based_file_encryption_method != EncryptionMethod::Plaintext + && self.multi_master_key_backend.is_initialized().await + } + + pub fn generate_data_key(&self) -> Result, Error> { + self.multi_master_key_backend + .generate_data_key(self.master_key_based_file_encryption_method) + } +} diff --git a/components/encryption/src/backup/mod.rs b/components/encryption/src/backup/mod.rs new file mode 100644 index 00000000000..6f7d0290826 --- /dev/null +++ b/components/encryption/src/backup/mod.rs @@ -0,0 +1,2 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. +pub mod backup_encryption; diff --git a/components/encryption/src/config.rs b/components/encryption/src/config.rs index 4c5805248e8..2b8ed30a73d 100644 --- a/components/encryption/src/config.rs +++ b/components/encryption/src/config.rs @@ -1,10 +1,19 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. -use cloud::kms::{SubConfigAzure, SubConfigGcp}; -use kvproto::encryptionpb::{EncryptionMethod, MasterKeyKms}; +use std::result; + +use cloud::{ + kms::{SubConfigAws, SubConfigAzure, SubConfigGcp}, + Config as CloudConfig, +}; +use kvproto::encryptionpb::{EncryptionMethod, MasterKey, MasterKeyKms, MasterKey_oneof_backend}; use online_config::OnlineConfig; use serde_derive::{Deserialize, Serialize}; -use tikv_util::config::ReadableDuration; +use tikv_util::{box_err, config::ReadableDuration}; + +use crate::Error; + +pub type Result = result::Result; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, OnlineConfig)] #[serde(default)] @@ -40,7 +49,7 @@ impl Default for EncryptionConfig { } } -#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(default)] #[serde(rename_all = "kebab-case")] pub struct FileConfig { @@ -48,7 +57,7 @@ pub struct FileConfig { } // TODO: the representation of Azure KMS to users needs to be discussed. -#[derive(Clone, Default, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(default)] #[serde(rename_all = "kebab-case")] pub struct AzureConfig { @@ -85,7 +94,7 @@ impl std::fmt::Debug for AzureConfig { } // TODO: the representation of GCP KMS to users needs to be discussed. -#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(default)] #[serde(rename_all = "kebab-case")] pub struct GcpConfig { @@ -95,7 +104,17 @@ pub struct GcpConfig { pub credential_file_path: Option, } -#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, OnlineConfig)] +#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[serde(default)] +#[serde(rename_all = "kebab-case")] +pub struct AwsConfig { + /// optional since can read from env if not directly passed from user. + pub access_key: Option, + /// optional since can read from env if not directly passed from user. + pub secret_access_key: Option, +} + +#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, OnlineConfig, Eq, Hash)] #[serde(default)] #[serde(rename_all = "kebab-case")] pub struct KmsConfig { @@ -109,60 +128,97 @@ pub struct KmsConfig { // Gcp Kms configuration. #[online_config(skip)] pub gcp: Option, + // optional aws Kms configuration. + #[online_config(skip)] + pub aws: Option, } +// Note: could merge SubConfigAzure and SubConfigGcp into KmsConfig impl KmsConfig { - pub fn into_proto(self) -> MasterKeyKms { - MasterKeyKms { - key_id: self.key_id, - region: self.region, - endpoint: self.endpoint, - vendor: self.vendor, - ..MasterKeyKms::default() + pub fn from_proto(proto: &MasterKeyKms) -> Self { + let mut config = KmsConfig { + key_id: proto.key_id.clone(), + region: proto.region.clone(), + endpoint: proto.endpoint.clone(), + vendor: proto.vendor.clone(), + azure: None, + gcp: None, + aws: None, + }; + if proto.has_azure_kms() { + let azure_config_proto = proto.azure_kms.as_ref().unwrap(); + let azure_config = AzureConfig { + tenant_id: azure_config_proto.tenant_id.clone(), + client_id: azure_config_proto.client_id.clone(), + keyvault_url: azure_config_proto.key_vault_url.clone(), + hsm_name: azure_config_proto.hsm_name.clone(), + hsm_url: azure_config_proto.hsm_url.clone(), + client_certificate: string_to_option(azure_config_proto.client_certificate.clone()), + client_certificate_path: string_to_option( + azure_config_proto.client_certificate_path.clone(), + ), + client_certificate_password: azure_config_proto.client_certificate_password.clone(), + client_secret: string_to_option(azure_config_proto.client_secret.clone()), + }; + config.azure = Some(azure_config); + } + if proto.has_gcp_kms() { + let gcp_config_proto = proto.gcp_kms.as_ref().unwrap(); + let gcp_config = GcpConfig { + credential_file_path: string_to_option(gcp_config_proto.credential.clone()), + }; + config.gcp = Some(gcp_config); + } + if proto.has_aws_kms() { + let aws_config_proto = proto.aws_kms.as_ref().unwrap(); + let aws_config = AwsConfig { + access_key: string_to_option(aws_config_proto.access_key.clone()), + secret_access_key: string_to_option(aws_config_proto.secret_access_key.clone()), + }; + config.aws = Some(aws_config) } + config } - - pub fn convert_to_azure_kms_config(self) -> (MasterKeyKms, SubConfigAzure) { - let azure_kms_cfg = { - let cfg = self.azure.unwrap(); - SubConfigAzure { - tenant_id: cfg.tenant_id, - client_id: cfg.client_id, - keyvault_url: cfg.keyvault_url, - hsm_name: cfg.hsm_name, - hsm_url: cfg.hsm_url, - client_certificate: cfg.client_certificate, - client_certificate_path: cfg.client_certificate_path, - client_certificate_password: cfg.client_certificate_password, - client_secret: cfg.client_secret, - } - }; - let mk = MasterKeyKms { - key_id: self.key_id, - region: self.region, - endpoint: self.endpoint, - vendor: self.vendor, - ..MasterKeyKms::default() - }; - (mk, azure_kms_cfg) + pub fn to_cloud_config(&self) -> Result { + Ok(CloudConfig { + key_id: cloud::kms::KeyId::new(self.key_id.clone()) + .map_err(|_| Error::Other(box_err!("key id should not be empty")))?, + location: cloud::kms::Location { + region: self.region.clone(), + endpoint: self.endpoint.clone(), + }, + vendor: self.vendor.clone(), + azure: self.azure.as_ref().map(|azure| SubConfigAzure { + tenant_id: azure.tenant_id.clone(), + client_id: azure.client_id.clone(), + keyvault_url: azure.keyvault_url.clone(), + hsm_name: azure.hsm_name.clone(), + hsm_url: azure.hsm_url.clone(), + client_certificate: azure.client_certificate.clone(), + client_certificate_path: azure.client_certificate_path.clone(), + client_certificate_password: azure.client_certificate_password.clone(), + client_secret: azure.client_secret.clone(), + }), + gcp: self.gcp.as_ref().map(|gcp| SubConfigGcp { + credential_file_path: gcp.credential_file_path.clone(), + }), + aws: self.aws.as_ref().map(|aws| SubConfigAws { + access_key: aws.access_key.clone(), + secret_access_key: aws.secret_access_key.clone(), + }), + }) } +} - pub fn convert_to_gcp_config(self) -> (MasterKeyKms, SubConfigGcp) { - let gcp_cfg = SubConfigGcp { - credential_file_path: self.gcp.unwrap().credential_file_path, - }; - let mk = MasterKeyKms { - key_id: self.key_id, - region: self.region, - endpoint: self.endpoint, - vendor: self.vendor, - ..MasterKeyKms::default() - }; - (mk, gcp_cfg) +fn string_to_option(string: String) -> Option { + if string.is_empty() { + None + } else { + Some(string) } } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "kebab-case", tag = "type")] #[derive(Default)] pub enum MasterKeyConfig { @@ -186,6 +242,26 @@ pub enum MasterKeyConfig { }, } +impl MasterKeyConfig { + pub fn from_proto(proto: &MasterKey) -> Option { + if let Some(backend) = &proto.backend { + match backend { + MasterKey_oneof_backend::Plaintext(_) => Some(MasterKeyConfig::Plaintext), + MasterKey_oneof_backend::File(key_file) => Some(MasterKeyConfig::File { + config: FileConfig { + path: key_file.path.clone(), + }, + }), + MasterKey_oneof_backend::Kms(kms) => Some(MasterKeyConfig::Kms { + config: KmsConfig::from_proto(kms), + }), + } + } else { + None + } + } +} + mod encryption_method_serde { use std::fmt; @@ -253,6 +329,8 @@ mod encryption_method_serde { #[cfg(test)] mod tests { + use kvproto::encryptionpb; + use super::*; #[test] @@ -268,12 +346,31 @@ mod tests { vendor: "".to_owned(), azure: None, gcp: None, + aws: None, }, }, previous_master_key: MasterKeyConfig::Plaintext, enable_file_dictionary_log: true, file_dictionary_rewrite_threshold: 1000000, }; + + let kms_config_aws = EncryptionConfig { + master_key: MasterKeyConfig::Kms { + config: KmsConfig { + key_id: "key_id".to_owned(), + region: "region".to_owned(), + endpoint: "endpoint".to_owned(), + vendor: "aws".to_owned(), + azure: None, + gcp: None, + aws: Some(AwsConfig { + access_key: Some("foo".into()), + secret_access_key: Some("bar".into()), + }), + }, + }, + ..kms_config.clone() + }; let kms_config_azure = EncryptionConfig { master_key: MasterKeyConfig::Kms { config: KmsConfig { @@ -290,6 +387,7 @@ mod tests { ..AzureConfig::default() }), gcp: None, + aws: None, }, }, ..kms_config.clone() @@ -306,24 +404,31 @@ mod tests { gcp: Some(GcpConfig { credential_file_path: Some("/tmp/credential.json".into()), }), + aws: None, }, }, ..kms_config.clone() }; // KMS with default(aws). - let kms_str = r#" + let kms_str_aws = r#" data-encryption-method = "aes128-ctr" data-key-rotation-period = "14d" enable-file-dictionary-log = true file-dictionary-rewrite-threshold = 1000000 [previous-master-key] type = "plaintext" + [master-key] type = "kms" key-id = "key_id" region = "region" endpoint = "endpoint" + vendor = "aws" + + [master-key.aws] + access-key = "foo" + secret-access-key = "bar" "#; // KMS with azure let kms_str_azure = r#" @@ -367,7 +472,7 @@ mod tests { credential-file-path = '/tmp/credential.json' "#; for (kms_cfg, kms_str) in [ - (kms_config, kms_str), + (kms_config_aws, kms_str_aws), (kms_config_azure, kms_str_azure), (kms_config_gcp, kms_str_gcp), ] { @@ -380,4 +485,178 @@ mod tests { ); } } + + #[test] + fn test_from_proto() { + // Test case 1: Basic KMS config without vendor-specific details + let proto = MasterKeyKms { + key_id: "test_key".to_string(), + region: "test_region".to_string(), + endpoint: "test_endpoint".to_string(), + vendor: "test_vendor".to_string(), + ..Default::default() + }; + let config = KmsConfig::from_proto(&proto); + assert_eq!(config.key_id, "test_key"); + assert_eq!(config.region, "test_region"); + assert_eq!(config.endpoint, "test_endpoint"); + assert_eq!(config.vendor, "test_vendor"); + assert!(config.azure.is_none()); + assert!(config.gcp.is_none()); + assert!(config.aws.is_none()); + // Test case 2: KMS config with Azure details + let mut proto_azure = proto.clone(); + proto_azure.azure_kms = Some(encryptionpb::AzureKms { + tenant_id: "azure_tenant".to_string(), + client_id: "azure_client".to_string(), + key_vault_url: "azure_vault".to_string(), + hsm_name: "azure_hsm".to_string(), + hsm_url: "azure_hsm_url".to_string(), + client_certificate: "azure_cert".to_string(), + client_certificate_path: "azure_cert_path".to_string(), + client_certificate_password: "azure_password".to_string(), + client_secret: "azure_secret".to_string(), + ..Default::default() + }) + .into(); + let config_azure = KmsConfig::from_proto(&proto_azure); + assert!(config_azure.azure.is_some()); + let azure_config = config_azure.azure.unwrap(); + assert_eq!(azure_config.tenant_id, "azure_tenant"); + assert_eq!(azure_config.client_id, "azure_client"); + assert_eq!(azure_config.keyvault_url, "azure_vault"); + assert_eq!(azure_config.hsm_name, "azure_hsm"); + assert_eq!(azure_config.hsm_url, "azure_hsm_url"); + assert_eq!( + azure_config.client_certificate, + Some("azure_cert".to_string()) + ); + assert_eq!( + azure_config.client_certificate_path, + Some("azure_cert_path".to_string()) + ); + assert_eq!(azure_config.client_certificate_password, "azure_password"); + assert_eq!(azure_config.client_secret, Some("azure_secret".to_string())); + + // Test case 3: KMS config with GCP details + let mut proto_gcp = proto.clone(); + proto_gcp.gcp_kms = Some(encryptionpb::GcpKms { + credential: "gcp_credential".to_string(), + ..Default::default() + }) + .into(); + let config_gcp = KmsConfig::from_proto(&proto_gcp); + assert!(config_gcp.gcp.is_some()); + let gcp_config = config_gcp.gcp.unwrap(); + assert_eq!( + gcp_config.credential_file_path, + Some("gcp_credential".to_string()) + ); + + // Test case 4: KMS config with AWS details + let mut proto_aws = proto.clone(); + proto_aws.aws_kms = Some(encryptionpb::AwsKms { + access_key: "aws_access".to_string(), + secret_access_key: "aws_secret".to_string(), + ..Default::default() + }) + .into(); + let config_aws = KmsConfig::from_proto(&proto_aws); + assert!(config_aws.aws.is_some()); + let aws_config = config_aws.aws.unwrap(); + assert_eq!(aws_config.access_key, Some("aws_access".to_string())); + assert_eq!(aws_config.secret_access_key, Some("aws_secret".to_string())); + } + + #[test] + fn test_to_cloud_config() { + // Test case 1: Basic KMS config without vendor-specific details + let kms_config = KmsConfig { + key_id: "test_key".to_string(), + region: "test_region".to_string(), + endpoint: "test_endpoint".to_string(), + vendor: "test_vendor".to_string(), + azure: None, + gcp: None, + aws: None, + }; + let cloud_config = kms_config.to_cloud_config().unwrap(); + assert_eq!(cloud_config.key_id.as_str(), "test_key"); + assert_eq!(cloud_config.location.region, "test_region"); + assert_eq!(cloud_config.location.endpoint, "test_endpoint"); + assert_eq!(cloud_config.vendor, "test_vendor"); + assert!(cloud_config.azure.is_none()); + assert!(cloud_config.gcp.is_none()); + assert!(cloud_config.aws.is_none()); + + // Test case 2: KMS config with Azure details + let kms_config_azure = KmsConfig { + azure: Some(AzureConfig { + tenant_id: "azure_tenant".to_string(), + client_id: "azure_client".to_string(), + keyvault_url: "azure_vault".to_string(), + hsm_name: "azure_hsm".to_string(), + hsm_url: "azure_hsm_url".to_string(), + client_certificate: Some("azure_cert".to_string()), + client_certificate_path: Some("azure_cert_path".to_string()), + client_certificate_password: "azure_password".to_string(), + client_secret: Some("azure_secret".to_string()), + }), + ..kms_config.clone() + }; + let cloud_config_azure = kms_config_azure.to_cloud_config().unwrap(); + assert!(cloud_config_azure.azure.is_some()); + let azure_config = cloud_config_azure.azure.unwrap(); + assert_eq!(azure_config.tenant_id, "azure_tenant"); + assert_eq!(azure_config.client_id, "azure_client"); + assert_eq!(azure_config.keyvault_url, "azure_vault"); + assert_eq!(azure_config.hsm_name, "azure_hsm"); + assert_eq!(azure_config.hsm_url, "azure_hsm_url"); + assert_eq!( + azure_config.client_certificate, + Some("azure_cert".to_string()) + ); + assert_eq!( + azure_config.client_certificate_path, + Some("azure_cert_path".to_string()) + ); + assert_eq!(azure_config.client_certificate_password, "azure_password"); + assert_eq!(azure_config.client_secret, Some("azure_secret".to_string())); + + // Test case 3: KMS config with GCP details + let kms_config_gcp = KmsConfig { + gcp: Some(GcpConfig { + credential_file_path: Some("gcp_credential".to_string()), + }), + ..kms_config.clone() + }; + let cloud_config_gcp = kms_config_gcp.to_cloud_config().unwrap(); + assert!(cloud_config_gcp.gcp.is_some()); + let gcp_config = cloud_config_gcp.gcp.unwrap(); + assert_eq!( + gcp_config.credential_file_path, + Some("gcp_credential".to_string()) + ); + + // Test case 4: KMS config with AWS details + let kms_config_aws = KmsConfig { + aws: Some(AwsConfig { + access_key: Some("aws_access".to_string()), + secret_access_key: Some("aws_secret".to_string()), + }), + ..kms_config.clone() + }; + let cloud_config_aws = kms_config_aws.to_cloud_config().unwrap(); + assert!(cloud_config_aws.aws.is_some()); + let aws_config = cloud_config_aws.aws.unwrap(); + assert_eq!(aws_config.access_key, Some("aws_access".to_string())); + assert_eq!(aws_config.secret_access_key, Some("aws_secret".to_string())); + + // Test case 5: KMS config with empty key_id (should return an error) + let kms_config_empty_key = KmsConfig { + key_id: "".to_string(), + ..kms_config.clone() + }; + kms_config_empty_key.to_cloud_config().unwrap_err(); + } } diff --git a/components/encryption/src/lib.rs b/components/encryption/src/lib.rs index c31e734ba9a..086c2c0ae8f 100644 --- a/components/encryption/src/lib.rs +++ b/components/encryption/src/lib.rs @@ -3,6 +3,7 @@ #![feature(let_chains)] #![feature(noop_waker)] +mod backup; mod config; mod crypter; mod encrypted_file; @@ -15,9 +16,12 @@ mod master_key; pub use master_key::fake; mod metrics; +pub mod test_utils; + use std::{io::ErrorKind, path::Path}; pub use self::{ + backup::backup_encryption::*, config::*, crypter::{verify_encryption_config, AesGcmCrypter, FileEncryptionInfo, Iv}, encrypted_file::EncryptedFile, @@ -27,7 +31,9 @@ pub use self::{ create_aes_ctr_crypter, DecrypterReader, DecrypterWriter, EncrypterReader, EncrypterWriter, }, manager::{DataKeyImporter, DataKeyManager, DataKeyManagerArgs}, - master_key::{Backend, FileBackend, KmsBackend, PlaintextBackend}, + master_key::{ + AsyncBackend, Backend, FileBackend, KmsBackend, MultiMasterKeyBackend, PlaintextBackend, + }, }; const TRASH_PREFIX: &str = "TRASH-"; diff --git a/components/encryption/src/manager/mod.rs b/components/encryption/src/manager/mod.rs index 79071b3610a..9250ed0714c 100644 --- a/components/encryption/src/manager/mod.rs +++ b/components/encryption/src/manager/mod.rs @@ -949,6 +949,19 @@ impl DataKeyManager { } Ok(()) } + + // same logic in raft_log_engine/src/engine#rename + pub fn rename_file(&self, src_name: &PathBuf, dst_name: &PathBuf) -> IoResult<()> { + let src_str = src_name.to_str().unwrap(); + let dst_str = dst_name.to_str().unwrap(); + self.link_file(src_str, dst_str)?; + let r = file_system::rename(src_name, dst_name); + let del_file = if r.is_ok() { src_str } else { dst_str }; + if let Err(e) = self.delete_file(del_file, None) { + warn!("fail to remove encryption metadata after renaming file"; "err" => ?e); + } + r + } } /// An RAII-style importer of data keys. It automatically creates data key that diff --git a/components/encryption/src/master_key/file.rs b/components/encryption/src/master_key/file.rs index 1b24a95e497..e28aecdcc0e 100644 --- a/components/encryption/src/master_key/file.rs +++ b/components/encryption/src/master_key/file.rs @@ -2,11 +2,12 @@ use std::{io::Read, path::Path}; +use async_trait::async_trait; use file_system::File; use kvproto::encryptionpb::EncryptedContent; use tikv_util::box_err; -use super::{Backend, MemAesGcmBackend}; +use super::{AsyncBackend, Backend, MemAesGcmBackend}; use crate::{AesGcmCrypter, Error, Iv, Result}; #[derive(Debug)] @@ -61,26 +62,25 @@ impl Backend for FileBackend { true } } +#[async_trait] +impl AsyncBackend for FileBackend { + async fn encrypt_async(&self, plaintext: &[u8]) -> Result { + self.encrypt(plaintext) + } + + async fn decrypt_async(&self, content: &EncryptedContent) -> Result> { + self.decrypt(content) + } +} #[cfg(test)] mod tests { - use std::{fs::File, io::Write, path::PathBuf}; - use hex::FromHex; use matches::assert_matches; - use tempfile::TempDir; use super::{super::metadata::MetadataKey, *}; use crate::*; - fn create_key_file(val: &str) -> (PathBuf, TempDir) { - let tmp_dir = TempDir::new().unwrap(); - let path = tmp_dir.path().join("key"); - let mut file = File::create(path.clone()).unwrap(); - file.write_all(format!("{}\n", val).as_bytes()).unwrap(); - (path, tmp_dir) - } - #[test] fn test_file_backend_ase_256_gcm() { // See more http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip @@ -90,8 +90,9 @@ mod tests { .unwrap(); let iv = Vec::from_hex("cafabd9672ca6c79a2fbdc22").unwrap(); - let (key_path, _tmp_key_dir) = - create_key_file("c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139"); + let (key_path, _tmp_key_dir) = test_utils::create_master_key_file_test_only( + "c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139", + ); let backend = FileBackend::new(&key_path).unwrap(); let iv = Iv::from_slice(iv.as_slice()).unwrap(); @@ -105,8 +106,9 @@ mod tests { fn test_file_backend_authenticate() { let pt = vec![1u8, 2, 3]; - let (key_path, _tmp_key_dir) = - create_key_file("c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139"); + let (key_path, _tmp_key_dir) = test_utils::create_master_key_file_test_only( + "c3d99825f2181f4808acd2068eac7441a65bd428f14d2aab43fefc0129091139", + ); let backend = FileBackend::new(&key_path).unwrap(); let encrypted_content = backend.encrypt(&pt).unwrap(); diff --git a/components/encryption/src/master_key/kms.rs b/components/encryption/src/master_key/kms.rs index c22bb3c03ea..ad89d217f92 100644 --- a/components/encryption/src/master_key/kms.rs +++ b/components/encryption/src/master_key/kms.rs @@ -2,6 +2,7 @@ use std::{sync::Mutex, time::Duration}; +use async_trait::async_trait; use cloud::kms::{CryptographyType, DataKeyPair, EncryptedKey, KmsProvider, PlainKey}; use kvproto::encryptionpb::EncryptedContent; use tikv_util::{ @@ -11,7 +12,7 @@ use tikv_util::{ }; use tokio::runtime::{Builder, Runtime}; -use super::{metadata::MetadataKey, Backend, MemAesGcmBackend}; +use super::{metadata::MetadataKey, AsyncBackend, Backend, MemAesGcmBackend}; use crate::{crypter::Iv, errors::cloud_convert_error, Error, Result}; #[derive(Debug)] @@ -38,7 +39,7 @@ impl State { #[derive(Debug)] pub struct KmsBackend { timeout_duration: Duration, - state: Mutex>, + state: tokio::sync::Mutex>, kms_provider: Box, // This mutex allows the decrypt_content API to be reference based runtime: Mutex, @@ -57,21 +58,25 @@ impl KmsBackend { Ok(KmsBackend { timeout_duration: Duration::from_secs(10), - state: Mutex::new(None), + state: tokio::sync::Mutex::new(None), runtime, kms_provider, }) } pub fn encrypt_content(&self, plaintext: &[u8], iv: Iv) -> Result { - let mut opt_state = self.state.lock().unwrap(); + let runtime = self.runtime.lock().unwrap(); + runtime.block_on(self.encrypt_content_async(plaintext, iv)) + } + + async fn encrypt_content_async(&self, plaintext: &[u8], iv: Iv) -> Result { + let mut opt_state = self.state.lock().await; if opt_state.is_none() { - let runtime = self.runtime.lock().unwrap(); - let data_key = runtime - .block_on(retry(|| { - with_timeout(self.timeout_duration, self.kms_provider.generate_data_key()) - })) - .map_err(cloud_convert_error("get data key failed".into()))?; + let data_key = retry(|| { + with_timeout(self.timeout_duration, self.kms_provider.generate_data_key()) + }) + .await + .map_err(cloud_convert_error("get data key failed".into()))?; *opt_state = Some(State::new_from_datakey(DataKeyPair { plaintext: PlainKey::new(data_key.plaintext.clone(), CryptographyType::AesGcm256) .map_err(cloud_convert_error("invalid plain key".into()))?, @@ -96,9 +101,14 @@ impl KmsBackend { Ok(content) } + pub fn decrypt_content(&self, content: &EncryptedContent) -> Result> { + let runtime = self.runtime.lock().unwrap(); + runtime.block_on(self.decrypt_content_async(content)) + } + // On decrypt failure, the rule is to return WrongMasterKey error in case it is // possible that a wrong master key has been used, or other error otherwise. - pub fn decrypt_content(&self, content: &EncryptedContent) -> Result> { + async fn decrypt_content_async(&self, content: &EncryptedContent) -> Result> { let vendor_name = self.kms_provider.name(); match content.metadata.get(MetadataKey::KmsVendor.as_str()) { Some(val) if val.as_slice() == vendor_name.as_bytes() => (), @@ -126,26 +136,25 @@ impl KmsBackend { }; { - let mut opt_state = self.state.lock().unwrap(); + let mut opt_state = self.state.lock().await; if let Some(state) = &*opt_state { if state.cached(&ciphertext_key) { return state.encryption_backend.decrypt_content(content); } } { - let runtime = self.runtime.lock().unwrap(); - let plaintext = runtime - .block_on(retry(|| { - with_timeout( - self.timeout_duration, - self.kms_provider.decrypt_data_key(&ciphertext_key), - ) - })) - .map_err(|e| { - Error::WrongMasterKey(box_err!(cloud_convert_error( - "decrypt encrypted key failed".into(), - )(e))) - })?; + let plaintext = retry(|| { + with_timeout( + self.timeout_duration, + self.kms_provider.decrypt_data_key(&ciphertext_key), + ) + }) + .await + .map_err(|e| { + Error::WrongMasterKey(box_err!(cloud_convert_error( + "decrypt encrypted key failed".into(), + )(e))) + })?; let data_key = DataKeyPair { encrypted: ciphertext_key, plaintext: PlainKey::new(plaintext, CryptographyType::AesGcm256) @@ -164,7 +173,8 @@ impl KmsBackend { // KmsProvider::decrypt_data_key() function. #[cfg(any(test, feature = "testexport"))] pub fn clear_state(&mut self) { - let mut opt_state = self.state.lock().unwrap(); + let runtime = self.runtime.lock().unwrap(); + let mut opt_state = runtime.block_on(self.state.lock()); *opt_state = None; } } @@ -182,6 +192,16 @@ impl Backend for KmsBackend { true } } +#[async_trait] +impl AsyncBackend for KmsBackend { + async fn encrypt_async(&self, plaintext: &[u8]) -> Result { + self.encrypt_content_async(plaintext, Iv::new_gcm()?).await + } + + async fn decrypt_async(&self, content: &EncryptedContent) -> Result> { + self.decrypt_content_async(content).await + } +} #[cfg(any(test, feature = "testexport"))] pub mod fake { diff --git a/components/encryption/src/master_key/mod.rs b/components/encryption/src/master_key/mod.rs index 329cff033e8..ab17ecdd0f0 100644 --- a/components/encryption/src/master_key/mod.rs +++ b/components/encryption/src/master_key/mod.rs @@ -1,9 +1,13 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. -use kvproto::encryptionpb::EncryptedContent; -use tikv_util::box_err; +use std::sync::Arc; -use crate::{Error, Result}; +use async_trait::async_trait; +use kvproto::encryptionpb::{EncryptedContent, EncryptionMethod, MasterKey}; +use tikv_util::{box_err, error}; +use tokio::sync::RwLock; + +use crate::{manager::generate_data_key, Error, MasterKeyConfig, Result}; /// Provide API to encrypt/decrypt key dictionary content. /// @@ -18,6 +22,12 @@ pub trait Backend: Sync + Send + std::fmt::Debug + 'static { fn is_secure(&self) -> bool; } +#[async_trait] +pub trait AsyncBackend: Sync + Send + std::fmt::Debug + 'static { + async fn encrypt_async(&self, plaintext: &[u8]) -> Result; + async fn decrypt_async(&self, ciphertext: &EncryptedContent) -> Result>; +} + mod mem; use self::mem::MemAesGcmBackend; @@ -70,6 +80,162 @@ impl Backend for PlaintextBackend { } } +#[async_trait] +impl AsyncBackend for PlaintextBackend { + async fn encrypt_async(&self, plaintext: &[u8]) -> Result { + self.encrypt(plaintext) + } + + async fn decrypt_async(&self, ciphertext: &EncryptedContent) -> Result> { + self.decrypt(ciphertext) + } +} + +/// Used for restore where multiple master keys are provided. +/// It will iterate the master key list and do the encryption/decryption. +/// If any master key succeeds, the request succeeds, if none succeeds, the +/// request will fail with a combined error of each master key error. +#[derive(Default, Debug, Clone)] +pub struct MultiMasterKeyBackend { + inner: Arc>, +} + +#[derive(Default, Debug)] +struct MultiMasterKeyBackendInner { + backends: Option>>, + pub(crate) configs: Option>, +} +impl MultiMasterKeyBackend { + pub fn new() -> Self { + MultiMasterKeyBackend { + inner: Arc::new(RwLock::new(MultiMasterKeyBackendInner { + backends: None, + configs: None, + })), + } + } + + pub async fn update_from_proto_if_needed( + &self, + master_keys_proto: Vec, + create_backend_fn: F, + ) -> Result<()> + where + F: Fn(&MasterKeyConfig) -> Result>, + { + if master_keys_proto.is_empty() { + return Ok(()); + } + let mut master_keys_config = Vec::new(); + for proto in master_keys_proto { + let opt_master_key_config = MasterKeyConfig::from_proto(&proto); + // sanity check + if opt_master_key_config.is_none() { + return Err(log_and_error( + "internal error: master key config should not be empty", + )); + } + master_keys_config.push(opt_master_key_config.unwrap()); + } + + self.update_from_config_if_needed(master_keys_config, create_backend_fn) + .await + } + + pub async fn update_from_config_if_needed( + &self, + master_keys_configs: Vec, + create_backend_fn: F, + ) -> Result<()> + where + F: Fn(&MasterKeyConfig) -> Result>, + { + if master_keys_configs.is_empty() { + return Ok(()); + } + + let mut write_guard = self.inner.write().await; + if write_guard.configs.as_ref() != Some(&master_keys_configs) { + write_guard.backends = Some(create_master_key_backends( + &master_keys_configs, + create_backend_fn, + )?); + write_guard.configs = Some(master_keys_configs); + } + Ok(()) + } + + pub async fn encrypt(&self, plaintext: &[u8]) -> Result { + let read_guard = self.inner.read().await; + if read_guard.backends.is_none() { + return Err(log_and_error( + "internal error: multi master key backend not initialized when encrypting", + )); + } + let mut errors = Vec::new(); + + for master_key_backend in read_guard.backends.as_ref().unwrap() { + match master_key_backend.encrypt_async(plaintext).await { + Ok(res) => return Ok(res), + Err(e) => errors.push(format!("Backend failed to encrypt with error: {}", e)), + } + } + + let combined_error = format!("failed to encrypt content: {}", errors.join("; ")); + Err(log_and_error(&combined_error)) + } + pub async fn decrypt(&self, ciphertext: &EncryptedContent) -> Result> { + let read_guard = self.inner.read().await; + if read_guard.backends.is_none() { + return Err(log_and_error( + "internal error: multi master key backend not initialized when decrypting", + )); + } + let mut errors = Vec::new(); + + for master_key_backend in read_guard.backends.as_ref().unwrap() { + match master_key_backend.decrypt_async(ciphertext).await { + Ok(res) => return Ok(res), + Err(e) => errors.push(format!("Backend failed to decrypt with error: {}", e)), + } + } + + let combined_error = format!("failed to decrypt content: {}", errors.join("; ")); + Err(log_and_error(&combined_error)) + } + + pub fn generate_data_key(&self, method: EncryptionMethod) -> Result> { + let (_id, key) = generate_data_key(method)?; + Ok(key) + } + + pub async fn is_initialized(&self) -> bool { + let read_guard = self.inner.read().await; + // configs and backends are updated together, should always be both empty or not + // empty. + read_guard.configs.is_some() && read_guard.backends.is_some() + } +} + +fn create_master_key_backends( + master_keys_config: &Vec, + create_backend_fn: F, +) -> Result>> +where + F: Fn(&MasterKeyConfig) -> Result>, +{ + let mut backends = Vec::new(); + for master_key_config in master_keys_config { + backends.push(create_backend_fn(master_key_config)?); + } + Ok(backends) +} + +fn log_and_error(err_msg: &str) -> Error { + error!("{}", err_msg); + Error::Other(box_err!(err_msg)) +} + #[cfg(test)] pub mod tests { use std::{collections::HashMap, sync::Mutex}; @@ -156,4 +322,145 @@ pub mod tests { true } } + + #[derive(Clone)] + struct MockAsyncBackend { + encrypt_result: Arc Result + Send + Sync>, + decrypt_result: Arc Result> + Send + Sync>, + } + + #[async_trait] + impl AsyncBackend for MockAsyncBackend { + async fn encrypt_async(&self, _plaintext: &[u8]) -> Result { + (self.encrypt_result)() + } + + async fn decrypt_async(&self, _ciphertext: &EncryptedContent) -> Result> { + (self.decrypt_result)() + } + } + + impl std::fmt::Debug for MockAsyncBackend { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("MockAsyncBackend").finish() + } + } + + fn create_mock_backend(encrypt_result: E, decrypt_result: D) -> Box + where + E: Fn() -> Result + Send + Sync + 'static, + D: Fn() -> Result> + Send + Sync + 'static, + { + Box::new(MockAsyncBackend { + encrypt_result: Arc::new(encrypt_result), + decrypt_result: Arc::new(decrypt_result), + }) + } + + // In your tests: + #[tokio::test] + async fn test_multi_master_key_backend_encrypt_decrypt_failure() { + let backend = MultiMasterKeyBackend::new(); + + let configs = vec![MasterKeyConfig::File { + config: FileConfig { + path: "test".to_string(), + }, + }]; + backend + .update_from_config_if_needed(configs, |_| { + Ok(create_mock_backend( + || { + Err(Error::Other(Box::new(std::io::Error::new( + ErrorKind::Other, + "Encrypt error", + )))) + }, + || { + Err(Error::Other(Box::new(std::io::Error::new( + ErrorKind::Other, + "Decrypt error", + )))) + }, + )) + }) + .await + .unwrap(); + + let encrypt_result = backend.encrypt(&[4, 5, 6]).await; + assert!(encrypt_result.is_err(), "Encryption should have failed"); + if let Err(e) = encrypt_result { + assert!( + e.to_string().contains("Encrypt error"), + "Unexpected error message: {}", + e + ); + } + + let decrypt_result = backend.decrypt(&EncryptedContent::default()).await; + assert!(decrypt_result.is_err(), "Decryption should have failed"); + if let Err(e) = decrypt_result { + assert!( + e.to_string().contains("Decrypt error"), + "Unexpected error message: {}", + e + ); + } + } + + #[tokio::test] + async fn test_multi_master_key_backend_inner_with_multiple_backends() { + let mut inner = MultiMasterKeyBackendInner::default(); + + let configs = vec![ + MasterKeyConfig::File { + config: FileConfig { + path: "test1".to_string(), + }, + }, + MasterKeyConfig::File { + config: FileConfig { + path: "test2".to_string(), + }, + }, + MasterKeyConfig::File { + config: FileConfig { + path: "test3".to_string(), + }, + }, + ]; + let backends: Vec> = vec![ + create_mock_backend( + || { + Err(Error::Other(Box::new(std::io::Error::new( + ErrorKind::Other, + "Encrypt error 1", + )))) + }, + || Ok(vec![1, 2, 3]), + ), + create_mock_backend( + || Ok(EncryptedContent::default()), + || { + Err(Error::Other(Box::new(std::io::Error::new( + ErrorKind::Other, + "Decrypt error 2", + )))) + }, + ), + create_mock_backend(|| Ok(EncryptedContent::default()), || Ok(vec![7, 8, 9])), + ]; + + inner.configs = Some(configs); + inner.backends = Some(backends); + + let backend = MultiMasterKeyBackend { + inner: Arc::new(RwLock::new(inner)), + }; + + backend.encrypt(&[10, 11, 12]).await.unwrap(); + + let decrypt_result = backend.decrypt(&EncryptedContent::default()).await.unwrap(); + assert_eq!(decrypt_result, vec![1, 2, 3]); + } } diff --git a/components/encryption/src/test_utils.rs b/components/encryption/src/test_utils.rs new file mode 100644 index 00000000000..723f96cc176 --- /dev/null +++ b/components/encryption/src/test_utils.rs @@ -0,0 +1,18 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::{fs::File, io::Write, path::PathBuf}; + +use rand::Rng; +use tempfile::TempDir; +pub fn create_master_key_file_test_only(val: &str) -> (PathBuf, TempDir) { + let tmp_dir = TempDir::new().unwrap(); + let path = tmp_dir.path().join("master_key"); + let mut file = File::create(path.clone()).unwrap(); + file.write_all(format!("{}\n", val).as_bytes()).unwrap(); + (path, tmp_dir) +} + +pub fn generate_random_master_key() -> String { + let master_key: [u8; 32] = rand::thread_rng().gen(); + hex::encode(master_key) +} diff --git a/components/external_storage/Cargo.toml b/components/external_storage/Cargo.toml index 52a06cdb9d2..422d33bbe34 100644 --- a/components/external_storage/Cargo.toml +++ b/components/external_storage/Cargo.toml @@ -6,7 +6,7 @@ publish = false license = "Apache-2.0" [dependencies] -async-compression = { version = "0.3.14", features = ["futures-io", "zstd"] } +async-compression = { version = "0.4.12", features = ["futures-io", "zstd"] } async-trait = "0.1" aws = { workspace = true } azure = { workspace = true } diff --git a/components/external_storage/src/export.rs b/components/external_storage/src/export.rs index 7d34f8aed08..a4fd48304a0 100644 --- a/components/external_storage/src/export.rs +++ b/components/external_storage/src/export.rs @@ -15,8 +15,8 @@ use tikv_util::time::{Instant, Limiter}; use crate::{ compression_reader_dispatcher, encrypt_wrap_reader, read_external_storage_into_file, - record_storage_create, BackendConfig, ExternalData, ExternalStorage, HdfsStorage, LocalStorage, - NoopStorage, RestoreConfig, UnpinReader, + record_storage_create, wrap_with_checksum_reader_if_needed, BackendConfig, ExternalData, + ExternalStorage, HdfsStorage, LocalStorage, NoopStorage, RestoreConfig, UnpinReader, }; pub fn create_storage( @@ -136,13 +136,13 @@ impl std::ops::Deref for BlobStore { } } -pub struct EncryptedExternalStorage { +pub struct AutoEncryptLocalRestoredFileExternalStorage { pub key_manager: Arc, pub storage: S, } #[async_trait] -impl ExternalStorage for EncryptedExternalStorage { +impl ExternalStorage for AutoEncryptLocalRestoredFileExternalStorage { fn name(&self) -> &'static str { self.storage.name() } @@ -169,30 +169,43 @@ impl ExternalStorage for EncryptedExternalStorage { let RestoreConfig { range, compression_type, - expected_sha256, + expected_plaintext_file_checksum: expected_sha256, file_crypter, + opt_encrypted_file_checksum, } = restore_config; - let reader = { + let (mut reader, opt_hasher) = { let inner = if let Some((off, len)) = range { self.read_part(storage_name, off, len) } else { self.read(storage_name) }; - compression_reader_dispatcher(compression_type, inner)? + // wrap with checksum reader if needed + // + let (checksum_reader, opt_hasher) = + wrap_with_checksum_reader_if_needed(opt_encrypted_file_checksum.is_some(), inner)?; + + // wrap with decrypter if needed + // + let encrypted_reader = encrypt_wrap_reader(file_crypter, checksum_reader)?; + + ( + compression_reader_dispatcher(compression_type, encrypted_reader)?, + opt_hasher, + ) }; let file_writer = self.key_manager.create_file_for_write(&restore_name)?; let min_read_speed: usize = 8192; - let mut input = encrypt_wrap_reader(file_crypter, reader)?; - read_external_storage_into_file( - &mut input, + &mut reader, file_writer, speed_limiter, expected_length, expected_sha256, min_read_speed, + opt_encrypted_file_checksum, + opt_hasher, ) .await } diff --git a/components/external_storage/src/lib.rs b/components/external_storage/src/lib.rs index 05dbf6f965d..ead1a2f9d18 100644 --- a/components/external_storage/src/lib.rs +++ b/components/external_storage/src/lib.rs @@ -11,14 +11,14 @@ extern crate tikv_alloc; use std::{ io::{self, Write}, marker::Unpin, - sync::Arc, + sync::{Arc, Mutex}, time::Duration, }; use async_compression::futures::bufread::ZstdDecoder; use async_trait::async_trait; use encryption::{DecrypterReader, FileEncryptionInfo, Iv}; -use file_system::File; +use file_system::{File, Sha256Reader}; use futures::io::BufReader; use futures_io::AsyncRead; use futures_util::AsyncReadExt; @@ -30,6 +30,8 @@ use tikv_util::{ time::{Instant, Limiter}, }; use tokio::time::timeout; +use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; +use url::Url; mod hdfs; pub use hdfs::{HdfsConfig, HdfsStorage}; @@ -66,8 +68,9 @@ pub struct BackendConfig { pub struct RestoreConfig { pub range: Option<(u64, u64)>, pub compression_type: Option, - pub expected_sha256: Option>, + pub expected_plaintext_file_checksum: Option>, pub file_crypter: Option, + pub opt_encrypted_file_checksum: Option>, } /// a reader dispatcher for different compression type. @@ -99,7 +102,7 @@ pub fn compression_reader_dispatcher( pub trait ExternalStorage: 'static + Send + Sync { fn name(&self) -> &'static str; - fn url(&self) -> io::Result; + fn url(&self) -> io::Result; /// Write all contents of the read to the given path. async fn write(&self, name: &str, reader: UnpinReader, content_length: u64) -> io::Result<()>; @@ -122,18 +125,31 @@ pub trait ExternalStorage: 'static + Send + Sync { let RestoreConfig { range, compression_type, - expected_sha256, + expected_plaintext_file_checksum: expected_sha256, file_crypter, + opt_encrypted_file_checksum, } = restore_config; - let reader = { + let (reader, opt_hasher) = { let inner = if let Some((off, len)) = range { self.read_part(storage_name, off, len) } else { self.read(storage_name) }; - compression_reader_dispatcher(compression_type, inner)? + // wrap with checksum reader if needed + // + let (checksum_reader, opt_hasher) = + wrap_with_checksum_reader_if_needed(opt_encrypted_file_checksum.is_some(), inner)?; + + // wrap with decrypter if needed + // + let encrypted_reader = encrypt_wrap_reader(file_crypter, checksum_reader)?; + + ( + compression_reader_dispatcher(compression_type, encrypted_reader)?, + opt_hasher, + ) }; let output = File::create(restore_name)?; // the minimum speed of reading data, in bytes/second. @@ -141,15 +157,15 @@ pub trait ExternalStorage: 'static + Send + Sync { // a "TimedOut" error. // (at 8 KB/s for a 2 MB buffer, this means we timeout after 4m16s.) let min_read_speed: usize = 8192; - let input = encrypt_wrap_reader(file_crypter, reader)?; - read_external_storage_into_file( - input, + reader, output, speed_limiter, expected_length, expected_sha256, min_read_speed, + opt_encrypted_file_checksum, + opt_hasher, ) .await } @@ -161,7 +177,7 @@ impl ExternalStorage for Arc { (**self).name() } - fn url(&self) -> io::Result { + fn url(&self) -> io::Result { (**self).url() } @@ -203,7 +219,7 @@ impl ExternalStorage for Box { self.as_ref().name() } - fn url(&self) -> io::Result { + fn url(&self) -> io::Result { self.as_ref().url() } @@ -263,8 +279,10 @@ pub async fn read_external_storage_into_file( mut output: Out, speed_limiter: &Limiter, expected_length: u64, - expected_sha256: Option>, + expected_plaintext_file_checksum: Option>, min_read_speed: usize, + opt_expected_encrypted_file_checksum: Option>, + opt_encrypted_file_hasher: Option>>, ) -> io::Result<()> where In: AsyncRead + Unpin, @@ -275,12 +293,8 @@ where // do the I/O copy from external_storage to the local file. let mut buffer = vec![0u8; READ_BUF_SIZE]; let mut file_length = 0; - let mut hasher = Hasher::new(MessageDigest::sha256()).map_err(|err| { - io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher failed to init: {}", err), - ) - })?; + let mut hasher = build_hasher()?; + let mut yield_checker = RescheduleChecker::new(tokio::task::yield_now, Duration::from_millis(10)); loop { @@ -294,13 +308,8 @@ where } speed_limiter.consume(bytes_read).await; output.write_all(&buffer[..bytes_read])?; - if expected_sha256.is_some() { - hasher.update(&buffer[..bytes_read]).map_err(|err| { - io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher udpate failed: {}", err), - ) - })?; + if expected_plaintext_file_checksum.is_some() { + update_hasher(&mut hasher, &buffer[..bytes_read])?; } file_length += bytes_read as u64; yield_checker.check().await; @@ -316,21 +325,18 @@ where )); } - if let Some(expected_s) = expected_sha256 { - let cal_sha256 = hasher.finish().map_or_else( - |err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher finish failed: {}", err), - )) - }, - |bytes| Ok(bytes.to_vec()), - )?; + calc_and_compare_checksums( + opt_expected_encrypted_file_checksum, + opt_encrypted_file_hasher, + )?; + + if let Some(expected_s) = expected_plaintext_file_checksum { + let cal_sha256 = finish_hasher(hasher)?; if !expected_s.eq(&cal_sha256) { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( - "sha256 not match, expect: {:?}, calculate: {:?}", + "plaintext file checksums do not match, expect: {:?}, calculate: {:?}", expected_s, cal_sha256, ), )); @@ -346,8 +352,10 @@ pub async fn read_external_storage_info_buff( reader: &mut (dyn AsyncRead + Unpin + Send), speed_limiter: &Limiter, expected_length: u64, - expected_sha256: Option>, + opt_expected_checksum: Option>, min_read_speed: usize, + opt_expected_encrypted_file_checksum: Option>, + opt_encrypted_file_hasher: Option>>, ) -> io::Result> { // the minimum speed of reading data, in bytes/second. // if reading speed is slower than this rate, we will stop with @@ -387,36 +395,27 @@ pub async fn read_external_storage_info_buff( ), )); } + + // check encrypted file checksum + // + calc_and_compare_checksums( + opt_expected_encrypted_file_checksum, + opt_encrypted_file_hasher, + )?; + // check sha256 of file - if let Some(sha256) = expected_sha256 { - let mut hasher = Hasher::new(MessageDigest::sha256()).map_err(|err| { - io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher failed to init: {}", err), - ) - })?; - hasher.update(&output).map_err(|err| { - io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher udpate failed: {}", err), - ) - })?; - - let cal_sha256 = hasher.finish().map_or_else( - |err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("openssl hasher finish failed: {}", err), - )) - }, - |bytes| Ok(bytes.to_vec()), - )?; - if !sha256.eq(&cal_sha256) { + if let Some(expected_checksum) = opt_expected_checksum { + let mut hasher = build_hasher()?; + + update_hasher(&mut hasher, &output)?; + + let cal_sha256 = finish_hasher(hasher)?; + if !expected_checksum.eq(&cal_sha256) { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "sha256 not match, expect: {:?}, calculate: {:?}", - sha256, cal_sha256, + expected_checksum, cal_sha256, ), )); } @@ -424,3 +423,75 @@ pub async fn read_external_storage_info_buff( Ok(output) } + +fn build_hasher() -> Result { + Hasher::new(MessageDigest::sha256()).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("openssl hasher failed to init: {}", err), + ) + }) +} + +fn update_hasher(hasher: &mut Hasher, data: &[u8]) -> Result<(), io::Error> { + hasher.update(data).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("openssl hasher update failed: {}", err), + ) + }) +} + +fn finish_hasher(mut hasher: Hasher) -> Result, io::Error> { + hasher.finish().map_or_else( + |err| { + Err(io::Error::new( + io::ErrorKind::Other, + format!("openssl hasher finish failed: {}", err), + )) + }, + |bytes| Ok(bytes.to_vec()), + ) +} + +fn calc_and_compare_checksums( + opt_expected_encrypted_file_checksum: Option>, + opt_encrypted_file_hasher: Option>>, +) -> Result<(), io::Error> { + if let Some(expected_encrypted_checksum) = opt_expected_encrypted_file_checksum { + if let Some(hasher) = opt_encrypted_file_hasher { + let calc_checksum = hasher.lock().unwrap().finish().map_or_else( + |err| { + Err(io::Error::new( + io::ErrorKind::Other, + format!("openssl hasher finish failed: {}", err), + )) + }, + |bytes| Ok(bytes.to_vec()), + )?; + + if !expected_encrypted_checksum.eq(&calc_checksum) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!( + "encrypted file checksums do not match, expected: {:?}, calculated: {:?}", + expected_encrypted_checksum, calc_checksum, + ), + )); + } + } + } + Ok(()) +} + +pub fn wrap_with_checksum_reader_if_needed( + contains_checksum: bool, + encrypted_reader: ExternalData<'_>, +) -> Result<(ExternalData<'_>, Option>>), io::Error> { + if contains_checksum { + let (checksum_reader, hasher) = Sha256Reader::new(encrypted_reader.compat())?; + Ok((Box::new(checksum_reader.compat()), Some(hasher))) + } else { + Ok((encrypted_reader, None)) + } +} diff --git a/components/file_system/src/lib.rs b/components/file_system/src/lib.rs index 1c5577f361a..48a7e59d447 100644 --- a/components/file_system/src/lib.rs +++ b/components/file_system/src/lib.rs @@ -29,8 +29,10 @@ pub use std::{ use std::{ io::{self, ErrorKind, Read, Write}, path::Path, + pin::Pin, str::FromStr, sync::{Arc, Mutex}, + task::{ready, Context, Poll}, }; pub use file::{File, OpenOptions}; @@ -50,6 +52,7 @@ pub use rate_limiter::{ }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use strum::{EnumCount, EnumIter}; +use tokio::io::{AsyncRead, ReadBuf}; #[derive(Clone, Copy, Debug, PartialEq)] pub enum IoOp { @@ -431,6 +434,34 @@ impl Read for Sha256Reader { } } +impl AsyncRead for Sha256Reader { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { + let initial_filled_len = buf.filled().len(); + ready!(Pin::new(&mut self.reader).poll_read(cx, buf))?; + + let filled_len = buf.filled().len(); + if initial_filled_len == filled_len { + return Poll::Ready(Ok(())); + } + let new_data = &buf.filled()[initial_filled_len..filled_len]; + + // Update the hasher with the read data + let mut hasher = self + .hasher + .lock() + .expect("failed to lock hasher in Sha256Reader async read"); + if let Err(e) = hasher.update(new_data) { + return Poll::Ready(Err(io::Error::new(ErrorKind::Other, e))); + } + + Poll::Ready(Ok(())) + } +} + pub const SPACE_PLACEHOLDER_FILE: &str = "space_placeholder_file"; /// Create a file with hole, to reserve space for TiKV. diff --git a/components/server/src/lib.rs b/components/server/src/lib.rs index 144cc1885d5..845dda6176d 100644 --- a/components/server/src/lib.rs +++ b/components/server/src/lib.rs @@ -15,3 +15,4 @@ pub mod raft_engine_switch; pub mod server; pub mod server2; pub mod signal_handler; +mod utils; diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 3b0eb1e2e7d..4b4db3acb8d 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -142,6 +142,7 @@ use crate::{ setup::*, signal_handler, tikv_util::sys::thread::ThreadBuildWrapper, + utils, }; #[inline] @@ -917,6 +918,12 @@ where Duration::from_secs(60), ); + // build stream backup encryption manager + let backup_encryption_manager = + utils::build_backup_encryption_manager(self.core.encryption_key_manager.clone()) + .expect("failed to build backup encryption manager in server"); + + // build stream backup endpoint let backup_stream_endpoint = backup_stream::Endpoint::new( raft_server.id(), PdStore::new(Checked::new(Sourced::new( @@ -932,7 +939,7 @@ where self.pd_client.clone(), self.concurrency_manager.clone(), BackupStreamResolver::V1(leadership_resolver), - self.core.encryption_key_manager.clone(), + backup_encryption_manager, ); backup_stream_worker.start(backup_stream_endpoint); self.core.to_stop.push(backup_stream_worker); diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index 7cb6c354f0c..b0e16b4d431 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -130,6 +130,7 @@ use crate::{ setup::*, signal_handler, tikv_util::sys::thread::ThreadBuildWrapper, + utils, }; #[inline] @@ -722,6 +723,11 @@ where )), ); + // build stream backup encryption manager + let backup_encryption_manager = + utils::build_backup_encryption_manager(self.core.encryption_key_manager.clone()) + .expect("failed to build backup encryption manager in server"); + let backup_stream_endpoint = backup_stream::Endpoint::new( self.node.as_ref().unwrap().id(), PdStore::new(Checked::new(Sourced::new( @@ -737,7 +743,7 @@ where self.pd_client.clone(), self.concurrency_manager.clone(), BackupStreamResolver::V2(self.router.clone().unwrap(), PhantomData), - self.core.encryption_key_manager.clone(), + backup_encryption_manager.clone(), ); backup_stream_worker.start(backup_stream_endpoint); self.core.to_stop.push(backup_stream_worker); diff --git a/components/server/src/utils.rs b/components/server/src/utils.rs new file mode 100644 index 00000000000..dd88ad7c0d1 --- /dev/null +++ b/components/server/src/utils.rs @@ -0,0 +1,19 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::{io, sync::Arc}; + +use encryption::{BackupEncryptionManager, DataKeyManager, MultiMasterKeyBackend}; +use kvproto::encryptionpb::EncryptionMethod; + +pub fn build_backup_encryption_manager( + opt_encryption_key_manager: Option>, +) -> Result { + let multi_master_key_backend = MultiMasterKeyBackend::new(); + + Ok(BackupEncryptionManager::new( + None, + EncryptionMethod::Plaintext, + multi_master_key_backend, + opt_encryption_key_manager, + )) +} diff --git a/components/sst_importer/Cargo.toml b/components/sst_importer/Cargo.toml index 41f29fb6c70..f3b260a7e87 100644 --- a/components/sst_importer/Cargo.toml +++ b/components/sst_importer/Cargo.toml @@ -27,6 +27,7 @@ collections = { workspace = true } crc32fast = "1.2" dashmap = "5" encryption = { workspace = true } +encryption_export = { workspace = true } engine_rocks = { workspace = true } engine_traits = { workspace = true } error_code = { workspace = true } @@ -56,7 +57,9 @@ txn_types = { workspace = true } uuid = { version = "0.8.1", features = ["serde", "v4"] } [dev-dependencies] +async-compression = { version = "0.4.12", features = ["tokio", "zstd"] } engine_test = { workspace = true } tempfile = "3.0" test_sst_importer = { workspace = true } test_util = { workspace = true } +tokio-util = { version = "0.7", features = ["compat"] } diff --git a/components/sst_importer/src/service.rs b/components/sst_importer/src/service.rs deleted file mode 100644 index a7c15e88539..00000000000 --- a/components/sst_importer/src/service.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. - -use grpcio::{RpcStatus, RpcStatusCode}; -use std::fmt::Debug; - -pub fn make_rpc_error(err: E) -> RpcStatus { - // FIXME: Just spewing debug error formatting here seems pretty unfriendly - RpcStatus::with_message(RpcStatusCode::UNKNOWN, format!("{:?}", err)) -} - -#[macro_export] -macro_rules! send_rpc_response { - ($res:ident, $sink:ident, $label:ident, $timer:ident) => {{ - let res = match $res { - Ok(resp) => { - IMPORT_RPC_DURATION - .with_label_values(&[$label, "ok"]) - .observe($timer.saturating_elapsed_secs()); - $sink.success(resp) - } - Err(e) => { - IMPORT_RPC_DURATION - .with_label_values(&[$label, "error"]) - .observe($timer.saturating_elapsed_secs()); - error_inc($label, &e); - $sink.fail(make_rpc_error(e)) - } - }; - let _ = res.map_err(|e| warn!("send rpc response"; "err" => %e)).await; - }}; -} diff --git a/components/sst_importer/src/sst_importer.rs b/components/sst_importer/src/sst_importer.rs index 1f9075599ea..e3047d59ae1 100644 --- a/components/sst_importer/src/sst_importer.rs +++ b/components/sst_importer/src/sst_importer.rs @@ -13,18 +13,21 @@ use std::{ use collections::HashSet; use dashmap::{mapref::entry::Entry, DashMap}; -use encryption::{DataKeyManager, FileEncryptionInfo}; +use encryption::{DataKeyManager, FileEncryptionInfo, MultiMasterKeyBackend}; +use encryption_export::create_async_backend; use engine_traits::{ name_to_cf, util::check_key_in_range, CfName, IterOptions, Iterator, KvEngine, RefIterable, SstCompressionType, SstExt, SstMetaInfo, SstReader, SstWriter, SstWriterBuilder, CF_DEFAULT, CF_WRITE, }; use external_storage::{ - compression_reader_dispatcher, encrypt_wrap_reader, ExternalStorage, RestoreConfig, + compression_reader_dispatcher, encrypt_wrap_reader, wrap_with_checksum_reader_if_needed, + ExternalStorage, RestoreConfig, }; use file_system::{IoType, OpenOptions}; use kvproto::{ brpb::{CipherInfo, StorageBackend}, + encryptionpb::{EncryptionMethod, FileEncryptionInfo_oneof_mode, MasterKey}, import_sstpb::{Range, *}, kvrpcpb::ApiVersion, metapb::Region, @@ -101,13 +104,12 @@ pub enum CacheKvFile { Fs(Arc), } -/// returns a error indices that we are going to panic in a invalid state. -/// (Rust panic information cannot be send to BR, hence client cannot know -/// what happens, so we pack it into a `Result`.) -fn bug(message: impl std::fmt::Display) -> Error { - Error::Io(std::io::Error::new( - std::io::ErrorKind::Other, - format!("BUG in TiKV: {}", message), +/// returns an error on an invalid internal state. +/// pass the error back to the client side for further debugging. +fn error(message: impl std::fmt::Display) -> Error { + Error::Io(io::Error::new( + ErrorKind::Other, + format!("internal error in TiKV: {}", message), )) } @@ -150,12 +152,13 @@ pub struct SstImporter { _download_rt: Runtime, file_locks: Arc>, memory_quota: Arc, + multi_master_keys_backend: MultiMasterKeyBackend, } impl SstImporter { pub fn new>( cfg: &Config, - root: P, + import_dir: P, key_manager: Option>, api_version: ApiVersion, raft_kv_v2: bool, @@ -190,7 +193,7 @@ impl SstImporter { "size" => ?memory_limit, ); - let dir = ImportDir::new(root)?; + let dir = ImportDir::new(import_dir)?; Ok(SstImporter { dir, @@ -202,6 +205,7 @@ impl SstImporter { cached_storage, _download_rt: download_rt, memory_quota: Arc::new(MemoryQuota::new(memory_limit as _)), + multi_master_keys_backend: MultiMasterKeyBackend::new(), }) } @@ -448,11 +452,10 @@ impl SstImporter { &self, file_length: u64, src_file_name: &str, - dst_file: std::path::PathBuf, + dst_file: PathBuf, backend: &StorageBackend, - support_kms: bool, speed_limiter: &Limiter, - restore_config: external_storage::RestoreConfig, + restore_config: RestoreConfig, ) -> Result<()> { self._download_rt .block_on(self.async_download_file_from_external_storage( @@ -460,7 +463,6 @@ impl SstImporter { src_file_name, dst_file, backend, - support_kms, speed_limiter, "", restore_config, @@ -490,17 +492,16 @@ impl SstImporter { &self, file_length: u64, src_file_name: &str, - dst_file: std::path::PathBuf, + dst_file: PathBuf, backend: &StorageBackend, - support_kms: bool, speed_limiter: &Limiter, cache_key: &str, - restore_config: external_storage::RestoreConfig, + restore_config: RestoreConfig, ) -> Result<()> { let start_read = Instant::now(); if let Some(p) = dst_file.parent() { file_system::create_dir_all(p).or_else(|e| { - if e.kind() == io::ErrorKind::AlreadyExists { + if e.kind() == ErrorKind::AlreadyExists { Ok(()) } else { Err(e) @@ -509,7 +510,7 @@ impl SstImporter { } let ext_storage = self.external_storage_or_cache(backend, cache_key)?; - let ext_storage = self.wrap_kms(ext_storage, support_kms); + let ext_storage = self.auto_encrypt_local_file_if_needed(ext_storage); let result = ext_storage .restore( @@ -537,7 +538,7 @@ impl SstImporter { .with_label_values(&["read"]) .observe(start_read.saturating_elapsed().as_secs_f64()); - debug!("downloaded file succeed"; + debug!("successfully download the file"; "name" => src_file_name, "url" => %util::url_for(&ext_storage), ); @@ -594,16 +595,14 @@ impl SstImporter { CACHED_FILE_IN_MEM.set(self.memory_quota.capacity() as _); - if self.import_support_download() { + if self.download_to_disk_only() { let shrink_file_count = shrink_files.len(); if shrink_file_count > 0 || retain_file_count > 0 { info!("shrink space by tick"; "shrink_files_count" => shrink_file_count, "retain_files_count" => retain_file_count); } for f in shrink_files { - if let Err(e) = file_system::remove_file(&f) { - info!("failed to remove file"; "filename" => ?f, "error" => ?e); - } + self.remove_file_no_throw(&f); } shrink_file_count } else { @@ -614,9 +613,7 @@ impl SstImporter { } } - // If memory_quota is 0, which represent download kv-file when import. - // Or read kv-file into buffer directly. - pub fn import_support_download(&self) -> bool { + pub fn download_to_disk_only(&self) -> bool { self.memory_quota.capacity() == 0 } @@ -633,11 +630,13 @@ impl SstImporter { } } - async fn exec_download( + async fn download_kv_file_to_mem_buf( &self, meta: &KvMeta, - ext_storage: Arc, + ext_storage: Arc, speed_limiter: &Limiter, + opt_file_encryption_info: Option, + opt_encrypted_file_checksum: Option>, ) -> Result { let start = Instant::now(); let permit = self @@ -661,15 +660,16 @@ impl SstImporter { Some((meta.get_range_offset(), range_length)) } }; - let restore_config = external_storage::RestoreConfig { + let restore_config = RestoreConfig { range, compression_type: Some(meta.get_compression_type()), - expected_sha256, - file_crypter: None, + expected_plaintext_file_checksum: expected_sha256, + file_crypter: opt_file_encryption_info, + opt_encrypted_file_checksum, }; let buff = self - .read_kv_files_from_external_storage( + .download_kv_files_from_external_storage_to_mem( file_length, meta.get_name(), ext_storage, @@ -689,11 +689,13 @@ impl SstImporter { }) } - pub async fn do_read_kv_file( + pub async fn download_kv_file_to_mem_cache( &self, meta: &KvMeta, - ext_storage: Arc, + ext_storage: Arc, speed_limiter: &Limiter, + opt_file_encryption_info: Option, + opt_encrypted_file_checksum: Option>, ) -> Result { let start = Instant::now(); let dst_name = format!("{}_{}", meta.get_name(), meta.get_range_offset()); @@ -711,7 +713,7 @@ impl SstImporter { Arc::clone(buff) } _ => { - return Err(bug(concat!( + return Err(error(concat!( "using both read-to-memory and download-to-file is unacceptable for now.", "(If you think it is possible in the future you are reading this, ", "please change this line to `return item.get.0.clone()`)", @@ -732,53 +734,71 @@ impl SstImporter { } cache - .get_or_try_init(|| self.exec_download(meta, ext_storage, speed_limiter)) + .get_or_try_init(|| { + self.download_kv_file_to_mem_buf( + meta, + ext_storage, + speed_limiter, + opt_file_encryption_info, + opt_encrypted_file_checksum, + ) + }) .await?; Ok(CacheKvFile::Mem(cache)) } - pub fn wrap_kms( + pub fn auto_encrypt_local_file_if_needed( &self, ext_storage: Arc, - support_kms: bool, - ) -> Arc { - // kv-files needn't are decrypted with KMS when download currently because these - // files are not encrypted when log-backup. It is different from - // sst-files because sst-files is encrypted when saved with rocksdb env - // with KMS. to do: support KMS when log-backup and restore point. - match (support_kms, self.key_manager.clone()) { - (true, Some(key_manager)) => Arc::new(external_storage::EncryptedExternalStorage { - key_manager, - storage: ext_storage, - }), - _ => ext_storage, + ) -> Arc { + if let Some(key_manager) = self.key_manager.clone() { + Arc::new( + external_storage::AutoEncryptLocalRestoredFileExternalStorage { + key_manager, + storage: ext_storage, + }, + ) + } else { + ext_storage } } - async fn read_kv_files_from_external_storage( + async fn download_kv_files_from_external_storage_to_mem( &self, file_length: u64, file_name: &str, - ext_storage: Arc, + ext_storage: Arc, speed_limiter: &Limiter, restore_config: RestoreConfig, ) -> Result> { let RestoreConfig { range, compression_type, - expected_sha256, + expected_plaintext_file_checksum: expected_sha256, file_crypter, + opt_encrypted_file_checksum, } = restore_config; - let mut reader = { + let (mut reader, opt_hasher) = { let inner = if let Some((off, len)) = range { ext_storage.read_part(file_name, off, len) } else { ext_storage.read(file_name) }; - let inner = compression_reader_dispatcher(compression_type, inner)?; - encrypt_wrap_reader(file_crypter, inner)? + // wrap with checksum reader if needed + // + let (checksum_reader, opt_hasher) = + wrap_with_checksum_reader_if_needed(opt_encrypted_file_checksum.is_some(), inner)?; + + // wrap with decrypter if needed + // + let encrypted_reader = encrypt_wrap_reader(file_crypter, checksum_reader)?; + + ( + compression_reader_dispatcher(compression_type, encrypted_reader)?, + opt_hasher, + ) }; let r = external_storage::read_external_storage_info_buff( @@ -787,6 +807,8 @@ impl SstImporter { file_length, expected_sha256, external_storage::MIN_READ_SPEED, + opt_encrypted_file_checksum, + opt_hasher, ) .await; let url = ext_storage.url()?.to_string(); @@ -800,54 +822,89 @@ impl SstImporter { Ok(buff) } - pub async fn read_from_kv_file( + pub async fn download_kv_file( &self, meta: &KvMeta, - ext_storage: Arc, + ext_storage: Arc, backend: &StorageBackend, speed_limiter: &Limiter, + opt_cipher_info: Option, + master_keys_proto: Vec, ) -> Result> { - let c = if self.import_support_download() { - self.do_download_kv_file(meta, backend, speed_limiter) - .await? + // update the master key backends if needed. + // + self.multi_master_keys_backend + .update_from_proto_if_needed(master_keys_proto, create_async_backend) + .await?; + + // extract backup file encryption info if configured + // + let opt_file_encryption_info = self + .extract_file_encryption_info(meta, opt_cipher_info) + .await?; + let opt_checksum = extract_checksum_info(meta); + + let c = if self.download_to_disk_only() { + self.download_kv_file_to_disk( + meta, + backend, + speed_limiter, + opt_file_encryption_info, + opt_checksum, + ) + .await? } else { - self.do_read_kv_file(meta, ext_storage, speed_limiter) - .await? + self.download_kv_file_to_mem_cache( + meta, + ext_storage, + speed_limiter, + opt_file_encryption_info, + opt_checksum, + ) + .await? }; match c { - // If cache memroy, it has been rewrite, return buffer directly. + // If cache in memory, it has been rewrite, and content is plaintext, + // return buffer directly. CacheKvFile::Mem(buff) => Ok(Arc::clone( &buff .get() - .ok_or_else(|| bug("invalid cache state"))? + .ok_or_else(|| error("invalid cache state"))? .content, )), - // If cache file name, it need to read and rewrite. + // If cache in a file, it needs to read and rewrite, and it is locally encrypted if + // data key manager is configured CacheKvFile::Fs(path) => { - let file = File::open(path.as_ref())?; - let mut reader = BufReader::new(file); let mut buffer = Vec::new(); - reader.read_to_end(&mut buffer)?; - + if let Some(key_manager) = self.key_manager.clone() { + let mut decrypter_reader = key_manager.open_file_for_read(path.as_ref())?; + decrypter_reader.read_to_end(&mut buffer)?; + } else { + let file = File::open(path.as_ref())?; + let mut reader = BufReader::new(file); + reader.read_to_end(&mut buffer)?; + } Ok(Arc::from(buffer.into_boxed_slice())) } } } - pub async fn do_download_kv_file( + pub async fn download_kv_file_to_disk( &self, meta: &KvMeta, backend: &StorageBackend, speed_limiter: &Limiter, + opt_file_encryption_info: Option, + opt_encrypted_file_checksum: Option>, ) -> Result { let offset = meta.get_range_offset(); let src_name = meta.get_name(); let dst_name = format!("{}_{}", src_name, offset); let path = self.dir.get_import_path(&dst_name)?; let start = Instant::now(); - let sha256 = meta.get_sha256().to_vec(); - let expected_sha256 = if !sha256.is_empty() { - Some(sha256) + let plaintext_file_checksum = meta.get_sha256().to_vec(); + let expected_plaintext_checksum = if !plaintext_file_checksum.is_empty() { + Some(plaintext_file_checksum) } else { None }; @@ -868,19 +925,20 @@ impl SstImporter { } else { Some((offset, range_length)) }; - let restore_config = external_storage::RestoreConfig { + + let restore_config = RestoreConfig { range, compression_type: Some(meta.compression_type), - expected_sha256, - file_crypter: None, + expected_plaintext_file_checksum: expected_plaintext_checksum, + file_crypter: opt_file_encryption_info, + opt_encrypted_file_checksum, }; + self.async_download_file_from_external_storage( meta.get_length(), src_name, path.temp.clone(), backend, - false, - // don't support encrypt for now. speed_limiter, "", restore_config, @@ -896,7 +954,7 @@ impl SstImporter { if let Some(p) = path.save.parent() { // we have v1 prefix in file name. file_system::create_dir_all(p).or_else(|e| { - if e.kind() == io::ErrorKind::AlreadyExists { + if e.kind() == ErrorKind::AlreadyExists { Ok(()) } else { Err(e) @@ -904,7 +962,12 @@ impl SstImporter { })?; } - file_system::rename(path.temp, path.save)?; + if let Some(manager) = self.key_manager.clone() { + manager.rename_file(&path.temp, &path.save)?; + } else { + file_system::rename(path.temp.clone(), path.save.clone())?; + } + IMPORTER_APPLY_DURATION .with_label_values(&["download"]) .observe(start.saturating_elapsed().as_secs_f64()); @@ -1099,7 +1162,7 @@ impl SstImporter { iv: meta.cipher_iv.to_owned(), }); - let restore_config = external_storage::RestoreConfig { + let restore_config = RestoreConfig { file_crypter, ..Default::default() }; @@ -1109,7 +1172,6 @@ impl SstImporter { name, path.temp.clone(), backend, - true, speed_limiter, ext.cache_key.unwrap_or(""), restore_config, @@ -1334,7 +1396,7 @@ impl SstImporter { } } - let _ = file_system::remove_file(&path.temp); + self.remove_file_no_throw(&path.temp); IMPORTER_DOWNLOAD_DURATION .with_label_values(&["rewrite"]) @@ -1355,7 +1417,7 @@ impl SstImporter { // nothing is written: prevents finishing the SST at all. // also delete the empty sst file that is created when creating sst_writer drop(sst_writer); - let _ = file_system::remove_file(&path.save); + self.remove_file_no_throw(&path.save); Ok(None) } } @@ -1416,6 +1478,107 @@ impl SstImporter { self.api_version, )) } + + async fn extract_file_encryption_info( + &self, + kv_meta: &KvMeta, + opt_cipher_info: Option, + ) -> Result> { + if let Some(encryption_info) = kv_meta.file_encryption_info.as_ref() { + if let Some(encryption_info_mode) = &encryption_info.mode { + match encryption_info_mode { + FileEncryptionInfo_oneof_mode::PlainTextDataKey(_) => { + if let Some(cipher_info) = opt_cipher_info { + if cipher_info.cipher_type == EncryptionMethod::Unknown + || cipher_info.cipher_type == EncryptionMethod::Plaintext + { + return Err(error( + "plaintext data key needed from client but plaintext or unknown provided", + )); + } + Ok(Some(FileEncryptionInfo { + method: cipher_info.cipher_type, + key: cipher_info.cipher_key, + iv: encryption_info.file_iv.clone(), + })) + } else { + Err(error( + "plaintext data key needed from client but not provided", + )) + } + } + FileEncryptionInfo_oneof_mode::MasterKeyBased(parsed_master_key_info) => { + // sanity check + if self.multi_master_keys_backend.is_initialized().await { + // decrypt encrypted data key + if parsed_master_key_info.data_key_encrypted_content.is_empty() { + return Err(error( + "internal error: couldn't find any encrypted data key information for log backup file", + )); + } + // get the first key for the current impl + // the field is a list for future extension + // when multiple master key backends are provided for high availability. + let plaintext_data_key = self + .multi_master_keys_backend + .decrypt( + parsed_master_key_info + .data_key_encrypted_content + .first() + .unwrap(), + ) + .await + .map_err(|e| { + error(format!("failed to decrypt encrypted data key: {:?}", e)) + })?; + Ok(Some(FileEncryptionInfo { + method: encryption_info.encryption_method, + key: plaintext_data_key, + iv: encryption_info.file_iv.clone(), + })) + } else { + Err(error( + "internal error: need to decrypt data key but multi master key backends is not initialized", + )) + } + } + } + } else { + // encryption info set but empty, should never happen + Err(error( + "internal error: encryption information is set in the kv file but empty, should never happen", + )) + } + } else { + // doesn't have encryption info, plaintext log backup files. + Ok(None) + } + } + + fn remove_file_no_throw(&self, path_buf: &PathBuf) { + // remove from file system + if let Err(e) = file_system::remove_file(path_buf) { + warn!("failed to remove file"; "filename" => ?path_buf, "error" => ?e); + } + // remove tracking from key manager if needed + if let Some(key_manager) = self.key_manager.as_ref() { + if let Err(e) = key_manager.delete_file(&path_buf.to_string_lossy(), None) { + warn!("failed to remove file from key manager"; "filename" => ?path_buf, "error" => ?e); + } + } + } +} + +fn extract_checksum_info(kv_meta: &KvMeta) -> Option> { + if let Some(encryption_info) = kv_meta.file_encryption_info.as_ref() { + if encryption_info.checksum.is_empty() { + None + } else { + Some(encryption_info.checksum.clone()) + } + } else { + None + } } fn key_to_bound(key: &[u8]) -> Bound<&[u8]> { @@ -1453,25 +1616,34 @@ fn is_after_end_bound>(value: &[u8], bound: &Bound) -> bool { #[cfg(test)] mod tests { use std::{ - io::{self, BufWriter, Write}, + io::{self, Cursor}, ops::Sub, usize, }; + use async_compression::tokio::write::ZstdEncoder; + use encryption::{EncrypterWriter, Iv}; use engine_rocks::get_env; use engine_traits::{ collect, Error as TraitError, ExternalSstFileInfo, Iterable, Iterator, RefIterable, - SstReader, SstWriter, CF_DEFAULT, DATA_CFS, + SstCompressionType::Zstd, SstReader, SstWriter, CF_DEFAULT, DATA_CFS, }; use external_storage::read_external_storage_info_buff; - use file_system::File; - use kvproto::encryptionpb::EncryptionMethod; + use file_system::Sha256Reader; + use kvproto::{ + brpb::CompressionType, + encryptionpb, + encryptionpb::{EncryptionMethod, MasterKeyBased, MasterKeyFile, PlainTextDataKey}, + }; use online_config::{ConfigManager, OnlineConfig}; use openssl::hash::{Hasher, MessageDigest}; - use tempfile::Builder; + use rand::Rng; + use tempfile::{Builder, TempDir}; use test_sst_importer::*; use test_util::new_test_key_manager; use tikv_util::{codec::stream_event::EventEncoder, stream::block_on_external_io}; + use tokio::io::{AsyncWrite, AsyncWriteExt}; + use tokio_util::compat::{FuturesAsyncWriteCompatExt, TokioAsyncWriteCompatExt}; use txn_types::{Value, WriteType}; use uuid::Uuid; @@ -1632,9 +1804,9 @@ mod tests { content_a == content_b } - fn new_key_manager_for_test() -> (tempfile::TempDir, Arc) { + fn new_key_manager_for_test() -> (TempDir, Arc) { // test with tde - let tmp_dir = tempfile::TempDir::new().unwrap(); + let tmp_dir = TempDir::new().unwrap(); let key_manager = new_test_key_manager(&tmp_dir, None, None, None); (tmp_dir, Arc::new(key_manager.unwrap().unwrap())) } @@ -1651,7 +1823,7 @@ mod tests { fn create_external_sst_file_with_write_fn( write_fn: F, - ) -> Result<(tempfile::TempDir, StorageBackend, SstMeta)> + ) -> Result<(TempDir, StorageBackend, SstMeta)> where F: FnOnce(&mut RocksSstWriter) -> Result<()>, { @@ -1675,7 +1847,7 @@ mod tests { Ok((ext_sst_dir, backend, meta)) } - fn create_sample_external_sst_file() -> Result<(tempfile::TempDir, StorageBackend, SstMeta)> { + fn create_sample_external_sst_file() -> Result<(TempDir, StorageBackend, SstMeta)> { create_external_sst_file_with_write_fn(|writer| { writer.put(b"zt123_r01", b"abc")?; writer.put(b"zt123_r04", b"xyz")?; @@ -1686,14 +1858,102 @@ mod tests { }) } - fn create_sample_external_kv_file() - -> Result<(tempfile::TempDir, StorageBackend, KvMeta, Vec)> { + fn create_sample_external_kv_file() -> Result<(TempDir, StorageBackend, KvMeta, Vec)> { + create_sample_external_kv_file_with_optional_encryption( + None, + Vec::new(), + EncryptionMethod::Plaintext, + false, + ) + } + fn create_sample_external_kv_file_with_optional_encryption( + opt_cipher_info: Option, + master_key_configs: Vec, + master_key_based_data_encryption_method: EncryptionMethod, + compression: bool, + ) -> Result<(TempDir, StorageBackend, KvMeta, Vec)> { let ext_dir = tempfile::tempdir()?; let file_name = "v1/t000001/abc.log"; let file_path = ext_dir.path().join(file_name); std::fs::create_dir_all(file_path.parent().unwrap())?; - let file = File::create(file_path).unwrap(); - let mut buff = BufWriter::new(file); + let file = block_on_external_io(tokio::fs::File::create(file_path.clone())).unwrap(); + + // write to a buffer first, later flush to disk + // + let mut file_buffer = Vec::new(); + let cursor = Cursor::new(&mut file_buffer); + let buf_writer = tokio::io::BufWriter::new(cursor); + let mut kv_meta = KvMeta::default(); + + // writer should compress the data first then encrypt, + // wrapping zstdEncoder around Encrypter + // + let writer = if let Some(cipher_info) = opt_cipher_info { + let iv = Iv::new_ctr().unwrap(); + // update meta + // + let mut encryption_info = encryptionpb::FileEncryptionInfo::new(); + encryption_info.set_file_iv(iv.as_slice().to_vec()); + encryption_info.set_encryption_method(cipher_info.cipher_type); + encryption_info.set_plain_text_data_key(PlainTextDataKey::new()); + kv_meta.set_file_encryption_info(encryption_info); + + Box::new( + EncrypterWriter::new( + buf_writer.compat_write(), + cipher_info.cipher_type, + &cipher_info.cipher_key, + iv, + ) + .unwrap() + .compat_write(), + ) as Box + } else if !master_key_configs.is_empty() { + let multi_master_key_backend = MultiMasterKeyBackend::new(); + block_on_external_io( + multi_master_key_backend + .update_from_proto_if_needed(master_key_configs, create_async_backend), + ) + .unwrap(); + + let iv = Iv::new_ctr().unwrap(); + let plaintext_data_key = multi_master_key_backend + .generate_data_key(master_key_based_data_encryption_method) + .unwrap(); + + let encryption_info = + block_on_external_io(multi_master_key_backend.encrypt(&plaintext_data_key)) + .unwrap(); + + let mut encryption_info_proto = encryptionpb::FileEncryptionInfo::new(); + let mut master_key_proto = MasterKeyBased::new(); + encryption_info_proto.set_file_iv(iv.as_slice().to_vec()); + encryption_info_proto.set_encryption_method(master_key_based_data_encryption_method); + master_key_proto.set_data_key_encrypted_content(protobuf::RepeatedField::from_vec( + vec![encryption_info], + )); + encryption_info_proto.set_master_key_based(master_key_proto); + kv_meta.set_file_encryption_info(encryption_info_proto); + + Box::new( + EncrypterWriter::new( + buf_writer.compat_write(), + master_key_based_data_encryption_method, + &plaintext_data_key, + iv, + ) + .unwrap() + .compat_write(), + ) as Box + } else { + Box::new(buf_writer) as Box + }; + + let mut writer = if compression { + Box::new(ZstdEncoder::new(writer)) as Box + } else { + writer + }; let kvs = vec![ (b"t1_r01".to_vec(), b"tidb".to_vec()), @@ -1704,23 +1964,45 @@ mod tests { let mut sha256 = Hasher::new(MessageDigest::sha256()).unwrap(); let mut len = 0; + let mut buf = vec![]; for kv in kvs { let encoded = EventEncoder::encode_event(&kv.0, &kv.1); for slice in encoded { - len += buff.write(slice.as_ref()).unwrap(); + len += block_on_external_io(writer.write(slice.as_ref())).unwrap(); sha256.update(slice.as_ref()).unwrap(); + buf.extend_from_slice(slice.as_ref()); } } + block_on_external_io(writer.flush()).unwrap(); + drop(writer); + + // calc checksum of the file buffer + // + if kv_meta.has_file_encryption_info() { + let mut tmp_buf = Vec::new(); + let (mut checksum_reader, hasher) = + Sha256Reader::new(Cursor::new(&mut file_buffer)).unwrap(); + checksum_reader.read_to_end(&mut tmp_buf).unwrap(); + let checksum = hasher.lock().unwrap().finish().unwrap().to_vec(); + kv_meta.mut_file_encryption_info().set_checksum(checksum); + } + + // actually write to disk + // + let mut buf_writer = tokio::io::BufWriter::new(file); + block_on_external_io(buf_writer.write_all(&file_buffer)).unwrap(); + block_on_external_io(buf_writer.flush()).unwrap(); - let mut kv_meta = KvMeta::default(); kv_meta.set_name(file_name.to_string()); kv_meta.set_cf(String::from("default")); kv_meta.set_is_delete(false); kv_meta.set_length(len as _); kv_meta.set_sha256(sha256.finish().unwrap().to_vec()); - + if compression { + kv_meta.set_compression_type(CompressionType::Zstd); + } let backend = external_storage::make_local_backend(ext_dir.path()); - Ok((ext_dir, backend, kv_meta, buff.buffer().to_vec())) + Ok((ext_dir, backend, kv_meta, buf)) } fn create_sample_external_rawkv_sst_file( @@ -1746,7 +2028,7 @@ mod tests { fn get_encoded_key(key: &[u8], ts: u64) -> Vec { keys::data_key( - txn_types::Key::from_raw(key) + Key::from_raw(key) .append_ts(TimeStamp::new(ts)) .as_encoded(), ) @@ -1875,6 +2157,8 @@ mod tests { input_len, Some(hash256), 8192, + None, + None, )) .unwrap(); assert_eq!(&*output, data); @@ -1893,9 +2177,11 @@ mod tests { 0, None, usize::MAX, + None, + None, )) .unwrap_err(); - assert_eq!(err.kind(), io::ErrorKind::TimedOut); + assert_eq!(err.kind(), ErrorKind::TimedOut); } #[test] @@ -1916,11 +2202,13 @@ mod tests { len, Some(sha_256.clone()), 0, + None, + None, )) .unwrap(); assert_eq!(&output, data); - // test without expected_sha245. + // test without expected_sha256. reader = data; let output = block_on_external_io(read_external_storage_info_buff( &mut reader, @@ -1928,11 +2216,13 @@ mod tests { len, None, 0, + None, + None, )) .unwrap(); assert_eq!(&output, data); - // test with wrong expectd_len. + // test with wrong expected len. reader = data; let err = block_on_external_io(read_external_storage_info_buff( &mut reader, @@ -1940,6 +2230,8 @@ mod tests { len + 1, Some(sha_256.clone()), 0, + None, + None, )) .unwrap_err(); assert!(err.to_string().contains("length not match")); @@ -1952,6 +2244,8 @@ mod tests { len, Some(sha_256[..sha_256.len() - 1].to_vec()), 0, + None, + None, )) .unwrap_err(); assert!(err.to_string().contains("sha256 not match")); @@ -1968,14 +2262,16 @@ mod tests { 0, None, usize::MAX, + None, + None, )) .unwrap_err(); - assert_eq!(err.kind(), io::ErrorKind::TimedOut); + assert_eq!(err.kind(), ErrorKind::TimedOut); } #[test] fn test_update_config_memory_use_ratio() { - // create SstImpoter with default. + // create SstImporter with default. let cfg = Config { memory_use_ratio: 0.3, ..Default::default() @@ -2022,7 +2318,7 @@ mod tests { } #[test] - fn test_do_read_kv_file() { + fn test_download_kv_file_to_mem_cache() { // create a sample kv file. let (_temp_dir, backend, kv_meta, buff) = create_sample_external_kv_file().unwrap(); @@ -2038,17 +2334,17 @@ mod tests { ) .unwrap(); let ext_storage = { - importer.wrap_kms( + importer.auto_encrypt_local_file_if_needed( importer.external_storage_or_cache(&backend, "").unwrap(), - false, ) }; - // test do_read_kv_file() - let output = block_on_external_io(importer.do_read_kv_file( + let output = block_on_external_io(importer.download_kv_file_to_mem_cache( &kv_meta, ext_storage, &Limiter::new(f64::INFINITY), + None, + None, )) .unwrap(); @@ -2058,7 +2354,7 @@ mod tests { output ); - // Do not shrint nothing. + // Do not shrink nothing. let shrink_size = importer.shrink_by_tick(); assert_eq!(shrink_size, 0); assert_eq!(importer.file_locks.len(), 1); @@ -2079,7 +2375,7 @@ mod tests { } #[test] - fn test_read_kv_files_from_external_storage() { + fn test_download_kv_files_from_external_storage_to_mem() { // create a sample kv file. let (_temp_dir, backend, kv_meta, buff) = create_sample_external_kv_file().unwrap(); @@ -2095,20 +2391,19 @@ mod tests { ) .unwrap(); let ext_storage = { - let inner = importer.wrap_kms( + let inner = importer.auto_encrypt_local_file_if_needed( importer.external_storage_or_cache(&backend, "").unwrap(), - false, ); Arc::new(inner) }; // test read all of the file. - let restore_config = external_storage::RestoreConfig { - expected_sha256: Some(kv_meta.get_sha256().to_vec()), + let restore_config = RestoreConfig { + expected_plaintext_file_checksum: Some(kv_meta.get_sha256().to_vec()), ..Default::default() }; - let output = block_on_external_io(importer.read_kv_files_from_external_storage( + let output = block_on_external_io(importer.download_kv_files_from_external_storage_to_mem( kv_meta.get_length(), kv_meta.get_name(), ext_storage.clone(), @@ -2126,12 +2421,12 @@ mod tests { // test read range of the file. let (offset, len) = (5, 16); - let restore_config = external_storage::RestoreConfig { + let restore_config = RestoreConfig { range: Some((offset, len)), ..Default::default() }; - let output = block_on_external_io(importer.read_kv_files_from_external_storage( + let output = block_on_external_io(importer.download_kv_files_from_external_storage_to_mem( len, kv_meta.get_name(), ext_storage, @@ -2157,15 +2452,14 @@ mod tests { let importer = SstImporter::::new( &cfg, import_dir, - Some(key_manager), + Some(key_manager.clone()), ApiVersion::V1, false, ) .unwrap(); let ext_storage = { - importer.wrap_kms( + importer.auto_encrypt_local_file_if_needed( importer.external_storage_or_cache(&backend, "").unwrap(), - false, ) }; let path = importer @@ -2176,16 +2470,18 @@ mod tests { .unwrap(); // test do_download_kv_file(). - assert!(importer.import_support_download()); - let output = block_on_external_io(importer.read_from_kv_file( + assert!(importer.download_to_disk_only()); + let output = block_on_external_io(importer.download_kv_file( &kv_meta, ext_storage, &backend, &Limiter::new(f64::INFINITY), + None, + Vec::new(), )) .unwrap(); assert_eq!(*output, buff); - check_file_exists(&path.save, None); + check_file_exists(&path.save, Some(&*key_manager)); // test shrink nothing. let shrint_files_cnt = importer.shrink_by_tick(); @@ -2197,7 +2493,7 @@ mod tests { } let shrint_files_cnt = importer.shrink_by_tick(); assert_eq!(shrint_files_cnt, 1); - check_file_not_exists(&path.save, None); + check_file_not_exists(&path.save, Some(&*key_manager)); } #[test] @@ -2220,14 +2516,13 @@ mod tests { // perform download file into .temp dir. let file_name = "sample.sst"; let path = importer.dir.get_import_path(file_name).unwrap(); - let restore_config = external_storage::RestoreConfig::default(); + let restore_config = RestoreConfig::default(); importer .download_file_from_external_storage( meta.get_length(), file_name, path.temp.clone(), &backend, - true, &Limiter::new(f64::INFINITY), restore_config, ) @@ -2248,15 +2543,15 @@ mod tests { let importer = SstImporter::::new( &Config::default(), import_dir, - Some(key_manager), + Some(key_manager.clone()), ApiVersion::V1, false, ) .unwrap(); let path = importer.dir.get_import_path(kv_meta.get_name()).unwrap(); - let restore_config = external_storage::RestoreConfig { - expected_sha256: Some(kv_meta.get_sha256().to_vec()), + let restore_config = RestoreConfig { + expected_plaintext_file_checksum: Some(kv_meta.get_sha256().to_vec()), ..Default::default() }; importer @@ -2265,13 +2560,13 @@ mod tests { kv_meta.get_name(), path.temp.clone(), &backend, - false, &Limiter::new(f64::INFINITY), restore_config, ) .unwrap(); - assert!(check_file_is_same( + check_file_exists(&path.temp, Some(&key_manager)); + assert!(!check_file_is_same( &_temp_dir.path().join(kv_meta.get_name()), &path.temp, )); @@ -2347,7 +2642,7 @@ mod tests { .unwrap(); let db_path = temp_dir.path().join("db"); - let env = get_env(Some(key_manager), None /* io_rate_limiter */).unwrap(); + let env = get_env(Some(key_manager.clone()), None /* io_rate_limiter */).unwrap(); let db = new_test_engine_with_env(db_path.to_str().unwrap(), DATA_CFS, env.clone()); let range = importer @@ -2372,6 +2667,12 @@ mod tests { assert!(sst_file_metadata.is_file()); assert_eq!(sst_file_metadata.len(), meta.get_length()); + // verified the tmp files are correctly cleaned up + check_file_not_exists( + importer.dir.join_for_read(&meta).unwrap().temp.as_path(), + Some(&*key_manager), + ); + // verifies the SST content is correct. let sst_reader = new_sst_reader(sst_file_path.to_str().unwrap(), Some(env)); sst_reader.verify_checksum().unwrap(); @@ -3026,7 +3327,7 @@ mod tests { let mut importer = SstImporter::::new(&cfg, &importer_dir, None, ApiVersion::V1, false) .unwrap(); - importer.set_compression_type(CF_DEFAULT, Some(SstCompressionType::Zstd)); + importer.set_compression_type(CF_DEFAULT, Some(Zstd)); let db_path = importer_dir.path().join("db"); let db = new_test_engine(db_path.to_str().unwrap(), DATA_CFS); @@ -3081,7 +3382,7 @@ mod tests { false, ) .unwrap(); - assert_eq!(importer.import_support_download(), false); + assert_eq!(importer.download_to_disk_only(), false); let import_dir = tempfile::tempdir().unwrap(); let importer = SstImporter::::new( @@ -3095,7 +3396,7 @@ mod tests { false, ) .unwrap(); - assert_eq!(importer.import_support_download(), true); + assert_eq!(importer.download_to_disk_only(), true); } #[test] @@ -3164,4 +3465,119 @@ mod tests { let _buff = v.0.clone(); assert_eq!(v.0.ref_count(), 2); } + + #[test] + fn test_download_kv_with_no_encryption() { + // test both on disk and in mem case + // + test_download_kv_with_optional_encryption(None, Vec::new(), true, true); + test_download_kv_with_optional_encryption(None, Vec::new(), false, true); + test_download_kv_with_optional_encryption(None, Vec::new(), true, false); + test_download_kv_with_optional_encryption(None, Vec::new(), false, false); + } + + #[test] + fn test_download_kv_with_plaintext_data_key() { + let data_key: [u8; 32] = rand::thread_rng().gen(); + let mut cipher = CipherInfo::new(); + cipher.set_cipher_key(data_key.to_vec()); + cipher.set_cipher_type(EncryptionMethod::Aes256Ctr); + + // test both on disk and in mem case + // + test_download_kv_with_optional_encryption(Some(cipher.clone()), Vec::new(), true, true); + test_download_kv_with_optional_encryption(Some(cipher.clone()), Vec::new(), false, true); + test_download_kv_with_optional_encryption(Some(cipher.clone()), Vec::new(), true, false); + test_download_kv_with_optional_encryption(Some(cipher), Vec::new(), false, false); + } + + #[test] + fn test_download_kv_with_master_key_based() { + // set up file backed master key + // + let hex_bytes = encryption::test_utils::generate_random_master_key(); + let (path, _dir) = encryption::test_utils::create_master_key_file_test_only(&hex_bytes); + + let mut master_key_file_proto = MasterKeyFile::new(); + master_key_file_proto.set_path(path.to_string_lossy().into_owned()); + + let mut master_key_proto = MasterKey::new(); + master_key_proto.set_file(master_key_file_proto); + + let master_key_proto_vec = vec![master_key_proto]; + + // test both on disk and in mem case + // + test_download_kv_with_optional_encryption(None, master_key_proto_vec.clone(), true, true); + test_download_kv_with_optional_encryption(None, master_key_proto_vec.clone(), false, true); + test_download_kv_with_optional_encryption(None, master_key_proto_vec.clone(), true, false); + test_download_kv_with_optional_encryption(None, master_key_proto_vec.clone(), false, false); + } + + fn test_download_kv_with_optional_encryption( + opt_cipher_info: Option, + master_key_configs: Vec, + in_mem: bool, + with_local_file_encryption: bool, + ) { + // set up external kv file + // + let (_dir, storage_backend, kv_meta, file_content) = + create_sample_external_kv_file_with_optional_encryption( + opt_cipher_info.clone(), + master_key_configs.clone(), + EncryptionMethod::Aes256Ctr, + true, + ) + .unwrap(); + + // set up importer + // + let import_dir = tempfile::tempdir().unwrap(); + let opt_key_manager = if with_local_file_encryption { + let (_, key_manager) = new_key_manager_for_test(); + Some(key_manager) + } else { + None + }; + let cfg = Config { + memory_use_ratio: if in_mem { 0.5 } else { 0.0 }, + ..Default::default() + }; + let importer = SstImporter::::new( + &cfg, + import_dir, + opt_key_manager.clone(), + ApiVersion::V1, + false, + ) + .unwrap(); + let ext_storage = { + importer.auto_encrypt_local_file_if_needed( + importer + .external_storage_or_cache(&storage_backend, "") + .unwrap(), + ) + }; + let path = importer + .dir + .get_import_path( + format!("{}_{}", kv_meta.get_name(), kv_meta.get_range_offset()).as_str(), + ) + .unwrap(); + + let output = block_on_external_io(importer.download_kv_file( + &kv_meta, + ext_storage, + &storage_backend, + &Limiter::new(f64::INFINITY), + opt_cipher_info, + master_key_configs, + )) + .unwrap(); + assert_eq!(*output, file_content); + if !in_mem { + check_file_exists(&path.save, opt_key_manager.as_deref()); + } + } } diff --git a/src/import/sst_service.rs b/src/import/sst_service.rs index 7e8195ea71a..f5c4bf809f7 100644 --- a/src/import/sst_service.rs +++ b/src/import/sst_service.rs @@ -388,7 +388,7 @@ impl ImportSstService { } } - async fn apply_imp( + async fn do_apply( mut req: ApplyRequest, importer: Arc>, writer: raft_writer::ThrottledTlsEngineWriter, @@ -406,10 +406,9 @@ impl ImportSstService { metas.push(req.take_meta()); rules.push(req.take_rewrite_rule()); } - let ext_storage = importer.wrap_kms( + let ext_storage = importer.auto_encrypt_local_file_if_needed( importer .external_storage_or_cache(req.get_storage_backend(), req.get_storage_cache_id())?, - false, ); let mut inflight_futures = VecDeque::new(); @@ -417,11 +416,13 @@ impl ImportSstService { let mut tasks = metas.iter().zip(rules.iter()).peekable(); while let Some((meta, rule)) = tasks.next() { let buff = importer - .read_from_kv_file( + .download_kv_file( meta, ext_storage.clone(), req.get_storage_backend(), &limiter, + req.cipher_info.clone().take(), + req.master_keys.clone().to_vec(), ) .await?; if let Some(mut r) = importer.do_apply_kv_file( @@ -834,17 +835,17 @@ impl ImportSst for ImportSstService { let mut resp = ApplyResponse::default(); if get_disk_status(0) != DiskUsage::Normal { resp.set_error(Error::DiskSpaceNotEnough.into()); - return crate::send_rpc_response!(Ok(resp), sink, label, start); + return send_rpc_response!(Ok(resp), sink, label, start); } - match Self::apply_imp(req, importer, applier, limiter, max_raft_size).await { + match Self::do_apply(req, importer, applier, limiter, max_raft_size).await { Ok(Some(r)) => resp.set_range(r), Err(e) => resp.set_error(e), _ => {} } debug!("finished apply kv file with {:?}", resp); - crate::send_rpc_response!(Ok(resp), sink, label, start); + send_rpc_response!(Ok(resp), sink, label, start); }; self.threads.spawn(handle_task); } From b88b86b60a94b7cd5b912459fc72394c019aa384 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Wed, 25 Sep 2024 11:17:53 +0800 Subject: [PATCH 086/144] raftkv: fix inaccurate async write duration metric (#17581) close tikv/tikv#17579 Fix inaccurate storage async write duration metric, which mistakenly included task wait time in the scheduler worker pool. This occurs because the metric is observed in a future running on the scheduler worker pool, leading to inflated values, especially under load. This can be misleading and cause confusion during troubleshooting. This commit corrects the metric by observing it in the async write callback. Signed-off-by: Neil Shen Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- src/server/raftkv/mod.rs | 87 ++++++++++++++++++--------------------- src/server/raftkv2/mod.rs | 43 +++++++++---------- 2 files changed, 60 insertions(+), 70 deletions(-) diff --git a/src/server/raftkv/mod.rs b/src/server/raftkv/mod.rs index 7eff47883e7..f824a07a44c 100644 --- a/src/server/raftkv/mod.rs +++ b/src/server/raftkv/mod.rs @@ -46,7 +46,7 @@ use raftstore::{ router::{LocalReadRouter, RaftStoreRouter, ReadContext}, store::{ self, util::encode_start_ts_into_flag_data, Callback as StoreCallback, RaftCmdExtraOpts, - ReadCallback, ReadIndexContext, ReadResponse, RegionSnapshot, StoreMsg, WriteResponse, + ReadIndexContext, ReadResponse, RegionSnapshot, StoreMsg, WriteResponse, }, }; use range_cache_memory_engine::RangeCacheMemoryEngine; @@ -57,7 +57,7 @@ use tikv_util::{ future::{paired_future_callback, paired_must_called_future_callback}, time::Instant, }; -use tracker::GLOBAL_TRACKERS; +use tracker::{get_tls_tracker_token, GLOBAL_TRACKERS}; use txn_types::{Key, TimeStamp, TxnExtra, TxnExtraScheduler, WriteBatchFlags}; use super::metrics::*; @@ -550,6 +550,10 @@ where }); let mut res = match on_write_result::(resp) { Ok(CmdRes::Resp(_)) => { + ASYNC_REQUESTS_COUNTER_VEC.write.success.inc(); + ASYNC_REQUESTS_DURATIONS_VEC + .write + .observe(begin_instant.saturating_elapsed_secs()); fail_point!("raftkv_async_write_finish"); Ok(()) } @@ -583,20 +587,9 @@ where tx.notify(res); } rx.inspect(move |ev| { - let WriteEvent::Finished(res) = ev else { - return; - }; - match res { - Ok(()) => { - ASYNC_REQUESTS_COUNTER_VEC.write.success.inc(); - ASYNC_REQUESTS_DURATIONS_VEC - .write - .observe(begin_instant.saturating_elapsed_secs()); - } - Err(e) => { - let status_kind = get_status_kind_from_engine_error(e); - ASYNC_REQUESTS_COUNTER_VEC.write.get(status_kind).inc(); - } + if let WriteEvent::Finished(Err(e)) = ev { + let status_kind = get_status_kind_from_engine_error(e); + ASYNC_REQUESTS_COUNTER_VEC.write.get(status_kind).inc(); } }) } @@ -722,10 +715,38 @@ where let mut cmd = RaftCmdRequest::default(); cmd.set_header(header); cmd.set_requests(vec![req].into()); + let tracker = get_tls_tracker_token(); let store_cb = StoreCallback::read(Box::new(move |resp| { - cb(on_read_result(resp).map_err(Error::into)); + let res = on_read_result(resp).map_err(Error::into); + if res.is_ok() { + let elapse = begin_instant.saturating_elapsed_secs(); + GLOBAL_TRACKERS.with_tracker(tracker, |tracker| { + if tracker.metrics.read_index_propose_wait_nanos > 0 { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_read_index_propose_wait + .observe( + tracker.metrics.read_index_propose_wait_nanos as f64 / 1_000_000_000.0, + ); + // snapshot may be handled by lease read in raftstore + if tracker.metrics.read_index_confirm_wait_nanos > 0 { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_read_index_confirm + .observe( + tracker.metrics.read_index_confirm_wait_nanos as f64 + / 1_000_000_000.0, + ); + } + } else if tracker.metrics.local_read { + ASYNC_REQUESTS_DURATIONS_VEC + .snapshot_local_read + .observe(elapse); + } + }); + ASYNC_REQUESTS_DURATIONS_VEC.snapshot.observe(elapse); + ASYNC_REQUESTS_COUNTER_VEC.snapshot.success.inc(); + } + cb(res); })); - let tracker = store_cb.read_tracker().unwrap(); let read_ctx = ReadContext::new(ctx.read_id, ctx.start_ts.map(|ts| ts.into_inner())); if res.is_ok() { @@ -756,35 +777,7 @@ where }; Err(e) } - Ok(CmdRes::Snap(s)) => { - let elapse = begin_instant.saturating_elapsed_secs(); - GLOBAL_TRACKERS.with_tracker(tracker, |tracker| { - if tracker.metrics.read_index_propose_wait_nanos > 0 { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_read_index_propose_wait - .observe( - tracker.metrics.read_index_propose_wait_nanos as f64 - / 1_000_000_000.0, - ); - // snapshot may be handled by lease read in raftstore - if tracker.metrics.read_index_confirm_wait_nanos > 0 { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_read_index_confirm - .observe( - tracker.metrics.read_index_confirm_wait_nanos as f64 - / 1_000_000_000.0, - ); - } - } else if tracker.metrics.local_read { - ASYNC_REQUESTS_DURATIONS_VEC - .snapshot_local_read - .observe(elapse); - } - }); - ASYNC_REQUESTS_DURATIONS_VEC.snapshot.observe(elapse); - ASYNC_REQUESTS_COUNTER_VEC.snapshot.success.inc(); - Ok(s) - } + Ok(CmdRes::Snap(s)) => Ok(s), Err(e) => { let status_kind = get_status_kind_from_engine_error(&e); ASYNC_REQUESTS_COUNTER_VEC.snapshot.get(status_kind).inc(); diff --git a/src/server/raftkv2/mod.rs b/src/server/raftkv2/mod.rs index 2f8bfb3d53a..8b76d69da3e 100644 --- a/src/server/raftkv2/mod.rs +++ b/src/server/raftkv2/mod.rs @@ -244,6 +244,10 @@ impl tikv_kv::Engine for RaftKv2 { .observe(elapse); } }); + // The observed snapshot duration is larger than the actual + // snapshot duration, because it includes the waiting time + // of this future. + // TODO: Fix the inaccuracy, see #17581. ASYNC_REQUESTS_DURATIONS_VEC.snapshot.observe(elapse); ASYNC_REQUESTS_COUNTER_VEC.snapshot.success.inc(); Ok(snap) @@ -323,16 +327,20 @@ impl tikv_kv::Engine for RaftKv2 { if WriteEvent::subscribed_committed(subscribed) { builder.subscribe_committed(); } - if let Some(cb) = on_applied { - builder.before_set(move |resp| { - let mut res = if !resp.get_header().has_error() { - Ok(()) - } else { - Err(tikv_kv::Error::from(resp.get_header().get_error().clone())) - }; + builder.before_set(move |resp| { + let mut res = if !resp.get_header().has_error() { + ASYNC_REQUESTS_COUNTER_VEC.write.success.inc(); + ASYNC_REQUESTS_DURATIONS_VEC + .write + .observe(begin_instant.saturating_elapsed_secs()); + Ok(()) + } else { + Err(tikv_kv::Error::from(resp.get_header().get_error().clone())) + }; + if let Some(cb) = on_applied { cb(&mut res); - }); - } + } + }); let (ch, sub) = builder.build(); let res = if inject_region_not_found { ch.report_error(cmd_resp::new_error(Error::RegionNotFound(region_id))); @@ -358,20 +366,9 @@ impl tikv_kv::Engine for RaftKv2 { early_err: res.err(), }) .inspect(move |ev| { - let WriteEvent::Finished(res) = ev else { - return; - }; - match res { - Ok(()) => { - ASYNC_REQUESTS_COUNTER_VEC.write.success.inc(); - ASYNC_REQUESTS_DURATIONS_VEC - .write - .observe(begin_instant.saturating_elapsed_secs()); - } - Err(e) => { - let status_kind = get_status_kind_from_engine_error(e); - ASYNC_REQUESTS_COUNTER_VEC.write.get(status_kind).inc(); - } + if let WriteEvent::Finished(Err(e)) = ev { + let status_kind = get_status_kind_from_engine_error(e); + ASYNC_REQUESTS_COUNTER_VEC.write.get(status_kind).inc(); } }) } From b8d5a89ae56434ad4a9a20ec1feb9f34817b90f2 Mon Sep 17 00:00:00 2001 From: glorv Date: Wed, 25 Sep 2024 13:53:08 +0800 Subject: [PATCH 087/144] resource_control: add new config `priority_ctl_strategy` to enhance priority control (#17544) ref tikv/tikv#17531 Add a new config `priority_ctl_strategy` to allow user choose different limit strategy to control low-priority tasks. Signed-off-by: glorv --- components/resource_control/src/config.rs | 105 ++++++++++++++++++ components/resource_control/src/lib.rs | 18 +-- components/resource_control/src/metrics.rs | 2 +- .../resource_control/src/resource_group.rs | 18 ++- components/resource_control/src/worker.rs | 34 +++--- components/server/src/server.rs | 11 +- components/server/src/server2.rs | 10 +- etc/config-template.toml | 16 +++ src/config/mod.rs | 4 +- tests/integrations/config/mod.rs | 7 +- tests/integrations/config/test-custom.toml | 1 + 11 files changed, 185 insertions(+), 41 deletions(-) create mode 100644 components/resource_control/src/config.rs diff --git a/components/resource_control/src/config.rs b/components/resource_control/src/config.rs new file mode 100644 index 00000000000..e4429fe6a27 --- /dev/null +++ b/components/resource_control/src/config.rs @@ -0,0 +1,105 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. +use std::{fmt, sync::Arc}; + +use online_config::{ConfigManager, ConfigValue, OnlineConfig}; +use serde::{Deserialize, Serialize}; +use tikv_util::config::VersionTrack; + +#[derive(Clone, Serialize, Deserialize, PartialEq, Debug, OnlineConfig)] +#[serde(default)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + #[online_config(skip)] + pub enabled: bool, + pub priority_ctl_strategy: PriorityCtlStrategy, +} + +impl Default for Config { + fn default() -> Self { + Self { + enabled: true, + priority_ctl_strategy: PriorityCtlStrategy::Moderate, + } + } +} + +/// PriorityCtlStrategy controls how resource quota is granted to low-priority +/// tasks. +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum PriorityCtlStrategy { + /// Prioritize the throughput and latency of high-priority tasks, result in + /// low-priority tasks running much slower. + Aggressive, + #[default] + /// Try to balance between the latency of high-prioirty tasks and throughput + /// of low-priority tasks. + Moderate, + /// Prioritize of overall throughput, the latency of high-priority tasks may + /// be significantly impacted when the overall load is high. + Conservative, +} + +impl PriorityCtlStrategy { + pub fn to_resource_util_percentage(self) -> f64 { + match self { + Self::Aggressive => 0.5, + Self::Moderate => 0.7, + Self::Conservative => 0.9, + } + } +} + +impl fmt::Display for PriorityCtlStrategy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let str_value = match *self { + Self::Aggressive => "aggressive", + Self::Moderate => "moderate", + Self::Conservative => "conservative", + }; + f.write_str(str_value) + } +} + +impl From for ConfigValue { + fn from(v: PriorityCtlStrategy) -> Self { + ConfigValue::String(format!("{}", v)) + } +} + +impl TryFrom for PriorityCtlStrategy { + type Error = String; + fn try_from(v: ConfigValue) -> Result { + if let ConfigValue::String(s) = v { + match s.as_str() { + "aggressive" => Ok(Self::Aggressive), + "moderate" => Ok(Self::Moderate), + "conservative" => Ok(Self::Conservative), + s => Err(format!("invalid config value: {}", s)), + } + } else { + panic!("expect ConfigValue::String, got: {:?}", v); + } + } +} + +pub struct ResourceContrlCfgMgr { + config: Arc>, +} + +impl ResourceContrlCfgMgr { + pub fn new(config: Arc>) -> Self { + Self { config } + } +} + +impl ConfigManager for ResourceContrlCfgMgr { + fn dispatch(&mut self, change: online_config::ConfigChange) -> online_config::Result<()> { + let cfg_str = format!("{:?}", change); + let res = self.config.update(|c| c.update(change)); + if res.is_ok() { + tikv_util::info!("update resource control config"; "change" => cfg_str); + } + res + } +} diff --git a/components/resource_control/src/lib.rs b/components/resource_control/src/lib.rs index b9a79e1f9ae..d3b2a7abffb 100644 --- a/components/resource_control/src/lib.rs +++ b/components/resource_control/src/lib.rs @@ -3,9 +3,7 @@ use std::sync::Arc; -use online_config::OnlineConfig; use pd_client::RpcClient; -use serde::{Deserialize, Serialize}; mod resource_group; pub use resource_group::{ @@ -25,6 +23,8 @@ pub use service::ResourceManagerService; pub mod channel; pub use channel::ResourceMetered; +pub mod config; + mod resource_limiter; pub use resource_limiter::ResourceLimiter; use tikv_util::worker::Worker; @@ -35,20 +35,6 @@ use worker::{ mod metrics; pub mod worker; -#[derive(Clone, Serialize, Deserialize, PartialEq, Debug, OnlineConfig)] -#[serde(default)] -#[serde(rename_all = "kebab-case")] -pub struct Config { - #[online_config(skip)] - pub enabled: bool, -} - -impl Default for Config { - fn default() -> Self { - Self { enabled: true } - } -} - pub fn start_periodic_tasks( mgr: &Arc, pd_client: Arc, diff --git a/components/resource_control/src/metrics.rs b/components/resource_control/src/metrics.rs index da40021659f..cdbe9788ba4 100644 --- a/components/resource_control/src/metrics.rs +++ b/components/resource_control/src/metrics.rs @@ -29,7 +29,7 @@ lazy_static! { ) .unwrap(); pub static ref BACKGROUND_TASK_RESOURCE_UTILITATION_VEC: IntGaugeVec = register_int_gauge_vec!( - "tikv_resource_control_bg_resource_utilitation", + "tikv_resource_control_bg_resource_utilization", "The total resource utilization percentage of background tasks", &["type"] ) diff --git a/components/resource_control/src/resource_group.rs b/components/resource_control/src/resource_group.rs index c78179c4a51..1332ed1950d 100644 --- a/components/resource_control/src/resource_group.rs +++ b/components/resource_control/src/resource_group.rs @@ -20,13 +20,14 @@ use kvproto::{ }; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use tikv_util::{ + config::VersionTrack, info, resource_control::{TaskMetadata, TaskPriority, DEFAULT_RESOURCE_GROUP_NAME}, time::Instant, }; use yatp::queue::priority::TaskPriorityProvider; -use crate::{metrics::deregister_metrics, resource_limiter::ResourceLimiter}; +use crate::{config::Config, metrics::deregister_metrics, resource_limiter::ResourceLimiter}; // a read task cost at least 50us. const DEFAULT_PRIORITY_PER_READ_TASK: u64 = 50; @@ -66,10 +67,18 @@ pub struct ResourceGroupManager { version_generator: AtomicU64, // the shared resource limiter of each priority priority_limiters: [Arc; TaskPriority::PRIORITY_COUNT], + // lastest config. + config: Arc>, } impl Default for ResourceGroupManager { fn default() -> Self { + Self::new(Config::default()) + } +} + +impl ResourceGroupManager { + pub fn new(config: Config) -> Self { let priority_limiters = TaskPriority::priorities().map(|p| { Arc::new(ResourceLimiter::new( p.as_str().to_owned(), @@ -85,6 +94,7 @@ impl Default for ResourceGroupManager { registry: Default::default(), version_generator: AtomicU64::new(0), priority_limiters, + config: Arc::new(VersionTrack::new(config)), }; // init the default resource group by default. @@ -101,9 +111,7 @@ impl Default for ResourceGroupManager { manager } -} -impl ResourceGroupManager { #[inline] pub fn get_group_count(&self) -> u64 { self.group_count.load(Ordering::Relaxed) @@ -219,6 +227,10 @@ impl ResourceGroupManager { self.resource_groups.get(&name.to_ascii_lowercase()) } + pub fn get_config(&self) -> &Arc> { + &self.config + } + pub fn get_all_resource_groups(&self) -> Vec { self.resource_groups .iter() diff --git a/components/resource_control/src/worker.rs b/components/resource_control/src/worker.rs index ae4b6b51b47..4bf8d1e457b 100644 --- a/components/resource_control/src/worker.rs +++ b/components/resource_control/src/worker.rs @@ -419,7 +419,7 @@ impl PriorityLimiterAdjustWorker { } }; - if process_cpu_stats.current_used < process_cpu_stats.total_quota * 0.5 { + if process_cpu_stats.current_used < process_cpu_stats.total_quota * 0.3 { if self.is_last_low_cpu { return; } @@ -438,10 +438,10 @@ impl PriorityLimiterAdjustWorker { } self.is_last_low_cpu = false; - let total_reqs: u64 = stats.iter().map(|s| s.req_count).sum(); - let max_reqs = stats.iter().map(|s| s.req_count).max().unwrap(); + let total_cpus: f64 = stats.iter().map(|s| s.cpu_secs).sum(); + let max_cpus = stats.iter().map(|s| s.cpu_secs).fold(0.0, f64::max); // there is only 1 active priority, do not restrict. - if total_reqs * 99 / 100 <= max_reqs { + if total_cpus * 0.99 <= max_cpus { self.trackers .iter() .skip(1) @@ -455,7 +455,15 @@ impl PriorityLimiterAdjustWorker { let cpu_duration: [_; TaskPriority::PRIORITY_COUNT] = array::from_fn(|i| stats[i].cpu_secs); let real_cpu_total: f64 = cpu_duration.iter().sum(); - let expect_pool_cpu_total = real_cpu_total * (process_cpu_stats.total_quota * 0.95) + + let available_quota_percentage = self + .resource_ctl + .get_config() + .value() + .priority_ctl_strategy + .to_resource_util_percentage(); + let expect_pool_cpu_total = real_cpu_total + * (process_cpu_stats.total_quota * available_quota_percentage) / process_cpu_stats.current_used; let mut limits = [0.0; 2]; let level_expected: [_; TaskPriority::PRIORITY_COUNT] = @@ -464,7 +472,7 @@ impl PriorityLimiterAdjustWorker { let mut expect_cpu_time_total = expect_pool_cpu_total - level_expected[0]; // still reserve a minimal cpu quota - let minimal_quota = process_cpu_stats.total_quota / MICROS_PER_SEC * 0.05; + let minimal_quota = process_cpu_stats.total_quota / MICROS_PER_SEC * 0.1; for i in 1..self.trackers.len() { if expect_cpu_time_total < minimal_quota { expect_cpu_time_total = minimal_quota; @@ -494,8 +502,6 @@ struct LimiterStats { cpu_secs: f64, // QuotaLimiter waited secs in total. wait_secs: f64, - // the total number of tasks that are scheduled. - req_count: u64, } struct HistogramTracker { @@ -566,7 +572,6 @@ impl PriorityLimiterStatsTracker { cpu_secs: stats_delta.total_consumed as f64 / MICROS_PER_SEC, wait_secs: stats_delta.total_wait_dur_us as f64 / MICROS_PER_SEC + normed_schedule_wait_dur_secs, - req_count: stats_delta.request_count, } } } @@ -962,6 +967,7 @@ mod tests { .set_rate_limit(f64::INFINITY); }; + #[track_caller] fn check(val: f64, expected: f64) { assert!( (val.is_infinite() && expected.is_infinite()) @@ -1015,7 +1021,7 @@ mod tests { priority_limiters[1].consume(Duration::from_millis(400), IoBytes::default(), true); } worker.adjust(); - check_limiter(f64::INFINITY, 5.2, 1.2); + check_limiter(f64::INFINITY, 3.2, 0.8); reset_quota(&mut worker, 6.4); for _i in 0..100 { @@ -1023,7 +1029,7 @@ mod tests { priority_limiters[1].consume(Duration::from_millis(200), IoBytes::default(), true); } worker.adjust(); - check_limiter(f64::INFINITY, 2.6, 0.6); + check_limiter(f64::INFINITY, 1.6, 0.8); reset_quota(&mut worker, 6.4); for _i in 0..100 { @@ -1039,7 +1045,7 @@ mod tests { priority_limiters[2].consume(Duration::from_millis(320), IoBytes::default(), true); } worker.adjust(); - check_limiter(f64::INFINITY, 5.2, 2.8); + check_limiter(f64::INFINITY, 3.2, 0.8); reset_quota(&mut worker, 6.0); for _i in 0..100 { @@ -1047,12 +1053,12 @@ mod tests { priority_limiters[2].consume(Duration::from_millis(360), IoBytes::default(), true); } worker.adjust(); - check_limiter(f64::INFINITY, 5.2, 5.2); + check_limiter(f64::INFINITY, 3.2, 3.2); // duration too small, unchanged. worker.resource_quota_getter.cpu_used = 6.0; worker.last_adjust_time = Instant::now_coarse() - Duration::from_millis(500); worker.adjust(); - check_limiter(f64::INFINITY, 5.2, 5.2); + check_limiter(f64::INFINITY, 3.2, 3.2); } } diff --git a/components/server/src/server.rs b/components/server/src/server.rs index 4b4db3acb8d..adfd5cf1df9 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -79,7 +79,7 @@ use range_cache_memory_engine::{ config::RangeCacheConfigManager, RangeCacheEngineContext, RangeCacheMemoryEngineStatistics, }; use resolved_ts::{LeadershipResolver, Task}; -use resource_control::ResourceGroupManager; +use resource_control::{config::ResourceContrlCfgMgr, ResourceGroupManager}; use security::SecurityManager; use service::{service_event::ServiceEvent, service_manager::GrpcServiceManager}; use snap_recovery::RecoveryService; @@ -373,7 +373,7 @@ where .create(); let resource_manager = if config.resource_control.enabled { - let mgr = Arc::new(ResourceGroupManager::default()); + let mgr = Arc::new(ResourceGroupManager::new(config.resource_control.clone())); let io_bandwidth = config.storage.io_rate_limit.max_bytes_per_sec.0; resource_control::start_periodic_tasks( &mgr, @@ -667,6 +667,13 @@ where Box::new(cfg_manager), ); + if let Some(resource_ctl) = &self.resource_manager { + cfg_controller.register( + tikv::config::Module::ResourceControl, + Box::new(ResourceContrlCfgMgr::new(resource_ctl.get_config().clone())), + ); + } + let storage_read_pool_handle = if self.core.config.readpool.storage.use_unified_pool() { unified_read_pool.as_ref().unwrap().handle() } else { diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index b0e16b4d431..dde83a9bffd 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -68,7 +68,7 @@ use raftstore_v2::{ }; use range_cache_memory_engine::RangeCacheMemoryEngineStatistics; use resolved_ts::Task; -use resource_control::ResourceGroupManager; +use resource_control::{config::ResourceContrlCfgMgr, ResourceGroupManager}; use security::SecurityManager; use service::{service_event::ServiceEvent, service_manager::GrpcServiceManager}; use tikv::{ @@ -336,7 +336,7 @@ where )); let resource_manager = if config.resource_control.enabled { - let mgr = Arc::new(ResourceGroupManager::default()); + let mgr = Arc::new(ResourceGroupManager::new(config.resource_control.clone())); let io_bandwidth = config.storage.io_rate_limit.max_bytes_per_sec.0; resource_control::start_periodic_tasks( &mgr, @@ -534,6 +534,12 @@ where tikv::config::Module::ResourceMetering, Box::new(cfg_manager), ); + if let Some(resource_ctl) = &self.resource_manager { + cfg_controller.register( + tikv::config::Module::ResourceControl, + Box::new(ResourceContrlCfgMgr::new(resource_ctl.get_config().clone())), + ); + } let storage_read_pool_handle = if self.core.config.readpool.storage.use_unified_pool() { unified_read_pool.as_ref().unwrap().handle() diff --git a/etc/config-template.toml b/etc/config-template.toml index e68e352f7a0..78aa3c31b77 100644 --- a/etc/config-template.toml +++ b/etc/config-template.toml @@ -161,6 +161,22 @@ # max-tasks-per-worker-normal = 2000 # max-tasks-per-worker-low = 2000 +[resource-control] +## Whether to enable resource control. +## When set to true, TiKV will use the priority queue to schedule the queued read/write requests from +## foreground users. The scheduling priority of a request is inversely related to the amount of resources +## already consumed by the resource group that receives this request, and positively related to the quota +## of the corresponding resource group. +# enabled = true + +## Configures the control strategy of low-priority tasks. +## Value options: +## - "aggressive". Prioritize the performance of high-priority tasks, low-priority tasks will run slower. +## - "moderate". Balance the latency of high-prioirty tasks and throughput of low-priority tasks. +## - "conservative". Prioritize of overall throughput, the latency of high-priority tasks may be significantly +## impacted when the overall load is high. +# priority-ctl-strategy = "moderate" + [server] ## Listening address. # addr = "127.0.0.1:20160" diff --git a/src/config/mod.rs b/src/config/mod.rs index 9fbc6eed656..efb8660fd11 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -59,7 +59,7 @@ use raftstore::{ store::{CompactionGuardGeneratorFactory, Config as RaftstoreConfig, SplitConfig}, }; use range_cache_memory_engine::RangeCacheEngineConfig; -use resource_control::Config as ResourceControlConfig; +use resource_control::config::Config as ResourceControlConfig; use resource_metering::Config as ResourceMeteringConfig; use security::SecurityConfig; use serde::{ @@ -4754,6 +4754,7 @@ pub enum Module { Cdc, ResolvedTs, ResourceMetering, + ResourceControl, BackupStream, Quota, Log, @@ -4785,6 +4786,7 @@ impl From<&str> for Module { "cdc" => Module::Cdc, "resolved_ts" => Module::ResolvedTs, "resource_metering" => Module::ResourceMetering, + "resource_control" => Module::ResourceControl, "quota" => Module::Quota, "log" => Module::Log, "memory" => Module::Memory, diff --git a/tests/integrations/config/mod.rs b/tests/integrations/config/mod.rs index 96040e9ea0e..8208c129000 100644 --- a/tests/integrations/config/mod.rs +++ b/tests/integrations/config/mod.rs @@ -24,7 +24,7 @@ use raftstore::{ coprocessor::{Config as CopConfig, ConsistencyCheckMethod}, store::Config as RaftstoreConfig, }; -use resource_control::Config as ResourceControlConfig; +use resource_control::config::{Config as ResourceControlConfig, PriorityCtlStrategy}; use security::SecurityConfig; use slog::Level; use test_util::assert_eq_debug; @@ -893,7 +893,10 @@ fn test_serde_custom_tikv_config() { value .split .optimize_for(value.coprocessor.region_max_size()); - value.resource_control = ResourceControlConfig { enabled: false }; + value.resource_control = ResourceControlConfig { + enabled: false, + priority_ctl_strategy: PriorityCtlStrategy::Aggressive, + }; let custom = read_file_in_project_dir("integrations/config/test-custom.toml"); let mut load: TikvConfig = toml::from_str(&custom).unwrap(); diff --git a/tests/integrations/config/test-custom.toml b/tests/integrations/config/test-custom.toml index 5554c0165c4..e6af548894b 100644 --- a/tests/integrations/config/test-custom.toml +++ b/tests/integrations/config/test-custom.toml @@ -685,3 +685,4 @@ split.split-contained-score = 0.5 [resource-control] enabled = false +priority-ctl-strategy = "aggressive" From d14c413095dd8a6efc6221f104f669c29df21690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=B2=9A?= <36239017+YuJuncen@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:25:50 +0800 Subject: [PATCH 088/144] added crc64 and origin region boundary for log backup (#17407) close tikv/tikv#17406 - Added crc64 / origin region boundary for flushing. - Flush now accepts a single structure `FlushContext`, where includes all observed regions' metadata. Signed-off-by: hillium Signed-off-by: hillium Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 1 + components/backup-stream/Cargo.toml | 1 + components/backup-stream/src/endpoint.rs | 14 +- components/backup-stream/src/lib.rs | 1 + components/backup-stream/src/router.rs | 153 +++++++++++++----- .../backup-stream/src/subscription_manager.rs | 16 +- .../backup-stream/src/subscription_track.rs | 3 +- .../backup-stream/tests/integration/mod.rs | 65 +++++++- 8 files changed, 196 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c991802f94..ff38a902c4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -482,6 +482,7 @@ dependencies = [ "bytes", "chrono", "concurrency_manager", + "crc64fast", "crossbeam", "crossbeam-channel", "dashmap", diff --git a/components/backup-stream/Cargo.toml b/components/backup-stream/Cargo.toml index 025fcb36f04..8907ff7c492 100644 --- a/components/backup-stream/Cargo.toml +++ b/components/backup-stream/Cargo.toml @@ -31,6 +31,7 @@ async-trait = { version = "0.1" } bytes = "1" chrono = { workspace = true } concurrency_manager = { workspace = true } +crc64fast = "0.1" crossbeam = { workspace = true } crossbeam-channel = { workspace = true } dashmap = "5" diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index 67742ab58c5..ee13b640c81 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -60,7 +60,7 @@ use crate::{ metadata::{store::MetaStore, MetadataClient, MetadataEvent, StreamTask}, metrics::{self, TaskStatus}, observer::BackupStreamObserver, - router::{self, ApplyEvents, Router, TaskSelector}, + router::{self, ApplyEvents, FlushContext, Router, TaskSelector}, subscription_manager::{RegionSubscriptionManager, ResolvedRegions}, subscription_track::{Ref, RefMut, ResolveResult, SubscriptionTracer}, try_send, @@ -819,19 +819,25 @@ where } } - fn do_flush(&self, task: String, mut resolved: ResolvedRegions) -> future![Result<()>] { + fn do_flush(&self, task: String, resolved: ResolvedRegions) -> future![Result<()>] { let router = self.range_router.clone(); let store_id = self.store_id; let mut flush_ob = self.flush_observer(); async move { let mut new_rts = resolved.global_checkpoint(); fail::fail_point!("delay_on_flush"); - flush_ob.before(resolved.take_resolve_result()).await; + flush_ob.before(resolved.resolve_results().to_vec()).await; if let Some(rewritten_rts) = flush_ob.rewrite_resolved_ts(&task).await { info!("rewriting resolved ts"; "old" => %new_rts, "new" => %rewritten_rts); new_rts = rewritten_rts.min(new_rts); } - if let Some(rts) = router.do_flush(&task, store_id, new_rts).await { + let cx = FlushContext { + task_name: &task, + store_id, + resolved_regions: &resolved, + resolved_ts: new_rts, + }; + if let Some(rts) = router.do_flush(cx).await { info!("flushing and refreshing checkpoint ts."; "checkpoint_ts" => %rts, "task" => %task, diff --git a/components/backup-stream/src/lib.rs b/components/backup-stream/src/lib.rs index 407c45bcaa3..6d7afa334c9 100644 --- a/components/backup-stream/src/lib.rs +++ b/components/backup-stream/src/lib.rs @@ -1,5 +1,6 @@ // Copyright 2022 TiKV Project Authors. Licensed under Apache-2.0. #![feature(slice_group_by)] +#![feature(trait_alias)] #![feature(result_flattening)] #![feature(assert_matches)] #![feature(test)] diff --git a/components/backup-stream/src/router.rs b/components/backup-stream/src/router.rs index 55e693c2b89..2e707fc325d 100644 --- a/components/backup-stream/src/router.rs +++ b/components/backup-stream/src/router.rs @@ -26,6 +26,7 @@ use kvproto::{ StreamBackupTaskInfo, StreamBackupTaskSecurityConfig_oneof_encryption, }, encryptionpb::{EncryptionMethod, FileEncryptionInfo, MasterKeyBased, PlainTextDataKey}, + metapb::RegionEpoch, raft_cmdpb::CmdType, }; use openssl::hash::{Hasher, MessageDigest}; @@ -60,6 +61,7 @@ use crate::{ errors::{ContextualResultExt, Error}, metadata::StreamTask, metrics::{HANDLE_KV_HISTOGRAM, SKIP_KV_COUNTER}, + subscription_manager::ResolvedRegions, subscription_track::TwoPhaseResolver, tempfiles::{self, ForRead, TempFilePool}, try_send, @@ -152,6 +154,14 @@ pub struct ApplyEvents { region_resolved_ts: u64, } +#[derive(Clone, Copy)] +pub struct FlushContext<'a> { + pub task_name: &'a str, + pub store_id: u64, + pub resolved_regions: &'a ResolvedRegions, + pub resolved_ts: TimeStamp, +} + impl ApplyEvents { /// Convert a [CmdBatch] to a vector of events. Ignoring admin / error /// commands. At the same time, advancing status of the `Resolver` by @@ -691,17 +701,12 @@ impl RouterInner { /// flush the specified task, once success, return the min resolved ts /// of this flush. returns `None` if failed. - #[instrument(skip(self, resolve_to))] - pub async fn do_flush( - &self, - task_name: &str, - store_id: u64, - resolve_to: TimeStamp, - ) -> Option { - let task = self.tasks.get(task_name); + #[instrument(skip(self, cx))] + pub async fn do_flush(&self, cx: FlushContext<'_>) -> Option { + let task = self.tasks.get(cx.task_name); match task { Some(task_handler) => { - let result = task_handler.do_flush(store_id, resolve_to).await; + let result = task_handler.do_flush(cx).await; // set false to flushing whether success or fail task_handler.set_flushing_status(false); @@ -713,7 +718,7 @@ impl RouterInner { try_send!( self.scheduler, Task::FatalError( - TaskSelector::ByName(task_name.to_owned()), + TaskSelector::ByName(cx.task_name.to_owned()), Box::new(e) ) ); @@ -827,6 +832,7 @@ impl TempFileKey { } /// The full name of the file owns the key. + #[allow(clippy::redundant_closure_call)] fn temp_file_name(&self) -> String { let timestamp = (|| { fail::fail_point!("temp_file_name_timestamp", |t| t.map_or_else( @@ -1133,6 +1139,36 @@ impl StreamTaskHandler { Ok(metadata) } + fn fill_region_info(&self, cx: FlushContext<'_>, metas: &mut MetadataInfo) { + let mut rmap = HashMap::, &[u8], &[u8])>::new(); + for res in cx.resolved_regions.resolve_results() { + rmap.entry(res.region.id) + .and_modify(|(epoch, start, end)| { + epoch.push(res.region.get_region_epoch()); + if *start > res.region.start_key.as_slice() { + *start = &res.region.start_key; + } + if *end < res.region.end_key.as_slice() { + *end = &res.region.end_key; + } + }) + .or_insert({ + let r = &res.region; + (vec![r.get_region_epoch()], &r.start_key, &r.end_key) + }); + } + + for fg in metas.file_groups.iter_mut() { + for f in fg.data_files_info.iter_mut() { + if let Some((epoches, start_key, end_key)) = rmap.get(&(f.region_id as _)) { + f.set_region_epoch(epoches.iter().copied().cloned().collect::>().into()); + f.set_region_start_key(start_key.to_vec()); + f.set_region_end_key(end_key.to_vec()); + } + } + } + } + pub fn set_flushing_status_cas(&self, expect: bool, new: bool) -> result::Result { self.flushing .compare_exchange(expect, new, Ordering::SeqCst, Ordering::SeqCst) @@ -1387,11 +1423,7 @@ impl StreamTaskHandler { /// function, and we would use `max(resolved_ts_provided, /// resolved_ts_from_file)`. #[instrument(skip_all)] - pub async fn do_flush( - &self, - store_id: u64, - resolved_ts_provided: TimeStamp, - ) -> Result> { + pub async fn do_flush(&self, cx: FlushContext<'_>) -> Result> { // do nothing if not flushing status. let result: Result> = async move { if !self.is_flushing() { @@ -1404,7 +1436,7 @@ impl StreamTaskHandler { let mut backup_metadata = self .move_to_flushing_files() .await? - .generate_backup_metadata(store_id) + .generate_backup_metadata(cx.store_id) .await?; fail::fail_point!("after_moving_to_flushing_files"); @@ -1418,7 +1450,7 @@ impl StreamTaskHandler { // only after flush is done. backup_metadata.min_resolved_ts = backup_metadata .min_resolved_ts - .max(Some(resolved_ts_provided.into_inner())); + .max(Some(cx.resolved_ts.into_inner())); let rts = backup_metadata.min_resolved_ts; // compress length @@ -1428,6 +1460,8 @@ impl StreamTaskHandler { .map(|d| (d.length, d.data_files_info.len())) .collect::>(); + // flush meta file to storage. + self.fill_region_info(cx, &mut backup_metadata); // flush backup metadata to external storage. self.flush_backup_metadata(backup_metadata).await?; crate::metrics::FLUSH_DURATION @@ -1678,6 +1712,7 @@ struct DataFile { end_key: Vec, number_of_entries: usize, file_size: usize, + crc64xor: u64, } #[derive(Debug)] @@ -1760,6 +1795,7 @@ impl DataFile { file_size: 0, start_key: vec![], end_key: vec![], + crc64xor: 0, }) } @@ -1782,6 +1818,10 @@ impl DataFile { let mut total_size = 0; for mut event in events.events { + let mut digest = crc64fast::Digest::new(); + digest.write(&event.key); + digest.write(&event.value); + self.crc64xor ^= digest.sum64(); let encoded = EventEncoder::encode_event(&event.key, &event.value); let mut size = 0; for slice in encoded { @@ -1844,6 +1884,7 @@ impl DataFile { .map(|bytes| bytes.to_vec()) .map_err(|err| Error::Other(box_err!("openssl hasher failed to init: {}", err)))?, ); + meta.set_crc64xor(self.crc64xor); meta.set_number_of_entries(self.number_of_entries as _); meta.set_max_ts(self.max_ts.into_inner() as _); meta.set_min_ts(self.min_ts.into_inner() as _); @@ -1918,6 +1959,8 @@ mod tests { use super::*; use crate::{config::BackupStreamConfigManager, utils}; + static EMPTY_RESOLVE: ResolvedRegions = ResolvedRegions::new(TimeStamp::zero(), vec![]); + #[derive(Debug)] struct KvEventsBuilder { events: ApplyEvents, @@ -2060,7 +2103,7 @@ mod tests { backend } - async fn task(name: String) -> Result<(StreamBackupTaskInfo, PathBuf)> { + async fn task_handler(name: String) -> Result<(StreamBackupTaskInfo, PathBuf)> { let mut stream_task = StreamBackupTaskInfo::default(); stream_task.set_name(name); let storage_path = std::env::temp_dir().join(format!("{}", uuid::Uuid::new_v4())); @@ -2129,7 +2172,7 @@ mod tests { }, BackupEncryptionManager::default(), ); - let (stream_task, storage_path) = task("dummy".to_owned()).await.unwrap(); + let (stream_task, storage_path) = task_handler("dummy".to_owned()).await.unwrap(); must_register_table(&router, stream_task, 1).await; let start_ts = write_simple_data(&router).await; @@ -2266,7 +2309,13 @@ mod tests { } // do_flush task_handler.set_flushing_status(true); - task_handler.do_flush(1, TimeStamp::new(1)).await.unwrap(); + let cx = FlushContext { + task_name: &task_handler.task.info.name, + store_id: 1, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: TimeStamp::new(1), + }; + task_handler.do_flush(cx).await.unwrap(); assert_eq!(task_handler.flush_failure_count(), 0); assert_eq!(task_handler.files.read().await.is_empty(), true); assert_eq!(task_handler.flushing_files.read().await.is_empty(), true); @@ -2368,25 +2417,26 @@ mod tests { }, BackupEncryptionManager::default(), )); - let (task, _path) = task("error_prone".to_owned()).await?; + let cx = FlushContext { + task_name: "error_prone", + store_id: 42, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: TimeStamp::max(), + }; + let (task, _path) = task_handler("error_prone".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; router.must_mut_task_info("error_prone", |i| { i.storage = Arc::new(ErrorStorage::with_first_time_error(i.storage.clone())) }); check_on_events_result(&router.on_events(build_kv_event(0, 10)).await); - assert!( - router - .do_flush("error_prone", 42, TimeStamp::max()) - .await - .is_none() - ); + assert!(router.do_flush(cx).await.is_none()); check_on_events_result(&router.on_events(build_kv_event(10, 10)).await); let t = router.get_task_handler("error_prone").unwrap(); - let _ = router.do_flush("error_prone", 42, TimeStamp::max()).await; + let _ = router.do_flush(cx).await; assert_eq!(t.total_size() > 0, true); t.set_flushing_status(true); - let _ = router.do_flush("error_prone", 42, TimeStamp::max()).await; + let _ = router.do_flush(cx).await; assert_eq!(t.total_size(), 0); Ok(()) } @@ -2423,7 +2473,13 @@ mod tests { let task = router.get_task_handler("nothing").unwrap(); task.set_flushing_status_cas(false, true).unwrap(); let ts = TimeStamp::compose(TimeStamp::physical_now(), 42); - let rts = router.do_flush("nothing", 1, ts).await.unwrap(); + let cx = FlushContext { + task_name: "nothing", + store_id: 1, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: ts, + }; + let rts = router.do_flush(cx).await.unwrap(); assert_eq!(ts.into_inner(), rts); } @@ -2441,7 +2497,7 @@ mod tests { }, BackupEncryptionManager::default(), )); - let (task, _path) = task("cleanup_test".to_owned()).await?; + let (task, _path) = task_handler("cleanup_test".to_owned()).await?; must_register_table(&router, task, 1).await; write_simple_data(&router).await; let tempfiles = router @@ -2496,19 +2552,20 @@ mod tests { }, BackupEncryptionManager::default(), )); - let (task, _path) = task("flush_failure".to_owned()).await?; + let (task, _path) = task_handler("flush_failure".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; router.must_mut_task_info("flush_failure", |i| { i.storage = Arc::new(ErrorStorage::with_always_error(i.storage.clone())) }); + let cx = FlushContext { + task_name: "flush_failure", + store_id: 42, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: TimeStamp::zero(), + }; for i in 0..=FLUSH_FAILURE_BECOME_FATAL_THRESHOLD { check_on_events_result(&router.on_events(build_kv_event((i * 10) as _, 10)).await); - assert_eq!( - router - .do_flush("flush_failure", 42, TimeStamp::zero()) - .await, - None, - ); + assert_eq!(router.do_flush(cx).await, None,); } let messages = collect_recv(rx); assert!( @@ -2833,7 +2890,7 @@ mod tests { BackupEncryptionManager::default(), )); - let (task, _path) = task("race".to_owned()).await?; + let (task, _path) = task_handler("race".to_owned()).await?; must_register_table(router.as_ref(), task, 1).await; router.must_mut_task_info("race", |i| { i.storage = Arc::new(NoopStorage::default()); @@ -2879,13 +2936,19 @@ mod tests { }) .unwrap(); + let cx = FlushContext { + task_name: "race", + store_id: 42, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: TimeStamp::max(), + }; // set flush status to true, because we disabled the auto flush. t.set_flushing_status(true); let router_clone = router.clone(); let _ = tokio::join!( // do flush in another thread tokio::spawn(async move { - router_clone.do_flush("race", 42, TimeStamp::max()).await; + router_clone.do_flush(cx).await; }), router.on_events(events_after_flush) ); @@ -2896,7 +2959,7 @@ mod tests { // set flush status to true, because we disabled the auto flush. t.set_flushing_status(true); - let res = router.do_flush("race", 42, TimeStamp::max()).await; + let res = router.do_flush(cx).await; // this time flush should success. assert!(res.is_some()); assert_eq!(t.files.read().await.len(), 0,); @@ -2984,7 +3047,13 @@ mod tests { task_handler.on_events(kv_events.clone()).await?; task_handler.set_flushing_status(true); let start = Instant::now(); - task_handler.do_flush(1, TimeStamp::new(1)).await?; + let cx = FlushContext { + task_name: &task_handler.task.info.name, + store_id: 1, + resolved_regions: &EMPTY_RESOLVE, + resolved_ts: TimeStamp::new(1), + }; + task_handler.do_flush(cx).await?; let duration = start.saturating_elapsed(); println!("Time taken for do_flush: {:?}", duration); diff --git a/components/backup-stream/src/subscription_manager.rs b/components/backup-stream/src/subscription_manager.rs index 26838b6cd57..d9d27e7b714 100644 --- a/components/backup-stream/src/subscription_manager.rs +++ b/components/backup-stream/src/subscription_manager.rs @@ -86,27 +86,23 @@ impl ResolvedRegions { /// Note: Maybe we can compute the global checkpoint internal and getting /// the interface clear. However we must take the `min_ts` or we cannot /// provide valid global checkpoint if there isn't any region checkpoint. - pub fn new(checkpoint: TimeStamp, checkpoints: Vec) -> Self { + pub const fn new(checkpoint: TimeStamp, checkpoints: Vec) -> Self { Self { items: checkpoints, checkpoint, } } - /// take the region checkpoints from the structure. - #[deprecated = "please use `take_resolve_result` instead."] - pub fn take_region_checkpoints(&mut self) -> Vec<(Region, TimeStamp)> { - std::mem::take(&mut self.items) - .into_iter() - .map(|x| (x.region, x.checkpoint)) - .collect() - } - /// take the resolve result from this struct. pub fn take_resolve_result(&mut self) -> Vec { std::mem::take(&mut self.items) } + /// Get the resolve results. + pub fn resolve_results(&self) -> &[ResolveResult] { + &self.items + } + /// get the global checkpoint. pub fn global_checkpoint(&self) -> TimeStamp { self.checkpoint diff --git a/components/backup-stream/src/subscription_track.rs b/components/backup-stream/src/subscription_track.rs index c1bd40197e7..c3cd1b7f6df 100644 --- a/components/backup-stream/src/subscription_track.rs +++ b/components/backup-stream/src/subscription_track.rs @@ -100,7 +100,7 @@ impl ActiveSubscription { } } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Clone)] pub enum CheckpointType { MinTs, StartTsOfInitialScan, @@ -120,6 +120,7 @@ impl std::fmt::Debug for CheckpointType { } } +#[derive(Clone)] pub struct ResolveResult { pub region: Region, pub checkpoint: TimeStamp, diff --git a/components/backup-stream/tests/integration/mod.rs b/components/backup-stream/tests/integration/mod.rs index 01a51ddc504..ed161c68047 100644 --- a/components/backup-stream/tests/integration/mod.rs +++ b/components/backup-stream/tests/integration/mod.rs @@ -7,19 +7,24 @@ mod suite; mod all { - use std::time::{Duration, Instant}; + use std::{ + os::unix::ffi::OsStrExt, + time::{Duration, Instant}, + }; use backup_stream::{ errors::Error, router::TaskSelector, GetCheckpointResult, RegionCheckpointOperation, RegionSet, Task, }; use futures::{Stream, StreamExt}; + use kvproto::metapb::RegionEpoch; use pd_client::PdClient; use test_raftstore::IsolationFilterFactory; use tikv::config::BackupStreamConfig; use tikv_util::{box_err, defer, info, HandyRwLock}; use tokio::time::timeout; use txn_types::{Key, TimeStamp}; + use walkdir::WalkDir; use super::suite::{ make_record_key, make_split_key_at_record, mutation, run_async_test, SuiteBuilder, @@ -44,6 +49,64 @@ mod all { suite.cluster.shutdown(); } + #[test] + fn region_boundaries() { + let mut suite = SuiteBuilder::new_named("region_boundaries") + .nodes(1) + .build(); + let round = run_async_test(async { + suite.must_split(&make_split_key_at_record(1, 42)); + suite.must_split(&make_split_key_at_record(1, 86)); + let round1 = suite.write_records(0, 128, 1).await; + suite.must_register_task(1, "region_boundaries"); + round1 + }); + suite.force_flush_files("region_boundaries"); + suite.wait_for_flush(); + suite.check_for_write_records(suite.flushed_files.path(), round.iter().map(Vec::as_slice)); + + let a_meta = WalkDir::new(suite.flushed_files.path().join("v1/backupmeta")) + .contents_first(true) + .into_iter() + .find(|v| { + v.as_ref() + .is_ok_and(|v| v.file_name().as_bytes().ends_with(b".meta")) + }) + .unwrap() + .unwrap(); + let mut a_meta_content = protobuf::parse_from_bytes::( + &std::fs::read(a_meta.path()).unwrap(), + ) + .unwrap(); + let dfs = a_meta_content.mut_file_groups()[0].mut_data_files_info(); + // Two regions, two CFs. + assert_eq!(dfs.len(), 6); + dfs.sort_by(|x1, x2| x1.start_key.cmp(&x2.start_key)); + let hnd_key = |hnd| make_split_key_at_record(1, hnd); + let epoch = |ver, conf_ver| { + let mut e = RegionEpoch::new(); + e.set_version(ver); + e.set_conf_ver(conf_ver); + e + }; + assert_eq!(dfs[0].region_start_key, b""); + assert_eq!(dfs[0].region_end_key, hnd_key(42)); + assert_eq!(dfs[0].region_epoch.len(), 1, "{:?}", dfs[0]); + assert_eq!(dfs[0].region_epoch[0], epoch(2, 1), "{:?}", dfs[0]); + + assert_eq!(dfs[2].region_start_key, hnd_key(42)); + assert_eq!(dfs[2].region_end_key, hnd_key(86)); + assert_eq!(dfs[2].region_epoch.len(), 1, "{:?}", dfs[2]); + assert_eq!(dfs[2].region_epoch[0], epoch(3, 1), "{:?}", dfs[2]); + + assert_eq!(dfs[4].region_start_key, hnd_key(86)); + assert_eq!(dfs[4].region_end_key, b""); + assert_eq!(dfs[4].region_epoch.len(), 1, "{:?}", dfs[4]); + assert_eq!(dfs[4].region_epoch[0], epoch(3, 1), "{:?}", dfs[4]); + + suite.cluster.shutdown(); + } + /// This test tests whether we can handle some weird transactions and their /// race with initial scanning. /// Generally, those transactions: From dccee481560e7fdf64c71f2ef9924e5f38e53aeb Mon Sep 17 00:00:00 2001 From: ekexium Date: Wed, 25 Sep 2024 15:31:14 +0800 Subject: [PATCH 089/144] *: Prevent resolved-ts from being blocked by pipelined DML transactions. (#17540) ref tikv/tikv#17459 Prevent resolved-ts from being blocked by pipelined DML transactions. Signed-off-by: ekexium --- Cargo.lock | 2 +- components/backup-stream/src/endpoint.rs | 11 +- components/backup-stream/src/event_loader.rs | 9 +- components/backup-stream/src/observer.rs | 14 +- components/backup-stream/src/router.rs | 2 +- .../backup-stream/src/subscription_manager.rs | 11 +- .../backup-stream/src/subscription_track.rs | 78 +++-- components/backup-stream/tests/suite.rs | 6 +- components/resolved_ts/src/cmd.rs | 9 + components/resolved_ts/src/endpoint.rs | 52 ++- components/resolved_ts/src/resolver.rs | 300 ++++++++++++++---- components/server/src/server.rs | 11 +- components/server/src/server2.rs | 11 +- components/test_raftstore-v2/src/server.rs | 8 +- components/test_raftstore/src/server.rs | 8 +- src/server/metrics.rs | 1 + src/server/service/kv.rs | 30 +- src/storage/metrics.rs | 1 + src/storage/mod.rs | 63 +++- src/storage/txn/actions/tests.rs | 95 +++++- .../acquire_pessimistic_lock_resumed.rs | 2 +- src/storage/txn/commands/atomic_store.rs | 4 +- .../txn/commands/check_secondary_locks.rs | 6 +- src/storage/txn/commands/check_txn_status.rs | 6 +- src/storage/txn/commands/compare_and_swap.rs | 4 +- src/storage/txn/commands/flush.rs | 94 +----- src/storage/txn/commands/mod.rs | 9 +- .../txn/commands/pessimistic_rollback.rs | 4 +- src/storage/txn/commands/prewrite.rs | 20 +- src/storage/txn/commands/txn_heart_beat.rs | 80 ++++- src/storage/txn/scheduler.rs | 16 +- src/storage/txn/txn_status_cache.rs | 29 +- 32 files changed, 748 insertions(+), 248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff38a902c4c..0ec94cddfe2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2848,7 +2848,7 @@ dependencies = [ [[package]] name = "kvproto" version = "0.0.2" -source = "git+https://github.com/pingcap/kvproto.git#199f352dc2b3bdfdc3b96e01bc3bca81148b0171" +source = "git+https://github.com/pingcap/kvproto.git#4a3e17f5e62dc3999e2c0f63293fdeffced80626" dependencies = [ "futures 0.3.15", "grpcio", diff --git a/components/backup-stream/src/endpoint.rs b/components/backup-stream/src/endpoint.rs index ee13b640c81..7fede7dad0c 100644 --- a/components/backup-stream/src/endpoint.rs +++ b/components/backup-stream/src/endpoint.rs @@ -10,6 +10,7 @@ use std::{ }; use concurrency_manager::ConcurrencyManager; +use dashmap::DashMap; use encryption::BackupEncryptionManager; use engine_traits::KvEngine; use error_code::ErrorCodeExt; @@ -25,7 +26,10 @@ use raftstore::{ router::CdcHandle, }; use resolved_ts::{resolve_by_raft, LeadershipResolver}; -use tikv::config::{BackupStreamConfig, ResolvedTsConfig}; +use tikv::{ + config::{BackupStreamConfig, ResolvedTsConfig}, + storage::txn::txn_status_cache::TxnStatusCache, +}; use tikv_util::{ box_err, config::ReadableDuration, @@ -85,7 +89,7 @@ pub struct Endpoint { pub(crate) subs: SubscriptionTracer, pub(crate) concurrency_manager: ConcurrencyManager, - // Note: some of fields are public so test cases are able to access them. + // Note: some of the fields are public so test cases are able to access them. pub range_router: Router, observer: BackupStreamObserver, pool: Runtime, @@ -122,6 +126,7 @@ where concurrency_manager: ConcurrencyManager, resolver: BackupStreamResolver, backup_encryption_manager: BackupEncryptionManager, + txn_status_cache: Arc, ) -> Self { crate::metrics::STREAM_ENABLED.inc(); let pool = create_tokio_runtime((config.num_threads / 2).max(1), "backup-stream") @@ -154,7 +159,7 @@ where }; let initial_scan_throughput_quota = Limiter::new(limit); info!("the endpoint of stream backup started"; "path" => %config.temp_path); - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer(Arc::new(DashMap::new()), txn_status_cache.clone()); let initial_scan_semaphore = Arc::new(Semaphore::new(config.initial_scan_concurrency)); let (region_operator, op_loop) = RegionSubscriptionManager::start( diff --git a/components/backup-stream/src/event_loader.rs b/components/backup-stream/src/event_loader.rs index 467b0bcaa92..a990ea2a82b 100644 --- a/components/backup-stream/src/event_loader.rs +++ b/components/backup-stream/src/event_loader.rs @@ -160,7 +160,7 @@ impl EventLoader { debug!("meet lock during initial scanning."; "key" => %utils::redact(&lock_at), "ts" => %lock.ts); if utils::should_track_lock(&lock) { resolver - .track_phase_one_lock(lock.ts, lock_at) + .track_phase_one_lock(lock.ts, lock_at, lock.generation) .map_err(|_| Error::OutOfQuota { region_id: self.region.id, })?; @@ -483,7 +483,10 @@ mod tests { use futures::executor::block_on; use kvproto::metapb::*; - use tikv::storage::{txn::tests::*, TestEngineBuilder}; + use tikv::storage::{ + txn::{tests::*, txn_status_cache::TxnStatusCache}, + TestEngineBuilder, + }; use tikv_kv::SnapContext; use tikv_util::memory::{MemoryQuota, OwnedAllocated}; use txn_types::TimeStamp; @@ -524,7 +527,7 @@ mod tests { }); r.unwrap(); let mut events = ApplyEvents::with_capacity(1024, 42); - let mut res = TwoPhaseResolver::new(42, None); + let mut res = TwoPhaseResolver::new(42, None, Arc::new(TxnStatusCache::new_for_test())); loader.emit_entries_to(&mut events, &mut res).unwrap(); assert_ne!(events.len(), 0); assert_ne!(data_load, 0); diff --git a/components/backup-stream/src/observer.rs b/components/backup-stream/src/observer.rs index 6a40a336fb8..e72cba90cd8 100644 --- a/components/backup-stream/src/observer.rs +++ b/components/backup-stream/src/observer.rs @@ -189,8 +189,9 @@ impl RegionChangeObserver for BackupStreamObserver { #[cfg(test)] mod tests { - use std::{assert_matches::assert_matches, time::Duration}; + use std::{assert_matches::assert_matches, sync::Arc, time::Duration}; + use dashmap::DashMap; use engine_panic::PanicEngine; use kvproto::metapb::Region; use raft::StateRole; @@ -198,6 +199,7 @@ mod tests { Cmd, CmdBatch, CmdObserveInfo, CmdObserver, ObserveHandle, ObserveLevel, ObserverContext, RegionChangeEvent, RegionChangeObserver, RegionChangeReason, RoleChange, RoleObserver, }; + use tikv::storage::txn::txn_status_cache::TxnStatusCache; use tikv_util::{worker::dummy_scheduler, HandyRwLock}; use super::BackupStreamObserver; @@ -220,7 +222,10 @@ mod tests { // Prepare: assuming a task wants the range of [0001, 0010]. let o = BackupStreamObserver::new(sched); - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer( + Arc::new(DashMap::new()), + Arc::new(TxnStatusCache::new_for_test()), + ); assert!(o.ranges.wl().add((b"0001".to_vec(), b"0010".to_vec()))); // Test regions can be registered. @@ -245,7 +250,10 @@ mod tests { // Prepare: assuming a task wants the range of [0001, 0010]. let o = BackupStreamObserver::new(sched); - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer( + Arc::new(DashMap::new()), + Arc::new(TxnStatusCache::new_for_test()), + ); assert!(o.ranges.wl().add((b"0001".to_vec(), b"0010".to_vec()))); // Test regions can be registered. diff --git a/components/backup-stream/src/router.rs b/components/backup-stream/src/router.rs index 2e707fc325d..36dd70ac5f5 100644 --- a/components/backup-stream/src/router.rs +++ b/components/backup-stream/src/router.rs @@ -213,7 +213,7 @@ impl ApplyEvents { Ok(lock) => { if utils::should_track_lock(&lock) { resolver - .track_lock(lock.ts, key) + .track_lock(lock.ts, key, lock.generation) .map_err(|_| Error::OutOfQuota { region_id })?; } } diff --git a/components/backup-stream/src/subscription_manager.rs b/components/backup-stream/src/subscription_manager.rs index d9d27e7b714..e1803048d71 100644 --- a/components/backup-stream/src/subscription_manager.rs +++ b/components/backup-stream/src/subscription_manager.rs @@ -831,6 +831,7 @@ mod test { time::Duration, }; + use dashmap::DashMap; use encryption::BackupEncryptionManager; use engine_test::{kv::KvTestEngine, raft::RaftTestEngine}; use kvproto::{ @@ -842,7 +843,10 @@ mod test { router::{CdcRaftRouter, ServerRaftStoreRouter}, RegionInfo, }; - use tikv::{config::BackupStreamConfig, storage::Statistics}; + use tikv::{ + config::BackupStreamConfig, + storage::{txn::txn_status_cache::TxnStatusCache, Statistics}, + }; use tikv_util::{box_err, info, memory::MemoryQuota, worker::dummy_scheduler}; use tokio::{sync::mpsc::Sender, task::JoinHandle}; use txn_types::TimeStamp; @@ -1031,7 +1035,10 @@ mod test { let meta_cli = SlashEtcStore::default(); let meta_cli = MetadataClient::new(meta_cli, 1); let (scheduler, mut output) = dummy_scheduler(); - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer( + Arc::new(DashMap::new()), + Arc::new(TxnStatusCache::new_for_test()), + ); let memory_manager = Arc::new(MemoryQuota::new(1024)); let (tx, mut rx) = tokio::sync::mpsc::channel(8); let router = RouterInner::new( diff --git a/components/backup-stream/src/subscription_track.rs b/components/backup-stream/src/subscription_track.rs index c3cd1b7f6df..e0b10418bd9 100644 --- a/components/backup-stream/src/subscription_track.rs +++ b/components/backup-stream/src/subscription_track.rs @@ -9,6 +9,7 @@ use dashmap::{ use kvproto::metapb::Region; use raftstore::coprocessor::*; use resolved_ts::{Resolver, TsSource, TxnLocks}; +use tikv::storage::txn::txn_status_cache::TxnStatusCache; use tikv_util::{ info, memory::{MemoryQuota, MemoryQuotaExceeded}, @@ -18,9 +19,18 @@ use txn_types::TimeStamp; use crate::{debug, metrics::TRACK_REGION, utils}; -/// A utility to tracing the regions being subscripted. -#[derive(Clone, Default, Debug)] -pub struct SubscriptionTracer(Arc>); +/// A utility to tracing the regions being subscribed. +#[derive(Clone)] +pub struct SubscriptionTracer( + pub Arc>, + pub Arc, +); + +impl std::fmt::Debug for SubscriptionTracer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SubscriptionTracer").field(&self.0).finish() + } +} /// The state of the subscription state machine: /// Initial state is `ABSENT`, the subscription isn't in the tracer. @@ -73,8 +83,13 @@ impl std::fmt::Debug for ActiveSubscription { } impl ActiveSubscription { - pub fn new(region: Region, handle: ObserveHandle, start_ts: Option) -> Self { - let resolver = TwoPhaseResolver::new(region.get_id(), start_ts); + pub fn new( + region: Region, + handle: ObserveHandle, + start_ts: Option, + txn_status_cache: Arc, + ) -> Self { + let resolver = TwoPhaseResolver::new(region.get_id(), start_ts, txn_status_cache); Self { handle, meta: region, @@ -227,7 +242,7 @@ impl SubscriptionTracer { let e = self.0.entry(region.id); match e { Entry::Occupied(o) => { - let sub = ActiveSubscription::new(region.clone(), handle, start_ts); + let sub = ActiveSubscription::new(region.clone(), handle, start_ts, self.1.clone()); let (_, s) = o.replace_entry(SubscribeState::Running(sub)); if !s.is_pending() { // If there is another subscription already (perhaps repeated Start), @@ -238,7 +253,7 @@ impl SubscriptionTracer { } Entry::Vacant(e) => { warn!("excepted state transform: absent -> running"; utils::slog_region(region)); - let sub = ActiveSubscription::new(region.clone(), handle, start_ts); + let sub = ActiveSubscription::new(region.clone(), handle, start_ts, self.1.clone()); e.insert(SubscribeState::Running(sub)); } } @@ -487,17 +502,18 @@ pub struct TwoPhaseResolver { } enum FutureLock { - Lock(Vec, TimeStamp), + Lock(Vec, TimeStamp, u64 /* generation */), Unlock(Vec), } impl std::fmt::Debug for FutureLock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Lock(arg0, arg1) => f + Self::Lock(arg0, arg1, generation) => f .debug_tuple("Lock") .field(&format_args!("{}", utils::redact(arg0))) .field(arg1) + .field(generation) .finish(), Self::Unlock(arg0) => f .debug_tuple("Unlock") @@ -524,11 +540,12 @@ impl TwoPhaseResolver { &mut self, start_ts: TimeStamp, key: Vec, + generation: u64, ) -> Result<(), MemoryQuotaExceeded> { if !self.in_phase_one() { warn!("backup stream tracking lock as if in phase one"; "start_ts" => %start_ts, "key" => %utils::redact(&key)) } - self.resolver.track_lock(start_ts, key, None)?; + self.resolver.track_lock(start_ts, key, None, generation)?; Ok(()) } @@ -536,12 +553,14 @@ impl TwoPhaseResolver { &mut self, start_ts: TimeStamp, key: Vec, + generation: u64, ) -> Result<(), MemoryQuotaExceeded> { if self.in_phase_one() { - self.future_locks.push(FutureLock::Lock(key, start_ts)); + self.future_locks + .push(FutureLock::Lock(key, start_ts, generation)); return Ok(()); } - self.resolver.track_lock(start_ts, key, None)?; + self.resolver.track_lock(start_ts, key, None, generation)?; Ok(()) } @@ -556,9 +575,9 @@ impl TwoPhaseResolver { fn handle_future_lock(&mut self, lock: FutureLock) { match lock { - FutureLock::Lock(key, ts) => { + FutureLock::Lock(key, ts, generation) => { // TODO: handle memory quota exceed, for now, quota is set to usize::MAX. - self.resolver.track_lock(ts, key, None).unwrap(); + self.resolver.track_lock(ts, key, None, generation).unwrap(); } FutureLock::Unlock(key) => self.resolver.untrack_lock(&key, None), } @@ -580,11 +599,15 @@ impl TwoPhaseResolver { self.resolver.resolved_ts() } - pub fn new(region_id: u64, stable_ts: Option) -> Self { + pub fn new( + region_id: u64, + stable_ts: Option, + txn_status_cache: Arc, + ) -> Self { // TODO: limit the memory usage of the resolver. let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); Self { - resolver: Resolver::new(region_id, memory_quota), + resolver: Resolver::new(region_id, memory_quota, txn_status_cache), future_locks: Default::default(), stable_ts, } @@ -623,9 +646,11 @@ impl std::fmt::Debug for TwoPhaseResolver { mod test { use std::sync::Arc; + use dashmap::DashMap; use kvproto::metapb::{Region, RegionEpoch}; use raftstore::coprocessor::ObserveHandle; use resolved_ts::TxnLocks; + use tikv::storage::txn::txn_status_cache::TxnStatusCache; use txn_types::TimeStamp; use super::{SubscriptionTracer, TwoPhaseResolver}; @@ -635,14 +660,15 @@ mod test { fn test_two_phase_resolver() { let key = b"somewhere_over_the_rainbow"; let ts = TimeStamp::new; - let mut r = TwoPhaseResolver::new(42, Some(ts(42))); - r.track_phase_one_lock(ts(48), key.to_vec()).unwrap(); + let mut r = + TwoPhaseResolver::new(42, Some(ts(42)), Arc::new(TxnStatusCache::new_for_test())); + r.track_phase_one_lock(ts(48), key.to_vec(), 0).unwrap(); // When still in phase one, the resolver should not be advanced. r.untrack_lock(&key[..]); assert_eq!(r.resolve(ts(50)), ts(42)); // Even new lock tracked... - r.track_lock(ts(52), key.to_vec()).unwrap(); + r.track_lock(ts(52), key.to_vec(), 0).unwrap(); r.untrack_lock(&key[..]); assert_eq!(r.resolve(ts(53)), ts(42)); @@ -651,7 +677,7 @@ mod test { assert_eq!(r.resolve(ts(54)), ts(54)); // It should be able to track incremental locks. - r.track_lock(ts(55), key.to_vec()).unwrap(); + r.track_lock(ts(55), key.to_vec(), 0).unwrap(); assert_eq!(r.resolve(ts(56)), ts(55)); r.untrack_lock(&key[..]); assert_eq!(r.resolve(ts(57)), ts(57)); @@ -669,7 +695,10 @@ mod test { #[test] fn test_delay_remove() { - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer( + Arc::new(DashMap::new()), + Arc::new(TxnStatusCache::new_for_test()), + ); let handle = ObserveHandle::new(); subs.register_region(®ion(1, 1, 1), handle, Some(TimeStamp::new(42))); assert!(subs.get_subscription_of(1).is_some()); @@ -680,7 +709,10 @@ mod test { #[test] fn test_cal_checkpoint() { - let subs = SubscriptionTracer::default(); + let subs = SubscriptionTracer( + Arc::new(DashMap::new()), + Arc::new(TxnStatusCache::new_for_test()), + ); subs.register_region( ®ion(1, 1, 1), ObserveHandle::new(), @@ -707,7 +739,7 @@ mod test { region4_sub .value_mut() .resolver - .track_lock(TimeStamp::new(128), b"Alpi".to_vec()) + .track_lock(TimeStamp::new(128), b"Alpi".to_vec(), 0) .unwrap(); subs.register_region(®ion(5, 8, 1), ObserveHandle::new(), None); subs.deregister_region_if(®ion(5, 8, 1), |_, _| true); diff --git a/components/backup-stream/tests/suite.rs b/components/backup-stream/tests/suite.rs index 2c75abaeaf5..d8dd45962a9 100644 --- a/components/backup-stream/tests/suite.rs +++ b/components/backup-stream/tests/suite.rs @@ -39,7 +39,10 @@ use tempfile::TempDir; use test_pd_client::TestPdClient; use test_raftstore::{new_server_cluster, Cluster, Config, ServerCluster}; use test_util::retry; -use tikv::config::{BackupStreamConfig, ResolvedTsConfig}; +use tikv::{ + config::{BackupStreamConfig, ResolvedTsConfig}, + storage::txn::txn_status_cache::TxnStatusCache, +}; use tikv_util::{ codec::{ number::NumberEncoder, @@ -412,6 +415,7 @@ impl Suite { MultiMasterKeyBackend::default(), sim.encryption.clone(), ), + Arc::new(TxnStatusCache::new_for_test()), ); worker.start(endpoint); } diff --git a/components/resolved_ts/src/cmd.rs b/components/resolved_ts/src/cmd.rs index 2195c086974..7a848381269 100644 --- a/components/resolved_ts/src/cmd.rs +++ b/components/resolved_ts/src/cmd.rs @@ -20,6 +20,7 @@ pub enum ChangeRow { start_ts: TimeStamp, lock_type: LockType, value: Option, + generation: u64, }, Commit { key: Key, @@ -117,6 +118,7 @@ impl ChangeLog { short_value, ts, lock_type, + generation, .. } = lock; let value = default.map_or(short_value, |v| Some(v.into_put().1)); @@ -125,6 +127,7 @@ impl ChangeLog { start_ts: ts, lock_type, value, + generation, } }), (None, Some(KeyOp::Delete), _) => Some(ChangeRow::Commit { @@ -395,6 +398,7 @@ mod tests { start_ts: 1.into(), value: Some(b"v1".to_vec()), lock_type: LockType::Put, + generation: 0, }, ChangeRow::Commit { key: k1.clone(), @@ -407,6 +411,7 @@ mod tests { start_ts: 3.into(), value: Some(b"v2".to_vec()), lock_type: LockType::Put, + generation: 0, }, ChangeRow::Commit { key: k1.clone(), @@ -419,6 +424,7 @@ mod tests { start_ts: 4.into(), value: Some(vec![b'v'; 512]), lock_type: LockType::Put, + generation: 0, }, ChangeRow::Commit { key: k1.clone(), @@ -431,6 +437,7 @@ mod tests { start_ts: 5.into(), value: Some(b"v3".to_vec()), lock_type: LockType::Put, + generation: 0, }, ChangeRow::Commit { key: k1.clone(), @@ -443,6 +450,7 @@ mod tests { start_ts: 6.into(), value: Some(b"v4".to_vec()), lock_type: LockType::Put, + generation: 0, }, ChangeRow::Commit { key: k1.clone(), @@ -455,6 +463,7 @@ mod tests { start_ts: 7.into(), value: Some(b"v5".to_vec()), lock_type: LockType::Put, + generation: 0, }, // Rollback of the txn@start_ts=7 will be missing as overlapped rollback is not // hanlded. diff --git a/components/resolved_ts/src/endpoint.rs b/components/resolved_ts/src/endpoint.rs index 7710f14b085..a02cdc8877e 100644 --- a/components/resolved_ts/src/endpoint.rs +++ b/components/resolved_ts/src/endpoint.rs @@ -27,7 +27,7 @@ use raftstore::{ }, }; use security::SecurityManager; -use tikv::config::ResolvedTsConfig; +use tikv::{config::ResolvedTsConfig, storage::txn::txn_status_cache::TxnStatusCache}; use tikv_util::{ memory::{HeapSize, MemoryQuota}, warn, @@ -45,7 +45,7 @@ use crate::{ Error, Result, TsSource, TxnLocks, ON_DROP_WARN_HEAP_SIZE, }; -/// grace period for identifying identifying slow resolved-ts and safe-ts. +/// grace period for identifying slow resolved-ts and safe-ts. const SLOW_LOG_GRACE_PERIOD_MS: u64 = 1000; const MEMORY_QUOTA_EXCEEDED_BACKOFF: Duration = Duration::from_secs(30); @@ -157,6 +157,7 @@ enum PendingLock { Track { key: Key, start_ts: TimeStamp, + generation: u64, }, Untrack { key: Key, @@ -193,9 +194,15 @@ impl ObserveRegion { rrp: Arc, memory_quota: Arc, cancelled: Sender<()>, + txn_status_cache: Arc, ) -> Self { ObserveRegion { - resolver: Resolver::with_read_progress(meta.id, Some(rrp), memory_quota.clone()), + resolver: Resolver::with_read_progress( + meta.id, + Some(rrp), + memory_quota.clone(), + txn_status_cache, + ), meta, handle: ObserveHandle::new(), resolver_status: ResolverStatus::Pending { @@ -235,9 +242,15 @@ impl ObserveRegion { ChangeLog::Rows { rows, index } => { for row in rows { let lock = match row { - ChangeRow::Prewrite { key, start_ts, .. } => PendingLock::Track { + ChangeRow::Prewrite { + key, + start_ts, + generation, + .. + } => PendingLock::Track { key: key.clone(), start_ts: *start_ts, + generation: *generation, }, ChangeRow::Commit { key, @@ -296,17 +309,23 @@ impl ObserveRegion { ChangeLog::Rows { rows, index } => { for row in rows { match row { - ChangeRow::Prewrite { key, start_ts, .. } => { + ChangeRow::Prewrite { + key, + start_ts, + generation, + .. + } => { self.resolver.track_lock( *start_ts, key.to_raw().unwrap(), Some(*index), + *generation, )?; } ChangeRow::Commit { key, .. } => self .resolver .untrack_lock(&key.to_raw().unwrap(), Some(*index)), - // One pc command do not contains any lock, so just skip it + // One pc command do not contain any lock, so just skip it ChangeRow::OnePc { .. } => { self.resolver.update_tracked_index(*index); } @@ -330,8 +349,12 @@ impl ObserveRegion { panic!("region {:?} resolver has ready", self.meta.id) } for (key, lock) in locks { - self.resolver - .track_lock(lock.ts, key.to_raw().unwrap(), Some(apply_index))?; + self.resolver.track_lock( + lock.ts, + key.to_raw().unwrap(), + Some(apply_index), + lock.generation, + )?; } } ScanEntries::None => { @@ -343,11 +366,16 @@ impl ObserveRegion { resolver_status.drain_pending_locks(self.meta.id); for lock in pending_locks { match lock { - PendingLock::Track { key, start_ts } => { + PendingLock::Track { + key, + start_ts, + generation, + } => { self.resolver.track_lock( start_ts, key.to_raw().unwrap(), Some(pending_tracked_index), + generation, )?; } PendingLock::Untrack { key, .. } => self @@ -380,6 +408,7 @@ pub struct Endpoint { scan_concurrency_semaphore: Arc, scheduler: Scheduler, advance_worker: AdvanceTsWorker, + txn_status_cache: Arc, _phantom: PhantomData<(T, E)>, } @@ -659,6 +688,7 @@ where concurrency_manager: ConcurrencyManager, env: Arc, security_mgr: Arc, + txn_status_cache: Arc, ) -> Self { let (region_read_progress, store_id) = { let meta = store_meta.lock().unwrap(); @@ -689,6 +719,7 @@ where scanner_pool, scan_concurrency_semaphore, regions: HashMap::default(), + txn_status_cache, _phantom: PhantomData, }; ep.handle_advance_resolved_ts(leader_resolver); @@ -709,6 +740,7 @@ where read_progress, self.memory_quota.clone(), cancelled_tx, + self.txn_status_cache.clone(), ); let observe_handle = observe_region.handle.clone(); observe_region @@ -1229,7 +1261,7 @@ impl LeaderStats { last_resolve_attempt: resolver.as_mut().and_then(|r| r.take_last_attempt()), min_lock: resolver .as_ref() - .and_then(|r| r.oldest_transaction().map(|(t, tk)| (*t, tk.clone()))), + .and_then(|r| r.oldest_transaction().map(|(t, tk)| (t, tk.clone()))), applied_index: region_read_progress.applied_index(), lock_num: resolver.as_ref().map(|r| r.num_locks()), txn_num: resolver.as_ref().map(|r| r.num_transactions()), diff --git a/components/resolved_ts/src/resolver.rs b/components/resolved_ts/src/resolver.rs index 2aec9c336cd..7c3f1d74976 100644 --- a/components/resolved_ts/src/resolver.rs +++ b/components/resolved_ts/src/resolver.rs @@ -2,8 +2,9 @@ use std::{cmp, collections::BTreeMap, sync::Arc, time::Duration}; -use collections::{HashMap, HashMapEntry}; +use collections::{HashMap, HashMapEntry, HashSet}; use raftstore::store::RegionReadProgress; +use tikv::storage::txn::txn_status_cache::{TxnState, TxnStatusCache}; use tikv_util::{ memory::{MemoryQuota, MemoryQuotaExceeded}, time::Instant, @@ -80,6 +81,13 @@ pub struct Resolver { locks_by_key: HashMap, TimeStamp>, // start_ts -> locked keys. lock_ts_heap: BTreeMap, + // the start_ts of large transactions, which use a different tracking strategy with normal + // transactions. + large_txn_ts: HashSet, + // each large transaction tracked by this resolver has a representative key tracked. So that + // when the large transaction is rolled back, we can rely on this key to guarantee that + // eventually there will be orphaned transactions. + large_txn_key_representative: HashMap, TimeStamp>, // The last shrink time. last_aggressive_shrink_time: Instant, // The timestamps that guarantees no more commit will happen before. @@ -96,6 +104,7 @@ pub struct Resolver { memory_quota: Arc, // The last attempt of resolve(), used for diagnosis. last_attempt: Option, + txn_status_cache: Arc, } #[derive(Clone)] @@ -169,20 +178,37 @@ impl Drop for Resolver { } impl Resolver { - pub fn new(region_id: u64, memory_quota: Arc) -> Resolver { - Resolver::with_read_progress(region_id, None, memory_quota) + pub fn new( + region_id: u64, + memory_quota: Arc, + txn_status_cache: Arc, + ) -> Resolver { + Resolver::with_read_progress(region_id, None, memory_quota, txn_status_cache) + } + + #[cfg(test)] + fn new_for_test(region_id: u64, memory_quota: Arc) -> Resolver { + Resolver::with_read_progress( + region_id, + None, + memory_quota, + Arc::new(TxnStatusCache::new_for_test()), + ) } pub fn with_read_progress( region_id: u64, read_progress: Option>, memory_quota: Arc, + txn_status_cache: Arc, ) -> Resolver { Resolver { region_id, resolved_ts: TimeStamp::zero(), locks_by_key: HashMap::default(), lock_ts_heap: BTreeMap::new(), + large_txn_ts: HashSet::::default(), + large_txn_key_representative: HashMap::, TimeStamp>::default(), last_aggressive_shrink_time: Instant::now_coarse(), read_progress, tracked_index: 0, @@ -190,6 +216,7 @@ impl Resolver { stopped: false, memory_quota, last_attempt: None, + txn_status_cache, } } @@ -245,6 +272,12 @@ impl Resolver { self.locks_by_key.len() * (key_bytes / key_count + std::mem::size_of::()) + self.lock_ts_heap.len() * (std::mem::size_of::() + std::mem::size_of::()) + + self + .large_txn_key_representative + .keys() + .map(|k| k.len() + std::mem::size_of::()) + .sum::() + + self.large_txn_ts.len() * std::mem::size_of::() } fn lock_heap_size(&self, key: &[u8]) -> usize { @@ -278,11 +311,12 @@ impl Resolver { start_ts: TimeStamp, key: Vec, index: Option, + generation: u64, /* generation is used to identify whether the lock is a pipelined + * transaction's lock */ ) -> Result<(), MemoryQuotaExceeded> { if let Some(index) = index { self.update_tracked_index(index); } - let bytes = self.lock_heap_size(&key); debug!( "track lock {}@{}", &log_wrappers::Value::key(&key), @@ -290,8 +324,22 @@ impl Resolver { "region_id" => self.region_id, "memory_in_use" => self.memory_quota.in_use(), "memory_capacity" => self.memory_quota.capacity(), - "key_heap_size" => bytes, + "generation" => generation, ); + if generation == 0 { + self.track_normal_lock(start_ts, key)?; + } else { + self.track_large_txn_lock(start_ts, key)?; + } + Ok(()) + } + + fn track_normal_lock( + &mut self, + start_ts: TimeStamp, + key: Vec, + ) -> Result<(), MemoryQuotaExceeded> { + let bytes = self.lock_heap_size(&key); self.memory_quota.alloc(bytes)?; let key: Arc<[u8]> = key.into_boxed_slice().into(); match self.locks_by_key.entry(key) { @@ -318,36 +366,43 @@ impl Resolver { if let Some(index) = index { self.update_tracked_index(index); } - let start_ts = if let Some(start_ts) = self.locks_by_key.remove(key) { + if let Some(start_ts) = self.locks_by_key.remove(key) { let bytes = self.lock_heap_size(key); self.memory_quota.free(bytes); - start_ts + debug!( + "untrack lock {}@{}", + &log_wrappers::Value::key(key), + start_ts; + "region_id" => self.region_id, + "memory_in_use" => self.memory_quota.in_use(), + ); + if let Some(txn_locks) = self.lock_ts_heap.get_mut(&start_ts) { + if txn_locks.lock_count > 0 { + txn_locks.lock_count -= 1; + } + if txn_locks.lock_count == 0 { + self.lock_ts_heap.remove(&start_ts); + } + }; + // Use a large ratio to amortize the cost of rehash. + let shrink_ratio = 8; + self.shrink_ratio(shrink_ratio); + } else if let Some(start_ts) = self.large_txn_key_representative.remove(key) { + let is_new = self.large_txn_ts.remove(&start_ts); + debug_assert!(is_new, "large txn lock should be untracked only once"); + debug!( + "untrack lock {}@{}", + &log_wrappers::Value::key(key), + start_ts; + "region_id" => self.region_id, + "memory_in_use" => self.memory_quota.in_use(), + ); } else { - debug!("untrack a lock that was not tracked before"; + debug!("untrack a lock whose key is not tracked, should be from a pipelined transaction"; "key" => &log_wrappers::Value::key(key), "region_id" => self.region_id, ); - return; - }; - debug!( - "untrack lock {}@{}", - &log_wrappers::Value::key(key), - start_ts; - "region_id" => self.region_id, - "memory_in_use" => self.memory_quota.in_use(), - ); - - if let Some(txn_locks) = self.lock_ts_heap.get_mut(&start_ts) { - if txn_locks.lock_count > 0 { - txn_locks.lock_count -= 1; - } - if txn_locks.lock_count == 0 { - self.lock_ts_heap.remove(&start_ts); - } - }; - // Use a large ratio to amortize the cost of rehash. - let shrink_ratio = 8; - self.shrink_ratio(shrink_ratio); + } } /// Try to advance resolved ts. @@ -377,15 +432,13 @@ impl Resolver { // Find the min start ts. let min_lock = self.oldest_transaction(); let has_lock = min_lock.is_some(); - let min_start_ts = min_lock.as_ref().map(|(ts, _)| **ts).unwrap_or(min_ts); + let min_txn_ts = min_lock.as_ref().map(|(ts, _)| *ts).unwrap_or(min_ts); // No more commit happens before the ts. - let new_resolved_ts = cmp::min(min_start_ts, min_ts); + let new_resolved_ts = cmp::min(min_txn_ts, min_ts); // reason is the min source of the new resolved ts. let reason = match (min_lock, min_ts) { - (Some((lock_ts, txn_locks)), min_ts) if *lock_ts < min_ts => { - TsSource::Lock(txn_locks.clone()) - } + (Some((lock_ts, txn_locks)), min_ts) if lock_ts < min_ts => TsSource::Lock(txn_locks), (Some(_), _) => source, (None, _) => source, }; @@ -429,45 +482,140 @@ impl Resolver { self.resolved_ts } - pub(crate) fn log_locks(&self, min_start_ts: u64) { - // log lock with the minimum start_ts >= min_start_ts - if let Some((start_ts, txn_locks)) = self - .lock_ts_heap - .range(TimeStamp::new(min_start_ts)..) - .next() - { + /// Logs the txns with min start_ts or min_commit_ts. Search from + /// `lower_bound`. Normal txns are logged with start_ts. + /// Large txns are logged with min_commit_ts. + pub(crate) fn log_locks(&self, lower_bound: u64) { + self.log_min_lock(lower_bound.into()); + self.log_min_large_txn(lower_bound.into()); + } + + fn log_min_lock(&self, lower_bound: TimeStamp) { + if let Some((start_ts, txn_locks)) = self.lock_ts_heap.range(lower_bound..).next() { info!( - "locks with the minimum start_ts in resolver"; - "region_id" => self.region_id, + "non-large txn locks with the minimum start_ts in resolver"; + "search_lower_bound" => lower_bound, "start_ts" => start_ts, "txn_locks" => ?txn_locks, + "region_id" => self.region_id, + ); + } + } + + fn log_min_large_txn(&self, lower_bound: TimeStamp) { + let min_min_commit_ts_txn = self + .large_txn_ts + .iter() + .filter_map(|&start_ts| { + self.lookup_min_commit_ts(start_ts) + .map(|min_commit_ts| (start_ts, min_commit_ts)) + }) + .filter(|(_, min_commit_ts)| *min_commit_ts >= lower_bound) + .min_by_key(|(_, min_commit_ts)| *min_commit_ts); + + if let Some((start_ts, min_commit_ts)) = min_min_commit_ts_txn { + info!( + "large txn locks with the minimum min_commit_ts in resolver"; + "search_lower_bound" => lower_bound, + "start_ts" => start_ts, + "min_commit_ts" => min_commit_ts, + "region_id" => self.region_id, ); } } + // Map a transaction's start_ts to a min_commit_ts. + // When a large txn is committed or rolled back, return None. + // When not found in cache, fallback to its start_ts as start_ts is also a valid + // min_commit_ts + fn lookup_min_commit_ts(&self, start_ts: TimeStamp) -> Option { + match self.txn_status_cache.get(start_ts) { + None => { + info!("Large txn not found in cache"; "start_ts" => start_ts); + Some(start_ts) + } + // TODO: optimization: whenever a large txn is committed or rolled back, we can stop + // tracking this txn + Some(TxnState::Ongoing { min_commit_ts }) => Some(min_commit_ts), + Some(TxnState::Committed { .. }) | Some(TxnState::RolledBack) => None, + } + } + pub(crate) fn num_locks(&self) -> u64 { - self.locks_by_key.len() as u64 + // this is inaccurate, but it's just for monitoring. + // TODO: count the number of locks of large transactions, namely also track + // TxnLocks + (self.locks_by_key.len() + self.large_txn_ts.len()) as u64 } pub(crate) fn num_transactions(&self) -> u64 { - self.lock_ts_heap.len() as u64 + (self.lock_ts_heap.len() + self.large_txn_ts.len()) as u64 } pub(crate) fn read_progress(&self) -> Option<&Arc> { self.read_progress.as_ref() } - pub(crate) fn oldest_transaction(&self) -> Option<(&TimeStamp, &TxnLocks)> { - self.lock_ts_heap.iter().next() + // Return the transaction with the smallest min_commit_ts. When min_commit_ts + // is unknown, use start_ts instead. + pub(crate) fn oldest_transaction(&self) -> Option<(TimeStamp, TxnLocks)> { + let oldest_normal_txn = self + .lock_ts_heap + .iter() + .next() + .map(|(ts, txn_locks)| (ts, txn_locks.clone())); + + let oldest_large_txn = self + .large_txn_ts + .iter() + .filter_map(|start_ts| self.lookup_min_commit_ts(*start_ts)) + .min() + .map(|ts| { + ( + ts, + TxnLocks { + lock_count: 1, + // TODO: maybe fill this + sample_lock: None, + }, + ) + }); + + match (oldest_normal_txn, oldest_large_txn) { + (Some((&ts1, txn_locks1)), Some((ts2, txn_locks2))) => { + if ts1 < ts2 { + Some((ts1, txn_locks1)) + } else { + Some((ts2, txn_locks2)) + } + } + (Some((&ts, txn_locks)), None) => Some((ts, txn_locks)), + (None, Some((ts, txn_locks))) => Some((ts, txn_locks)), + (None, None) => None, + } } pub(crate) fn take_last_attempt(&mut self) -> Option { self.last_attempt.take() } + + fn track_large_txn_lock( + &mut self, + start_ts: TimeStamp, + key: Vec, + ) -> Result<(), MemoryQuotaExceeded> { + let is_new = self.large_txn_ts.insert(start_ts); + if is_new { + self.large_txn_key_representative.insert(key, start_ts); + } + Ok(()) + } } #[cfg(test)] mod tests { + use std::time::SystemTime; + use txn_types::Key; use super::*; @@ -535,12 +683,12 @@ mod tests { for (i, case) in cases.into_iter().enumerate() { let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let mut resolver = Resolver::new(1, memory_quota); + let mut resolver = Resolver::new_for_test(1, memory_quota); for e in case.clone() { match e { Event::Lock(start_ts, key) => { resolver - .track_lock(start_ts.into(), key.into_raw().unwrap(), None) + .track_lock(start_ts.into(), key.into_raw().unwrap(), None, 0) .unwrap(); } Event::Unlock(key) => resolver.untrack_lock(&key.into_raw().unwrap(), None), @@ -560,11 +708,11 @@ mod tests { #[test] fn test_memory_quota() { let memory_quota = Arc::new(MemoryQuota::new(1024)); - let mut resolver = Resolver::new(1, memory_quota.clone()); + let mut resolver = Resolver::new_for_test(1, memory_quota.clone()); let mut key = vec![0; 77]; let lock_size = resolver.lock_heap_size(&key); let mut ts = TimeStamp::default(); - while resolver.track_lock(ts, key.clone(), None).is_ok() { + while resolver.track_lock(ts, key.clone(), None, 0).is_ok() { ts.incr(); key[0..8].copy_from_slice(&ts.into_inner().to_be_bytes()); } @@ -585,13 +733,13 @@ mod tests { #[test] fn test_untrack_lock_shrink_ratio() { let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let mut resolver = Resolver::new(1, memory_quota); + let mut resolver = Resolver::new_for_test(1, memory_quota); let mut key = vec![0; 16]; let mut ts = TimeStamp::default(); for _ in 0..1000 { ts.incr(); key[0..8].copy_from_slice(&ts.into_inner().to_be_bytes()); - let _ = resolver.track_lock(ts, key.clone(), None); + let _ = resolver.track_lock(ts, key.clone(), None, 0); } assert!( resolver.locks_by_key.capacity() >= 1000, @@ -640,7 +788,7 @@ mod tests { #[test] fn test_idempotent_track_and_untrack_lock() { let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); - let mut resolver = Resolver::new(1, memory_quota); + let mut resolver = Resolver::new_for_test(1, memory_quota); let mut key = vec![0; 16]; // track_lock @@ -650,7 +798,7 @@ mod tests { for k in 0..100u64 { key[0..8].copy_from_slice(&k.to_be_bytes()); key[8..16].copy_from_slice(&ts.into_inner().to_be_bytes()); - let _ = resolver.track_lock(ts, key.clone(), None); + let _ = resolver.track_lock(ts, key.clone(), None, 0); } let in_use1 = resolver.memory_quota.in_use(); let key_count1 = resolver.locks_by_key.len(); @@ -664,7 +812,7 @@ mod tests { for k in 0..100u64 { key[0..8].copy_from_slice(&k.to_be_bytes()); key[8..16].copy_from_slice(&ts.into_inner().to_be_bytes()); - let _ = resolver.track_lock(ts, key.clone(), None); + let _ = resolver.track_lock(ts, key.clone(), None, 0); } let in_use2 = resolver.memory_quota.in_use(); let key_count2 = resolver.locks_by_key.len(); @@ -710,4 +858,44 @@ mod tests { assert_eq!(resolver.locks_by_key.len(), 0); assert_eq!(resolver.lock_ts_heap.len(), 0); } + + #[test] + fn test_large_txn_tracking() { + let memory_quota = Arc::new(MemoryQuota::new(std::usize::MAX)); + let txn_status_cache = Arc::new(TxnStatusCache::new(100)); + let mut resolver = Resolver::new(1, memory_quota, txn_status_cache.clone()); + let key: Vec = vec![1, 2, 3, 4]; + let key2: Vec = vec![5, 6, 7, 8]; + + // track 2 large txns + resolver.track_lock(1.into(), key.clone(), None, 1).unwrap(); + resolver + .track_lock(2.into(), key2.clone(), None, 1) + .unwrap(); + assert_eq!(resolver.num_locks(), 2); + assert_eq!(resolver.num_transactions(), 2); + assert_eq!(resolver.locks_by_key.len(), 0); + assert_eq!(resolver.large_txn_ts.len(), 2); + assert_eq!(resolver.large_txn_key_representative.len(), 2); + assert_eq!(resolver.resolved_ts(), TimeStamp::zero()); + + assert_eq!(resolver.resolve(20.into(), None, TsSource::PdTso), 1.into()); + + txn_status_cache.upsert( + 1.into(), + TxnState::Ongoing { + min_commit_ts: 10.into(), + }, + SystemTime::now(), + ); + txn_status_cache.upsert( + 2.into(), + TxnState::Ongoing { + min_commit_ts: 5.into(), + }, + SystemTime::now(), + ); + + assert_eq!(resolver.resolve(20.into(), None, TsSource::PdTso), 5.into()); + } } diff --git a/components/server/src/server.rs b/components/server/src/server.rs index adfd5cf1df9..4d53aa76ed5 100644 --- a/components/server/src/server.rs +++ b/components/server/src/server.rs @@ -113,7 +113,10 @@ use tikv::{ config_manager::StorageConfigManger, kv::LocalTablets, mvcc::MvccConsistencyCheckObserver, - txn::flow_controller::{EngineFlowController, FlowController}, + txn::{ + flow_controller::{EngineFlowController, FlowController}, + txn_status_cache::TxnStatusCache, + }, Engine, Storage, }, }; @@ -684,6 +687,9 @@ where )); storage_read_pools.handle() }; + let txn_status_cache = Arc::new(TxnStatusCache::new( + self.core.config.storage.txn_status_cache_capacity, + )); let storage = Storage::<_, _, F>::from_engine( engines.engine.clone(), @@ -702,6 +708,7 @@ where .as_ref() .map(|m| m.derive_controller("scheduler-worker-pool".to_owned(), true)), self.resource_manager.clone(), + txn_status_cache.clone(), ) .unwrap_or_else(|e| fatal!("failed to create raft storage: {}", e)); cfg_controller.register( @@ -947,6 +954,7 @@ where self.concurrency_manager.clone(), BackupStreamResolver::V1(leadership_resolver), backup_encryption_manager, + txn_status_cache.clone(), ); backup_stream_worker.start(backup_stream_endpoint); self.core.to_stop.push(backup_stream_worker); @@ -1111,6 +1119,7 @@ where self.concurrency_manager.clone(), server.env(), self.security_mgr.clone(), + storage.get_scheduler().get_txn_status_cache(), ); self.resolved_ts_scheduler = Some(rts_worker.scheduler()); rts_worker.start_with_timer(rts_endpoint); diff --git a/components/server/src/server2.rs b/components/server/src/server2.rs index dde83a9bffd..db60172cf8f 100644 --- a/components/server/src/server2.rs +++ b/components/server/src/server2.rs @@ -101,7 +101,10 @@ use tikv::{ config_manager::StorageConfigManger, kv::LocalTablets, mvcc::MvccConsistencyCheckObserver, - txn::flow_controller::{FlowController, TabletFlowController}, + txn::{ + flow_controller::{FlowController, TabletFlowController}, + txn_status_cache::TxnStatusCache, + }, Engine, Storage, }, }; @@ -551,6 +554,9 @@ where )); storage_read_pools.handle() }; + let txn_status_cache = Arc::new(TxnStatusCache::new( + self.core.config.storage.txn_status_cache_capacity, + )); let storage = Storage::<_, _, F>::from_engine( engines.engine.clone(), @@ -569,6 +575,7 @@ where .as_ref() .map(|m| m.derive_controller("scheduler-worker-pool".to_owned(), true)), self.resource_manager.clone(), + txn_status_cache.clone(), ) .unwrap_or_else(|e| fatal!("failed to create raft storage: {}", e)); cfg_controller.register( @@ -705,6 +712,7 @@ where self.concurrency_manager.clone(), self.env.clone(), self.security_mgr.clone(), + storage.get_scheduler().get_txn_status_cache(), ); self.resolved_ts_scheduler = Some(rts_worker.scheduler()); rts_worker.start_with_timer(rts_endpoint); @@ -750,6 +758,7 @@ where self.concurrency_manager.clone(), BackupStreamResolver::V2(self.router.clone().unwrap(), PhantomData), backup_encryption_manager.clone(), + txn_status_cache.clone(), ); backup_stream_worker.start(backup_stream_endpoint); self.core.to_stop.push(backup_stream_worker); diff --git a/components/test_raftstore-v2/src/server.rs b/components/test_raftstore-v2/src/server.rs index e73efd2c0a1..16db9fa396d 100644 --- a/components/test_raftstore-v2/src/server.rs +++ b/components/test_raftstore-v2/src/server.rs @@ -68,7 +68,10 @@ use tikv::{ storage::{ self, kv::{FakeExtension, LocalTablets, RaftExtension, SnapContext}, - txn::flow_controller::{EngineFlowController, FlowController}, + txn::{ + flow_controller::{EngineFlowController, FlowController}, + txn_status_cache::TxnStatusCache, + }, Engine, Storage, }, }; @@ -467,6 +470,7 @@ impl ServerCluster { ); gc_worker.start(node_id).unwrap(); + let txn_status_cache = Arc::new(TxnStatusCache::new_for_test()); let rts_worker = if cfg.resolved_ts.enable { // Resolved ts worker let mut rts_worker = LazyWorker::new("resolved-ts"); @@ -484,6 +488,7 @@ impl ServerCluster { concurrency_manager.clone(), self.env.clone(), self.security_mgr.clone(), + txn_status_cache.clone(), ); // Start the worker rts_worker.start(rts_endpoint); @@ -545,6 +550,7 @@ impl ServerCluster { .as_ref() .map(|m| m.derive_controller("scheduler-worker-pool".to_owned(), true)), resource_manager.clone(), + txn_status_cache, )?; self.storages.insert(node_id, raft_kv_v2.clone()); diff --git a/components/test_raftstore/src/server.rs b/components/test_raftstore/src/server.rs index c2858b08413..b7bd0eb4014 100644 --- a/components/test_raftstore/src/server.rs +++ b/components/test_raftstore/src/server.rs @@ -76,7 +76,10 @@ use tikv::{ storage::{ self, kv::{FakeExtension, LocalTablets, SnapContext}, - txn::flow_controller::{EngineFlowController, FlowController}, + txn::{ + flow_controller::{EngineFlowController, FlowController}, + txn_status_cache::TxnStatusCache, + }, Engine, Storage, }, }; @@ -400,6 +403,7 @@ impl ServerCluster { ); gc_worker.start(node_id).unwrap(); + let txn_status_cache = Arc::new(TxnStatusCache::new_for_test()); let rts_worker = if cfg.resolved_ts.enable { // Resolved ts worker let mut rts_worker = LazyWorker::new("resolved-ts"); @@ -417,6 +421,7 @@ impl ServerCluster { concurrency_manager.clone(), self.env.clone(), self.security_mgr.clone(), + txn_status_cache.clone(), ); // Start the worker rts_worker.start(rts_endpoint); @@ -477,6 +482,7 @@ impl ServerCluster { .as_ref() .map(|m| m.derive_controller("scheduler-worker-pool".to_owned(), true)), resource_manager.clone(), + txn_status_cache, )?; self.storages.insert(node_id, raft_kv.clone()); diff --git a/src/server/metrics.rs b/src/server/metrics.rs index 1d02cabd491..ae06155f4a1 100644 --- a/src/server/metrics.rs +++ b/src/server/metrics.rs @@ -66,6 +66,7 @@ make_auto_flush_static_metric! { kv_flush, kv_buffer_batch_get, get_health_feedback, + broadcast_txn_status, } pub label_enum GcCommandKind { diff --git a/src/server/service/kv.rs b/src/server/service/kv.rs index 6a93e3f52b8..be895af869a 100644 --- a/src/server/service/kv.rs +++ b/src/server/service/kv.rs @@ -82,7 +82,7 @@ pub struct Service { storage: Storage, // For handling coprocessor requests. copr: Endpoint, - // For handling corprocessor v2 requests. + // For handling coprocessor v2 requests. copr_v2: coprocessor_v2::Endpoint, // For handling snapshot. snap_scheduler: Scheduler, @@ -458,6 +458,13 @@ impl Tikv for Service { BufferBatchGetResponse ); + handle_request!( + broadcast_txn_status, + future_broadcast_txn_status, + BroadcastTxnStatusRequest, + BroadcastTxnStatusResponse + ); + fn kv_import(&mut self, _: RpcContext<'_>, _: ImportRequest, _: UnarySink) { unimplemented!(); } @@ -1466,6 +1473,7 @@ fn handle_batch_commands_request( RawCoprocessor, future_raw_coprocessor(copr_v2, storage), coprocessor; PessimisticLock, future_acquire_pessimistic_lock(storage), kv_pessimistic_lock; PessimisticRollback, future_pessimistic_rollback(storage), kv_pessimistic_rollback; + BroadcastTxnStatus, future_broadcast_txn_status(storage), broadcast_txn_status; } Ok(()) @@ -2266,6 +2274,26 @@ fn future_raw_coprocessor( async move { Ok(ret.await) } } +fn future_broadcast_txn_status( + storage: &Storage, + mut req: BroadcastTxnStatusRequest, +) -> impl Future> { + let (cb, f) = paired_future_callback(); + let res = storage.update_txn_status_cache( + req.take_context(), + req.take_txn_status().into_iter().collect(), + cb, + ); + + async move { + let _ = match res { + Err(e) => Err(e), + Ok(_) => f.await?, + }; + Ok(BroadcastTxnStatusResponse::default()) + } +} + macro_rules! txn_command_future { ($fn_name: ident, $req_ty: ident, $resp_ty: ident, ($req: ident) {$($prelude: stmt)*}; ($v: ident, $resp: ident, $tracker: ident) $else_branch: block) => { txn_command_future!(inner $fn_name, $req_ty, $resp_ty, ($req) {$($prelude)*}; ($v, $resp, $tracker) { diff --git a/src/storage/metrics.rs b/src/storage/metrics.rs index 46e4aa62b86..a2d68bf6d07 100644 --- a/src/storage/metrics.rs +++ b/src/storage/metrics.rs @@ -153,6 +153,7 @@ make_auto_flush_static_metric! { flashback_to_version_rollback_lock, flashback_to_version_write, flush, + update_txn_status_cache, raw_get, raw_batch_get, raw_scan, diff --git a/src/storage/mod.rs b/src/storage/mod.rs index da2a1db51b9..1ee1913a8c9 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -61,6 +61,7 @@ mod read_pool; mod types; use std::{ + assert_matches::assert_matches, borrow::Cow, iter, marker::PhantomData, @@ -69,7 +70,7 @@ use std::{ atomic::{self, AtomicBool, AtomicU64, Ordering}, Arc, }, - time::Duration, + time::{Duration, SystemTime}, }; use api_version::{ApiV1, ApiV2, KeyMode, KvFormat, RawValue}; @@ -81,6 +82,7 @@ use engine_traits::{ }; use futures::{future::Either, prelude::*}; use kvproto::{ + kvrpcpb, kvrpcpb::{ ApiVersion, ChecksumAlgorithm, CommandPri, Context, GetRequest, IsolationLevel, KeyRange, LockInfo, RawGetRequest, @@ -104,6 +106,7 @@ use tracker::{ }; use txn_types::{Key, KvPair, Lock, LockType, TimeStamp, TsSet, Value}; +use self::kv::SnapContext; pub use self::{ errors::{get_error_kind_from_header, get_tag_from_header, Error, ErrorHeaderKind, ErrorInner}, kv::{ @@ -118,7 +121,6 @@ pub use self::{ StorageCallback, TxnStatus, }, }; -use self::{kv::SnapContext, test_util::latest_feature_gate}; use crate::{ read_pool::{ReadPool, ReadPoolHandle}, server::{lock_manager::waiter_manager, metrics::ResourcePriority}, @@ -128,10 +130,12 @@ use crate::{ lock_manager::{LockManager, MockLockManager}, metrics::{CommandKind, *}, mvcc::{metrics::ScanLockReadTimeSource::resolve_lock, MvccReader, PointGetterBuilder}, + test_util::latest_feature_gate, txn::{ commands::{RawAtomicStore, RawCompareAndSwap, TypedCommand}, flow_controller::{EngineFlowController, FlowController}, scheduler::TxnScheduler, + txn_status_cache::{TxnState, TxnStatusCache}, Command, Error as TxnError, ErrorInner as TxnErrorInner, }, types::StorageCallbackType, @@ -219,7 +223,7 @@ pub struct Storage { impl Clone for Storage { #[inline] fn clone(&self) -> Self { - let refs = self.refs.fetch_add(1, atomic::Ordering::SeqCst); + let refs = self.refs.fetch_add(1, Ordering::SeqCst); trace!( "Storage referenced"; "original_ref" => refs @@ -245,7 +249,7 @@ impl Clone for Storage { impl Drop for Storage { #[inline] fn drop(&mut self) { - let refs = self.refs.fetch_sub(1, atomic::Ordering::SeqCst); + let refs = self.refs.fetch_sub(1, Ordering::SeqCst); trace!( "Storage de-referenced"; "original_ref" => refs @@ -276,6 +280,7 @@ impl Storage { causal_ts_provider: Option>, resource_ctl: Option>, resource_manager: Option>, + txn_status_cache: Arc, ) -> Result { assert_eq!(config.api_version(), F::TAG, "Api version not match"); @@ -293,6 +298,7 @@ impl Storage { feature_gate, resource_ctl, resource_manager.clone(), + txn_status_cache, ); info!("Storage started."); @@ -3245,6 +3251,38 @@ impl Storage { .and_then(|res| future::ready(res)), ) } + + pub fn update_txn_status_cache( + &self, + ctx: Context, + txn_statuses: Vec, + callback: Callback<()>, + ) -> Result<()> { + const CMD: CommandKind = CommandKind::update_txn_status_cache; + let priority = ctx.get_priority(); + let metadata = TaskMetadata::from_ctx(ctx.get_resource_control_context()); + let cache = self.get_scheduler().get_txn_status_cache(); + let f = async move { + let now = SystemTime::now(); + for txn_status in txn_statuses { + let txn_state = TxnState::from_ts( + txn_status.start_ts.into(), + txn_status.min_commit_ts.into(), + txn_status.commit_ts.into(), + txn_status.rolled_back, + ); + if txn_status.is_completed { + // large_txn_cache is only for **ongoing** large txns, so remove it when + // completed. + assert_matches!(txn_state, TxnState::Committed { .. } | TxnState::RolledBack); + cache.remove_large_txn(txn_status.start_ts.into()); + } + cache.upsert(txn_status.start_ts.into(), txn_state, now); + } + callback(Ok(())); + }; + self.sched_raw_command(metadata, priority, CMD, f) + } } pub async fn get_raw_key_guard( @@ -3546,7 +3584,7 @@ impl TestStorageBuilder { pub fn pipelined_pessimistic_lock(self, enabled: bool) -> Self { self.pipelined_pessimistic_lock - .store(enabled, atomic::Ordering::Relaxed); + .store(enabled, Ordering::Relaxed); self } @@ -3557,7 +3595,7 @@ impl TestStorageBuilder { pub fn in_memory_pessimistic_lock(self, enabled: bool) -> Self { self.in_memory_pessimistic_lock - .store(enabled, atomic::Ordering::Relaxed); + .store(enabled, Ordering::Relaxed); self } @@ -3613,6 +3651,7 @@ impl TestStorageBuilder { ts_provider, Some(resource_ctl), Some(manager), + Arc::new(TxnStatusCache::new_for_test()), ) } @@ -3648,6 +3687,7 @@ impl TestStorageBuilder { None, Some(resource_ctl), Some(manager), + Arc::new(TxnStatusCache::new_for_test()), ) } @@ -3686,6 +3726,7 @@ impl TestStorageBuilder { None, Some(resource_controller), Some(resource_manager), + Arc::new(TxnStatusCache::new_for_test()), ) } } @@ -4255,7 +4296,7 @@ mod tests { statistics: &mut Statistics::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); @@ -8376,7 +8417,7 @@ mod tests { // No lock. storage .sched_txn_command( - commands::TxnHeartBeat::new(k.clone(), 10.into(), 100, Context::default()), + commands::TxnHeartBeat::new(k.clone(), 10.into(), 100, 0, Context::default()), expect_fail_callback(tx.clone(), 0, |e| match e { Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(mvcc::Error( box mvcc::ErrorInner::TxnNotFound { .. }, @@ -8418,7 +8459,7 @@ mod tests { // remains 100. storage .sched_txn_command( - commands::TxnHeartBeat::new(k.clone(), 10.into(), 90, Context::default()), + commands::TxnHeartBeat::new(k.clone(), 10.into(), 90, 0, Context::default()), expect_value_callback(tx.clone(), 0, uncommitted(lock_with_ttl(100), false)), ) .unwrap(); @@ -8428,7 +8469,7 @@ mod tests { // updated to 110. storage .sched_txn_command( - commands::TxnHeartBeat::new(k.clone(), 10.into(), 110, Context::default()), + commands::TxnHeartBeat::new(k.clone(), 10.into(), 110, 0, Context::default()), expect_value_callback(tx.clone(), 0, uncommitted(lock_with_ttl(110), false)), ) .unwrap(); @@ -8437,7 +8478,7 @@ mod tests { // Lock not match. Nothing happens except throwing an error. storage .sched_txn_command( - commands::TxnHeartBeat::new(k, 11.into(), 150, Context::default()), + commands::TxnHeartBeat::new(k, 11.into(), 150, 0, Context::default()), expect_fail_callback(tx, 0, |e| match e { Error(box ErrorInner::Txn(TxnError(box TxnErrorInner::Mvcc(mvcc::Error( box mvcc::ErrorInner::TxnNotFound { .. }, diff --git a/src/storage/txn/actions/tests.rs b/src/storage/txn/actions/tests.rs index 0fc73804aff..3bb2bbf2c2a 100644 --- a/src/storage/txn/actions/tests.rs +++ b/src/storage/txn/actions/tests.rs @@ -2,19 +2,27 @@ //! This file contains tests and testing tools which affects multiple actions +use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::{ - Assertion, AssertionLevel, Context, + Assertion, AssertionLevel, Context, ExtraOp, PrewriteRequestPessimisticAction::{self, *}, }; use prewrite::{prewrite, CommitKind, TransactionKind, TransactionProperties}; -use tikv_kv::SnapContext; +use tikv_kv::{SnapContext, Statistics}; use super::*; use crate::storage::{ kv::WriteData, + lock_manager::MockLockManager, mvcc::{tests::write, Error, Key, Mutation, MvccTxn, SnapshotReader, TimeStamp}, - txn, Engine, + txn, + txn::{ + commands::{Flush, WriteContext, WriteResult}, + txn_status_cache::TxnStatusCache, + }, + Engine, }; pub fn must_prewrite_put_impl( @@ -199,6 +207,87 @@ pub fn must_prewrite_put( ); } +pub fn flush_put_impl( + engine: &mut E, + key: &[u8], + value: impl Into>, + pk: impl Into>, + start_ts: impl Into, + generation: u64, + should_not_exist: bool, +) -> txn::Result { + flush_put_impl_with_assertion( + engine, + key, + value, + pk, + start_ts, + generation, + should_not_exist, + Assertion::None, + ) +} + +pub fn flush_put_impl_with_assertion( + engine: &mut E, + key: &[u8], + value: impl Into>, + pk: impl Into>, + start_ts: impl Into, + generation: u64, + should_not_exist: bool, + assertion: Assertion, +) -> txn::Result { + let key = Key::from_raw(key); + let start_ts = start_ts.into(); + let mut m = if should_not_exist { + Mutation::make_insert(key, value.into()) + } else { + Mutation::make_put(key, value.into()) + }; + m.set_assertion(assertion); + let cmd = Flush::new( + start_ts, + pk.into(), + vec![m], + generation, + 3000, + AssertionLevel::Strict, + Context::new(), + ); + let mut statistics = Statistics::default(); + let cm = ConcurrencyManager::new(start_ts); + let context = WriteContext { + lock_mgr: &MockLockManager::new(), + concurrency_manager: cm.clone(), + extra_op: ExtraOp::Noop, + statistics: &mut statistics, + async_apply_prewrite: false, + raw_ext: None, + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), + }; + let snapshot = engine.snapshot(Default::default()).unwrap(); + cmd.cmd.process_write(snapshot.clone(), context) +} + +pub fn must_flush_put( + engine: &mut E, + key: &[u8], + value: impl Into>, + pk: impl Into>, + start_ts: impl Into, + generation: u64, +) { + let res = flush_put_impl(engine, key, value, pk, start_ts, generation, false); + assert!(res.is_ok()); + let res = res.unwrap(); + let to_be_write = res.to_be_write; + if to_be_write.modifies.is_empty() { + return; + } + engine.write(&Context::new(), to_be_write).unwrap(); +} + pub fn must_prewrite_put_on_region( engine: &mut E, region_id: u64, diff --git a/src/storage/txn/commands/acquire_pessimistic_lock_resumed.rs b/src/storage/txn/commands/acquire_pessimistic_lock_resumed.rs index 16d5177fa12..336ed6d43f5 100644 --- a/src/storage/txn/commands/acquire_pessimistic_lock_resumed.rs +++ b/src/storage/txn/commands/acquire_pessimistic_lock_resumed.rs @@ -286,7 +286,7 @@ mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); diff --git a/src/storage/txn/commands/atomic_store.rs b/src/storage/txn/commands/atomic_store.rs index f90d1fcde0b..7626ee2a6d7 100644 --- a/src/storage/txn/commands/atomic_store.rs +++ b/src/storage/txn/commands/atomic_store.rs @@ -71,6 +71,8 @@ impl WriteCommand for RawAtomicStore { #[cfg(test)] mod tests { + use std::sync::Arc; + use api_version::{test_kv_format_impl, ApiV2, KvFormat, RawValue}; use engine_traits::CF_DEFAULT; use futures::executor::block_on; @@ -120,7 +122,7 @@ mod tests { statistics: &mut statistic, async_apply_prewrite: false, raw_ext, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let cmd: Command = cmd.into(); let write_result = cmd.process_write(snap, context).unwrap(); diff --git a/src/storage/txn/commands/check_secondary_locks.rs b/src/storage/txn/commands/check_secondary_locks.rs index 5f9759ce379..aff85ca3e61 100644 --- a/src/storage/txn/commands/check_secondary_locks.rs +++ b/src/storage/txn/commands/check_secondary_locks.rs @@ -236,6 +236,8 @@ impl WriteCommand for CheckSecondaryLocks { #[cfg(test)] pub mod tests { + use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::Context; use tikv_util::deadline::Deadline; @@ -278,7 +280,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); @@ -317,7 +319,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); diff --git a/src/storage/txn/commands/check_txn_status.rs b/src/storage/txn/commands/check_txn_status.rs index c3e5410a692..f2bbdac7478 100644 --- a/src/storage/txn/commands/check_txn_status.rs +++ b/src/storage/txn/commands/check_txn_status.rs @@ -163,6 +163,8 @@ impl WriteCommand for CheckTxnStatus { #[cfg(test)] pub mod tests { + use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::{ self, Context, LockInfo, PrewriteRequestPessimisticAction::*, WriteConflictReason, @@ -226,7 +228,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); @@ -280,7 +282,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .map(|r| { diff --git a/src/storage/txn/commands/compare_and_swap.rs b/src/storage/txn/commands/compare_and_swap.rs index 2658cfe7a4d..89b3287219a 100644 --- a/src/storage/txn/commands/compare_and_swap.rs +++ b/src/storage/txn/commands/compare_and_swap.rs @@ -222,7 +222,7 @@ mod tests { statistics: &mut statistic, async_apply_prewrite: false, raw_ext, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let ret = cmd.cmd.process_write(snap, context)?; match ret.pr { @@ -277,7 +277,7 @@ mod tests { statistics: &mut statistic, async_apply_prewrite: false, raw_ext, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let cmd: Command = cmd.into(); let write_result = cmd.process_write(snap, context).unwrap(); diff --git a/src/storage/txn/commands/flush.rs b/src/storage/txn/commands/flush.rs index 63c05385a30..519786781de 100644 --- a/src/storage/txn/commands/flush.rs +++ b/src/storage/txn/commands/flush.rs @@ -219,111 +219,27 @@ impl Flush { mod tests { use std::assert_matches::assert_matches; - use concurrency_manager::ConcurrencyManager; - use kvproto::kvrpcpb::{Assertion, AssertionLevel, Context, ExtraOp}; - use tikv_kv::{Engine, Statistics}; - use txn_types::{Key, Mutation, TimeStamp}; + use kvproto::kvrpcpb::{Assertion, Context}; + use tikv_kv::Engine; + use txn_types::TimeStamp; use crate::storage::{ - lock_manager::MockLockManager, mvcc::{ tests::{must_get, must_locked}, Error as MvccError, ErrorInner as MvccErrorInner, }, txn, txn::{ - commands::{Flush, WriteContext, WriteResult}, tests::{ - must_acquire_pessimistic_lock, must_acquire_pessimistic_lock_err, must_commit, + flush_put_impl, flush_put_impl_with_assertion, must_acquire_pessimistic_lock, + must_acquire_pessimistic_lock_err, must_commit, must_flush_put, must_pessimistic_locked, must_prewrite_put, must_prewrite_put_err, }, - txn_status_cache::TxnStatusCache, Error, ErrorInner, }, ProcessResult, TestEngineBuilder, }; - pub fn flush_put_impl( - engine: &mut E, - key: &[u8], - value: impl Into>, - pk: impl Into>, - start_ts: impl Into, - generation: u64, - should_not_exist: bool, - ) -> txn::Result { - flush_put_impl_with_assertion( - engine, - key, - value, - pk, - start_ts, - generation, - should_not_exist, - Assertion::None, - ) - } - - pub fn flush_put_impl_with_assertion( - engine: &mut E, - key: &[u8], - value: impl Into>, - pk: impl Into>, - start_ts: impl Into, - generation: u64, - should_not_exist: bool, - assertion: Assertion, - ) -> txn::Result { - let key = Key::from_raw(key); - let start_ts = start_ts.into(); - let mut m = if should_not_exist { - Mutation::make_insert(key, value.into()) - } else { - Mutation::make_put(key, value.into()) - }; - m.set_assertion(assertion); - let cmd = Flush::new( - start_ts, - pk.into(), - vec![m], - generation, - 3000, - AssertionLevel::Strict, - Context::new(), - ); - let mut statistics = Statistics::default(); - let cm = ConcurrencyManager::new(start_ts); - let context = WriteContext { - lock_mgr: &MockLockManager::new(), - concurrency_manager: cm.clone(), - extra_op: ExtraOp::Noop, - statistics: &mut statistics, - async_apply_prewrite: false, - raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), - }; - let snapshot = engine.snapshot(Default::default()).unwrap(); - cmd.cmd.process_write(snapshot.clone(), context) - } - - pub fn must_flush_put( - engine: &mut E, - key: &[u8], - value: impl Into>, - pk: impl Into>, - start_ts: impl Into, - generation: u64, - ) { - let res = flush_put_impl(engine, key, value, pk, start_ts, generation, false); - assert!(res.is_ok()); - let res = res.unwrap(); - let to_be_write = res.to_be_write; - if to_be_write.modifies.is_empty() { - return; - } - engine.write(&Context::new(), to_be_write).unwrap(); - } - pub fn must_flush_put_with_assertion( engine: &mut E, key: &[u8], diff --git a/src/storage/txn/commands/mod.rs b/src/storage/txn/commands/mod.rs index 5ff54b334cb..48654c826a7 100644 --- a/src/storage/txn/commands/mod.rs +++ b/src/storage/txn/commands/mod.rs @@ -310,6 +310,7 @@ impl From for TypedCommand { Key::from_raw(req.get_primary_lock()), req.get_start_version().into(), req.get_advise_lock_ttl(), + req.get_min_commit_ts(), req.take_context(), ) } @@ -642,7 +643,7 @@ pub struct WriteContext<'a, L: LockManager> { pub async_apply_prewrite: bool, pub raw_ext: Option, // use for apiv2 - pub txn_status_cache: &'a TxnStatusCache, + pub txn_status_cache: Arc, } pub struct ReaderWithStats<'a, S: Snapshot> { @@ -930,7 +931,7 @@ pub mod test_util { statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let ret = cmd.cmd.process_write(snap, context)?; let res = match ret.pr { @@ -1091,7 +1092,7 @@ pub mod test_util { statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let ret = cmd.cmd.process_write(snap, context)?; @@ -1117,7 +1118,7 @@ pub mod test_util { statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let ret = cmd.cmd.process_write(snap, context)?; diff --git a/src/storage/txn/commands/pessimistic_rollback.rs b/src/storage/txn/commands/pessimistic_rollback.rs index 12ecf098597..f51319190cb 100644 --- a/src/storage/txn/commands/pessimistic_rollback.rs +++ b/src/storage/txn/commands/pessimistic_rollback.rs @@ -127,6 +127,8 @@ impl WriteCommand for PessimisticRollback { #[cfg(test)] pub mod tests { + use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::Context; use tikv_util::deadline::Deadline; @@ -173,7 +175,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let result = command.process_write(snapshot, write_context).unwrap(); write(engine, &ctx, result.to_be_write.modifies); diff --git a/src/storage/txn/commands/prewrite.rs b/src/storage/txn/commands/prewrite.rs index 38b22f24960..581e248d9f1 100644 --- a/src/storage/txn/commands/prewrite.rs +++ b/src/storage/txn/commands/prewrite.rs @@ -996,6 +996,8 @@ pub(in crate::storage::txn) fn fallback_1pc_locks(txn: &mut MvccTxn) { #[cfg(test)] mod tests { + use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use engine_rocks::ReadPerfInstant; use engine_traits::CF_WRITE; @@ -1670,7 +1672,7 @@ mod tests { statistics: &mut Statistics::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), } }; } @@ -1842,7 +1844,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: case.async_apply_prewrite, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let mut engine = TestEngineBuilder::new().build().unwrap(); let snap = engine.snapshot(Default::default()).unwrap(); @@ -1953,7 +1955,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); let result = cmd.cmd.process_write(snap, context).unwrap(); @@ -1982,7 +1984,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); let result = cmd.cmd.process_write(snap, context).unwrap(); @@ -2066,7 +2068,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); let result = cmd.cmd.process_write(snap, context).unwrap(); @@ -2099,7 +2101,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); let result = cmd.cmd.process_write(snap, context).unwrap(); @@ -2370,7 +2372,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); assert!(prewrite_cmd.cmd.process_write(snap, context).is_err()); @@ -2395,7 +2397,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); assert!(prewrite_cmd.cmd.process_write(snap, context).is_err()); @@ -2602,7 +2604,7 @@ mod tests { statistics: &mut statistics, async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }; let snap = engine.snapshot(Default::default()).unwrap(); let res = prewrite_cmd.cmd.process_write(snap, context).unwrap(); diff --git a/src/storage/txn/commands/txn_heart_beat.rs b/src/storage/txn/commands/txn_heart_beat.rs index 5195a805aa6..11c53a05878 100644 --- a/src/storage/txn/commands/txn_heart_beat.rs +++ b/src/storage/txn/commands/txn_heart_beat.rs @@ -37,6 +37,8 @@ command! { /// The new TTL that will be used to update the lock's TTL. If the lock's TTL is already /// greater than `advise_ttl`, nothing will happen. advise_ttl: u64, + /// The updated min_commit_ts of the primary key. Piggybacked on the heartbeat command. + min_commit_ts: u64, } in_heap => { primary_key, @@ -71,10 +73,28 @@ impl WriteCommand for TxnHeartBeat { let lock = match reader.load_lock(&self.primary_key)? { Some(mut lock) if lock.ts == self.start_ts => { + let mut updated = false; + if lock.ttl < self.advise_ttl { lock.ttl = self.advise_ttl; + updated = true; + } + + // only for non-async-commit pipelined transactions, we can update the + // min_commit_ts + if !lock.use_async_commit + && lock.generation > 0 + && self.min_commit_ts > 0 + && lock.min_commit_ts < self.min_commit_ts.into() + { + lock.min_commit_ts = self.min_commit_ts.into(); + updated = true; + } + + if updated { txn.put_lock(self.primary_key.clone(), &lock, false); } + lock } _ => { @@ -109,6 +129,8 @@ impl WriteCommand for TxnHeartBeat { #[cfg(test)] pub mod tests { + use std::sync::Arc; + use concurrency_manager::ConcurrencyManager; use kvproto::kvrpcpb::Context; use tikv_util::deadline::Deadline; @@ -136,12 +158,13 @@ pub mod tests { let snapshot = engine.snapshot(Default::default()).unwrap(); let start_ts = start_ts.into(); let cm = ConcurrencyManager::new(start_ts); - let command = crate::storage::txn::commands::TxnHeartBeat { + let command = TxnHeartBeat { ctx: Context::default(), primary_key: Key::from_raw(primary_key), start_ts, advise_ttl, deadline: Deadline::from_now(DEFAULT_EXECUTION_DURATION_LIMIT), + min_commit_ts: 0, }; let result = command .process_write( @@ -153,7 +176,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .unwrap(); @@ -178,12 +201,13 @@ pub mod tests { let snapshot = engine.snapshot(Default::default()).unwrap(); let start_ts = start_ts.into(); let cm = ConcurrencyManager::new(start_ts); - let command = crate::storage::txn::commands::TxnHeartBeat { + let command = TxnHeartBeat { ctx, primary_key: Key::from_raw(primary_key), start_ts, advise_ttl, deadline: Deadline::from_now(DEFAULT_EXECUTION_DURATION_LIMIT), + min_commit_ts: 0, }; assert!( command @@ -196,7 +220,7 @@ pub mod tests { statistics: &mut Default::default(), async_apply_prewrite: false, raw_ext: None, - txn_status_cache: &TxnStatusCache::new_for_test(), + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), }, ) .is_err() @@ -251,4 +275,52 @@ pub mod tests { must_pessimistic_locked(&mut engine, k, 8, 15); } + + #[test] + fn test_heartbeat_piggyback_min_commit_ts() { + let mut engine = TestEngineBuilder::new().build().unwrap(); + + let (k, v) = (b"k1", b"v1"); + + // Create a lock with TTL=100. + must_flush_put(&mut engine, k, v, k, 5, 1); + must_locked(&mut engine, k, 5); + + let ctx = Context::default(); + let snapshot = engine.snapshot(Default::default()).unwrap(); + let start_ts = 5.into(); + let cm = ConcurrencyManager::new(start_ts); + let command = TxnHeartBeat { + ctx: ctx.clone(), + primary_key: Key::from_raw(k), + start_ts, + advise_ttl: 3333, + min_commit_ts: 10, + deadline: Deadline::from_now(DEFAULT_EXECUTION_DURATION_LIMIT), + }; + let result = command + .process_write( + snapshot, + WriteContext { + lock_mgr: &MockLockManager::new(), + concurrency_manager: cm, + extra_op: Default::default(), + statistics: &mut Default::default(), + async_apply_prewrite: false, + raw_ext: None, + txn_status_cache: Arc::new(TxnStatusCache::new_for_test()), + }, + ) + .unwrap(); + if let ProcessResult::TxnStatus { + txn_status: TxnStatus::Uncommitted { lock, .. }, + } = result.pr + { + write(&engine, &ctx, result.to_be_write.modifies); + assert_eq!(lock.ttl, 3333); + assert_eq!(lock.min_commit_ts, 10.into()); + } else { + unreachable!(); + } + } } diff --git a/src/storage/txn/scheduler.rs b/src/storage/txn/scheduler.rs index b82a84c55d1..d486ff97523 100644 --- a/src/storage/txn/scheduler.rs +++ b/src/storage/txn/scheduler.rs @@ -284,7 +284,7 @@ struct TxnSchedulerInner { resource_manager: Option>, feature_gate: FeatureGate, - txn_status_cache: TxnStatusCache, + txn_status_cache: Arc, memory_quota: Arc, @@ -445,6 +445,7 @@ impl TxnScheduler { feature_gate: FeatureGate, resource_ctl: Option>, resource_manager: Option>, + txn_status_cache: Arc, ) -> Self { let t = Instant::now_coarse(); let mut task_slots = Vec::with_capacity(TASKS_SLOTS_NUM); @@ -482,7 +483,7 @@ impl TxnScheduler { quota_limiter, resource_manager, feature_gate, - txn_status_cache: TxnStatusCache::new(config.txn_status_cache_capacity), + txn_status_cache, memory_quota: Arc::new(MemoryQuota::new(config.memory_quota.0 as _)), in_memory_peer_size_limit: dynamic_configs.in_memory_peer_size_limit, in_memory_instance_size_limit: dynamic_configs.in_memory_instance_size_limit, @@ -1307,7 +1308,7 @@ impl TxnScheduler { statistics: &mut sched_details.stat, async_apply_prewrite: txn_scheduler.inner.enable_async_apply_prewrite, raw_ext, - txn_status_cache: &txn_scheduler.inner.txn_status_cache, + txn_status_cache: txn_scheduler.inner.txn_status_cache.clone(), }; let begin_instant = Instant::now(); let res = unsafe { @@ -2094,9 +2095,8 @@ impl TxnScheduler { } } - #[cfg(test)] - pub fn get_txn_status_cache(&self) -> &TxnStatusCache { - &self.inner.txn_status_cache + pub fn get_txn_status_cache(&self) -> Arc { + self.inner.txn_status_cache.clone() } } @@ -2255,6 +2255,7 @@ mod tests { latest_feature_gate(), Some(controller), Some(resource_manager), + Arc::new(TxnStatusCache::new_for_test()), ), engine, ) @@ -2343,7 +2344,7 @@ mod tests { Context::default(), ) .into(), - commands::TxnHeartBeat::new(Key::from_raw(b"k"), 10.into(), 100, Context::default()) + commands::TxnHeartBeat::new(Key::from_raw(b"k"), 10.into(), 100, 0, Context::default()) .into(), ]; @@ -2607,6 +2608,7 @@ mod tests { feature_gate.clone(), Some(controller), Some(resource_manager), + Arc::new(TxnStatusCache::new_for_test()), ); // Use sync mode if pipelined_pessimistic_lock is false. assert_eq!(scheduler.pessimistic_lock_mode(), PessimisticLockMode::Sync); diff --git a/src/storage/txn/txn_status_cache.rs b/src/storage/txn/txn_status_cache.rs index 4edff6bc7a8..371cb5a7298 100644 --- a/src/storage/txn/txn_status_cache.rs +++ b/src/storage/txn/txn_status_cache.rs @@ -131,6 +131,7 @@ //! large transactions, preventing either type from dominating the cache and //! evicting information about transactions of the other type. use std::{ + cmp::max, sync::{atomic::AtomicU64, Arc}, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -178,6 +179,25 @@ pub enum TxnState { RolledBack, } +impl TxnState { + pub fn from_ts( + start_ts: TimeStamp, + min_commit_ts: TimeStamp, + commit_ts: TimeStamp, + rolled_back: bool, + ) -> Self { + if rolled_back { + TxnState::RolledBack + } else if commit_ts.is_zero() { + TxnState::Ongoing { + min_commit_ts: max(start_ts, min_commit_ts), + } + } else { + TxnState::Committed { commit_ts } + } + } +} + /// Defines the policy to evict expired entries from the cache. /// [`TxnStatusCache`] needs to keep entries for a while, so the common /// policy that only limiting capacity is not proper to be used here. @@ -346,7 +366,7 @@ impl TxnStatusCache { ) } - #[cfg(test)] + // Not #[cfg(test)]: needed for integration tests in separate files pub fn new_for_test() -> Self { // 1M capacity should be enough for tests. Self::with_slots_and_time_limit( @@ -401,9 +421,10 @@ impl TxnStatusCache { fxhash::hash(&start_ts) % self.normal_cache.len() } - /// Insert a transaction status into the cache, or update it. The current - /// system time should be passed from outside to avoid getting system time - /// repeatedly when multiple items are being inserted. + /// Insert a transaction status into the cache. If it already exists, update + /// it. The current system time should be passed from outside to avoid + /// getting system time repeatedly when multiple items are being + /// inserted. pub fn upsert(&self, start_ts: TimeStamp, state: TxnState, now: SystemTime) { if !self.is_enabled { return; From c67e7c37786f9d153ede85a1c8daacebe2610688 Mon Sep 17 00:00:00 2001 From: Liqi Geng Date: Wed, 25 Sep 2024 16:36:38 +0800 Subject: [PATCH 090/144] Support date_add/date_sub expression functions (#17541) close tikv/tikv#17529 Support date_add/date_sub expression functions Signed-off-by: gengliqi Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- .../tidb_query_datatype/src/codec/error.rs | 6 + .../src/codec/mysql/decimal.rs | 10 +- .../src/codec/mysql/duration.rs | 14 +- .../src/codec/mysql/mod.rs | 2 +- .../src/codec/mysql/time/interval.rs | 1774 +++++++++++++++++ .../src/codec/mysql/time/mod.rs | 538 ++++- .../tidb_query_datatype/src/expr/ctx.rs | 2 + components/tidb_query_datatype/src/lib.rs | 1 + components/tidb_query_expr/src/impl_cast.rs | 22 +- components/tidb_query_expr/src/impl_time.rs | 1180 ++++++++++- components/tidb_query_expr/src/lib.rs | 56 + .../tipb_helper/src/expr_def_builder.rs | 40 +- 13 files changed, 3586 insertions(+), 61 deletions(-) create mode 100644 components/tidb_query_datatype/src/codec/mysql/time/interval.rs diff --git a/Cargo.lock b/Cargo.lock index 0ec94cddfe2..18df7af3d7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6870,7 +6870,7 @@ dependencies = [ [[package]] name = "tipb" version = "0.0.1" -source = "git+https://github.com/pingcap/tipb.git#87f5b80908ab561fb7875c88114488cad15727b1" +source = "git+https://github.com/pingcap/tipb.git#cf70966bef25e205cb845c19265301542d1238d1" dependencies = [ "futures 0.3.15", "grpcio", diff --git a/components/tidb_query_datatype/src/codec/error.rs b/components/tidb_query_datatype/src/codec/error.rs index 785424b31ca..2d48ee08b65 100644 --- a/components/tidb_query_datatype/src/codec/error.rs +++ b/components/tidb_query_datatype/src/codec/error.rs @@ -21,6 +21,7 @@ pub const ERR_TRUNCATE_WRONG_VALUE: i32 = 1292; pub const ERR_UNKNOWN_TIMEZONE: i32 = 1298; pub const ERR_DIVISION_BY_ZERO: i32 = 1365; pub const ERR_DATA_TOO_LONG: i32 = 1406; +pub const ERR_DATETIME_FUNCTION_OVERFLOW: i32 = 1441; pub const ERR_INCORRECT_PARAMETERS: i32 = 1583; pub const ERR_DATA_OUT_OF_RANGE: i32 = 1690; pub const ERR_CANNOT_CONVERT_STRING: i32 = 3854; @@ -100,6 +101,11 @@ impl Error { Error::Eval(msg, ERR_CANNOT_CONVERT_STRING) } + pub fn datetime_function_overflow() -> Error { + let msg = "Datetime function field overflow"; + Error::Eval(msg.into(), ERR_DATETIME_FUNCTION_OVERFLOW) + } + pub fn code(&self) -> i32 { match *self { Error::Eval(_, code) => code, diff --git a/components/tidb_query_datatype/src/codec/mysql/decimal.rs b/components/tidb_query_datatype/src/codec/mysql/decimal.rs index 0930973233c..8d3e291fa4e 100644 --- a/components/tidb_query_datatype/src/codec/mysql/decimal.rs +++ b/components/tidb_query_datatype/src/codec/mysql/decimal.rs @@ -1047,6 +1047,11 @@ impl Decimal { } } + /// `frac_cnt` returns fraction count. + pub fn frac_cnt(&self) -> u8 { + self.frac_cnt + } + /// `digit_bounds` returns bounds of decimal digits in the number. fn digit_bounds(&self) -> (u8, u8) { let mut buf_beg = 0; @@ -1741,11 +1746,6 @@ impl Decimal { pub fn result_frac_cnt(&self) -> u8 { self.result_frac_cnt } - - #[cfg(test)] - pub fn frac_cnt(&self) -> u8 { - self.frac_cnt - } } macro_rules! enable_conv_for_int { diff --git a/components/tidb_query_datatype/src/codec/mysql/duration.rs b/components/tidb_query_datatype/src/codec/mysql/duration.rs index 7279f788146..9205776d25e 100644 --- a/components/tidb_query_datatype/src/codec/mysql/duration.rs +++ b/components/tidb_query_datatype/src/codec/mysql/duration.rs @@ -20,9 +20,13 @@ use crate::{ FieldTypeAccessor, }; -pub const NANOS_PER_SEC: i64 = 1_000_000_000; -pub const NANOS_PER_MILLI: i64 = 1_000_000; pub const NANOS_PER_MICRO: i64 = 1_000; +pub const NANOS_PER_MILLI: i64 = 1_000_000; +pub const NANOS_PER_SEC: i64 = 1_000_000_000; +pub const NANOS_PER_MIN: i64 = 60 * NANOS_PER_SEC; +pub const NANOS_PER_HOUR: i64 = 60 * NANOS_PER_MIN; +pub const NANOS_PER_DAY: i64 = 24 * NANOS_PER_HOUR; + pub const MICROS_PER_SEC: i64 = 1_000_000; pub const NANO_WIDTH: usize = 9; pub const MICRO_WIDTH: usize = 6; @@ -34,10 +38,10 @@ pub const MAX_HOUR_PART: u32 = 838; pub const MAX_MINUTE_PART: u32 = 59; pub const MAX_SECOND_PART: u32 = 59; pub const MAX_NANOS_PART: u32 = 999_999_999; -pub const MAX_NANOS: i64 = ((MAX_HOUR_PART as i64 * SECS_PER_HOUR) +pub const MAX_SECS: i64 = MAX_HOUR_PART as i64 * SECS_PER_HOUR + MAX_MINUTE_PART as i64 * SECS_PER_MINUTE - + MAX_SECOND_PART as i64) - * NANOS_PER_SEC; + + MAX_SECOND_PART as i64; +pub const MAX_NANOS: i64 = MAX_SECS * NANOS_PER_SEC; const MAX_DURATION_INT_VALUE: u32 = MAX_HOUR_PART * 10000 + MAX_MINUTE_PART * 100 + MAX_SECOND_PART; #[inline] diff --git a/components/tidb_query_datatype/src/codec/mysql/mod.rs b/components/tidb_query_datatype/src/codec/mysql/mod.rs index 95523b24297..2bcfeb8ee23 100644 --- a/components/tidb_query_datatype/src/codec/mysql/mod.rs +++ b/components/tidb_query_datatype/src/codec/mysql/mod.rs @@ -15,7 +15,7 @@ pub const DEFAULT_FSP: i8 = 0; /// inrements. pub const DEFAULT_DIV_FRAC_INCR: u8 = 4; -fn check_fsp(fsp: i8) -> Result { +pub fn check_fsp(fsp: i8) -> Result { if fsp == UNSPECIFIED_FSP { return Ok(DEFAULT_FSP as u8); } diff --git a/components/tidb_query_datatype/src/codec/mysql/time/interval.rs b/components/tidb_query_datatype/src/codec/mysql/time/interval.rs new file mode 100644 index 00000000000..28818c7a8ec --- /dev/null +++ b/components/tidb_query_datatype/src/codec/mysql/time/interval.rs @@ -0,0 +1,1774 @@ +// Copyright 2024 TiKV Project Authors. Licensed under Apache-2.0. + +use std::{collections::HashMap, str::FromStr}; + +use lazy_static::lazy_static; +use regex::Regex; + +use crate::{ + codec::{ + data_type::{BytesRef, Decimal, Real}, + mysql::{duration::*, RoundMode, DEFAULT_FSP, MAX_FSP, MIN_FSP}, + Error, Result, + }, + expr::EvalContext, +}; + +/// See https://dev.mysql.com/doc/refman/8.0/en/expressions.html#temporal-intervals +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum IntervalUnit { + Microsecond, + Second, + Minute, + Hour, + Day, + Week, + Month, + Quarter, + Year, + SecondMicrosecond, + MinuteMicrosecond, + MinuteSecond, + HourMicrosecond, + HourSecond, + HourMinute, + DayMicrosecond, + DaySecond, + DayMinute, + DayHour, + YearMonth, +} + +impl IntervalUnit { + pub fn from_str(unit: &str) -> Result { + use IntervalUnit::*; + match unit.to_uppercase().as_str() { + "MICROSECOND" => Ok(Microsecond), + "SECOND" => Ok(Second), + "MINUTE" => Ok(Minute), + "HOUR" => Ok(Hour), + "DAY" => Ok(Day), + "WEEK" => Ok(Week), + "MONTH" => Ok(Month), + "QUARTER" => Ok(Quarter), + "YEAR" => Ok(Year), + "SECOND_MICROSECOND" => Ok(SecondMicrosecond), + "MINUTE_MICROSECOND" => Ok(MinuteMicrosecond), + "MINUTE_SECOND" => Ok(MinuteSecond), + "HOUR_MICROSECOND" => Ok(HourMicrosecond), + "HOUR_SECOND" => Ok(HourSecond), + "HOUR_MINUTE" => Ok(HourMinute), + "DAY_MICROSECOND" => Ok(DayMicrosecond), + "DAY_SECOND" => Ok(DaySecond), + "DAY_MINUTE" => Ok(DayMinute), + "DAY_HOUR" => Ok(DayHour), + "YEAR_MONTH" => Ok(YearMonth), + _ => Err(box_err!("unknown unit str {}", unit)), + } + } + + pub fn is_clock_unit(&self) -> bool { + use IntervalUnit::*; + matches!( + self, + Microsecond + | Second + | Minute + | Hour + | SecondMicrosecond + | MinuteMicrosecond + | HourMicrosecond + | DayMicrosecond + | MinuteSecond + | HourSecond + | DaySecond + | HourMinute + | DayMinute + | DayHour + ) + } +} + +#[derive(Clone, Copy, PartialEq)] +#[repr(usize)] +enum TimeIndex { + Year = 0, + Month = 1, + Day = 2, + Hour = 3, + Minute = 4, + Second = 5, + Microsecond = 6, + Max = 7, +} + +lazy_static! { + static ref ONE_TO_SIX_DIGIT_REGEX: Regex = Regex::new(r"^[0-9]{0,6}").unwrap(); + static ref NUMERIC_REGEX: Regex = Regex::new(r"[0-9]+").unwrap(); + static ref INTERVAL_REGEX: Regex = Regex::new(r"^[+-]?[\d]+").unwrap(); + /// Index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' interval string Format. + /// IntervalUnit -> (Time Index, Max Count) + static ref INTERVAL_STR_INDEX_MAP: HashMap = { + [ + // 'SECONDS.MICROSECONDS' + (IntervalUnit::SecondMicrosecond, (TimeIndex::Microsecond, 2)), + // 'MINUTES:SECONDS.MICROSECONDS' + (IntervalUnit::MinuteMicrosecond, (TimeIndex::Microsecond, 3)), + // 'MINUTES:SECONDS' + (IntervalUnit::MinuteSecond, (TimeIndex::Second, 2)), + // 'HOURS:MINUTES:SECONDS.MICROSECONDS' + (IntervalUnit::HourMicrosecond, (TimeIndex::Microsecond, 4)), + // 'HOURS:MINUTES:SECONDS' + (IntervalUnit::HourSecond, (TimeIndex::Second, 3)), + // 'HOURS:MINUTES' + (IntervalUnit::HourMinute, (TimeIndex::Minute, 2)), + // 'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' + (IntervalUnit::DayMicrosecond, (TimeIndex::Microsecond, 5)), + // 'DAYS HOURS:MINUTES:SECONDS' + (IntervalUnit::DaySecond, (TimeIndex::Second, 4)), + // 'DAYS HOURS:MINUTES' + (IntervalUnit::DayMinute, (TimeIndex::Minute, 3)), + // 'DAYS HOURS' + (IntervalUnit::DayHour, (TimeIndex::Hour, 2)), + // 'YEARS-MONTHS' + (IntervalUnit::YearMonth, (TimeIndex::Month, 2)), + ].iter().cloned().collect() + }; +} + +#[derive(Debug, PartialEq)] +pub struct Interval { + month: i64, + nano: i64, + fsp: i8, +} + +impl Interval { + pub fn parse_from_str(ctx: &mut EvalContext, unit: &IntervalUnit, input: &str) -> Result { + Self::parse_from_str_internal(ctx, unit, input, false) + } + + #[inline] + fn parse_from_str_internal( + ctx: &mut EvalContext, + unit: &IntervalUnit, + input: &str, + for_duration: bool, + ) -> Result { + if let Some(&(index, max_cnt)) = INTERVAL_STR_INDEX_MAP.get(unit) { + Self::parse_time_value(ctx, input, index, max_cnt, for_duration) + } else { + Self::parse_single_time_value(ctx, unit, input, for_duration) + } + } + + fn parse_single_time_value( + ctx: &mut EvalContext, + unit: &IntervalUnit, + input: &str, + for_duration: bool, + ) -> Result { + use IntervalUnit::*; + // Find decimal point position + let decimal_point_pos = input.find('.').unwrap_or(input.len()); + + // Handle negative sign + let mut sign: i64 = 1; + let integer_part = if input.starts_with('-') { + sign = -1; + &input[1..decimal_point_pos] + } else { + &input[..decimal_point_pos] + }; + + // Parse integer part before decimal point + let iv = match i64::from_str(integer_part) { + Ok(val) => val * sign, + Err(_) => { + if for_duration { + return Err(Error::incorrect_datetime_value(input)); + } + ctx.handle_invalid_time_error(Error::incorrect_datetime_value(input))?; + 0 + } + }; + // Rounded integer value + let mut riv = iv; + + // Handle decimal part + let mut decimal_len = 0; + let mut dv = 0i64; + if decimal_point_pos < input.len() - 1 { + let dv_pre = &input[decimal_point_pos + 1..]; + let mut dv_pre = ONE_TO_SIX_DIGIT_REGEX + .find(dv_pre) + .map_or("", |m| m.as_str()) + .to_string(); + decimal_len = dv_pre.len(); + if decimal_len < MAX_FSP as usize { + dv_pre.push_str(&"0".repeat(MAX_FSP as usize - decimal_len)); + } + decimal_len = std::cmp::min(decimal_len, MAX_FSP as usize); + + dv = match i64::from_str(&dv_pre[..MAX_FSP as usize]) { + Ok(val) => val, + Err(_) => { + if for_duration { + return Err(Error::incorrect_datetime_value(input)); + } + ctx.handle_invalid_time_error(Error::incorrect_datetime_value(input))?; + 0 + } + }; + + // Round up, and we should keep 6 digits for microsecond, so dv should in + // [000000, 999999]. + if dv >= 500_000 { + riv += sign; + } + if *unit != Second { + if for_duration { + return Err(Error::incorrect_datetime_value(input)); + } + ctx.handle_invalid_time_error(Error::incorrect_datetime_value(input))?; + } + dv *= sign; + } + + match unit { + Microsecond => { + if for_duration && riv.abs() > MAX_SECS * 1_000 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: riv * NANOS_PER_MICRO, + fsp: MAX_FSP, + }) + } + Second => { + if for_duration && iv.abs() > MAX_SECS { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: iv * NANOS_PER_SEC + dv * NANOS_PER_MICRO, + fsp: decimal_len as i8, + }) + } + Minute => { + if for_duration && riv.abs() > (MAX_HOUR_PART * 60 + MAX_MINUTE_PART) as i64 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: riv * NANOS_PER_MIN, + fsp: 0, + }) + } + Hour => { + if for_duration && riv.abs() > MAX_HOUR_PART as i64 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: riv * NANOS_PER_HOUR, + fsp: 0, + }) + } + Day => { + if for_duration && riv.abs() > MAX_HOUR_PART as i64 / 24 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: riv * NANOS_PER_DAY, + fsp: 0, + }) + } + Week => { + if for_duration && riv.abs() * 7 > MAX_HOUR_PART as i64 / 24 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: 0, + nano: riv * NANOS_PER_DAY * 7, + fsp: 0, + }) + } + Month => { + if for_duration && riv.abs() > 1 { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: riv, + nano: 0, + fsp: 0, + }) + } + Quarter => { + if for_duration { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: riv * 3, + nano: 0, + fsp: 0, + }) + } + Year => { + if for_duration { + return Err(Error::datetime_function_overflow()); + } + Ok(Self { + month: riv * 12, + nano: 0, + fsp: 0, + }) + } + _ => Err(box_err!("invalid single time unit {:?}", unit)), + } + } + + fn parse_time_value( + ctx: &mut EvalContext, + input: &str, + index: TimeIndex, + max_cnt: usize, + for_duration: bool, + ) -> Result { + let mut neg = false; + let original_input = input; + + // Trim spaces and check if negative + let mut input = input.trim(); + if input.starts_with('-') { + neg = true; + input = &input[1..]; + } + + // Initialize fields as "0" + let mut fields = ["0"; TimeIndex::Max as usize]; + + let matches: Vec<&str> = NUMERIC_REGEX.find_iter(input).map(|m| m.as_str()).collect(); + + if matches.len() > max_cnt || matches.len() > index as usize + 1 { + if for_duration { + return Err(Error::incorrect_datetime_value(original_input)); + } + ctx.handle_invalid_time_error(Error::incorrect_datetime_value(original_input))?; + return Ok(Self { + month: 0, + nano: 0, + fsp: DEFAULT_FSP, + }); + } + + // Populate fields in reverse order + for (i, &matched) in matches.iter().rev().enumerate() { + fields[index as usize - i] = &matched; + } + + // Helper to parse integer fields and handle errors + let mut parse_field = |field: &str| -> Result { + match i64::from_str(field) { + Ok(val) => Ok(val), + Err(_) => { + if for_duration { + return Err(Error::incorrect_datetime_value(original_input)); + } + ctx.handle_invalid_time_error(Error::incorrect_datetime_value(original_input))?; + Ok(0) + } + } + }; + + // Parse the fields (year, month, day, hour, minute, second, microsecond) + let years = parse_field(fields[TimeIndex::Year as usize])?; + let months = parse_field(fields[TimeIndex::Month as usize])?; + let days = parse_field(fields[TimeIndex::Day as usize])?; + let hours = parse_field(fields[TimeIndex::Hour as usize])?; + let minutes = parse_field(fields[TimeIndex::Minute as usize])?; + let seconds = parse_field(fields[TimeIndex::Second as usize])?; + + let mut frac_part = fields[TimeIndex::Microsecond as usize].to_string(); + let frac_part_len = frac_part.len(); + if frac_part_len < MAX_FSP as usize { + frac_part.push_str(&"0".repeat(MAX_FSP as usize - frac_part_len)); + } + let microseconds = parse_field(&frac_part)?; + + // Convert everything into nanoseconds for the Interval struct + let total_nanos = days * NANOS_PER_DAY + + hours * NANOS_PER_HOUR + + minutes * NANOS_PER_MIN + + seconds * NANOS_PER_SEC + + microseconds * NANOS_PER_MICRO; + + let month = if neg { + -(years * 12 + months) + } else { + years * 12 + months + }; + let nano = if neg { -total_nanos } else { total_nanos }; + + // Return Interval with month, nano, and fsp values + Ok(Self { + month, + nano, + fsp: if index == TimeIndex::Microsecond { + MAX_FSP + } else { + MIN_FSP + }, + }) + } + + pub fn extract_duration( + ctx: &mut EvalContext, + unit: &IntervalUnit, + input: &str, + ) -> Result { + let val = Self::parse_from_str_internal(ctx, unit, input, true)?; + use IntervalUnit::*; + match unit { + Microsecond | Second | Minute | Hour | Day | Week | Month | Quarter | Year => Ok( + Duration::from_nanos(val.month * 30 * NANOS_PER_DAY + val.nano, val.fsp)?, + ), + _ => { + if val.month != 0 || val.nano.abs() > MAX_NANOS { + return Err(Error::datetime_function_overflow()); + } + Ok(Duration::from_nanos(val.nano, val.fsp)?) + } + } + } + + pub fn negate(&self) -> Self { + Self { + month: -self.month, + nano: -self.nano, + fsp: self.fsp, + } + } + + pub fn month(&self) -> i64 { + self.month + } + + pub fn nano(&self) -> i64 { + self.nano + } + + pub fn fsp(&self) -> i8 { + self.fsp + } +} + +/// Convert to a string which has a uniform interval format and then can be +/// parsed into Interval struct. +pub trait ConvertToIntervalStr { + fn to_interval_string( + &self, + ctx: &mut EvalContext, + unit: IntervalUnit, + is_unsigned: bool, + decimal: isize, + ) -> Result; +} + +impl<'a> ConvertToIntervalStr for BytesRef<'a> { + #[inline] + fn to_interval_string( + &self, + ctx: &mut EvalContext, + unit: IntervalUnit, + _is_unsigned: bool, + _decimal: isize, + ) -> Result { + let mut interval = "0".to_string(); + let input = std::str::from_utf8(self).map_err(Error::Encoding)?; + use IntervalUnit::*; + match unit { + Microsecond | Minute | Hour | Day | Week | Month | Quarter | Year => { + let trimmed = input.trim(); + if let Some(m) = INTERVAL_REGEX.find(trimmed) { + interval = m.as_str().to_string(); + } + + if interval != trimmed { + ctx.handle_truncate(true)?; + } + } + Second => { + // The unit SECOND is specially handled, for example: + // date + INTERVAL "1e2" SECOND = date + INTERVAL 100 second + // date + INTERVAL "1.6" SECOND = date + INTERVAL 1.6 second + // But: + // date + INTERVAL "1e2" MINUTE = date + INTERVAL 1 MINUTE + // date + INTERVAL "1.6" MINUTE = date + INTERVAL 1 MINUTE + let dec = Decimal::from_bytes(self)?.into_result(ctx)?; + interval = dec.to_string(); + } + _ => { + interval = input.to_string(); + } + } + Ok(interval) + } +} + +impl ConvertToIntervalStr for i64 { + #[inline] + fn to_interval_string( + &self, + _ctx: &mut EvalContext, + _unit: IntervalUnit, + is_unsigned: bool, + _decimal: isize, + ) -> Result { + if is_unsigned { + Ok((*self as u64).to_string()) + } else { + Ok(self.to_string()) + } + } +} + +impl ConvertToIntervalStr for Real { + #[inline] + fn to_interval_string( + &self, + _ctx: &mut EvalContext, + _unit: IntervalUnit, + _is_unsigned: bool, + decimal: isize, + ) -> Result { + if decimal < 0 { + Ok(self.to_string()) + } else { + Ok(format!("{:.*}", decimal as usize, self.into_inner())) + } + } +} + +impl ConvertToIntervalStr for Decimal { + #[inline] + fn to_interval_string( + &self, + ctx: &mut EvalContext, + unit: IntervalUnit, + _is_unsigned: bool, + _decimal: isize, + ) -> Result { + let mut interval = self.to_string(); + use IntervalUnit::*; + match unit { + HourMinute | MinuteSecond | YearMonth | DayHour | DayMinute | DaySecond + | DayMicrosecond | HourMicrosecond | HourSecond | MinuteMicrosecond + | SecondMicrosecond => { + let mut neg = false; + if !interval.is_empty() && interval.starts_with('-') { + neg = true; + interval = interval[1..].to_string(); + } + match unit { + HourMinute | MinuteSecond => interval = interval.replace('.', ":"), + YearMonth => interval = interval.replace('.', "-"), + DayHour => interval = interval.replace('.', " "), + DayMinute => interval = "0 ".to_string() + &interval.replace('.', ":"), + DaySecond => interval = "0 00:".to_string() + &interval.replace('.', ":"), + DayMicrosecond => interval = "0 00:00:".to_string() + &interval, + HourMicrosecond => interval = "00:00:".to_string() + &interval, + HourSecond => interval = "00:".to_string() + &interval.replace('.', ":"), + MinuteMicrosecond => interval = "00:".to_string() + &interval, + SecondMicrosecond => (), + _ => unreachable!(), + } + if neg { + interval = "-".to_string() + &interval; + } + } + Second => (), + _ => { + let rounded = self.round(0, RoundMode::HalfEven).into_result(ctx)?; + let int_val = rounded.as_i64().into_result(ctx)?; + interval = int_val.to_string(); + } + } + Ok(interval) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::expr::{EvalConfig, Flag}; + + #[test] + fn test_is_clock_unit() -> Result<()> { + let cases = vec![ + ("MICROSECOND", true), + ("secOnd", true), + ("MINUTE", true), + ("HOUR", true), + ("daY", false), + ("WeeK", false), + ("MONTH", false), + ("QUARTER", false), + ("year", false), + ("SECOND_MIcROSECOnD", true), + ("MINUTE_MICROSECOND", true), + ("MINUTE_second", true), + ("HOUR_MICROSECOND", true), + ("HOUR_SECOND", true), + ("HOUR_MINUTE", true), + ("DAY_MICROSECOND", true), + ("DAY_SECOND", true), + ("DAY_MINUTE", true), + ("DAY_HOUR", true), + ("year_MONTH", false), + ]; + for (str, result) in cases { + let unit = IntervalUnit::from_str(str)?; + assert_eq!(unit.is_clock_unit(), result); + } + Ok(()) + } + + #[test] + fn test_bytes_ref_to_interval_string() { + use IntervalUnit::*; + let cases = vec![ + (b"365" as &[u8], Microsecond, "365"), + (b"10", Minute, "10"), + (b"-123", Minute, "-123"), + (b"24", Hour, "24"), + (b" 365", Day, "365"), + (b"abc", Day, "0"), + (b" -221", Week, "-221"), + (b"a6", Month, "0"), + (b"-24a", Quarter, "-24"), + (b"1024", Year, "1024"), + (b"1e2", Second, "100"), + (b"-2e4", Second, "-20000"), + (b"1.6", Second, "1.6"), + (b"-1.6554", Second, "-1.6554"), + ]; + + let mut config = EvalConfig::new(); + config.set_flag(Flag::TRUNCATE_AS_WARNING); + let mut ctx = EvalContext::new(std::sync::Arc::new(config)); + for (input, unit, expected) in cases { + let result = input.to_interval_string(&mut ctx, unit, false, 0).unwrap(); + assert_eq!(result, expected); + } + + let mut ctx = EvalContext::default(); + let err_cases = vec![(b"abc" as &[u8], Day), (b"a6", Month), (b"-24a", Quarter)]; + for (input, unit) in err_cases { + input + .to_interval_string(&mut ctx, unit, false, 0) + .unwrap_err(); + } + } + + #[test] + fn test_i64_to_interval_string() { + let cases = vec![ + (42i64, false, "42"), + (-100i64, false, "-100"), + (0i64, false, "0"), + (9999999999i64, false, "9999999999"), + (-9999999999i64, false, "-9999999999"), + (9999999999i64, true, "9999999999"), + (-9999999999i64, true, "18446744063709551617"), + ]; + + let mut ctx = EvalContext::default(); + for (input, is_unsigned, expected) in cases { + let result = input + .to_interval_string(&mut ctx, IntervalUnit::Second, is_unsigned, 0) + .unwrap(); + assert_eq!(result, expected); + } + } + + #[test] + fn test_real_to_interval_string() { + let mut ctx = EvalContext::default(); + + let cases = vec![ + (1.2345, 4, "1.2345"), + (1.2345, 5, "1.23450"), + (1.2345, 2, "1.23"), + (-1.6789, 3, "-1.679"), + (-1.6789, 6, "-1.678900"), + (100.779, 0, "101"), + (-100.779, 0, "-101"), + (-123.123, -1, "-123.123"), + (-123.1239123, -1, "-123.1239123"), + ]; + + for (input, decimal, expected) in cases { + let real = Real::new(input).unwrap(); + let result = real + .to_interval_string(&mut ctx, IntervalUnit::Second, false, decimal) + .unwrap(); + assert_eq!(result, expected); + } + } + + #[test] + fn test_decimal_to_interval() { + use IntervalUnit::*; + let cases = vec![ + // Basic unit cases + ("12.34", Year, "12"), + ("-12.34", Month, "-12"), + ("12.5", Day, "13"), + ("12.45", Hour, "12"), + ("-12.6", Minute, "-13"), + ("12.34", Second, "12.34"), + ("-12.34", Second, "-12.34"), + // Compound unit cases + ("12.34", HourMinute, "12:34"), + ("-12.34", MinuteSecond, "-12:34"), + ("12.34", YearMonth, "12-34"), + ("-12.34", YearMonth, "-12-34"), + ("12.34", DayHour, "12 34"), + ("-12.34", DayHour, "-12 34"), + ("12.34", DayMinute, "0 12:34"), + ("-12.3400", DayMinute, "-0 12:3400"), + ("12.34", DaySecond, "0 00:12:34"), + ("-12.34", DaySecond, "-0 00:12:34"), + ("12.34", DayMicrosecond, "0 00:00:12.34"), + ("-12.34", DayMicrosecond, "-0 00:00:12.34"), + ("12.34", HourMicrosecond, "00:00:12.34"), + ("-12.34", HourMicrosecond, "-00:00:12.34"), + ("12.34", HourSecond, "00:12:34"), + ("-12.34", HourSecond, "-00:12:34"), + ("12.34", MinuteMicrosecond, "00:12.34"), + ("-12.34", MinuteMicrosecond, "-00:12.34"), + ("12.34", SecondMicrosecond, "12.34"), + ("-12.34", SecondMicrosecond, "-12.34"), + // Rounding case + ("12.99", Year, "13"), + ("12.49", Year, "12"), + ("-12.99", Year, "-13"), + ]; + + let mut ctx = EvalContext::default(); + for (input, unit, expected) in cases { + let decimal = Decimal::from_str(input).unwrap(); + let result = decimal + .to_interval_string(&mut ctx, unit, false, 0) + .unwrap(); + assert_eq!( + result, expected, + "Failed for input: {}, unit: {:?}", + input, unit + ); + } + } + + #[test] + fn test_interval_parse_from_str() { + use IntervalUnit::*; + let cases = vec![ + ( + "123456", + Microsecond, + Interval { + month: 0, + nano: 123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123456", + Microsecond, + Interval { + month: 0, + nano: -123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2.123456", + Second, + Interval { + month: 0, + nano: 2 * NANOS_PER_SEC + 123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-2.123456", + Second, + Interval { + month: 0, + nano: -2 * NANOS_PER_SEC - 123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2.12345", + Second, + Interval { + month: 0, + nano: 2 * NANOS_PER_SEC + 123450 * NANOS_PER_MICRO, + fsp: 5, + }, + ), + ( + "-2.12345", + Second, + Interval { + month: 0, + nano: -2 * NANOS_PER_SEC - 123450 * NANOS_PER_MICRO, + fsp: 5, + }, + ), + ( + "2.1234567", + Second, + Interval { + month: 0, + nano: 2 * NANOS_PER_SEC + 123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-2.1234567", + Second, + Interval { + month: 0, + nano: -2 * NANOS_PER_SEC - 123456 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2.99", + Second, + Interval { + month: 0, + nano: 2 * NANOS_PER_SEC + 990000 * NANOS_PER_MICRO, + fsp: 2, + }, + ), + ( + "-2.50000", + Second, + Interval { + month: 0, + nano: -2 * NANOS_PER_SEC - 500000 * NANOS_PER_MICRO, + fsp: 5, + }, + ), + ( + "2.500000", + Minute, + Interval { + month: 0, + nano: 3 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-2.50000", + Minute, + Interval { + month: 0, + nano: -3 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "99.9", + Minute, + Interval { + month: 0, + nano: 100 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-99.4", + Minute, + Interval { + month: 0, + nano: -99 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "99.9", + Hour, + Interval { + month: 0, + nano: 100 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "-99.4", + Hour, + Interval { + month: 0, + nano: -99 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "99.9", + Day, + Interval { + month: 0, + nano: 100 * NANOS_PER_DAY, + fsp: 0, + }, + ), + ( + "-99.4", + Day, + Interval { + month: 0, + nano: -99 * NANOS_PER_DAY, + fsp: 0, + }, + ), + ( + "99.9", + Week, + Interval { + month: 0, + nano: 100 * NANOS_PER_DAY * 7, + fsp: 0, + }, + ), + ( + "-99.4", + Week, + Interval { + month: 0, + nano: -99 * NANOS_PER_DAY * 7, + fsp: 0, + }, + ), + ( + "99.9", + Month, + Interval { + month: 100, + nano: 0, + fsp: 0, + }, + ), + ( + "-99.4", + Month, + Interval { + month: -99, + nano: 0, + fsp: 0, + }, + ), + ( + "99.9", + Quarter, + Interval { + month: 100 * 3, + nano: 0, + fsp: 0, + }, + ), + ( + "-99.4", + Quarter, + Interval { + month: -99 * 3, + nano: 0, + fsp: 0, + }, + ), + ( + "99.9", + Year, + Interval { + month: 100 * 12, + nano: 0, + fsp: 0, + }, + ), + ( + "-99.4", + Year, + Interval { + month: -99 * 12, + nano: 0, + fsp: 0, + }, + ), + // Compound unit cases + ( + "123", + SecondMicrosecond, + Interval { + month: 0, + nano: 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123", + SecondMicrosecond, + Interval { + month: 0, + nano: -123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123.123", + SecondMicrosecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123.123", + SecondMicrosecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123", + MinuteMicrosecond, + Interval { + month: 0, + nano: 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123", + MinuteMicrosecond, + Interval { + month: 0, + nano: -123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123.123", + MinuteMicrosecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123.123", + MinuteMicrosecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2:123.123", + MinuteMicrosecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-62:123.123", + MinuteMicrosecond, + Interval { + month: 0, + nano: -62 * NANOS_PER_MIN - 123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123", + MinuteSecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-123", + MinuteSecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "2:123", + MinuteSecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-2:123", + MinuteSecond, + Interval { + month: 0, + nano: -2 * NANOS_PER_MIN - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "123", + HourMicrosecond, + Interval { + month: 0, + nano: 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123", + HourMicrosecond, + Interval { + month: 0, + nano: -123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123.123", + HourMicrosecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123.123", + HourMicrosecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2:123.123", + HourMicrosecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-62:123.123", + HourMicrosecond, + Interval { + month: 0, + nano: -62 * NANOS_PER_MIN - 123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "12:2:123.123", + HourMicrosecond, + Interval { + month: 0, + nano: 12 * NANOS_PER_HOUR + + 2 * NANOS_PER_MIN + + 123 * NANOS_PER_SEC + + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-2:62:123.123", + HourMicrosecond, + Interval { + month: 0, + nano: -2 * NANOS_PER_HOUR + - 62 * NANOS_PER_MIN + - 123 * NANOS_PER_SEC + - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123", + HourSecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-123", + HourSecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "2:123", + HourSecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-2:123", + HourSecond, + Interval { + month: 0, + nano: -2 * NANOS_PER_MIN - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "9:62:123", + HourSecond, + Interval { + month: 0, + nano: 9 * NANOS_PER_HOUR + 62 * NANOS_PER_MIN + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-55:62:123", + HourSecond, + Interval { + month: 0, + nano: -55 * NANOS_PER_HOUR - 62 * NANOS_PER_MIN - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "123", + HourMinute, + Interval { + month: 0, + nano: 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-123", + HourMinute, + Interval { + month: 0, + nano: -123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "2:123", + HourMinute, + Interval { + month: 0, + nano: 2 * NANOS_PER_HOUR + 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-88:123", + HourMinute, + Interval { + month: 0, + nano: -88 * NANOS_PER_HOUR - 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "123", + DayMicrosecond, + Interval { + month: 0, + nano: 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123", + DayMicrosecond, + Interval { + month: 0, + nano: -123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123.123", + DayMicrosecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-123.123", + DayMicrosecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "2:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-62:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: -62 * NANOS_PER_MIN - 123 * NANOS_PER_SEC - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "12:2:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: 12 * NANOS_PER_HOUR + + 2 * NANOS_PER_MIN + + 123 * NANOS_PER_SEC + + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-2:62:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: -2 * NANOS_PER_HOUR + - 62 * NANOS_PER_MIN + - 123 * NANOS_PER_SEC + - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "9 12:2:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: 9 * NANOS_PER_DAY + + 12 * NANOS_PER_HOUR + + 2 * NANOS_PER_MIN + + 123 * NANOS_PER_SEC + + 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "-77 2:62:123.123", + DayMicrosecond, + Interval { + month: 0, + nano: -77 * NANOS_PER_DAY + - 2 * NANOS_PER_HOUR + - 62 * NANOS_PER_MIN + - 123 * NANOS_PER_SEC + - 123000 * NANOS_PER_MICRO, + fsp: 6, + }, + ), + ( + "123", + DaySecond, + Interval { + month: 0, + nano: 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-123", + DaySecond, + Interval { + month: 0, + nano: -123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "2:123", + DaySecond, + Interval { + month: 0, + nano: 2 * NANOS_PER_MIN + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-2:123", + DaySecond, + Interval { + month: 0, + nano: -2 * NANOS_PER_MIN - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "9:62:123", + DaySecond, + Interval { + month: 0, + nano: 9 * NANOS_PER_HOUR + 62 * NANOS_PER_MIN + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-55:62:123", + DaySecond, + Interval { + month: 0, + nano: -55 * NANOS_PER_HOUR - 62 * NANOS_PER_MIN - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "1 9:62:123", + DaySecond, + Interval { + month: 0, + nano: NANOS_PER_DAY + + 9 * NANOS_PER_HOUR + + 62 * NANOS_PER_MIN + + 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "-3 55:62:123", + DaySecond, + Interval { + month: 0, + nano: -3 * NANOS_PER_DAY + - 55 * NANOS_PER_HOUR + - 62 * NANOS_PER_MIN + - 123 * NANOS_PER_SEC, + fsp: 0, + }, + ), + ( + "123", + DayMinute, + Interval { + month: 0, + nano: 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-123", + DayMinute, + Interval { + month: 0, + nano: -123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "2:123", + DayMinute, + Interval { + month: 0, + nano: 2 * NANOS_PER_HOUR + 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-88:123", + DayMinute, + Interval { + month: 0, + nano: -88 * NANOS_PER_HOUR - 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "08 2:123", + DayMinute, + Interval { + month: 0, + nano: 8 * NANOS_PER_DAY + 2 * NANOS_PER_HOUR + 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "-70 88:123", + DayMinute, + Interval { + month: 0, + nano: -70 * NANOS_PER_DAY - 88 * NANOS_PER_HOUR - 123 * NANOS_PER_MIN, + fsp: 0, + }, + ), + ( + "123", + DayHour, + Interval { + month: 0, + nano: 123 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "-123", + DayHour, + Interval { + month: 0, + nano: -123 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "66 123", + DayHour, + Interval { + month: 0, + nano: 66 * NANOS_PER_DAY + 123 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "-77 123", + DayHour, + Interval { + month: 0, + nano: -77 * NANOS_PER_DAY - 123 * NANOS_PER_HOUR, + fsp: 0, + }, + ), + ( + "123", + YearMonth, + Interval { + month: 123, + nano: 0, + fsp: 0, + }, + ), + ( + "-123", + YearMonth, + Interval { + month: -123, + nano: 0, + fsp: 0, + }, + ), + ( + "99 123", + YearMonth, + Interval { + month: 99 * 12 + 123, + nano: 0, + fsp: 0, + }, + ), + ( + "-7 123", + YearMonth, + Interval { + month: -7 * 12 - 123, + nano: 0, + fsp: 0, + }, + ), + ]; + let mut ctx = EvalContext::default(); + for (input, unit, expected) in cases { + let result = Interval::parse_from_str(&mut ctx, &unit, input).unwrap(); + assert_eq!( + result, expected, + "Failed for input: {}, unit: {:?}", + input, unit + ); + } + + let err_cases = vec![ + ("12:12.123", SecondMicrosecond), + ("20:12:12.123", MinuteMicrosecond), + ("12:12:12", MinuteSecond), + ("1 12:12:12.11", HourMicrosecond), + ("12:12:12.123", HourSecond), + ("12:12:12", HourMinute), + ("3 2 12:12:12.123", DayMicrosecond), + ("3 12:12:12.123", DaySecond), + ("3 12:12:12", DayMinute), + ("3 12:12", DayHour), + ("99 123:123", YearMonth), + ]; + for (input, unit) in err_cases { + let result = Interval::parse_from_str(&mut ctx, &unit, input).unwrap(); + assert_eq!( + result, + Interval { + month: 0, + nano: 0, + fsp: DEFAULT_FSP + }, + "Failed for input: {}, unit: {:?}", + input, + unit + ); + } + } + + #[test] + fn test_interval_extract_duration() { + use IntervalUnit::*; + let cases = vec![ + ( + "123456", + Microsecond, + Duration::from_nanos(123456 * NANOS_PER_MICRO, 6), + ), + ( + "-123456", + Microsecond, + Duration::from_nanos(-123456 * NANOS_PER_MICRO, 6), + ), + ( + "2.123456", + Second, + Duration::from_nanos(2 * NANOS_PER_SEC + 123456 * NANOS_PER_MICRO, 6), + ), + ( + "-2.123456", + Second, + Duration::from_nanos(-2 * NANOS_PER_SEC - 123456 * NANOS_PER_MICRO, 6), + ), + ( + "2.12345", + Second, + Duration::from_nanos(2 * NANOS_PER_SEC + 123450 * NANOS_PER_MICRO, 5), + ), + ( + "-2.12345", + Second, + Duration::from_nanos(-2 * NANOS_PER_SEC - 123450 * NANOS_PER_MICRO, 5), + ), + ( + "2.1234567", + Second, + Duration::from_nanos(2 * NANOS_PER_SEC + 123456 * NANOS_PER_MICRO, 6), + ), + ( + "-2.1234567", + Second, + Duration::from_nanos(-2 * NANOS_PER_SEC - 123456 * NANOS_PER_MICRO, 6), + ), + ( + "2.99", + Second, + Duration::from_nanos(2 * NANOS_PER_SEC + 990000 * NANOS_PER_MICRO, 2), + ), + ( + "-2.50000", + Second, + Duration::from_nanos(-2 * NANOS_PER_SEC - 500000 * NANOS_PER_MICRO, 5), + ), + ("99", Minute, Duration::from_nanos(99 * NANOS_PER_MIN, 0)), + ("-99", Minute, Duration::from_nanos(-99 * NANOS_PER_MIN, 0)), + ("30", Day, Duration::from_nanos(30 * NANOS_PER_DAY, 0)), + ("-30", Day, Duration::from_nanos(-30 * NANOS_PER_DAY, 0)), + ("2", Week, Duration::from_nanos(2 * NANOS_PER_DAY * 7, 0)), + ("-2", Week, Duration::from_nanos(-2 * NANOS_PER_DAY * 7, 0)), + ("1", Month, Duration::from_nanos(30 * NANOS_PER_DAY, 0)), + ("-1", Month, Duration::from_nanos(-30 * NANOS_PER_DAY, 0)), + ( + "29 12:23:36.1234", + DayMicrosecond, + Duration::from_nanos( + 29 * NANOS_PER_DAY + + 12 * NANOS_PER_HOUR + + 23 * NANOS_PER_MIN + + 36 * NANOS_PER_SEC + + 123400 * NANOS_PER_MICRO, + 6, + ), + ), + ( + "-29 12:23:36.1234", + DayMicrosecond, + Duration::from_nanos( + -29 * NANOS_PER_DAY + - 12 * NANOS_PER_HOUR + - 23 * NANOS_PER_MIN + - 36 * NANOS_PER_SEC + - 123400 * NANOS_PER_MICRO, + 6, + ), + ), + ]; + let mut ctx = EvalContext::default(); + for (input, unit, expected) in cases { + let result = Interval::extract_duration(&mut ctx, &unit, input).unwrap(); + assert_eq!( + result, + expected.unwrap(), + "Failed for input: {}, unit: {:?}", + input, + unit + ); + } + let err_cases = vec![ + ("2.500000", Minute), + ("-2.50000", Minute), + ("99.9", Hour), + ("-99.4", Hour), + ("35", Day), + ("-35", Day), + ("2", Month), + ("-2", Month), + ("99", Quarter), + ("-99", Quarter), + ("99", Year), + ("-99", Year), + ("-34 23:59:59.1234", DayMicrosecond), + ]; + for (input, unit) in err_cases { + let result = Interval::extract_duration(&mut ctx, &unit, input); + result.unwrap_err(); + } + } +} diff --git a/components/tidb_query_datatype/src/codec/mysql/time/mod.rs b/components/tidb_query_datatype/src/codec/mysql/time/mod.rs index 4befe30c3c1..0983e1b9c6d 100644 --- a/components/tidb_query_datatype/src/codec/mysql/time/mod.rs +++ b/components/tidb_query_datatype/src/codec/mysql/time/mod.rs @@ -1,6 +1,7 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. pub mod extension; +pub mod interval; mod tz; pub mod weekmode; @@ -9,6 +10,7 @@ use std::{ convert::{TryFrom, TryInto}, fmt::Write, hash::{Hash, Hasher}, + intrinsics::unlikely, }; use bitfield::bitfield; @@ -22,7 +24,7 @@ use crate::{ codec::{ convert::ConvertTo, data_type::Real, - mysql::{check_fsp, Decimal, Duration}, + mysql::{check_fsp, Decimal, Duration, Res, DEFAULT_FSP, MAX_FSP}, Error, Result, TEN_POW, }, expr::{EvalContext, Flag, SqlMode}, @@ -565,7 +567,7 @@ mod parser { pub fn parse( ctx: &mut EvalContext, input: &str, - time_type: TimeType, + time_type_opt: Option, fsp: u8, round: bool, ) -> Option