25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-22 17:28:25 +01:00

Improve check of mnesia schema opearations

This commit is contained in:
Christophe Romain 2017-01-18 16:53:36 +01:00
parent ba47fd4649
commit 3029e84faf

View File

@ -35,12 +35,16 @@
-define(STORAGE_TYPES, [disc_copies, disc_only_copies, ram_copies]). -define(STORAGE_TYPES, [disc_copies, disc_only_copies, ram_copies]).
-define(NEED_RESET, [local_content, type]). -define(NEED_RESET, [local_content, type]).
create(Module, Name, TabDef) -> -include("logger.hrl").
Schema = schema(Module, Name, TabDef),
create(Module, Name, TabDef)
when is_atom(Module), is_atom(Name), is_list(TabDef) ->
Path = os:getenv("EJABBERD_SCHEMA_PATH"),
Schema = schema(Path, Module, Name, TabDef),
{attributes, Attrs} = lists:keyfind(attributes, 1, Schema), {attributes, Attrs} = lists:keyfind(attributes, 1, Schema),
case catch mnesia:table_info(Name, attributes) of case catch mnesia:table_info(Name, attributes) of
{'EXIT', _} -> {'EXIT', _} ->
mnesia:create_table(Name, Schema); mnesia_op(create, [Name, TabDef]);
Attrs -> Attrs ->
case need_reset(TabDef, Schema) of case need_reset(TabDef, Schema) of
true -> reset(Name, Schema); true -> reset(Name, Schema);
@ -51,18 +55,23 @@ create(Module, Name, TabDef) ->
true -> fun(Old) -> Module:transform(Old) end; true -> fun(Old) -> Module:transform(Old) end;
false -> fun(Old) -> transform(OldAttrs, Attrs, Old) end false -> fun(Old) -> transform(OldAttrs, Attrs, Old) end
end, end,
mnesia:transform_table(Name, Fun, Attrs) mnesia_op(transform_table, [Name, Fun, Attrs])
end. end.
reset(Name, TabDef) -> reset(Name, TabDef)
mnesia:delete_table(Name), when is_atom(Name), is_list(TabDef) ->
ejabberd_mnesia:create(?MODULE, Name, TabDef). mnesia_op(delete_table, [Name]),
mnesia_op(create, [Name, TabDef]).
update(Name, TabDef) -> update(Name, TabDef)
when is_atom(Name), is_list(TabDef) ->
{attributes, Attrs} = lists:keyfind(attributes, 1, TabDef), {attributes, Attrs} = lists:keyfind(attributes, 1, TabDef),
update(Name, Attrs, TabDef). update(Name, Attrs, TabDef).
update(Name, Attrs, TabDef) -> update(Name, Attrs, TabDef) ->
Storage = mnesia:table_info(Name, storage_type), Storage = case catch mnesia:table_info(Name, storage_type) of
{'EXIT', _} -> unknown;
Type -> Type
end,
NewStorage = lists:foldl( NewStorage = lists:foldl(
fun({Key, _}, Acc) -> fun({Key, _}, Acc) ->
case lists:member(Key, ?STORAGE_TYPES) of case lists:member(Key, ?STORAGE_TYPES) of
@ -70,35 +79,42 @@ update(Name, Attrs, TabDef) ->
false -> Acc false -> Acc
end end
end, Storage, TabDef), end, Storage, TabDef),
R1 = if Storage=/=NewStorage -> R1 = [mnesia_op(change_table_copy_type, [Name, node(), NewStorage])
mnesia:change_table_copy_type(Name, node(), NewStorage); || Storage=/=NewStorage],
true ->
{atomic, ok}
end,
CurIndexes = [lists:nth(N-1, Attrs) || N<-mnesia:table_info(Name, index)], CurIndexes = [lists:nth(N-1, Attrs) || N<-mnesia:table_info(Name, index)],
NewIndexes = proplists:get_value(index, TabDef, []), NewIndexes = proplists:get_value(index, TabDef, []),
[mnesia:del_table_index(Name, Attr) R2 = [mnesia_op(del_table_index, [Name, Attr])
|| Attr <- CurIndexes--NewIndexes], || Attr <- CurIndexes--NewIndexes],
R2 = [mnesia:add_table_index(Name, Attr) R3 = [mnesia_op(add_table_index, [Name, Attr])
|| Attr <- NewIndexes--CurIndexes], || Attr <- NewIndexes--CurIndexes],
lists:foldl( lists:foldl(
fun({atomic, ok}, Acc) -> Acc; fun({atomic, ok}, Acc) -> Acc;
(Error, _Acc) -> Error (Error, _Acc) -> Error
end, {atomic, ok}, [R1|R2]). end, {atomic, ok}, R1++R2++R3).
% %
% utilities % utilities
% %
schema(Module, Name, TabDef) -> schema(false, Module, _Name, TabDef) ->
case parse(Module) of ?DEBUG("No custom ~s schema path", [Module]),
TabDef;
schema(Path, Module, Name, TabDef) ->
File = filename:join(Path, atom_to_list(Module)++".mnesia"),
case parse(File) of
{ok, CustomDefs} -> {ok, CustomDefs} ->
case lists:keyfind(Name, 1, CustomDefs) of case lists:keyfind(Name, 1, CustomDefs) of
{Name, CustomDef} -> merge(TabDef, CustomDef); {Name, CustomDef} ->
_ -> TabDef ?INFO_MSG("Using custom ~s schema for table ~s",
end; [Module, Name]),
merge(TabDef, CustomDef);
_ -> _ ->
TabDef TabDef
end;
{error, Error} ->
?ERROR_MSG("Can not use custom ~s schema for table ~s: ~p",
[Module, Name, Error]),
TabDef
end. end.
merge(TabDef, CustomDef) -> merge(TabDef, CustomDef) ->
@ -119,24 +135,15 @@ merge(TabDef, CustomDef) ->
lists:ukeysort(1, CustomDef), lists:ukeysort(1, CustomDef),
lists:ukeysort(1, CleanDef)). lists:ukeysort(1, CleanDef)).
parse(Module) -> parse(File) ->
case os:getenv("EJABBERD_SCHEMA_PATH") of
false ->
{error, undefined};
Path ->
File = filename:join(Path, atom_to_list(Module)++".mnesia"),
case file:consult(File) of case file:consult(File) of
{ok, Terms} -> parse(Terms, []); {ok, Terms} -> parse(Terms, []);
Error -> Error Error -> Error
end
end. end.
parse([], Acc) -> parse([], Acc) ->
{ok, lists:reverse(Acc)}; {ok, lists:reverse(Acc)};
parse([{Name, Storage, TabDef}|Tail], Acc) parse([{Name, Storage, TabDef}|Tail], Acc)
when is_atom(Name), when is_atom(Name), is_atom(Storage), is_list(TabDef) ->
is_atom(Storage),
is_list(TabDef) ->
NewDef = case lists:member(Storage, ?STORAGE_TYPES) of NewDef = case lists:member(Storage, ?STORAGE_TYPES) of
true -> [{Storage, [node()]} | TabDef]; true -> [{Storage, [node()]} | TabDef];
false -> TabDef false -> TabDef
@ -166,3 +173,13 @@ transform(OldAttrs, Attrs, Old) ->
end, [], lists:reverse(Attrs)), end, [], lists:reverse(Attrs)),
{Attrs, NewRecord} = lists:unzip(After), {Attrs, NewRecord} = lists:unzip(After),
list_to_tuple([Name|NewRecord]). list_to_tuple([Name|NewRecord]).
mnesia_op(Fun, Args) ->
case apply(mnesia, Fun, Args) of
{atomic, ok} ->
{atomic, ok};
Other ->
?ERROR_MSG("failure on mnesia ~s ~p: ~p",
[Fun, Args, Other]),
Other
end.