Skip to content

Commit

Permalink
Bundle keep-while into a tree record
Browse files Browse the repository at this point in the history
In most cases in khepri_machine, the keep while conditions are updated
along with the root of the tree. This change bundles the root of the
tree, the keep while conditions and the keep while condition reverse
index into one record. The child commit while refactor functions that
currently take the Root and Extra to take the Tree instead and
AppliedChanges will be passed as a separate argument.
  • Loading branch information
the-mikedavis committed Feb 14, 2023
1 parent a85525e commit dee8110
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/khepri_import_export.erl
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export(StoreId, PathPattern, Module, ModulePriv)
%% @private

do_export(
#khepri_machine{root = Root} = State,
#khepri_machine{tree = #tree{root = Root}} = State,
PathPattern, Module, ModulePriv) ->
%% Initialize export using the callback module.
case open_write(Module, ModulePriv) of
Expand Down Expand Up @@ -275,7 +275,7 @@ open_write(Module, ModulePriv) ->
%% @private

write(
#khepri_machine{keep_while_conds = KeepWhileConds},
#khepri_machine{tree = #tree{keep_while_conds = KeepWhileConds}},
Path, #node{payload = Payload},
Module, ModulePriv) ->
Extra = case KeepWhileConds of
Expand Down
77 changes: 44 additions & 33 deletions src/khepri_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
-type tree_node() :: #node{}.
%% A node in the tree structure.

-type tree() :: #tree{}.

-type props() :: #{payload_version := khepri:payload_version(),
child_list_version := khepri:child_list_version()}.
%% Properties attached to each node in the tree structure.
Expand Down Expand Up @@ -213,7 +215,7 @@ fold(StoreId, PathPattern, Fun, Acc, Options)
PathPattern1 = khepri_path:from_string(PathPattern),
khepri_path:ensure_is_valid(PathPattern1),
{QueryOptions, TreeOptions} = split_query_options(Options),
Query = fun(#?MODULE{root = Root}) ->
Query = fun(#?MODULE{tree = #tree{root = Root}}) ->
try
find_matching_nodes(
Root, PathPattern1, Fun, Acc, TreeOptions)
Expand Down Expand Up @@ -569,7 +571,7 @@ ack_triggers_execution(StoreId, TriggeredStoredProcs)

get_keep_while_conds_state(StoreId, Options)
when ?IS_STORE_ID(StoreId) ->
Query = fun(#?MODULE{keep_while_conds = KeepWhileConds}) ->
Query = fun(#?MODULE{tree = #tree{keep_while_conds = KeepWhileConds}}) ->
{ok, KeepWhileConds}
end,
Options1 = Options#{favor => consistency},
Expand Down Expand Up @@ -1095,7 +1097,7 @@ handle_aux(
khepri_projection:trigger(Projection, Path, OldProps, NewProps),
{no_reply, AuxState, LogState};
handle_aux(_RaState, cast, restore_projections, AuxState, LogState,
#?MODULE{projections = Projections, root = Root}) ->
#?MODULE{tree = #tree{root = Root}, projections = Projections}) ->
maps:foreach(fun(Projection, PathPattern) ->
restore_projection(
Projection, Root, PathPattern)
Expand Down Expand Up @@ -1184,7 +1186,7 @@ apply(
apply(
Meta,
#register_projection{pattern = PathPattern, projection = Projection},
#?MODULE{projections = Projections, root = Root} = State) ->
#?MODULE{tree = #tree{root = Root}, projections = Projections} = State) ->
Reply = khepri_projection:init(Projection),
State1 = case Reply of
ok ->
Expand Down Expand Up @@ -1264,9 +1266,9 @@ emitted_triggers_to_side_effects(_State) ->
%% @private

overview(#?MODULE{config = #config{store_id = StoreId},
root = Root,
triggers = Triggers,
keep_while_conds = KeepWhileConds}) ->
tree = #tree{root = Root,
keep_while_conds = KeepWhileConds},
triggers = Triggers}) ->
TreeOptions = #{props_to_return => [payload,
payload_version,
child_list_version,
Expand Down Expand Up @@ -1522,7 +1524,8 @@ update_keep_while_conds_revidx(
end, KeepWhileCondsRevIdx1, KeepWhile).

locate_sproc_and_execute_tx(
#?MODULE{root = Root} = State, PathPattern, Args, AllowUpdates) ->
#?MODULE{tree = #tree{root = Root}} = State,
PathPattern, Args, AllowUpdates) ->
TreeOptions = #{expect_specific_node => true,
props_to_return => [raw_payload]},
{StandaloneFun, Args1} =
Expand Down Expand Up @@ -1655,9 +1658,10 @@ find_matching_nodes_cb(_, {interrupted, _, _}, _, Acc, _) ->
%% @private

insert_or_update_node(
#?MODULE{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx} = State,
#?MODULE{tree =
#tree{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx}} = State,
PathPattern, Payload,
#{keep_while := KeepWhile},
TreeOptions) ->
Expand Down Expand Up @@ -1708,9 +1712,10 @@ insert_or_update_node(
keep_while_conds_revidx := KeepWhileCondsRevIdx1} =
update_keep_while_conds_extra(Extra, ResolvedPath, KeepWhile),
State1 = State#?MODULE{
root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx = KeepWhileCondsRevIdx1},
tree = #tree{root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx =
KeepWhileCondsRevIdx1}},
{State2, SideEffects} = create_tree_change_side_effects(
State, State1, Ret2, AppliedChanges),
{State2, {ok, Ret2}, SideEffects};
Expand All @@ -1719,9 +1724,10 @@ insert_or_update_node(
{State, Error}
end;
insert_or_update_node(
#?MODULE{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx} = State,
#?MODULE{tree =
#tree{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx}} = State,
PathPattern, Payload,
_Extra, TreeOptions) ->
Fun = fun(Path, Node, Result) ->
Expand All @@ -1739,10 +1745,11 @@ insert_or_update_node(
keep_while_conds_revidx := KeepWhileCondsRevIdx1,
applied_changes := AppliedChanges},
Ret2} ->
State1 = State#?MODULE{root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx =
KeepWhileCondsRevIdx1},
State1 = State#?MODULE{tree =
#tree{root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx =
KeepWhileCondsRevIdx1}},
{State2, SideEffects} = create_tree_change_side_effects(
State, State1, Ret2, AppliedChanges),
{State2, {ok, Ret2}, SideEffects};
Expand Down Expand Up @@ -1813,9 +1820,10 @@ can_continue_update_after_node_not_found1(_) ->
%% @private

delete_matching_nodes(
#?MODULE{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx} = State,
#?MODULE{tree =
#tree{root = Root,
keep_while_conds = KeepWhileConds,
keep_while_conds_revidx = KeepWhileCondsRevIdx}} = State,
PathPattern,
TreeOptions) ->
Ret1 = do_delete_matching_nodes(
Expand All @@ -1830,9 +1838,11 @@ delete_matching_nodes(
applied_changes := AppliedChanges},
Ret2} ->
State1 = State#?MODULE{
root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx = KeepWhileCondsRevIdx1},
tree =
#tree{root = Root1,
keep_while_conds = KeepWhileConds1,
keep_while_conds_revidx =
KeepWhileCondsRevIdx1}},
{State2, SideEffects} = create_tree_change_side_effects(
State, State1, Ret2, AppliedChanges),
{State2, {ok, Ret2}, SideEffects};
Expand Down Expand Up @@ -1875,8 +1885,9 @@ create_tree_change_side_effects(
{NewState1, ProjectionEffects ++ TriggerEffects}.

create_projection_side_effects(
#?MODULE{root = InitialRoot} = _InitialState,
#?MODULE{projections = Projections, root = NewRoot} = _NewState,
#?MODULE{tree = #tree{root = InitialRoot}} = _InitialState,
#?MODULE{tree = #tree{root = NewRoot},
projections = Projections} = _NewState,
Changes) ->
%% Note: the order in which updates are applied to projections should not
%% be relied on.
Expand Down Expand Up @@ -2000,7 +2011,7 @@ create_trigger_side_effects(
#?MODULE{triggers = Triggers,
emitted_triggers = EmittedTriggers} = _InitialState,
#?MODULE{config = #config{store_id = StoreId},
root = Root} = NewState,
tree = #tree{root = Root}} = NewState,
Changes) ->
TriggeredStoredProcs = list_triggered_sprocs(Root, Changes, Triggers),

Expand Down Expand Up @@ -2977,14 +2988,14 @@ remove_expired_nodes([PathToDelete | Rest], Root, Extra, FunAcc) ->
end.

-ifdef(TEST).
get_root(#?MODULE{root = Root}) ->
get_root(#?MODULE{tree = #tree{root = Root}}) ->
Root.

get_keep_while_conds(
#?MODULE{keep_while_conds = KeepWhileConds}) ->
#?MODULE{tree = #tree{keep_while_conds = KeepWhileConds}}) ->
KeepWhileConds.

get_keep_while_conds_revidx(
#?MODULE{keep_while_conds_revidx = KeepWhileCondsRevIdx}) ->
#?MODULE{tree = #tree{keep_while_conds_revidx = KeepWhileCondsRevIdx}}) ->
KeepWhileCondsRevIdx.
-endif.
18 changes: 2 additions & 16 deletions src/khepri_machine.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,11 @@
%% Copyright © 2021-2023 VMware, Inc. or its affiliates. All rights reserved.
%%

-include("src/khepri_payload.hrl").

%% Structure representing each node in the tree, including the root node.

-define(INIT_DATA_VERSION, 1).
-define(INIT_CHILD_LIST_VERSION, 1).
-define(INIT_NODE_PROPS, #{payload_version => ?INIT_DATA_VERSION,
child_list_version => ?INIT_CHILD_LIST_VERSION}).
-include("src/khepri_tree.hrl").

%% TODO: Query this value from Ra itself.
-define(SNAPSHOT_INTERVAL, 4096).

-record(node, {props = ?INIT_NODE_PROPS :: khepri_machine:props(),
payload = ?NO_PAYLOAD :: khepri_payload:payload(),
child_nodes = #{} :: #{khepri_path:component() := #node{}}}).

%% Record representing the state machine configuration.
-record(config,
{store_id :: khepri:store_id(),
Expand All @@ -30,10 +19,7 @@
%% State machine's internal state record.
-record(khepri_machine,
{config = #config{} :: khepri_machine:machine_config(),
root = #node{} :: khepri_machine:tree_node(),
keep_while_conds = #{} :: khepri_machine:keep_while_conds_map(),
keep_while_conds_revidx = #{}
:: khepri_machine:keep_while_conds_revidx(),
tree = #tree{} :: khepri_machine:tree(),
triggers = #{} ::
#{khepri:trigger_id() =>
#{sproc := khepri_path:native_path(),
Expand Down
24 changes: 24 additions & 0 deletions src/khepri_tree.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright © 2021-2023 VMware, Inc. or its affiliates. All rights reserved.
%%

-include("src/khepri_payload.hrl").

%% Structure representing each node in the tree, including the root node.

-define(INIT_DATA_VERSION, 1).
-define(INIT_CHILD_LIST_VERSION, 1).
-define(INIT_NODE_PROPS, #{payload_version => ?INIT_DATA_VERSION,
child_list_version => ?INIT_CHILD_LIST_VERSION}).

-record(node, {props = ?INIT_NODE_PROPS :: khepri_machine:props(),
payload = ?NO_PAYLOAD :: khepri_payload:payload(),
child_nodes = #{} :: #{khepri_path:component() := #node{}}}).

-record(tree, {root :: khepri_machine:tree_node(),
keep_while_conds = #{} :: khepri_machine:keep_while_conds_map(),
keep_while_conds_revidx = #{} ::
khepri_machine:keep_while_conds_revidx()}).
4 changes: 2 additions & 2 deletions src/khepri_tx.erl
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ count(PathPattern) ->

count(PathPattern, Options) ->
PathPattern1 = khepri_tx_adv:path_from_string(PathPattern),
{#khepri_machine{root = Root},
{#khepri_machine{tree = #tree{root = Root}},
_SideEffects} = khepri_tx_adv:get_tx_state(),
Fun = fun khepri_machine:count_node_cb/3,
{_QueryOptions, TreeOptions} = khepri_machine:split_query_options(Options),
Expand Down Expand Up @@ -471,7 +471,7 @@ fold(PathPattern, Fun, Acc) ->

fold(PathPattern, Fun, Acc, Options) ->
PathPattern1 = khepri_tx_adv:path_from_string(PathPattern),
{#khepri_machine{root = Root},
{#khepri_machine{tree = #tree{root = Root}},
_SideEffects} = khepri_tx_adv:get_tx_state(),
{_QueryOptions, TreeOptions} = khepri_machine:split_query_options(Options),
TreeOptions1 = TreeOptions#{expect_specific_node => false},
Expand Down
3 changes: 2 additions & 1 deletion src/khepri_tx_adv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ get_many(PathPattern, Options) ->
do_get_many(PathPattern, Fun, Acc, Options) ->
PathPattern1 = path_from_string(PathPattern),
{_QueryOptions, TreeOptions} = khepri_machine:split_query_options(Options),
{#khepri_machine{root = Root}, _SideEffects} = get_tx_state(),
{#khepri_machine{tree = #tree{root = Root}},
_SideEffects} = get_tx_state(),
Ret = khepri_machine:find_matching_nodes(
Root, PathPattern1, Fun, Acc, TreeOptions),
case Ret of
Expand Down

0 comments on commit dee8110

Please sign in to comment.