Rename subtree to subgraph (#265)

Intially, a fold instruction was designed based on idea that its iterable can't expand,
so AIR was considered as a subtree. But after introducing recursive streams in #225, it's
no more a subtree, but a subgraph.
This commit is contained in:
Mike Voronov 2022-05-17 15:53:33 +03:00 committed by GitHub
parent dbd42cdf3d
commit 24f0d66bed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 146 additions and 146 deletions

View File

@ -182,4 +182,4 @@ and it's possible to address its fields separately: `%last_error%.$.instruction`
- Added join behaviour ([PR 11](https://github.com/fluencelabs/aquavm/pull/11)):
- if `call` uses non existing variable, it is just being passed and isn't executed without any error
- `par` becomes completed when at least one of its subtree is completed
- `par` becomes completed when at least one of its subgraph is completed

View File

@ -83,7 +83,7 @@ pub(crate) fn set_remote_call_result<'i>(
trace_ctx: &mut TraceHandler,
) {
exec_ctx.next_peer_pks.push(peer_pk);
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
let new_call_result = CallResult::sent_peer_id(exec_ctx.run_parameters.current_peer_id.clone());
trace_ctx.meet_call_end(new_call_result);

View File

@ -50,7 +50,7 @@ pub(super) fn handle_prev_state<'i>(
// this call was failed on one of the previous executions,
// here it's needed to bubble this special error up
CallServiceFailed(ret_code, err_msg) => {
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
let ret_code = *ret_code;
let err_msg = err_msg.clone();
trace_ctx.meet_call_end(prev_result);
@ -67,7 +67,7 @@ pub(super) fn handle_prev_state<'i>(
}
// result hasn't been prepared yet
None => {
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
Ok(StateDescriptor::not_ready(prev_result))
}
}
@ -79,7 +79,7 @@ pub(super) fn handle_prev_state<'i>(
return Ok(StateDescriptor::can_execute_now(prev_result));
}
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
Ok(StateDescriptor::cant_execute_now(prev_result))
}
// this instruction's been already executed

View File

@ -106,7 +106,7 @@ impl<'i> ResolvedCall<'i> {
let call_id = exec_ctx.next_call_request_id();
exec_ctx.call_requests.insert(call_id, request_params);
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
trace_ctx.meet_call_end(CallResult::sent_peer_id_with_call_id(
exec_ctx.run_parameters.current_peer_id.clone(),
call_id,

View File

@ -94,7 +94,7 @@ fn fail_with_error_object(
exec_ctx
.last_error_descriptor
.set_from_error_object(error.clone(), tetraplet);
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
Err(ExecutionError::Catchable(Rc::new(CatchableError::UserError { error })))
}

View File

@ -98,12 +98,12 @@ fn execute_iterations<'i>(
trace_to_exec_err!(trace_ctx.meet_generation_end(fold_id), fold_stream)?;
result?;
if !exec_ctx.subtree_complete {
if !exec_ctx.subgraph_complete {
break;
}
}
Ok(exec_ctx.subtree_complete)
Ok(exec_ctx.subgraph_complete)
}
fn should_stop_iteration(iteration_result: &ExecutionResult<bool>) -> bool {

View File

@ -109,15 +109,15 @@ macro_rules! log_instruction {
$exec_ctx.next_peer_pks
);
log::trace!(
target: air_log_targets::SUBTREE_COMPLETE,
" subtree complete: {}",
$exec_ctx.subtree_complete
target: air_log_targets::SUBGRAPH_COMPLETE,
" subgraph complete: {}",
$exec_ctx.subgraph_complete
);
log::trace!(
target: air_log_targets::SUBTREE_ELEMENTS,
" subtree elements count: {:?}",
$trace_ctx.subtree_sizes()
target: air_log_targets::SUBGRAPH_ELEMENTS,
" subgraph elements count: {:?}",
$trace_ctx.subgraph_sizes()
);
log::debug!(
target: air_log_targets::NEW_EXECUTED_TRACE,
@ -127,13 +127,13 @@ macro_rules! log_instruction {
};
}
/// This macro converts joinable errors to Ok and sets subtree complete to false.
/// This macro converts joinable errors to Ok and sets subgraph complete to false.
#[macro_export]
macro_rules! joinable {
($cmd:expr, $exec_ctx:expr) => {
match $cmd {
Err(e) if e.is_joinable() => {
$exec_ctx.subtree_complete = false;
$exec_ctx.subgraph_complete = false;
return Ok(());
}
v => v,

View File

@ -27,7 +27,7 @@ use crate::trace_to_exec_err;
use completeness_updater::ParCompletenessUpdater;
use air_parser::ast::Par;
use air_trace_handler::SubtreeType;
use air_trace_handler::SubgraphType;
#[rustfmt::skip]
impl<'i> ExecutableInstruction<'i> for Par<'i> {
@ -37,72 +37,72 @@ impl<'i> ExecutableInstruction<'i> for Par<'i> {
let mut completeness_updater = ParCompletenessUpdater::new();
trace_to_exec_err!(trace_ctx.meet_par_start(), self)?;
// execute a left subtree of par
let left_result = execute_subtree(self, exec_ctx, trace_ctx, &mut completeness_updater, SubtreeType::Left)?;
// execute a left subgraph of par
let left_result = execute_subgraph(self, exec_ctx, trace_ctx, &mut completeness_updater, SubgraphType::Left)?;
// execute a right subtree of par
let right_result = execute_subtree(self, exec_ctx, trace_ctx, &mut completeness_updater, SubtreeType::Right)?;
// execute a right subgraph of par
let right_result = execute_subgraph(self, exec_ctx, trace_ctx, &mut completeness_updater, SubgraphType::Right)?;
completeness_updater.set_completeness(exec_ctx);
prepare_par_result(left_result, right_result, exec_ctx)
}
}
/// Execute provided subtree and update Par state in trace_ctx.new_trace.
fn execute_subtree<'i>(
/// Execute provided subgraph and update Par state in trace_ctx.new_trace.
fn execute_subgraph<'i>(
par: &Par<'i>,
exec_ctx: &mut ExecutionCtx<'i>,
trace_ctx: &mut TraceHandler,
completeness_updater: &mut ParCompletenessUpdater,
subtree_type: SubtreeType,
) -> ExecutionResult<SubtreeResult> {
let subtree = match subtree_type {
SubtreeType::Left => &par.0,
SubtreeType::Right => &par.1,
subgraph_type: SubgraphType,
) -> ExecutionResult<SubgraphResult> {
let subgraph = match subgraph_type {
SubgraphType::Left => &par.0,
SubgraphType::Right => &par.1,
};
exec_ctx.subtree_complete = determine_subtree_complete(subtree);
exec_ctx.subgraph_complete = determine_subgraph_complete(subgraph);
// execute a subtree
let result = match subtree.execute(exec_ctx, trace_ctx) {
// execute a subgraph
let result = match subgraph.execute(exec_ctx, trace_ctx) {
Ok(_) => {
trace_to_exec_err!(trace_ctx.meet_par_subtree_end(subtree_type), par)?;
SubtreeResult::Succeeded
trace_to_exec_err!(trace_ctx.meet_par_subgraph_end(subgraph_type), par)?;
SubgraphResult::Succeeded
}
Err(e) if e.is_catchable() => {
exec_ctx.subtree_complete = false;
trace_to_exec_err!(trace_ctx.meet_par_subtree_end(subtree_type), par)?;
SubtreeResult::Failed(e)
exec_ctx.subgraph_complete = false;
trace_to_exec_err!(trace_ctx.meet_par_subgraph_end(subgraph_type), par)?;
SubgraphResult::Failed(e)
}
Err(e) => {
exec_ctx.subtree_complete = false;
exec_ctx.subgraph_complete = false;
return Err(e);
}
};
completeness_updater.update_completeness(exec_ctx, subtree_type);
completeness_updater.update_completeness(exec_ctx, subgraph_type);
Ok(result)
}
enum SubtreeResult {
enum SubgraphResult {
Succeeded,
Failed(ExecutionError),
}
fn prepare_par_result(
left_result: SubtreeResult,
right_result: SubtreeResult,
left_result: SubgraphResult,
right_result: SubgraphResult,
exec_ctx: &mut ExecutionCtx<'_>,
) -> ExecutionResult<()> {
match (left_result, right_result) {
(SubtreeResult::Succeeded, _) | (_, SubtreeResult::Succeeded) => {
(SubgraphResult::Succeeded, _) | (_, SubgraphResult::Succeeded) => {
exec_ctx.last_error_descriptor.meet_par_successed_end();
Ok(())
}
(SubtreeResult::Failed(_), SubtreeResult::Failed(err)) => Err(err),
(SubgraphResult::Failed(_), SubgraphResult::Failed(err)) => Err(err),
}
}
fn determine_subtree_complete(next_instruction: &Instruction<'_>) -> bool {
fn determine_subgraph_complete(next_instruction: &Instruction<'_>) -> bool {
// this is needed to prevent situation when on such pattern
// (fold (Iterable i
// (par
@ -110,6 +110,6 @@ fn determine_subtree_complete(next_instruction: &Instruction<'_>) -> bool {
// (next i)
// )
// )
// par will be completed after the last next that wouldn't change subtree_complete
// par will be completed after the last next that wouldn't change subgraph_complete
!matches!(next_instruction, Instruction::Next(_))
}

View File

@ -15,32 +15,32 @@
*/
use super::ExecutionCtx;
use super::SubtreeType;
use super::SubgraphType;
#[derive(Debug, Default, Clone)]
pub(super) struct ParCompletenessUpdater {
left_subtree_complete: bool,
right_subtree_complete: bool,
left_subgraph_complete: bool,
right_subgraph_complete: bool,
}
impl ParCompletenessUpdater {
pub(super) fn new() -> Self {
Self {
left_subtree_complete: false,
right_subtree_complete: false,
left_subgraph_complete: false,
right_subgraph_complete: false,
}
}
pub(super) fn update_completeness(&mut self, exec_ctx: &ExecutionCtx<'_>, subtree_type: SubtreeType) {
match subtree_type {
SubtreeType::Left => self.left_subtree_complete = exec_ctx.subtree_complete,
SubtreeType::Right => self.right_subtree_complete = exec_ctx.subtree_complete,
pub(super) fn update_completeness(&mut self, exec_ctx: &ExecutionCtx<'_>, subgraph_type: SubgraphType) {
match subgraph_type {
SubgraphType::Left => self.left_subgraph_complete = exec_ctx.subgraph_complete,
SubgraphType::Right => self.right_subgraph_complete = exec_ctx.subgraph_complete,
}
}
pub(super) fn set_completeness(self, exec_ctx: &mut ExecutionCtx<'_>) {
// par is completed if at least one of its subtrees is completed
let subtree_complete = self.left_subtree_complete || self.right_subtree_complete;
exec_ctx.subtree_complete = subtree_complete;
// par is completed if at least one of its subgraphs is completed
let subgraph_complete = self.left_subgraph_complete || self.right_subgraph_complete;
exec_ctx.subgraph_complete = subgraph_complete;
}
}

View File

@ -25,10 +25,10 @@ impl<'i> super::ExecutableInstruction<'i> for Seq<'i> {
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
log_instruction!(seq, exec_ctx, trace_ctx);
exec_ctx.subtree_complete = true;
exec_ctx.subgraph_complete = true;
self.0.execute(exec_ctx, trace_ctx)?;
if exec_ctx.subtree_complete {
if exec_ctx.subgraph_complete {
self.1.execute(exec_ctx, trace_ctx)?;
}

View File

@ -26,10 +26,10 @@ impl<'i> super::ExecutableInstruction<'i> for Xor<'i> {
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
log_instruction!(xor, exec_ctx, trace_ctx);
exec_ctx.subtree_complete = true;
exec_ctx.subgraph_complete = true;
match self.0.execute(exec_ctx, trace_ctx) {
Err(e) if e.is_catchable() => {
exec_ctx.subtree_complete = true;
exec_ctx.subgraph_complete = true;
exec_ctx.last_error_descriptor.meet_xor_right_branch();
print_xor_log(&e);
@ -44,7 +44,7 @@ fn print_xor_log(e: &ExecutionError) {
if e.is_match_or_mismatch() {
// These errors actually aren't real errors, but a way to bubble execution_step up from match
// to a corresponding xor. They'll become errors iff there is no such xor and execution_step is
// bubble up until the very beginning of current subtree. So the error message shouldn't
// bubble up until the very beginning of current subgraph. So the error message shouldn't
// be print out in order not to confuse users.
return;
}

View File

@ -43,13 +43,13 @@ pub(crate) struct ExecutionCtx<'i> {
/// None means that there weren't any error.
pub(crate) last_error_descriptor: LastErrorDescriptor,
/// Indicates that previous executed subtree is complete.
/// A subtree treats as a complete if all subtree elements satisfy the following rules:
/// - at least one of par subtrees is completed
/// - at least one of xor subtrees is completed without an error
/// - all of seq subtrees are completed
/// Indicates that previous executed subgraph is complete.
/// A subgraph treats as a complete if all subgraph elements satisfy the following rules:
/// - at least one of par subgraphs is completed
/// - at least one of xor subgraphs is completed without an error
/// - all of seq subgraphs are completed
/// - call executed successfully (executed state is Executed)
pub(crate) subtree_complete: bool,
pub(crate) subgraph_complete: bool,
/// Tracker of all met instructions.
pub(crate) tracker: InstructionTracker,
@ -70,7 +70,7 @@ impl<'i> ExecutionCtx<'i> {
Self {
run_parameters,
subtree_complete: true,
subgraph_complete: true,
last_call_request_id,
call_results,
..<_>::default()
@ -123,7 +123,7 @@ impl<'i> Display for ExecutionCtx<'i> {
writeln!(f, "current peer id: {}", self.run_parameters.current_peer_id)?;
writeln!(f, "init peer id: {}", self.run_parameters.init_peer_id)?;
writeln!(f, "timestamp: {}", self.run_parameters.timestamp)?;
writeln!(f, "subtree complete: {}", self.subtree_complete)?;
writeln!(f, "subgraph complete: {}", self.subgraph_complete)?;
writeln!(f, "next peer public keys: {:?}", self.next_peer_pks)?;
Ok(())

View File

@ -73,7 +73,7 @@ pub(crate) struct Scalars<'i> {
/// Terminology used here (mainly to resolve concerns re difference between scalars and values):
/// - scalar is an AIR scalar, iterable and non iterable. A scalar is addressed by a name.
/// - value is concrete value assigned to scalar on certain depth
/// - scope is a variable scope where variable is visible. If we consider fold as a tree where
/// - scope is a variable scope where variable is visible. If we consider fold as a graph where
/// each next produces a new level, then scope is a level in this tree. Please note that it
/// includes variable defined after next instruction.
/// - depth is a count of seen scopes (or a depth in a tree met in the previous definition)

View File

@ -280,7 +280,7 @@ fn access_last_error_by_not_exists_field() {
}
#[test]
fn last_error_with_par_one_subtree_failed() {
fn last_error_with_par_one_subgraph_failed() {
let fallible_peer_id = "fallible_peer_id";
let fallible_call_service_name = "fallible_call_service";
let mut fallible_vm = create_avm(fallible_call_service(fallible_call_service_name), fallible_peer_id);

View File

@ -34,7 +34,7 @@ fn par_ap_behaviour() {
(seq
(par
(call "{relay_id}" ("peer" "timeout") [join_it] $result)
(ap "fast_result" $result) ;; ap doesn't affect the subtree_complete flag
(ap "fast_result" $result) ;; ap doesn't affect the subgraph_complete flag
)
(call "{client_id}" ("op" "return") [$result.$[0]])
)

View File

@ -28,8 +28,8 @@ fn issue_180() {
(call "{peer_2_id}" ("" "") [] join_var)
(seq
(par
(call "{peer_1_id}" ("" "") [join_var]) ;; sets subtree_complete to false
(fold join_var iterator ;; (on < 0.17.3) triggers ValueNotFound exception and doesn't touch subtree_complete flag
(call "{peer_1_id}" ("" "") [join_var]) ;; sets subgraph_complete to false
(fold join_var iterator ;; (on < 0.17.3) triggers ValueNotFound exception and doesn't touch subgraph_complete flag
(null)
)
)

View File

@ -68,10 +68,10 @@ impl SubTraceDesc {
}
impl ExecutedState {
pub fn par(left_subtree_size: usize, right_subtree_size: usize) -> Self {
pub fn par(left_subgraph_size: usize, right_subgraph_size: usize) -> Self {
let par_result = ParResult {
left_size: left_subtree_size as _,
right_size: right_subtree_size as _,
left_size: left_subgraph_size as _,
right_size: right_subgraph_size as _,
};
Self::Par(par_result)
@ -93,9 +93,9 @@ impl std::fmt::Display for ExecutedState {
match self {
Par(ParResult {
left_size: left_subtree_size,
right_size: right_subtree_size,
}) => write!(f, "par({}, {})", left_subtree_size, right_subtree_size),
left_size: left_subgraph_size,
right_size: right_subgraph_size,
}) => write!(f, "par({}, {})", left_subgraph_size, right_subgraph_size),
Call(RequestSentBy(sender)) => write!(f, r"{}", sender),
Call(Executed(value)) => {
write!(f, "executed({})", value)

View File

@ -23,11 +23,11 @@ pub const DATA_CACHE: &str = "data_cache";
/// Print out next_peer_pks at the beginning of each instruction execution_step.
pub const NEXT_PEER_PKS: &str = "next_peer_pks";
/// Print out subtree_complete value at the beginning of each instruction execution_step.
pub const SUBTREE_COMPLETE: &str = "subtree_complete";
/// Print out subgraph_complete value at the beginning of each instruction execution_step.
pub const SUBGRAPH_COMPLETE: &str = "subgraph_complete";
/// Print out count of element in the current subtree at the beginning of each instruction execution_step.
pub const SUBTREE_ELEMENTS: &str = "subtree_elements_count";
/// Print out count of element in the current subgraph at the beginning of each instruction execution_step.
pub const SUBGRAPH_ELEMENTS: &str = "subgraph_elements_count";
/// Print out state of data cache at the beginning of each instruction execution_step.
pub const NEW_EXECUTED_TRACE: &str = "new_executed_trace";
@ -49,8 +49,8 @@ pub const TARGET_MAP: [(&str, i32); 10] = [
(INSTRUCTION, 1 << 1),
(DATA_CACHE, 1 << 2),
(NEXT_PEER_PKS, 1 << 3),
(SUBTREE_COMPLETE, 1 << 4),
(SUBTREE_ELEMENTS, 1 << 5),
(SUBGRAPH_COMPLETE, 1 << 4),
(SUBGRAPH_ELEMENTS, 1 << 5),
(NEW_EXECUTED_TRACE, 1 << 6),
(EXECUTED_TRACE_MERGE, 1 << 7),
(RUN_PARAMS, 1 << 8),

View File

@ -23,8 +23,8 @@ meet_call_start
Expected sequence of `TraceHandler` calls for the `par` instruction:
```
meet_par_start
-> meet_par_subtree_end(..., SubtreeType::Left)
-> meet_par_subtree_end(..., SubtreeType::Right)
-> meet_par_subgraph_end(..., SubgraphType::Left)
-> meet_par_subgraph_end(..., SubgraphType::Right)
```
### Fold instruction

View File

@ -50,7 +50,7 @@ impl TraceHandler {
&self.data_keeper.result_trace
}
pub fn subtree_sizes(&self) -> (usize, usize) {
pub fn subgraph_sizes(&self) -> (usize, usize) {
let prev_len = self.data_keeper.prev_slider().subtrace_len();
let current_len = self.data_keeper.current_slider().subtrace_len();
@ -95,13 +95,13 @@ impl TraceHandler {
Ok(())
}
pub fn meet_par_subtree_end(&mut self, subtree_type: SubtreeType) -> TraceHandlerResult<()> {
match subtree_type {
SubtreeType::Left => {
pub fn meet_par_subgraph_end(&mut self, subgraph_type: SubgraphType) -> TraceHandlerResult<()> {
match subgraph_type {
SubgraphType::Left => {
let par_fsm = self.fsm_keeper.last_par()?;
par_fsm.left_completed(&mut self.data_keeper);
}
SubtreeType::Right => {
SubgraphType::Right => {
let par_fsm = self.fsm_keeper.pop_par()?;
par_fsm.right_completed(&mut self.data_keeper);
}

View File

@ -29,7 +29,7 @@ pub use merger::MergeCtxType;
pub use merger::MergeError;
pub use merger::MergerApResult;
pub use merger::MergerCallResult;
pub use state_automata::SubtreeType;
pub use state_automata::SubgraphType;
pub type TraceHandlerResult<T> = std::result::Result<T, TraceHandlerError>;

View File

@ -75,7 +75,7 @@ pub(super) fn resolve_fold_lore(fold: &FoldResult, merge_ctx: &MergeCtx) -> Merg
/// It could be seen that this function does a convolution of lens with respect to generations.
/// This is needed to handle (fold (par (next ... cases, because of subtrace_len of a Fold state
/// describes only states inside this iteration without states that next brings, however a Par
/// lens describe the whole subtree, where "next" states are included.
/// lens describe the whole subgraph, where "next" states are included.
// TODO: in future it's possible to change a format of a Fold state to one behaves like Par,
// because this function adds some overhead

View File

@ -41,7 +41,7 @@ pub enum StateFSMError {
#[error("overflow is occurred while calculating the new position of a {2} slider for resolved par {0:?} and current position {1}'")]
ParPosOverflow(ParResult, usize, MergeCtxType),
/// Errors occurred when ParResult.0 + ParResult.1 value is bigger than current subtree size.
/// Errors occurred when ParResult.0 + ParResult.1 value is bigger than current subgraph size.
#[error("underflow is occurred while calculating the new position of a {2} slider for resolved par {0:?} and current subtrace len {1}'")]
ParLenUnderflow(ParResult, usize, MergeCtxType),

View File

@ -18,7 +18,7 @@ use super::*;
use crate::MergeCtxType;
use crate::ResolvedFold;
/// This state updater manage to do the same thing as SubTreeStateUpdater in ParFSM,
/// This state updater manage to do the same thing as CtxStateHandler in ParFSM,
/// for details please see its detailed comment.
#[derive(Debug, Default, Clone)]
pub(super) struct CtxStateHandler {

View File

@ -22,7 +22,7 @@ mod state_inserter;
mod utils;
pub use errors::StateFSMError;
pub use par_fsm::SubtreeType;
pub use par_fsm::SubgraphType;
pub(crate) type FSMResult<T> = std::result::Result<T, StateFSMError>;

View File

@ -35,14 +35,14 @@ pub(crate) struct ParFSM {
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SubtreeType {
pub enum SubgraphType {
Left,
Right,
}
impl ParFSM {
pub(crate) fn from_left_started(ingredients: MergerParResult, data_keeper: &mut DataKeeper) -> FSMResult<Self> {
// default is a par with empty left and right subtrees
// default is a par with empty left and right subgraphs
let prev_par = ingredients.prev_par.unwrap_or_default();
let current_par = ingredients.current_par.unwrap_or_default();
@ -58,31 +58,31 @@ impl ParFSM {
par_builder,
};
par_fsm.prepare_sliders(data_keeper, SubtreeType::Left)?;
par_fsm.prepare_sliders(data_keeper, SubgraphType::Left)?;
Ok(par_fsm)
}
pub(crate) fn left_completed(&mut self, data_keeper: &mut DataKeeper) {
self.par_builder.track(data_keeper, SubtreeType::Left);
self.state_handler.handle_subtree_end(data_keeper, SubtreeType::Left);
self.par_builder.track(data_keeper, SubgraphType::Left);
self.state_handler.handle_subgraph_end(data_keeper, SubgraphType::Left);
// all invariants were checked in the ctor
let _ = self.prepare_sliders(data_keeper, SubtreeType::Right);
let _ = self.prepare_sliders(data_keeper, SubgraphType::Right);
}
pub(crate) fn right_completed(mut self, data_keeper: &mut DataKeeper) {
self.par_builder.track(data_keeper, SubtreeType::Right);
self.par_builder.track(data_keeper, SubgraphType::Right);
let state = self.par_builder.build();
self.state_inserter.insert(data_keeper, state);
self.state_handler.handle_subtree_end(data_keeper, SubtreeType::Right);
self.state_handler.handle_subgraph_end(data_keeper, SubgraphType::Right);
}
fn prepare_sliders(&self, data_keeper: &mut DataKeeper, subtree_type: SubtreeType) -> FSMResult<()> {
let (prev_len, current_len) = match subtree_type {
SubtreeType::Left => (self.prev_par.left_size, self.current_par.left_size),
SubtreeType::Right => (self.prev_par.right_size, self.current_par.right_size),
fn prepare_sliders(&self, data_keeper: &mut DataKeeper, subgraph_type: SubgraphType) -> FSMResult<()> {
let (prev_len, current_len) = match subgraph_type {
SubgraphType::Left => (self.prev_par.left_size, self.current_par.left_size),
SubgraphType::Right => (self.prev_par.right_size, self.current_par.right_size),
};
data_keeper.prev_slider_mut().set_subtrace_len(prev_len as _)?;
@ -94,11 +94,11 @@ impl ParFSM {
use std::fmt;
impl fmt::Display for SubtreeType {
impl fmt::Display for SubgraphType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubtreeType::Left => write!(f, "left"),
SubtreeType::Right => write!(f, "right"),
SubgraphType::Left => write!(f, "left"),
SubgraphType::Right => write!(f, "right"),
}
}
}

View File

@ -20,37 +20,37 @@ use super::*;
#[derive(Debug, Default, Clone)]
pub(super) struct ParBuilder {
saved_states_count: usize,
left_subtree_size: usize,
right_subtree_size: usize,
left_subgraph_size: usize,
right_subgraph_size: usize,
}
impl ParBuilder {
// StateInserter here needs to guaranteed that ParBuilder creates after it,
// it must be so to right track a left subtree size
// it must be so to right track a left subgraph size
pub(super) fn from_keeper(data_keeper: &DataKeeper, _: &StateInserter) -> Self {
let saved_states_count = data_keeper.result_states_count();
Self {
saved_states_count,
left_subtree_size: 0,
right_subtree_size: 0,
left_subgraph_size: 0,
right_subgraph_size: 0,
}
}
pub(super) fn track(&mut self, data_keeper: &DataKeeper, subtree_type: SubtreeType) {
pub(super) fn track(&mut self, data_keeper: &DataKeeper, subgraph_type: SubgraphType) {
let prev_states_count = self.saved_states_count;
let states_count = data_keeper.result_states_count();
let resulted_states_count = states_count - prev_states_count;
match subtree_type {
SubtreeType::Left => self.left_subtree_size = resulted_states_count,
SubtreeType::Right => self.right_subtree_size = resulted_states_count,
match subgraph_type {
SubgraphType::Left => self.left_subgraph_size = resulted_states_count,
SubgraphType::Right => self.right_subgraph_size = resulted_states_count,
}
self.saved_states_count = data_keeper.result_trace.len();
}
pub(super) fn build(self) -> ExecutedState {
// TODO: check that usize could be converted into u32
ExecutedState::par(self.left_subtree_size, self.right_subtree_size)
ExecutedState::par(self.left_subgraph_size, self.right_subgraph_size)
}
}

View File

@ -23,12 +23,12 @@ use new_states_calculation::compute_new_states;
///
/// To see why it's really needed, imagine the following trace:
/// [par 9, 3]
/// [par 3, 5] <- left subtree of [par 9, 3]
/// [call rs 1] [call rs 2] [call rs 3] <- left subtree of [par 3, 5]
/// [call rs 4] [call rs 5] [call rs 6] [call rs 7] [call rs 8] <- right subtree of [par 3, 5]
/// [par 1, 1] <- right subtree of [par 9, 3]
/// [call e 9] <- left subtree of [par 1, 1]
/// [call e 10] <- right subtree of [par 1, 1]
/// [par 3, 5] <- left subgraph of [par 9, 3]
/// [call rs 1] [call rs 2] [call rs 3] <- left subgraph of [par 3, 5]
/// [call rs 4] [call rs 5] [call rs 6] [call rs 7] [call rs 8] <- right subgraph of [par 3, 5]
/// [par 1, 1] <- right subgraph of [par 9, 3]
/// [call e 9] <- left subgraph of [par 1, 1]
/// [call e 10] <- right subgraph of [par 1, 1]
///
/// where
/// call rs N - request sent state of Nth call
@ -50,7 +50,7 @@ use new_states_calculation::compute_new_states;
/// )
///
/// Suppose that call 5 (corresponds to [call rs 5]) will fail (f.e. call_service returns a service
/// error). Since it's wrapped with xor, then right subtree of xor (null) will be executed.
/// error). Since it's wrapped with xor, then right subgraph of xor (null) will be executed.
/// After that next par will be executed. This par has corresponding state [par 1, 1] in a trace,
/// and to allow slider to pop it it's needed to set updated position in a proper way, because
/// otherwise [call rs 6] will be returned.
@ -65,24 +65,24 @@ pub(super) struct CtxStateHandler {
}
impl CtxStateHandler {
/// Prepare new states that sliders will have after finishing executing of each subtree.
/// Prepare new states that sliders will have after finishing executing of each subgraph.
pub(super) fn prepare(
prev_par: ParResult,
current_par: ParResult,
data_keeper: &mut DataKeeper,
) -> FSMResult<Self> {
let left_pair = compute_new_states(data_keeper, prev_par, current_par, SubtreeType::Left)?;
let right_pair = compute_new_states(data_keeper, prev_par, current_par, SubtreeType::Right)?;
let left_pair = compute_new_states(data_keeper, prev_par, current_par, SubgraphType::Left)?;
let right_pair = compute_new_states(data_keeper, prev_par, current_par, SubgraphType::Right)?;
let handler = Self { left_pair, right_pair };
Ok(handler)
}
pub(super) fn handle_subtree_end(self, data_keeper: &mut DataKeeper, subtree_type: SubtreeType) {
match subtree_type {
SubtreeType::Left => update_ctx_states(self.left_pair, data_keeper),
SubtreeType::Right => update_ctx_states(self.right_pair, data_keeper),
pub(super) fn handle_subgraph_end(self, data_keeper: &mut DataKeeper, subgraph_type: SubgraphType) {
match subgraph_type {
SubgraphType::Left => update_ctx_states(self.left_pair, data_keeper),
SubgraphType::Right => update_ctx_states(self.right_pair, data_keeper),
}
}
}

View File

@ -21,11 +21,11 @@ pub(super) fn compute_new_states(
data_keeper: &DataKeeper,
prev_par: ParResult,
current_par: ParResult,
subtree_type: SubtreeType,
subgraph_type: SubgraphType,
) -> FSMResult<CtxStatesPair> {
let (prev_len, current_len) = match subtree_type {
SubtreeType::Left => (prev_par.left_size, current_par.left_size),
SubtreeType::Right => {
let (prev_len, current_len) = match subgraph_type {
SubgraphType::Left => (prev_par.left_size, current_par.left_size),
SubgraphType::Right => {
let prev_par_size = prev_par.size().ok_or(StateFSMError::ParLenOverflow(prev_par))?;
let current_par_size = current_par.size().ok_or(StateFSMError::ParLenOverflow(current_par))?;
@ -40,15 +40,15 @@ pub(super) fn compute_new_states(
Ok(pair)
}
fn compute_new_state(par_subtree_len: usize, slider: &TraceSlider, par: ParResult) -> FSMResult<CtxState> {
fn compute_new_state(par_subgraph_len: usize, slider: &TraceSlider, par: ParResult) -> FSMResult<CtxState> {
let pos = slider
.position()
.checked_add(par_subtree_len)
.checked_add(par_subgraph_len)
.ok_or_else(|| StateFSMError::ParPosOverflow(par, slider.position(), MergeCtxType::Previous))?;
let subtrace_len = slider
.subtrace_len()
.checked_sub(par_subtree_len)
.checked_sub(par_subgraph_len)
.ok_or_else(|| StateFSMError::ParLenUnderflow(par, slider.subtrace_len(), MergeCtxType::Current))?;
let new_state = CtxState::new(pos, subtrace_len);