aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2011-12-03 17:53:15 +0100
committerAnders Svensson <[email protected]>2011-12-04 17:47:48 +0100
commit22f9111ef12ed58aeb5a15ed55a983c9b19cddb8 (patch)
treed20531044fc7ffabb4155a94d4c11c093bc24ea1
parent23dbc347fe872f953d0f146ecb87ddc34ea608d7 (diff)
downloadotp-22f9111ef12ed58aeb5a15ed55a983c9b19cddb8.tar.gz
otp-22f9111ef12ed58aeb5a15ed55a983c9b19cddb8.tar.bz2
otp-22f9111ef12ed58aeb5a15ed55a983c9b19cddb8.zip
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.
-rw-r--r--lib/diameter/src/compiler/diameter_dict_util.erl91
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl18
2 files changed, 34 insertions, 75 deletions
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 ::=",
"<XXX> &"},
- {beam_not_on_path,
+ {not_loaded,
[{"@avp_types", "@inherits nomod XXX &"},
{"CEA ::=", "<XXX> &"}]},
{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),