diff options
Diffstat (limited to 'lib/asn1/src/asn1_db.erl')
-rw-r--r-- | lib/asn1/src/asn1_db.erl | 263 |
1 files changed, 125 insertions, 138 deletions
diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl index f680b3d064..843fc66c9c 100644 --- a/lib/asn1/src/asn1_db.erl +++ b/lib/asn1/src/asn1_db.erl @@ -1,167 +1,154 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% -module(asn1_db). -%-compile(export_all). --export([dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). --export([dbget_all_mod/1,dbstop/0,dbclear/0,dberase_module/1,dbstart/1,stop_server/1]). -%% internal exports --export([dbloop0/1,dbloop/2]). -%% Db stuff -dbstart(Includes) -> - start_server(asn1db, asn1_db, dbloop0, [Includes]). +-export([dbstart/1,dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). +-export([dbget_all_mod/1,dbclear/0,dberase_module/1,dbstop/0]). -dbloop0(Includes) -> - dbloop(Includes, ets:new(asn1, [set,named_table])). - -opentab(Tab,Mod,[]) -> - opentab(Tab,Mod,["."]); -opentab(Tab,Mod,Includes) -> - Base = lists:concat([Mod,".asn1db"]), - opentab2(Tab,Base,Mod,Includes,ok). +-record(state, {parent, monitor, includes, table}). -opentab2(_Tab,_Base,_Mod,[],Error) -> - Error; -opentab2(Tab,Base,Mod,[Ih|It],_Error) -> - File = filename:join(Ih,Base), - case ets:file2tab(File) of - {ok,Modtab} -> - ets:insert(Tab,{Mod, Modtab}), - {ok,Modtab}; - NewErr -> - opentab2(Tab,Base,Mod,It,NewErr) +%% Interface +dbstart(Includes) -> + Parent = self(), + case get(?MODULE) of + undefined -> + put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)), + true; + _Pid -> + req({new_includes, Includes}) end. - -dbloop(Includes, Tab) -> - receive - {From,{set, Mod, K2, V}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:insert(Modtab,{K2, V}), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {get, Mod, K2}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - case Result of - {ok,Newtab} -> - From ! {asn1db, lookup(Newtab, K2)}; - _Error -> - From ! {asn1db, undefined} - end, - dbloop(Includes, Tab); - {From, {all_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2list(Modtab)}, - dbloop(Includes, Tab); - {From, {delete_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:delete(Modtab), - ets:delete(Tab,Mod), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {save, OutFile,Mod}} -> - [{_,Mtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2file(Mtab,OutFile)}, - dbloop(Includes,Tab); - {From, {load, Mod}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - From ! {asn1db,Result}, - dbloop(Includes,Tab); - {From, {new, Mod}} -> - case ets:lookup(Tab,Mod) of - [{_,Modtab}] -> - ets:delete(Modtab); - _ -> - true - end, - Tabname = list_to_atom(lists:concat(["asn1_",Mod])), - ets:new(Tabname, [set,named_table]), - ets:insert(Tab,{Mod,Tabname}), - From ! {asn1db, ok}, - dbloop(Includes,Tab); - {From, stop} -> - From ! {asn1db, ok}; %% nothing to store - {From, clear} -> - ModTabList = [Mt||{_,Mt} <- ets:tab2list(Tab)], - lists:foreach(fun(T) -> ets:delete(T) end,ModTabList), - ets:delete(Tab), - From ! {asn1db, cleared}, - dbloop(Includes, ets:new(asn1, [set])); - {From,{new_includes,[NewIncludes]}} -> - From ! {asn1db,done}, - dbloop(NewIncludes,Tab) +dbnew(Module) -> req({new, Module}). +dbsave(OutFile, Module) -> req({save, OutFile, Module}). +dbload(Module) -> req({load, Module}). +dbput(Module, K, V) -> req({set, Module, K, V}). +dbget(Module, K) -> req({get, Module, K}). +dbget_all(K) -> req({get_all, K}). +dbget_all_mod(Mod) -> req({all_mod, Mod}). +dbclear() -> req(clear). +dberase_module({module,M}) -> req({delete_mod, M}). +dbstop() -> Resp = req(stop), erase(?MODULE), Resp. + +%% Internal functions +req(Request) -> + DbPid = get(?MODULE), + Ref = erlang:monitor(process,DbPid), + get(?MODULE) ! {{Ref, self()}, Request}, + receive + {{Ref,?MODULE}, Reply} -> + erlang:demonitor(Ref,[flush]), + Reply; + {'DOWN',Ref,_,_,Info} -> + exit({db_error,Info}) end. +reply({Ref,From}, Response) -> + From ! {{Ref,?MODULE}, Response}. -%%all(Tab, K) -> -%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})). -%%pickup(K, []) -> []; -%%pickup(K, [[V1,V2] |T]) -> -%% [{{K,V1},V2} | pickup(K, T)]. +init(Parent, Includes) -> + MRef = erlang:monitor(process, Parent), + loop(#state{parent = Parent, monitor = MRef, includes = Includes, + table = ets:new(?MODULE, [])}). -lookup(Tab, K) -> - case ets:lookup(Tab, K) of - [] -> undefined; - [{K,V}] -> V +loop(#state{parent = Parent, monitor = MRef, table = Table, + includes = Includes} = State) -> + receive + {From, {set, Mod, K2, V}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:insert(Modtab, {K2, V}), + reply(From, ok), + loop(State); + {From, {get, Mod, K2}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + case Result of + {ok, Newtab} -> reply(From, lookup(Newtab, K2)); + _Error -> reply(From, undefined) + end, + loop(State); + {From, {all_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2list(Modtab)), + loop(State); + {From, {delete_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:delete(Modtab), + ets:delete(Table, Mod), + reply(From, ok), + loop(State); + {From, {save, OutFile, Mod}} -> + [{_,Mtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2file(Mtab, OutFile)), + loop(State); + {From, {load, Mod}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + reply(From, Result), + loop(State); + {From, {new, Mod}} -> + case ets:lookup(Table, Mod) of + [{_, Modtab}] -> ets:delete(Modtab); + _ -> true + end, + ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []), + ets:insert(Table, {Mod, ModTableId}), + reply(From, ok), + loop(State); + {From, clear} -> + [ets:delete(Mt) || {_, Mt} <- ets:tab2list(Table)], + ets:delete(Table), + reply(From, cleared), + loop(State#state{table = ets:new(asn1, [set])}); + {From, {new_includes, NewIncludes}} -> + reply(From, true), + loop(State#state{includes = NewIncludes}); + {From, stop} -> + reply(From, stopped); %% Nothing to store + {'DOWN', MRef, process, Parent, Reason} -> + exit(Reason) end. +opentab(Tab, Mod, []) -> + opentab(Tab, Mod, ["."]); +opentab(Tab, Mod, Includes) -> + Base = lists:concat([Mod, ".asn1db"]), + opentab2(Tab, Base, Mod, Includes, ok). -dbnew(Module) -> req({new,Module}). -dbsave(OutFile,Module) -> req({save,OutFile,Module}). -dbload(Module) -> req({load,Module}). - -dbput(Module,K,V) -> req({set, Module, K, V}). -dbget(Module,K) -> req({get, Module, K}). -dbget_all(K) -> req({get_all, K}). -dbget_all_mod(Mod) -> req({all_mod,Mod}). -dbstop() -> stop_server(asn1db). -dbclear() -> req(clear). -dberase_module({module,M})-> - req({delete_mod, M}). - -req(R) -> - asn1db ! {self(), R}, - receive {asn1db, Reply} -> Reply end. - -stop_server(Name) -> - stop_server(Name, whereis(Name)). -stop_server(_, undefined) -> stopped; -stop_server(Name, _Pid) -> - Name ! {self(), stop}, - receive {Name, _} -> stopped end. - - -start_server(Name,Mod,Fun,Args) -> - case whereis(Name) of - undefined -> - register(Name, spawn(Mod,Fun, Args)); - _Pid -> - req({new_includes,Args}) +opentab2(_Tab, _Base, _Mod, [], Error) -> + Error; +opentab2(Tab, Base, Mod, [Ih|It], _Error) -> + File = filename:join(Ih, Base), + case ets:file2tab(File) of + {ok, Modtab} -> + ets:insert(Tab, {Mod, Modtab}), + {ok, Modtab}; + NewErr -> + opentab2(Tab, Base, Mod, It, NewErr) end. - +lookup(Tab, K) -> + case ets:lookup(Tab, K) of + [] -> undefined; + [{K,V}] -> V + end. |