-module(db). -behaviour(gen_server). %% API. -export([start_link/0, stop/0, init_tables/0]). -export([add/1, find/1]). %% API for testing. -export([dump/1, destroy_tables/0, info_tables/0, dump_to_file/1]). %% gen_server callbacks. -export([init/1, handle_call/3, terminate/2, handle_cast/2, handle_info/2, code_change/3]). -include_lib("stdlib/include/qlc.hrl"). -include("plop.hrl"). %% @doc Run once, or rather every time you start on a new database. %% If run more than once, we'll get {aborted, {already_exists, TABLE}}. init_tables() -> %% We've once upon a time invoked mnesia:create_schema/1 with the %% nodes that will be part of the database. RamCopies = [], DiscCopies = [], DiscOnlyCopies = [node()], mnesia:start(), mnesia:create_table(plop, [{type, set}, {ram_copies, RamCopies}, {disc_copies, DiscCopies}, {disc_only_copies, DiscOnlyCopies}, {attributes, record_info(fields, plop)}]), mnesia:add_table_index(plop, hash). destroy_tables() -> mnesia:delete_table(plop). info_tables() -> mnesia:table_info(plop, all). dump_to_file(Filename) -> mnesia:dump_to_textfile(Filename). init(_Args) -> {ok, []}. % TODO: return state start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). stop() -> gen_server:call(?MODULE, stop). add(Entry) -> gen_server:call(?MODULE, {add, Entry}). find(Hash) -> gen_server:call(?MODULE, {find, Hash}). dump(Table) -> gen_server:call(?MODULE, {dump, Table}). %%%%%%%%%%%%%%%%%%%% handle_cast(_Request, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. terminate(_Reason, _State) -> io:format("~p terminating~n", [?MODULE]), ok. %%%%%%%%%%%%%%%%%%%% handle_call(stop, _From, State) -> {stop, normal, stopped, State}; handle_call({add, Entry}, _From, State) -> F = fun() -> mnesia:write(Entry) end, Res = mnesia:transaction(F), {reply, Res, State}; handle_call({dump, Table}, _From, State) -> F = fun() -> Q = qlc:q([E || E <- mnesia:table(Table)]), qlc:e(Q) end, Res = mnesia:transaction(F), {reply, Res, State}; handle_call({find, Hash}, _From, State) -> {reply, mnesia:dirty_read({plop, Hash}), State}.