Maxim Sokhatsky 12 лет назад
Родитель
Сommit
5f12bed983
1 измененных файлов с 140 добавлено и 0 удалено
  1. 140 0
      src/store_mnesia.erl

+ 140 - 0
src/store_mnesia.erl

@@ -0,0 +1,140 @@
+-module(store_mnesia).
+-author('Maxim Sokhatsky').
+-copyright('Synrc Research Center s.r.o.').
+-include_lib("kvs/include/config.hrl").
+-include_lib("kvs/include/users.hrl").
+-include_lib("kvs/include/groups.hrl").
+-include_lib("kvs/include/feeds.hrl").
+-include_lib("kvs/include/acls.hrl").
+-include_lib("kvs/include/invites.hrl").
+-include_lib("kvs/include/meetings.hrl").
+-include_lib("kvs/include/membership.hrl").
+-include_lib("kvs/include/payments.hrl").
+-include_lib("kvs/include/purchases.hrl").
+-include_lib("kvs/include/accounts.hrl").
+-include_lib("kvs/include/log.hrl").
+-include_lib("kvs/include/translations.hrl").
+-include_lib("stdlib/include/qlc.hrl").
+-compile(export_all).
+-define(CREATE_TAB(T), create_table(T, record_info(fields, T), [{storage, permanent}]) ).
+
+start() -> mnesia:start(), mnesia:change_table_copy_type(schema, node(), disc_copies).
+stop() -> mnesia:stop().
+delete() -> mnesia:delete_schema([node()]).
+initialize() ->
+    mnesia:create_schema([node()]),
+    ?CREATE_TAB(payment),
+    ?CREATE_TAB(acl),
+    ?CREATE_TAB(acl_entry),
+    ?CREATE_TAB(feed),
+    ?CREATE_TAB(team),
+    ?CREATE_TAB(entry),
+    ?CREATE_TAB(comment),
+    ?CREATE_TAB(user),
+    ?CREATE_TAB(user_product),
+    ?CREATE_TAB(user_payment),
+    ?CREATE_TAB(user_status),
+    ?CREATE_TAB(membership),
+    ?CREATE_TAB(account),
+    ?CREATE_TAB(subscription),
+    ?CREATE_TAB(group_subscription),
+    ?CREATE_TAB(group),
+    ?CREATE_TAB(id_seq),
+    ?CREATE_TAB(transaction),
+    ?CREATE_TAB(translation),
+    ok = add_table_index(comment, entry_id),
+    ok = add_table_index(entry, feed_id),
+    ok = add_table_index(entry, entry_id),
+    ok = add_table_index(entry, from),
+    ok = add_table_index(user, facebook_id),
+    ok = add_table_index(user, email),
+    ok.
+
+dir() ->
+    Tables = mnesia:system_info(local_tables),
+    [{table,atom_to_list(T)}||T<-Tables].
+get(RecordName, Key) -> just_one(fun() -> mnesia:read(RecordName, Key) end).
+put(Records) when is_list(Records) -> void(fun() -> lists:foreach(fun mnesia:write/1, Records) end);
+put(Record) -> put([Record]).
+
+delete(Keys) when is_list(Keys) -> void(fun() -> lists:foreach(fun mnesia:delete_object/1, Keys) end);
+delete(Keys) -> delete([Keys]).
+delete(Tab, Key) -> mnesia:transaction(fun()-> mnesia:delete({Tab, Key}) end), ok.
+
+multi_select(RecordName, Keys) when is_list(Keys) -> flatten(fun() -> [mnesia:read({RecordName, Key}) || Key <- Keys] end).
+
+select(From, PredicateFunction) when is_function(PredicateFunction) -> exec(qlc:q([Record || Record <- mnesia:table(From), apply(PredicateFunction, [Record])]));
+select(From, [{where, Fn}, {order, {Idx, Order}}]) -> exec(qlc:q([R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])]));
+select(From, [{where, Fn}, {order, {Idx, Order}}, {limit, {1, Length}}]) ->
+    {atomic, Recs} = mnesia:transaction(fun()->
+        QC = qlc:cursor(qlc:q(
+            [R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])])),
+        Ret = qlc:eval(qlc:next_answers(QC, Length)),
+        qlc:delete_cursor(QC),
+        Ret
+    end),
+    Recs;
+
+select(From, [{where, Fn}, {order, {Idx, Order}}, {limit, {Offset, Length}}]) ->
+    {atomic, Recs} = mnesia:transaction(fun()->
+        QC = qlc:cursor(qlc:q(
+            [R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])])),
+        qlc:next_answers(QC, Offset - 1),
+        Ret = qlc:eval(qlc:next_answers(QC, Length)),
+        qlc:delete_cursor(QC),
+        Ret
+    end),
+    Recs;
+
+select(RecordName, Key) -> many(fun() -> mnesia:read({RecordName, Key}) end).
+count(RecordName) -> mnesia:table_info(RecordName, size).
+all(RecordName) -> flatten(fun() -> Lists = mnesia:all_keys(RecordName), [ mnesia:read({RecordName, G}) || G <- Lists ] end).
+all_by_index(RecordName,Key,Value) -> flatten(fun() -> Lists = mnesia:all_keys(RecordName), [ mnesia:read({RecordName, G}) || G <- Lists ] end).
+
+next_id(RecordName) -> next_id(RecordName, 1).
+next_id(RecordName, Incr) ->
+    [RecordStr] = io_lib:format("~p",[RecordName]),
+    mnesia:dirty_update_counter({id_seq, RecordStr}, Incr).
+
+just_one(Fun) ->
+    case mnesia:transaction(Fun) of
+        {atomic, []} -> {error, not_found};
+        {atomic, [R]} -> {ok, R};
+        {atomic, [_|_]} -> {error, duplicated};
+        _ -> {error, not_found} end.
+
+flatten(Fun) -> case mnesia:transaction(Fun) of {atomic, R} -> lists:flatten(R); _ -> [] end.
+many(Fun) -> case mnesia:transaction(Fun) of {atomic, R} -> R; _ -> [] end.
+void(Fun) -> case mnesia:transaction(Fun) of {atomic, ok} -> ok; {aborted, Error} -> {error, Error} end.
+
+create_table(Record, RecordInfo,  Opts0) ->
+    Attr = [{attributes, RecordInfo}],
+    Opts = transform_opts(Opts0),
+    AllOpts = lists:concat([Opts, Attr]),
+    case mnesia:create_table(Record, lists:flatten(AllOpts)) of
+        {atomic, ok}                         -> ok;
+        {aborted, {already_exists, Record}}  -> ok;
+        {aborted, Err}                       -> {error, Err} end.
+
+add_table_index(Record, Field) ->
+    case mnesia:add_table_index(Record, Field) of
+        {atomic, ok}                        -> ok;
+        {aborted,{already_exists,Record,_}} -> ok;
+        {aborted, Err}                      -> {error, Err} end.
+
+transform_opts(Opts) -> transform_opts(Opts, []).
+transform_opts([], Acc) -> lists:reverse(Acc);
+transform_opts([{storage, Value} | Rest], Acc0) ->
+    NewOpts = storage_to_mnesia_type(Value),
+    Acc = [NewOpts | Acc0],
+    transform_opts(Rest, Acc);
+transform_opts([Other | Rest], Acc0) ->
+    Acc = [Other | Acc0],
+    transform_opts(Rest, Acc).
+
+storage_to_mnesia_type(permanent) -> {disc_copies, [node()]};
+storage_to_mnesia_type(temporary) -> {ram_copies, [node()]};
+storage_to_mnesia_type(ondisk) -> {disc_only_copies, [node()]}.
+
+exec(Q) -> F = fun() -> qlc:e(Q) end, {atomic, Val} = mnesia:transaction(F), Val.
+