From aa79af71aaaa7c382a60d8b10790059c00a83ca3 Mon Sep 17 00:00:00 2001 From: aj heller Date: Mon, 17 Dec 2012 18:02:16 -0800 Subject: [PATCH] fixes db crash; simplifies the ezic_db proxy module The db crash happens when calling `ezic_db:get_all(X)` when `X` is not a valid table name. `ezic_db_ets` crashes, causing the `ezic_db` server to crash, tossing the database with it. The solution prevents ezic_db_ets:get_all/1 from crashing, and instead returns an error value. The simplification here eliminated some code through deduplication. The `handle_call` functions could be improved similarly. --- src/ezic_db.erl | 64 +++++++++++++++++------------------------- src/ezic_db_ets.erl | 10 ++++++- src/ezic_db_mnesia.erl | 2 ++ 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/ezic_db.erl b/src/ezic_db.erl index 0d18006..b9599b9 100644 --- a/src/ezic_db.erl +++ b/src/ezic_db.erl @@ -28,7 +28,7 @@ ]). --record(state, {zones, rules, get_all, flatzone, insert_all, wipe, implementation}). +-record(state, {mod}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PUBLIC API @@ -78,25 +78,12 @@ get_implementation() -> start_link(StartArgs) -> gen_server:start_link({local, ?MODULE}, ?MODULE, StartArgs, []). -init(ezic_db_mnesia) -> - ezic_db_mnesia:init(), - State = #state{zones = fun ezic_db_mnesia:zones/1, - rules = fun ezic_db_mnesia:rules/1, - get_all = fun ezic_db_mnesia:get_all/1, - flatzone = fun ezic_db_mnesia:flatzone/2, - insert_all = fun ezic_db_mnesia:insert_all/1, - wipe = fun ezic_db_mnesia:wipe/1, - implementation = "mnesia"}, - {ok, State}; -init(_) -> - ezic_db_ets:init(), - State = #state{zones = fun ezic_db_ets:zones/1, - rules = fun ezic_db_ets:rules/1, - get_all = fun ezic_db_ets:get_all/1, - flatzone = fun ezic_db_ets:flatzone/2, - insert_all = fun ezic_db_ets:insert_all/1, - wipe = fun ezic_db_ets:wipe/1, - implementation = "ets"}, + +%% TODO: create a db behavior +init(DbModule) when DbModule =:= ezic_db_mnesia; + DbModule=:= ezic_db_ets -> + DbModule:init(), + State = #state{mod = DbModule}, {ok, State}. %%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -105,39 +92,40 @@ init(_) -> handle_call({zones, Name}, _, State) -> - ZoneFun= State#state.zones, - Matches= ZoneFun(Name), + Mod= State#state.mod, + Matches= Mod:zones(Name), {reply, Matches, State}; handle_call({rules, Name}, _, State) -> - RuleFun= State#state.rules, - Matches= RuleFun(Name), + Mod= State#state.mod, + Matches= Mod:rules(Name), {reply, Matches, State}; handle_call({all, Tab}, _, State) -> - GetAllFun= State#state.get_all, - Matches= GetAllFun(Tab), + Mod= State#state.mod, + Matches= Mod:get_all(Tab), {reply, Matches, State}; handle_call({flatzone, Date, Name}, _, State) -> - FlatzoneFun= State#state.flatzone, - Result= FlatzoneFun(Date, Name), + Mod= State#state.mod, + Result= Mod:flatzone(Date, Name), {reply, Result, State}; handle_call({insert_all, Records}, _, State) -> - InsertAllFun= State#state.insert_all, - InsertAllFun(Records), + Mod= State#state.mod, + Mod:insert_all(Records), {noreply, State}; handle_call({wipe, Tab}, _, State) -> - WipeFun= State#state.wipe, - Result= WipeFun(Tab), + Mod= State#state.mod, + Result= Mod:wipe(Tab), {reply, Result, State}; handle_call({flatten}, _, State) -> - GetAllFun= State#state.get_all, - Zones= GetAllFun(zone), - Rules= GetAllFun(rule), + Mod= State#state.mod, + Zones= Mod:get_all(zone), + Rules= Mod:get_all(rule), FlatZone= ezic_flatten:flatten(Zones, Rules), - InsertAllFun= State#state.insert_all, - Result= InsertAllFun(FlatZone), + Result= Mod:insert_all(FlatZone), {reply, Result, State}; handle_call({implementation}, _, State) -> - {reply, State#state.implementation, State}; + Mod= State#state.mod, + Impl= Mod:implementation(), + {reply, Impl, State}; handle_call(_, _, State) -> {noreply, State}. diff --git a/src/ezic_db_ets.erl b/src/ezic_db_ets.erl index f2ed119..09ef44b 100644 --- a/src/ezic_db_ets.erl +++ b/src/ezic_db_ets.erl @@ -13,13 +13,17 @@ , get_all/1 , insert_all/1 , wipe/1 + , implementation/0 ]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PUBLIC API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +implementation() -> ?MODULE. + zones(TzName) -> ets:select(zone, [{#zone{name=TzName, _='_'}, [], ['$_']}]). @@ -43,7 +47,11 @@ flatzone(Date, TzName) -> get_all(Tab) -> - ets:lookup(Tab, Tab). + try ets:lookup(Tab, Tab) of X -> X + catch error:X -> {error, X} + end. + + insert_all(Records) -> diff --git a/src/ezic_db_mnesia.erl b/src/ezic_db_mnesia.erl index 8169f75..7aec684 100644 --- a/src/ezic_db_mnesia.erl +++ b/src/ezic_db_mnesia.erl @@ -13,6 +13,7 @@ , get_all/1 , insert_all/1 , wipe/1 + , implementation/0 ]). -define(create(Record), @@ -23,6 +24,7 @@ ])). +implementation() -> ?MODULE. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % READ - db reading methods