mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 23:20:18 +00:00
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:
parent
dbd42cdf3d
commit
24f0d66bed
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 })))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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(_))
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(())
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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]])
|
||||
)
|
||||
|
@ -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)
|
||||
)
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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>;
|
||||
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user