kvs_mnesia.erl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. -module(kvs_mnesia).
  2. -include("backend.hrl").
  3. -include("kvs.hrl").
  4. -include("metainfo.hrl").
  5. -include_lib("mnesia/src/mnesia.hrl").
  6. -include_lib("stdlib/include/qlc.hrl").
  7. -export(?BACKEND).
  8. -export([info/1,exec/1,dump/1]).
  9. db() -> "".
  10. seq_pad() -> application:get_env(kvs, seq_pad, []).
  11. start() -> mnesia:start().
  12. stop() -> mnesia:stop().
  13. destroy() -> [mnesia:delete_table(T)||{_,T}<-kvs:dir()], mnesia:delete_schema([node()]), ok.
  14. destroy(_) -> [mnesia:delete_table(T)||{_,T}<-kvs:dir()], mnesia:delete_schema([node()]), ok.
  15. leave() -> ok.
  16. leave(_) -> ok.
  17. version() -> {version,"KVS MNESIA"}.
  18. dir() -> [{table,T}||T<-mnesia:system_info(local_tables)].
  19. join([], _) -> mnesia:start(), mnesia:change_table_copy_type(schema, node(), disc_copies), initialize();
  20. join(Node, _) ->
  21. mnesia:start(),
  22. mnesia:change_config(extra_db_nodes, [Node]),
  23. mnesia:change_table_copy_type(schema, node(), disc_copies),
  24. [{Tb, mnesia:add_table_copy(Tb, node(), Type)}
  25. || {Tb, [{N, Type}]} <- [{T, mnesia:table_info(T, where_to_commit)}
  26. || T <- mnesia:system_info(tables)], Node==N].
  27. initialize() ->
  28. mnesia:create_schema([node()]),
  29. Res = [ kvs:initialize(kvs_mnesia,Module) || Module <- kvs:modules() ],
  30. mnesia:wait_for_tables([ T#table.name || T <- kvs:tables()],infinity),
  31. Res.
  32. index(Tab,Key,Value) ->
  33. lists:flatten(many(fun() -> mnesia:index_read(Tab,Value,Key) end)).
  34. keys(Tab,_) -> mnesia:all_keys(Tab).
  35. key_match(_Tab,_Id,_) -> [].
  36. get(RecordName, Key, _) -> just_one(fun() -> mnesia:read(RecordName, Key) end).
  37. put(R) -> put(R,db()).
  38. put(Records, _) when is_list(Records) -> void(fun() -> lists:foreach(fun mnesia:write/1, Records) end);
  39. put(Record, X) -> put([Record], X).
  40. delete(Tab, Key, _) ->
  41. case mnesia:activity(context(),fun()-> mnesia:delete({Tab, Key}) end) of
  42. {aborted,Reason} -> {error,Reason};
  43. {atomic,_Result} -> ok;
  44. _ -> ok end.
  45. delete_range(_,_,_) -> {error, not_found}.
  46. match(Record) -> lists:flatten(many(fun() -> mnesia:match_object(Record) end)).
  47. index_match(Record, Index) -> lists:flatten(many(fun() -> mnesia:index_match_object(Record, Index) end)).
  48. count(RecordName) -> mnesia:table_info(RecordName, size).
  49. all(R, _) -> lists:flatten(many(fun() -> L= mnesia:all_keys(R), [ mnesia:read({R, G}) || G <- L ] end)).
  50. seq(RecordName, []) -> seq(RecordName, 1);
  51. seq(RecordName, Incr) ->
  52. Val = integer_to_list(mnesia:dirty_update_counter({id_seq, RecordName}, Incr)),
  53. case (20 - length(Val) > 0) and lists:member(RecordName, seq_pad()) of true -> string:copies("0", 20 - length(Val)); _ -> "" end ++ Val.
  54. many(Fun) -> case mnesia:activity(context(),Fun) of {atomic, [R]} -> R; {aborted, Error} -> {error, Error}; X -> X end.
  55. void(Fun) -> case mnesia:activity(context(),Fun) of {atomic, ok} -> ok; {aborted, Error} -> {error, Error}; X -> X end.
  56. info(T) -> try mnesia:table_info(T,all) catch _:_ -> [] end.
  57. create_table(Name,Options) -> mnesia:create_table(Name, Options).
  58. add_table_index(Record, Field) -> mnesia:add_table_index(Record, Field).
  59. exec(Q) -> F = fun() -> qlc:e(Q) end, {atomic, Val} = mnesia:activity(context(),F), Val.
  60. just_one(Fun) ->
  61. case mnesia:activity(context(),Fun) of
  62. {atomic, []} -> {error, not_found};
  63. {atomic, [R]} -> {ok, R};
  64. [] -> {error, not_found};
  65. [R] -> {ok,R};
  66. R when is_list(R) -> {ok,R};
  67. Error -> Error end.
  68. context() -> application:get_env(kvs,mnesia_context,async_dirty).
  69. dump() -> dump([ N || #table{name=N} <- kvs:tables() ]), ok.
  70. dump(short) ->
  71. Gen = fun(T) ->
  72. {S,M,C}=lists:unzip3([ dump_info(R) || R <- T ]),
  73. {lists:usort(S),lists:sum(M),lists:sum(C)}
  74. end,
  75. dump_format([ {T,Gen(T)} || T <- [ N || #table{name=N} <- kvs:tables() ] ]);
  76. dump(Table) when is_atom(Table) -> dump(Table);
  77. dump(Tables) ->
  78. dump_format([{T,dump_info(T)} || T <- lists:flatten(Tables) ]).
  79. dump_info(T) ->
  80. {mnesia:table_info(T,storage_type),
  81. mnesia:table_info(T,memory) * erlang:system_info(wordsize) / 1024 / 1024,
  82. mnesia:table_info(T,size)}.
  83. dump_format(List) ->
  84. io:format("~20s ~32s ~14s ~10s~n~n",["NAME","STORAGE TYPE","MEMORY (MB)","ELEMENTS"]),
  85. [ io:format("~20s ~32w ~14.2f ~10b~n",[T,S,M,C]) || {T,{S,M,C}} <- List ],
  86. io:format("~nSnapshot taken: ~p~n",[calendar:now_to_datetime(os:timestamp())]).