From 22f9111ef12ed58aeb5a15ed55a983c9b19cddb8 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sat, 3 Dec 2011 17:53:15 +0100 Subject: Don't explicitly load inherited modules Just use include options to add to the code path and expect that dependent modules will either already have been loaded or will be loaded dynamically, thereby avoiding having a module being left as both current and old code when compiling concurrently. Not a problem for a human user interactively compiling one module at a time but the compiler test suite for one will compile concurrently. In any case, leaving behind old code is probably not what someone would expect while relying on the code path probably is. --- lib/diameter/src/compiler/diameter_dict_util.erl | 91 ++++++++---------------- lib/diameter/test/diameter_compiler_SUITE.erl | 18 +---- 2 files changed, 34 insertions(+), 75 deletions(-) (limited to 'lib') diff --git a/lib/diameter/src/compiler/diameter_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl index 51a3091883..201b153f0f 100644 --- a/lib/diameter/src/compiler/diameter_dict_util.erl +++ b/lib/diameter/src/compiler/diameter_dict_util.erl @@ -51,14 +51,14 @@ Opts :: list(). parse(File, Opts) -> - put({?MODULE, verbose}, lists:member(verbose, Opts)), + putr(verbose, lists:member(verbose, Opts)), try {ok, do_parse(File, Opts)} catch {Reason, ?MODULE, _Line} -> {error, Reason} after - erase({?MODULE, verbose}) + eraser(verbose) end. %% =========================================================================== @@ -174,12 +174,11 @@ fmt(enumerated_avp_not_defined) -> fmt(avp_not_defined) -> "AVP ~s referenced at line ~p neither defined nor inherited"; -fmt(beam_not_on_path) -> - "Module ~s not found"; - fmt(recompile) -> "Module ~p appears to have been compiler with an incompatible " "version of the dictionary compiler and must be recompiled"; +fmt(not_loaded) -> + "Module ~p is not on the code path or could not be loaded"; fmt(no_dict) -> "Module ~p does not appear to be a diameter dictionary". @@ -234,8 +233,8 @@ io(K, Id) K == prefix -> [?NL, section(K), ?SP, tok(Id)]; -io(vendor, {Id, Name}) -> - [?NL, section(vendor) | [[?SP, tok(X)] || X <- [Id, Name]]]; +io(vendor = K, {Id, Name}) -> + [?NL, section(K) | [[?SP, tok(X)] || X <- [Id, Name]]]; io(avp_types = K, Body) -> [?NL, ?NL, section(K), ?NL, [body(K,A) || A <- Body]]; @@ -252,11 +251,7 @@ io(K, Body) K == codecs; K == enum; K == define -> - if [] == Body -> - []; - true -> - [[?NL, pairs(K, T)] || T <- Body] - end. + [[?NL, pairs(K, T)] || T <- Body]. pairs(K, {Id, Avps}) -> [?NL, section(K), ?SP, tok(Id), ?NL, [[?NL, body(K, A)] || A <- Avps]]. @@ -510,7 +505,7 @@ report(What, [F | A]) when is_function(F) -> report(What, apply(F, A)); report(What, Data) -> - report(get({?MODULE, verbose}), What, Data). + report(getr(verbose), What, Data). report(true, Tag, Data) -> io:format("##~n## ~p ~p~n", [Tag, Data]); @@ -1114,18 +1109,16 @@ import_key({Mod, Avps}, Key) -> %% name, Line points to the corresponding @inherit and each Avp is %% from Mod:dict(). Lineno is 0 if the import is implicit. -inherit(Dict, Options) -> - Path = [D || {include, D} <- Options] - ++ [".", code:lib_dir(diameter, ebin)], - foldl([fun find_avps/3, Path], [], find(inherits, Dict)). +inherit(Dict, Opts) -> + code:add_pathsa([D || {include, D} <- Opts]), + foldl(fun inherit_avps/2, [], find(inherits, Dict)). %% Note that the module order of the returned lists is reversed %% relative to @inherits. -find_avps([Line, {_,_,M} | Names], Acc, Path) -> +inherit_avps([Line, {_,_,M} | Names], Acc) -> Mod = ?A(M), report(inherit_from, Mod), - Avps = avps_from_beam(find_beam(Mod, Path), Mod), %% could be empty - case find_avps(Names, Avps) of + case find_avps(Names, avps_from_module(Mod)) of {_, [{_, L, N} | _]} -> ?RETURN(requested_avp_not_found, [Mod, Line, N, L]); {Found, []} -> @@ -1138,9 +1131,9 @@ find_avps([], Avps) -> %% ... or specified AVPs. find_avps(Names, Avps) -> - foldl(fun fa/2, {[], Names}, Avps). + foldl(fun acc_avp/2, {[], Names}, Avps). -fa({Name, _Code, _Type, _Flags} = A, {Found, Not} = Acc) -> +acc_avp({Name, _Code, _Type, _Flags} = A, {Found, Not} = Acc) -> case lists:keyfind(Name, 3, Not) of {_, Line, Name} -> {[{Line, A} | Found], lists:keydelete(Name, 3, Not)}; @@ -1148,45 +1141,11 @@ fa({Name, _Code, _Type, _Flags} = A, {Found, Not} = Acc) -> Acc end. -%% find_beam/2 +%% avps_from_module/2 -find_beam(Mod, Dirs) - when is_atom(Mod) -> - find_beam(atom_to_list(Mod), Dirs); -find_beam(Mod, Dirs) -> - Beam = Mod ++ code:objfile_extension(), - case try_path(Dirs, Beam) of - {value, Path} -> - Path; - false -> - ?RETURN(beam_not_on_path, [Mod]) - end. - -try_path([D|Ds], Fname) -> - Path = filename:join(D, Fname), - case file:read_file_info(Path) of - {ok, _} -> - {value, Path}; - _ -> - try_path(Ds, Fname) - end; -try_path([], _) -> - false. - -%% avps_from_beam/2 - -avps_from_beam(Path, Mod) -> - report(beam, Path), - ok = load_module(code:is_loaded(Mod), Mod, Path), +avps_from_module(Mod) -> orddict:fetch(avp_types, dict(Mod)). -load_module(false, Mod, Path) -> - R = filename:rootname(Path, code:objfile_extension()), - {module, Mod} = code:load_abs(R), - ok; -load_module({file, _}, _, _) -> - ok. - dict(Mod) -> try Mod:dict() of [?VERSION | Dict] -> @@ -1194,8 +1153,11 @@ dict(Mod) -> _ -> ?RETURN(recompile, [Mod]) catch - error:_ -> - ?RETURN(no_dict, [Mod]) + error: _ -> + ?RETURN(choose(false == code:is_loaded(Mod), + not_loaded, + no_dict), + [Mod]) end. %% =========================================================================== @@ -1260,6 +1222,15 @@ avp_is_defined(Name, Dict, Line) -> %% =========================================================================== +putr(Key, Value) -> + put({?MODULE, Key}, Value). + +getr(Key) -> + get({?MODULE, Key}). + +eraser(Key) -> + erase({?MODULE, Key}). + choose(true, X, _) -> X; choose(false, _, X) -> X. diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl index c4de6e4f85..e2f4b3c931 100644 --- a/lib/diameter/test/diameter_compiler_SUITE.erl +++ b/lib/diameter/test/diameter_compiler_SUITE.erl @@ -30,8 +30,7 @@ end_per_suite/1]). %% testcases --export([base/1, - format/1, +-export([format/1, replace/1, replace/2]). -export([dict/0]). %% fake dictionary module @@ -167,7 +166,7 @@ {avp_not_defined, "CEA ::=", " &"}, - {beam_not_on_path, + {not_loaded, [{"@avp_types", "@inherits nomod XXX &"}, {"CEA ::=", " &"}]}, {recompile, @@ -201,8 +200,7 @@ suite() -> [{timetrap, {seconds, 5}}]. all() -> - [base, - format, + [format, replace]. %% Error handling testcases will make an erroneous dictionary out of @@ -219,16 +217,6 @@ end_per_suite(_Config) -> %% =========================================================================== %% testcases -%% base/1 - -%% This work around a minor deficiency in diameter_dict_util, that it -%% does deal well with compiling in parallel. Load the dictionary -%% ahead of time so that compilation doesn't. -base(_Config) -> - Base = filename:join([code:lib_dir(diameter, ebin), - "diameter_gen_base_rfc3588"]), - {module, _} = code:load_abs(Base). - %% Ensure that parse o format is the identity map. format(Config) -> Bin = proplists:get_value(base, Config), -- cgit v1.2.3