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:
parent
ba47fd4649
commit
3029e84faf
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user