Current section
Files
Jump to
Current section
Files
src/erldb_mnesia.erl
%%%-------------------------------------------------------------------
%%% @author daniel <>
%%% @copyright (C) 2013, daniel
%%% @doc
%%%
%%% @end
%%% Created : 1 Aug 2013 by daniel <>
%%%-------------------------------------------------------------------
-module(erldb_mnesia).
-behaviour(gen_server).
%% API
-export([start_link/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {}).
%%%===================================================================
%%% API
%%%===================================================================
start_link(Args) ->
WorkerArgs = proplists:get_value(worker_args, Args, []),
gen_server:start_link(?MODULE, WorkerArgs, []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init(_Args) ->
ok = ensure_start(),
{ok, #state{}}.
handle_call({init_table, Name, Args}, _From, State) ->
FieldName = get_fieldname(proplists:get_value(module_attr, Args), []),
Attr = [{disc_copies, [node()]}, {attributes, FieldName} | proplists:delete(module_attr, Args)],
Result = case mnesia:create_table(Name, Attr) of
{atomic, ok} -> {ok, Name};
{aborted, {already_exists,tags}} -> {ok, Name};
{aborted, Reason} -> {error, Reason}
end,
{reply, Result, State};
handle_call({find, Model, Conditions, _}, _From, State) ->
[{_,_,Key}] = Conditions,
Reply = transaction(read, Model, Key),
{reply, Reply, State};
handle_call({save, Object}, _From, State) ->
Model = element(1, Object),
Reply = transaction(write, Model, Object),
{reply, Reply, State};
handle_call({delete, Object, _Arguments}, _From, State) ->
Table = element(1, Object),
Key = element(2, Object),
Reply = transaction(delete, Table, Key),
{reply, Reply, State};
handle_call({update, Object, _}, _From, State) ->
Model = element(1, Object),
Reply = transaction(write, Model, Object),
{reply, Reply, State};
handle_call({supported_condition, Conditions}, _From, State) ->
Supported = ['='],
List = [Operators || {_, Operators, _} <- Conditions,
lists:member(Operators, Supported) == false],
Reply =
case List of
[] -> {ok, supported};
List -> {error, not_supported, List}
end,
{reply, Reply, State}.
handle_cast(_, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
-spec ensure_start() -> ok | {error, Reaon :: term()}.
ensure_start() ->
mnesia:create_schema([node()]),
case application:start(mnesia) of
ok ->
ok;
{error, {already_started, mnesia}} ->
ok;
Err ->
Err
end.
-spec get_fieldname(list(tuple()), Acc :: list()) -> list().
get_fieldname([], Acc) ->
lists:reverse(Acc);
get_fieldname([{field, X} | Tail], Acc) ->
get_fieldname(Tail, [element(1, hd(X)) | Acc]);
get_fieldname([{_,_}|Tail], Acc) ->
get_fieldname(Tail, Acc).
transaction(Action, Tab, Object) ->
Fun = case Action of
read -> fun() -> mnesia:read(Tab, Object) end;
write -> fun() -> mnesia:write(Tab, Object, write) end;
delete -> fun() -> mnesia:delete(Tab, Object, write) end
end,
case mnesia:transaction(Fun) of
{atomic, Response} -> {ok, Response};
{aborted, Reason} -> {error, Reason}
end.