From 93f0641c2122d6c23e2ac5f18579ef879599fc16 Mon Sep 17 00:00:00 2001 From: Adam Lindberg Date: Thu, 5 Jan 2012 17:03:12 +0100 Subject: [asn1] Abstract out table access to new module All table access is now performed in a separate module. This will allow changes to how ETS is handled by changing only this module. Note that the module exports a very ETS-like interface for now which would have to be maintained even if the data format would change (to a hash map for example). --- lib/asn1/src/Makefile | 5 +- lib/asn1/src/asn1ct.erl | 85 +++++++++++----------------------- lib/asn1/src/asn1ct_check.erl | 43 ++++++++--------- lib/asn1/src/asn1ct_gen.erl | 11 ++--- lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 4 +- lib/asn1/src/asn1ct_table.erl | 64 +++++++++++++++++++++++++ lib/asn1/test/asn1_app_test.erl | 4 +- 7 files changed, 122 insertions(+), 94 deletions(-) create mode 100644 lib/asn1/src/asn1ct_table.erl diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile index 3a59773d93..5614cbea91 100644 --- a/lib/asn1/src/Makefile +++ b/lib/asn1/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. 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 @@ -58,7 +58,8 @@ CT_MODULES= \ asn1ct_gen_ber_bin_v2 \ asn1ct_value \ asn1ct_tok \ - asn1ct_parser2 + asn1ct_parser2 \ + asn1ct_table RT_MODULES= \ asn1rt \ diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 1507b01d81..39082307cb 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -30,7 +30,7 @@ %% Application internal exports -export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3, value/1,vsn/0, - create_ets_table/2,get_name_of_def/1,get_pos_of_def/1]). + get_name_of_def/1,get_pos_of_def/1]). -export([read_config_data/1,get_gen_state_field/1,get_gen_state/0, partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2, get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1, @@ -126,13 +126,13 @@ compile1(File,Options) when is_list(Options) -> DbFile = outfile(Base,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - create_ets_table(asn1_functab,[named_table]), + asn1ct_table:new(asn1_functab, [named_table]), Continue1 = scan(File,Options), Continue2 = parse(Continue1,File,Options), Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule, DbFile,Options,[]), Continue4 = generate(Continue3,OutFile,EncodingRule,Options), - delete_tables([asn1_functab]), + asn1ct_table:delete(asn1_functab), Ret = compile_erl(Continue4,OutFile,Options), case inline(is_inline(Options), inline_output(Options,filename:rootname(File)), @@ -194,7 +194,7 @@ compile_set(SetBase,Files,Options) DbFile = outfile(SetBase,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - create_ets_table(asn1_functab,[named_table]), + asn1ct_table:new(asn1_functab, [named_table]), ScanRes = scan_set(Files,Options), ParseRes = parse_set(ScanRes,Options), Result = @@ -219,7 +219,7 @@ compile_set(SetBase,Files,Options) {error,{'unexpected error in scan/parse phase', lists:map(fun(X)->element(3,X) end,Other)}} end, - delete_tables([asn1_functab]), + asn1ct_table:delete(asn1_functab), Result. check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, @@ -231,7 +231,7 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, Options,InputModules), Continue2 = generate(Continue1,OutFile,EncRule,Options), - delete_tables([renamed_defs,original_imports,automatic_tags]), + asn1ct_table:delete([renamed_defs, original_imports, automatic_tags]), Ret = compile_erl(Continue2,OutFile,Options), case inline(is_inline(Options), @@ -252,12 +252,11 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, merge_modules(ParseRes,CommonName) -> ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes), NewModuleList = remove_name_collisions(ModuleList), - case ets:info(renamed_defs,size) of - 0 -> ets:delete(renamed_defs); - _ -> ok + case asn1ct_table:size(renamed_defs) of + 0 -> asn1ct_table:delete(renamed_defs); + _ -> ok end, save_imports(NewModuleList), -% io:format("~p~n~p~n~p~n~n",[ets:lookup(original_imports,'M1'),ets:lookup(original_imports,'M2'),ets:tab2list(original_imports)]), TypeOrVal = lists:append(lists:map(fun(X)->X#module.typeorval end, NewModuleList)), InputMNameList = lists:map(fun(X)->X#module.name end, @@ -277,7 +276,7 @@ merge_modules(ParseRes,CommonName) -> %% causes an exit if duplicate definition names exist in a module remove_name_collisions(Modules) -> - create_ets_table(renamed_defs,[named_table]), + asn1ct_table:new(renamed_defs, [named_table]), %% Name duplicates in the same module is not allowed. lists:foreach(fun exit_if_nameduplicate/1,Modules), %% Then remove duplicates in different modules and return the @@ -309,7 +308,8 @@ remove_name_collisions2(ModName,[T|Ts],Ms,Acc) -> %% rename T NewT = set_name_of_def(ModName,Name,T), %rename def warn_renamed_def(ModName,get_name_of_def(NewT),Name), - ets:insert(renamed_defs,{get_name_of_def(NewT),Name,ModName}), + asn1ct_table:insert(renamed_defs, + {get_name_of_def(NewT), Name, ModName}), remove_name_collisions2(ModName,Ts,NewMs,[NewT|Acc]); {NewMs,?dupl_equaldefs} -> % name duplicates, but identical defs %% keep name of T @@ -333,8 +333,8 @@ discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms], %% rename def NewT=set_name_of_def(N,Name,T), warn_renamed_def(N,get_name_of_def(NewT),Name), - ets:insert(renamed_defs,{get_name_of_def(NewT), - Name,N}), + asn1ct_table:insert(renamed_defs, + {get_name_of_def(NewT), Name, N}), {NewT,?dupl_uniquedefs bor RenamedOrDupl}; {Name,equal} -> %% delete def @@ -489,8 +489,9 @@ save_imports(ModuleList)-> [] -> ok; ImportsList2 -> - create_ets_table(original_imports,[named_table]), - lists:foreach(fun(X) -> ets:insert(original_imports,X) end,ImportsList2) + asn1ct_table:new(original_imports, [named_table]), + lists:foreach(fun(X) -> asn1ct_table:insert(original_imports, X) end, + ImportsList2) end. @@ -566,7 +567,7 @@ check_tagdefault(ModList) -> case have_same_tagdefault(ModList) of {true,TagDefault} -> TagDefault; {false,TagDefault} -> - create_ets_table(automatic_tags,[named_table]), + asn1ct_table:new(automatic_tags, [named_table]), save_automatic_tagged_types(ModList), TagDefault end. @@ -593,7 +594,7 @@ save_automatic_tagged_types([#module{tagdefault='AUTOMATIC', typeorval=TorV}|Ms]) -> Fun = fun(T) -> - ets:insert(automatic_tags,{get_name_of_def(T)}) + asn1ct_table:insert(automatic_tags, {get_name_of_def(T)}) end, lists:foreach(Fun,TorV), save_automatic_tagged_types(Ms); @@ -832,7 +833,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> _ -> ok end, put(encoding_options,Options), - create_ets_table(check_functions,[named_table]), + asn1ct_table:new(check_functions, [named_table]), %% create decoding function names and taglists for partial decode %% For the time being leave errors unnoticed !!!!!!!!! @@ -864,7 +865,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> erase(encoding_options), erase(tlv_format), % used in ber_bin, optimize erase(class_default_type),% used in ber_bin, optimize - ets:delete(check_functions), + asn1ct_table:delete(check_functions), case Result of {error,_} -> {false,Result}; @@ -1489,38 +1490,6 @@ print_listing([],_) -> ok. -%% functions to administer ets tables - -%% Always creates a new table -create_ets_table(Name,Options) when is_atom(Name) -> - case ets:info(Name) of - undefined -> - ets:new(Name,Options); - _ -> - ets:delete(Name), - ets:new(Name,Options) - end. - -%% Creates a new ets table only if no table exists -create_if_no_table(Name,Options) -> - case ets:info(Name) of - undefined -> - %% create a new table - create_ets_table(Name,Options); - _ -> ok - end. - - -delete_tables([Table|Ts]) -> - case ets:info(Table) of - undefined -> ok; - _ -> ets:delete(Table) - end, - delete_tables(Ts); -delete_tables([]) -> - ok. - - specialized_decode_prepare(Erule,M,TsAndVs,Options) -> case lists:member(asn1config,Options) of true -> @@ -2066,14 +2035,14 @@ get_config_info(CfgList,InfoType) -> %% Before saving anything check if a table exists %% The record gen_state is saved with the key {asn1_config,gen_state} save_config(Key,Info) -> - create_if_no_table(asn1_general,[named_table]), - ets:insert(asn1_general,{{asn1_config,Key},Info}). + asn1ct_table:new_reuse(asn1_general, [named_table]), + asn1ct_table:insert(asn1_general, {{asn1_config, Key}, Info}). read_config_data(Key) -> - case ets:info(asn1_general) of - undefined -> undefined; - _ -> - case ets:lookup(asn1_general,{asn1_config,Key}) of + case asn1ct_table:exists(asn1_general) of + false -> undefined; + true -> + case asn1ct_table:lookup(asn1_general,{asn1_config,Key}) of [{_,Data}] -> Data; Err -> % Err is [] when nothing was saved in the ets table %% io:format("strange data from config file ~w~n",[Err]), diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 105fc02819..3facd3f0ee 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. 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 @@ -94,8 +94,8 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used %% table to save instances of parameterized objects,object sets - asn1ct:create_ets_table(parameterized_objects,[named_table]), - asn1ct:create_ets_table(inlined_objects,[named_table]), + asn1ct_table:new(parameterized_objects, [named_table]), + asn1ct_table:new(inlined_objects, [named_table]), Terror = checkt(S,Types,[]), @@ -144,17 +144,17 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> NewObjectSets, [],[],[]), ?dbg("checko finished with errors:~n~p~n~n",[Oerror]), - InlinedObjTuples = ets:tab2list(inlined_objects), + InlinedObjTuples = asn1ct_table:to_list(inlined_objects), InlinedObjects = lists:map(Element2,InlinedObjTuples), - ets:delete(inlined_objects), - ParameterizedElems = ets:tab2list(parameterized_objects), + asn1ct_table:delete(inlined_objects), + ParameterizedElems = asn1ct_table:to_list(parameterized_objects), ParObjectSets = lists:filter(fun({_OSName,objectset,_}) -> true; (_)-> false end,ParameterizedElems), ParObjectSetNames = lists:map(Element1,ParObjectSets), ParTypes = lists:filter(fun({_TypeName,type,_}) -> true; (_) -> false end, ParameterizedElems), ParTypesNames = lists:map(Element1,ParTypes), - ets:delete(parameterized_objects), + asn1ct_table:delete(parameterized_objects), put(asn1_reference,undefined), Exporterror = check_exports(S,S#state.module), @@ -5116,16 +5116,16 @@ renamed_reference(S,#'Externaltypereference'{type=Name,module=Module}) -> renamed_reference(S,Name,Module) -> %% first check if there is a renamed type in this module %% second check if any type was imported with this name - case ets:info(renamed_defs) of - undefined -> undefined; - _ -> - case ets:match(renamed_defs,{'$1',Name,Module}) of + case asn1ct_table:exists(renamed_defs) of + false -> undefined; + true -> + case asn1ct_table:match(renamed_defs, {'$1',Name,Module}) of [] -> - case ets:info(original_imports) of - undefined -> + case asn1ct_table:exists(original_imports) of + false -> undefined; - _ -> - case ets:match(original_imports,{Module,'$1'}) of + true -> + case asn1ct_table:match(original_imports, {Module,'$1'}) of [] -> undefined; [[ImportsList]] -> @@ -6005,17 +6005,12 @@ tag_nums_root2([],Ext,Root2) -> [0,Ext,Root2]. is_automatic_tagged_in_multi_file(Name) -> - case ets:info(automatic_tags) of - undefined -> + case asn1ct_table:exists(automatic_tags) of + false -> %% this case when not multifile compilation false; - _ -> -% case ets:member(automatic_tags,Name) of - case ets:lookup(automatic_tags,Name) of -% true -> -% true; -% _ -> -% false + true -> + case asn1ct_table:lookup(automatic_tags, Name) of [] -> false; _ -> true end diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 0f8833f716..fda4e1c6d9 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. 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 @@ -169,7 +169,7 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) -> pgen_objectsets(Rtmod,Erules,Module,T). pgen_check_defaultval(Erules,Module) -> - CheckObjects = ets:tab2list(check_functions), + CheckObjects = asn1ct_table:to_list(check_functions), case get(asndebug) of true -> FileName = lists:concat([Module,".table"]), @@ -1598,7 +1598,7 @@ gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) -> NameList = [Cname|TopType], Name = list2name(NameList ++ [check]), emit({"'",Name,"'(",DefaultValue,", ",Element,")"}), - ets:insert(check_functions,{Name,Type}), + asn1ct_table:insert(check_functions, {Name, Type}), %% Must look for check functions in InnerType, %% that may be referenced or internal defined %% constructed types not used elsewhere. @@ -1744,10 +1744,9 @@ lookahead_reference(#'Externaltypereference'{module=M,type=T}) -> end. insert_once(Table,Object) -> - _Info = ets:info(Table), - case ets:lookup(Table,element(1,Object)) of + case asn1ct_table:lookup(Table, element(1, Object)) of [] -> - ets:insert(Table,Object); %returns true + asn1ct_table:insert(Table, Object); %returns true _ -> false end. diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 365bb84d52..597fb0030b 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. +%% Copyright Ericsson AB 2002-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 @@ -1834,7 +1834,7 @@ mk_object_val(Val, Ack, Len) -> mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1). add_func(F={_Func,_Arity}) -> - ets:insert(asn1_functab,{F}). + asn1ct_table:insert(asn1_functab, {F}). %% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding %% and therefore we only filter away the ExtensionAdditionGroup start and end markers diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl new file mode 100644 index 0000000000..b7ae1d7105 --- /dev/null +++ b/lib/asn1/src/asn1ct_table.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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(asn1ct_table). + +%% Table abstraction module for ASN.1 compiler + +-export([new/2]). +-export([new_reuse/2]). +-export([exists/1]). +-export([size/1]). +-export([insert/2]). +-export([lookup/2]). +-export([match/2]). +-export([to_list/1]). +-export([delete/1]). % TODO: Remove (since we run in a separate process) + + +%% Always creates a new table +new(Table, Options) -> + case ets:info(Table) of + undefined -> + ets:new(Table, Options); + _ -> + delete(Table), + ets:new(Table, Options) + end. + +new_reuse(Table, Options) -> + not exists(Table) andalso new(Table, Options). + +exists(Table) -> ets:info(Table) =/= undefined. + +size(Table) -> ets:info(Table, size). + +insert(Table, Tuple) -> ets:insert(Table, Tuple). + +lookup(Table, Key) -> ets:lookup(Table, Key). + +match(Table, MatchSpec) -> ets:match(Table, MatchSpec). + +to_list(Table) -> ets:tab2list(Table). + +delete(Tables) when is_list(Tables) -> + [delete(T) || T <- Tables], + true; +delete(Table) when is_atom(Table) -> + exists(Table) andalso ets:delete(Table). diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl index c3797f08b2..2c31c3259d 100644 --- a/lib/asn1/test/asn1_app_test.erl +++ b/lib/asn1/test/asn1_app_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-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 @@ -138,7 +138,7 @@ check_asn1ct_modules(Extra) -> asn1ct_name,asn1ct_constructed_per,asn1ct_constructed_ber, asn1ct_gen_ber,asn1ct_constructed_ber_bin_v2, asn1ct_gen_ber_bin_v2,asn1ct_value, - asn1ct_tok,asn1ct_parser2], + asn1ct_tok,asn1ct_parser2,asn1ct_table], case Extra -- ASN1CTMods of [] -> ok; -- cgit v1.2.3