Permalink
Browse files

Merge pull request #23 from spawngrid/alterline

Adds serialization and restoration functionality to seresye
  • Loading branch information...
2 parents baec43f + 5d6e626 commit 1e124c091a782ddb5a293627101408800e1adce4 @ericbmerritt ericbmerritt committed Mar 5, 2012
Showing with 73 additions and 5 deletions.
  1. +16 −4 src/seresye.erl
  2. +57 −1 src/seresye_engine.erl
View
@@ -16,7 +16,8 @@
add_rules/2, add_rule/2, add_rule/3, assert/2, get_kb/1,
get_rules_fired/1, get_client_state/1,
set_hooks/2, get_fired_rule/1,
- set_client_state/2, query_kb/2, remove_rule/2, retract/2]).
+ set_client_state/2, query_kb/2, serialize/1,
+ remove_rule/2, retract/2]).
%% gen_server callbacks
-export([start_link/0, start_link/1, start_link/2, init/1, handle_call/3,
@@ -27,7 +28,7 @@
%%====================================================================
start() ->
seresye_sup:start_engine().
-
+
start(Name) ->
seresye_sup:start_engine(Name).
@@ -86,6 +87,8 @@ get_kb(Name) ->
query_kb(Name, Pattern) ->
gen_server:call(Name, {query_kb, Pattern}).
+serialize(Name) ->
+ gen_server:call(Name, serialize).
%%%===================================================================
%%% gen_server callbacks
@@ -94,14 +97,19 @@ start_link() ->
gen_server:start_link(?MODULE, [], []).
start_link(Name) when is_atom(Name) ->
- gen_server:start_link({local, Name}, ?MODULE, [], []).
+ gen_server:start_link({local, Name}, ?MODULE, [], []);
+
+start_link(ClientState) when not is_atom(ClientState) ->
+ gen_server:start_link(?MODULE, [ClientState], []).
start_link(ClientState, Name) when is_atom(Name) ->
gen_server:start_link({local, Name}, ?MODULE, [ClientState], []).
init([]) ->
{ok, seresye_engine:new()};
+init([Engine]) when element(1, Engine) == seresye ->
+ {ok, seresye_engine:restore(Engine)};
init([ClientState]) ->
{ok, seresye_engine:new(ClientState)}.
@@ -208,7 +216,11 @@ handle_call({query_kb, Pattern}, _From, State0) ->
Type:Reason ->
{error, {Type, Reason}}
end,
- {reply, Reply, State0}.
+ {reply, Reply, State0};
+
+handle_call(serialize, _From, State) ->
+ Reply = seresye_engine:serialize(State),
+ {reply, Reply, State}.
handle_cast({set_hooks, Hooks}, State) ->
{noreply, seresye_engine:set_hooks(State, Hooks)};
@@ -24,7 +24,7 @@
%% External exports
%%====================================================================
--export([new/0, new/1,
+-export([new/0, new/1, serialize/1, restore/1, cleanup/1,
set_hooks/2, get_fired_rule/1,
add_rules/2, add_rule/2, add_rule/3, assert/2, get_kb/1,
get_rules_fired/1, get_client_state/1, set_client_state/2,
@@ -51,6 +51,62 @@ set_client_state(EngineState, NewState) ->
get_client_state(#seresye{client_state=State}) ->
State.
+cleanup(#seresye{ alfa = Alfa0, join = Join0 }) ->
+ [ begin (catch ets:delete(Tab)), Tab end || {_, Tab, _} <- Alfa0 ] ++
+ [ begin (catch ets:delete(Tab)), Tab end || {{Tab, _}, _, _, _, _} <- Join0, is_integer(Tab) ].
+
+restore(#seresye{ alfa = Alfa0, join = Join0 } = Engine) ->
+ TabCache = ets:new(tab_cache, []),
+ Alfa = [ {Cond, restore_tab(TabCache, Tab), Alfa_fun}
+ || {Cond, Tab, Alfa_fun} <- Alfa0 ],
+ Join = [ {case Key of
+ {Tab,V} when element(1,Tab) == ets_table ->
+ {restore_tab(TabCache, Tab), V};
+ _ ->
+ Key
+ end, Beta, Children, Parent, Pos} ||
+ {Key, Beta, Children, Parent, Pos} <- Join0 ],
+ ets:delete(TabCache),
+ Engine#seresye{ alfa = Alfa, join = Join }.
+
+serialize(#seresye{ alfa = Alfa0, join = Join0 } = Engine) ->
+ Alfa = [ {Cond, serialize_tab(Tab), Alfa_fun}
+ || {Cond, Tab, Alfa_fun} <- Alfa0 ],
+ Join = [ {case Key of
+ {Tab,V} when is_integer(Tab) ->
+ {serialize_tab(Tab), V};
+ _ ->
+ Key
+ end, Beta, Children, Parent, Pos} ||
+ {Key, Beta, Children, Parent, Pos} <- Join0 ],
+ Engine#seresye{ alfa = Alfa, join = Join }.
+
+% where
+serialize_tab(Tab) ->
+ case ets:info(Tab) of
+ undefined ->
+ Tab;
+ Info ->
+ {ets_table, Tab, Info, ets:tab2list(Tab)}
+ end.
+restore_tab(Cache, {ets_table, Tab, Info, Content}) ->
+ case ets:lookup(Cache, Tab) of
+ [{Tab, NewTab}] ->
+ NewTab;
+ [] ->
+ NewTab = ets:new(proplists:get_value(name, Info),
+ [ proplists:get_value(Opt, Info) ||
+ Opt <- [type,protection] ] ++
+ [ {Opt, proplists:get_value(Opt, Info)} ||
+ Opt <- [keypos] ]),
+ ets:insert(NewTab, Content),
+ ets:insert(Cache, {Tab, NewTab}),
+ NewTab
+ end;
+restore_tab(_Cache, Tab) ->
+ Tab.
+
+
%% @doc Insert a fact in the KB.
%% It also checks if the fact verifies any condition,
%% if this is the case the fact is also inserted in the alpha-memory

0 comments on commit 1e124c0

Please sign in to comment.