Skip to content

Commit 0effb4b

Browse files
committed
reaches
Signed-off-by: Bugen Zhao <[email protected]>
1 parent 98b7618 commit 0effb4b

File tree

2 files changed

+43
-9
lines changed

2 files changed

+43
-9
lines changed

src/common/src/util/recursive.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,41 +19,75 @@ use std::cell::RefCell;
1919
const RED_ZONE: usize = 128 * 1024; // 128KiB
2020
const STACK_SIZE: usize = 16 * RED_ZONE; // 2MiB
2121

22+
/// Recursion depth.
23+
struct Depth {
24+
/// The current depth.
25+
current: usize,
26+
/// The max depth reached so far, not considering the current depth.
27+
last_max: usize,
28+
}
29+
30+
impl Depth {
31+
const fn new() -> Self {
32+
Self {
33+
current: 0,
34+
last_max: 0,
35+
}
36+
}
37+
38+
fn reset(&mut self) {
39+
*self = Self::new();
40+
}
41+
}
42+
2243
/// The tracker for a recursive function.
2344
pub struct Tracker {
24-
depth: RefCell<usize>,
45+
depth: RefCell<Depth>,
2546
}
2647

2748
impl Tracker {
2849
/// Create a new tracker.
2950
pub const fn new() -> Self {
3051
Self {
31-
depth: RefCell::new(0),
52+
depth: RefCell::new(Depth::new()),
3253
}
3354
}
3455

3556
/// Retrieve the current depth of the recursion. Starts from 1 once the
3657
/// recursive function is called.
3758
pub fn depth(&self) -> usize {
38-
*self.depth.borrow()
59+
self.depth.borrow().current
60+
}
61+
62+
/// Check if the current depth reaches the given depth **for the first time**.
63+
///
64+
/// This is useful for logging without any duplication.
65+
pub fn depth_reaches(&self, depth: usize) -> bool {
66+
let d = self.depth.borrow();
67+
d.current == depth && d.current > d.last_max
3968
}
4069

4170
/// Run a recursive function. Grow the stack if necessary.
4271
fn recurse<T>(&self, f: impl FnOnce() -> T) -> T {
4372
struct DepthGuard<'a> {
44-
depth: &'a RefCell<usize>,
73+
depth: &'a RefCell<Depth>,
4574
}
4675

4776
impl<'a> DepthGuard<'a> {
48-
fn new(depth: &'a RefCell<usize>) -> Self {
49-
*depth.borrow_mut() += 1;
77+
fn new(depth: &'a RefCell<Depth>) -> Self {
78+
depth.borrow_mut().current += 1;
5079
Self { depth }
5180
}
5281
}
5382

5483
impl<'a> Drop for DepthGuard<'a> {
5584
fn drop(&mut self) {
56-
*self.depth.borrow_mut() -= 1;
85+
let mut d = self.depth.borrow_mut();
86+
d.last_max = d.last_max.max(d.current); // update the last max depth
87+
d.current -= 1; // restore the current depth
88+
if d.current == 0 {
89+
d.reset(); // reset state if the recursion is finished
90+
}
5791
}
5892
}
5993

src/frontend/src/optimizer/plan_node/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ impl dyn PlanNode {
710710
state: &mut BuildFragmentGraphState,
711711
) -> SchedulerResult<StreamPlanPb> {
712712
recursive::tracker!().recurse(|t| {
713-
if t.depth() == PLAN_DEPTH_THRESHOLD {
713+
if t.depth_reaches(PLAN_DEPTH_THRESHOLD) {
714714
notice_to_user(PLAN_TOO_DEEP_NOTICE);
715715
}
716716

@@ -762,7 +762,7 @@ impl dyn PlanNode {
762762
/// (for testing).
763763
pub fn to_batch_prost_identity(&self, identity: bool) -> SchedulerResult<BatchPlanPb> {
764764
recursive::tracker!().recurse(|t| {
765-
if t.depth() == PLAN_DEPTH_THRESHOLD {
765+
if t.depth_reaches(PLAN_DEPTH_THRESHOLD) {
766766
notice_to_user(PLAN_TOO_DEEP_NOTICE);
767767
}
768768

0 commit comments

Comments
 (0)