mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
Use yconf validator for custom Mnesia schemas
This commit is contained in:
parent
39cf8d86d6
commit
6011135d24
@ -45,8 +45,15 @@
|
||||
-include("logger.hrl").
|
||||
-include("ejabberd_stacktrace.hrl").
|
||||
|
||||
-record(state, {tables = #{} :: map(),
|
||||
schema = [] :: [{atom(), [{atom(), any()}]}]}).
|
||||
-record(state, {tables = #{} :: tables(),
|
||||
schema = [] :: [{atom(), custom_schema()}]}).
|
||||
|
||||
-type tables() :: #{atom() => {[{atom(), term()}], term()}}.
|
||||
-type custom_schema() :: [{ram_copies | disc_copies | disc_only_copies, [node()]} |
|
||||
{local_content, boolean()} |
|
||||
{type, set | ordered_set | bag} |
|
||||
{attributes, [atom()]} |
|
||||
{index, [atom()]}].
|
||||
|
||||
start() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
@ -201,79 +208,51 @@ schema(Name, Default, Schema) ->
|
||||
[Name, TabDefs]),
|
||||
TabDefs;
|
||||
false ->
|
||||
?DEBUG("No custom Mnesia schema for table '~s' found",
|
||||
[Name]),
|
||||
Default
|
||||
end.
|
||||
|
||||
-spec read_schema_file() -> [{atom(), custom_schema()}].
|
||||
read_schema_file() ->
|
||||
File = schema_path(),
|
||||
case fast_yaml:decode_from_file(File, [plain_as_atom]) of
|
||||
{ok, [Defs|_]} ->
|
||||
?INFO_MSG("Using custom Mnesia schema from ~s", [File]),
|
||||
lists:flatmap(
|
||||
fun({Tab, Opts}) ->
|
||||
case validate_schema_opts(File, Opts) of
|
||||
{ok, NewOpts} ->
|
||||
[{Tab, lists:ukeysort(1, NewOpts)}];
|
||||
error ->
|
||||
[]
|
||||
end
|
||||
end, Defs);
|
||||
{ok, Y} ->
|
||||
case econf:validate(validator(), lists:flatten(Y)) of
|
||||
{ok, []} ->
|
||||
?WARNING_MSG("Mnesia schema file ~s is empty", [File]),
|
||||
[];
|
||||
{ok, Config} ->
|
||||
lists:map(
|
||||
fun({Tab, Opts}) ->
|
||||
{Tab, lists:map(
|
||||
fun({storage_type, T}) -> {T, [node()]};
|
||||
(Other) -> Other
|
||||
end, Opts)}
|
||||
end, Config);
|
||||
{error, Reason, Ctx} ->
|
||||
?ERROR_MSG("Failed to read Mnesia schema from ~s: ~s",
|
||||
[File, econf:format_error(Reason, Ctx)]),
|
||||
[]
|
||||
end;
|
||||
{error, enoent} ->
|
||||
?DEBUG("No custom Mnesia schema file found", []),
|
||||
?DEBUG("No custom Mnesia schema file found at ~s", [File]),
|
||||
[];
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("Failed to read Mnesia schema file ~s: ~s",
|
||||
[File, fast_yaml:format_error(Reason)]),
|
||||
[]
|
||||
[File, fast_yaml:format_error(Reason)])
|
||||
end.
|
||||
|
||||
validate_schema_opts(File, Opts) ->
|
||||
try {ok, lists:map(
|
||||
fun({storage_type, Type}) when Type == ram_copies;
|
||||
Type == disc_copies;
|
||||
Type == disc_only_copies ->
|
||||
{Type, [node()]};
|
||||
({storage_type, _} = Opt) ->
|
||||
erlang:error({invalid_value, Opt});
|
||||
({local_content, Bool}) when is_boolean(Bool) ->
|
||||
{local_content, Bool};
|
||||
({local_content, _} = Opt) ->
|
||||
erlang:error({invalid_value, Opt});
|
||||
({type, Type}) when Type == set;
|
||||
Type == ordered_set;
|
||||
Type == bag ->
|
||||
{type, Type};
|
||||
({type, _} = Opt) ->
|
||||
erlang:error({invalid_value, Opt});
|
||||
({attributes, Attrs} = Opt) ->
|
||||
try lists:all(fun is_atom/1, Attrs) of
|
||||
true -> {attributes, Attrs};
|
||||
false -> erlang:error({invalid_value, Opt})
|
||||
catch _:_ -> erlang:error({invalid_value, Opt})
|
||||
end;
|
||||
({index, Indexes} = Opt) ->
|
||||
try lists:all(fun is_atom/1, Indexes) of
|
||||
true -> {index, Indexes};
|
||||
false -> erlang:error({invalid_value, Opt})
|
||||
catch _:_ -> erlang:error({invalid_value, Opt})
|
||||
end;
|
||||
(Opt) ->
|
||||
erlang:error({unknown_option, Opt})
|
||||
end, Opts)}
|
||||
catch _:{invalid_value, {Opt, Val}} ->
|
||||
?ERROR_MSG("Mnesia schema ~s is incorrect: invalid value ~p of "
|
||||
"option '~s'", [File, Val, Opt]),
|
||||
error;
|
||||
_:{unknown_option, Opt} ->
|
||||
?ERROR_MSG("Mnesia schema ~s is incorrect: unknown option ~p",
|
||||
[File, Opt]),
|
||||
error
|
||||
end.
|
||||
-spec validator() -> econf:validator().
|
||||
validator() ->
|
||||
econf:map(
|
||||
econf:atom(),
|
||||
econf:options(
|
||||
#{storage_type => econf:enum([ram_copies, disc_copies, disc_only_copies]),
|
||||
local_content => econf:bool(),
|
||||
type => econf:enum([set, ordered_set, bag]),
|
||||
attributes => econf:list(econf:atom()),
|
||||
index => econf:list(econf:atom())},
|
||||
[{return, orddict}, unique]),
|
||||
[unique]).
|
||||
|
||||
create(Name, TabDef) ->
|
||||
?INFO_MSG("Creating Mnesia table '~s'", [Name]),
|
||||
|
Loading…
Reference in New Issue
Block a user