1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
-module(dreki_dets_tasks).
-include("dreki.hrl").
%% Types
-type db() :: term().
-type args() :: #{db_name => binary()}.
%% storage-specific
-export([start/1, open/1, sync/1, close/1, stop/1]).
-export([checkout/1, checkin/1]).
-export([list/1, count/1, exists/2, get/2, create/2, update/2, delete/2]).
-define(DETS, dreki_tasks_dets).
dets_name(_Args = #{store_name := StoreName}) when is_binary(StoreName) ->
{dreki_dets_tasks, StoreName}.
file_name(_Args = #{file_name := FileName}) when is_binary(FileName) ->
binary:bin_to_list(FileName);
file_name(_Args = #{store_name := StoreName}) when is_binary(StoreName) ->
File = <<"tasks.", StoreName/binary, ".dets">>,
binary:bin_to_list(File).
-spec start(args()) -> {ok, db()} | {error, Reason::term()}.
start(Args) ->
dets:open_file(dets_name(Args), [{file, file_name(Args)}, {keypos, 2}]).
-spec open(args()) -> {ok, db()} | {error, Reason::term()}.
open(Args) ->
start(Args).
-spec close(db()) -> ok | {error, Reason::term()}.
close(Tab) ->
dets:close(Tab).
-spec stop(args()) -> ok | {error, Reason::term()}.
stop(Args) ->
Tab = dets_name(Args),
dets:close(Tab).
sync(Tab) ->
dets:sync(Tab).
checkout(Args) ->
start(Args).
checkin(Tab) ->
dets:close(Tab).
-spec list(db()) -> {ok, [dreki_task()]} | {error, Reason::term()}.
list(Tab) ->
dets:foldl(fun (T, {ok, Ts}) -> {ok, [T | Ts]} end, {ok, []}, Tab).
-spec count(db()) -> {ok, Count::non_neg_integer()} | {error, Reason::term()}.
count(Tab) ->
dets:foldl(fun (_T, {ok, Ct}) -> {ok, Ct + 1} end, {ok, 0}, Tab).
-spec exists(db(), dreki_id()) -> boolean.
exists(Tab, Id) ->
dets:member(Tab, Id).
-spec get(db(), dreki_id()) -> {ok, dreki_task()} | {error, {task_not_found, dreki_id()}}.
get(Tab, Id) ->
case dets:lookup(Tab, Id) of
[] -> {error, {task_not_found, Id}};
[Task] -> {ok, Task}
end.
-spec delete(db(), dreki_id()) -> ok | {error, Reason::term()}.
delete(Tab, Id) ->
dets:delete(Tab, Id).
-spec create(db(), dreki_task()) -> {ok, dreki_task()} | {error, Reason::term()}.
create(Tab, Task = #dreki_task{persisted=false}) ->
case dets:insert_new(Tab, Task#dreki_task{persisted=true, dirty=false}) of
true -> {ok, Task#dreki_task{persisted=true, dirty=false}};
false -> {error, {task_exists, Task#dreki_task.id}};
{error, Error} -> {error, Error}
end.
-spec update(db(), dreki_task()) -> {ok, dreki_task()} | {error, Reason::term()}.
update(_Tab, Task = #dreki_task{persisted=false}) ->
{error, {task_not_created, Task#dreki_task.id}};
update(_Tab, Task = #dreki_task{dirty=false}) ->
{ok, Task};
update(Tab, Task = #dreki_task{persisted=true, dirty=true}) ->
case dets:insert(Tab, Task#dreki_task{dirty=false}) of
ok -> {ok, Task#dreki_task{dirty=false}};
{error, Error} -> {error, Error}
end.
|