Starting DB implementation.
Added Makefile, id_counter.erl, and yaws.conf. Created ts_common module. Will contain common DB code. So far only list/3. Created ts_timeline module. DB code for storing timeline entries. Created ts_entry module, DB code for storing timelin entries.
This commit is contained in:
parent
111da51c73
commit
495336fc58
38
Makefile
Normal file
38
Makefile
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
MODS = $(wildcard src/*.erl)
|
||||||
|
BEAMS = $(MODS:src/%.erl=ebin/%.beam)
|
||||||
|
TEST_MODS = $(wildcard test/*.erl)
|
||||||
|
TEST_BEAMS = $(TEST_MODS:test/%.erl=test/%.beam)
|
||||||
|
|
||||||
|
all : compile test
|
||||||
|
|
||||||
|
compile : $(BEAMS)
|
||||||
|
|
||||||
|
compile-test : $(TEST_BEAMS)
|
||||||
|
|
||||||
|
test : start-test-server run-test stop-test-server
|
||||||
|
|
||||||
|
test-shell : compile compile-test
|
||||||
|
@echo Starting an interactive YAWS shell with test paths loaded.
|
||||||
|
@yaws -i --pa test --id test_inst
|
||||||
|
|
||||||
|
run-test : compile compile-test
|
||||||
|
@erl -pa ./ebin -pa ./test -run timestamper_api_tests test -run init stop -noshell
|
||||||
|
|
||||||
|
start-test-server :
|
||||||
|
@yaws -D --id test_inst
|
||||||
|
|
||||||
|
stop-test-server :
|
||||||
|
@yaws --stop --id test_inst
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ebin/* erl_crash.dump test/*.beam
|
||||||
|
|
||||||
|
init:
|
||||||
|
-mkdir ebin
|
||||||
|
|
||||||
|
ebin/%.beam : src/%.erl
|
||||||
|
erlc -W -o ebin $<
|
||||||
|
|
||||||
|
test/%.beam : test/%.erl
|
||||||
|
@echo Compiling sources...
|
||||||
|
erlc -W -o test $<
|
23
src/id_counter.erl
Normal file
23
src/id_counter.erl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-module(id_counter).
|
||||||
|
-export([create_table/1, next_counter/1, dirty_next_counter/1]).
|
||||||
|
|
||||||
|
-include("vbs_db_records.hrl").
|
||||||
|
|
||||||
|
%% Create the table structure for Mnesia
|
||||||
|
create_table(Opts) ->
|
||||||
|
mnesia:create_table(id_counter, Opts ++
|
||||||
|
[{attributes, record_info(fields, id_counter)}]).
|
||||||
|
|
||||||
|
%% Get the next id for a given name
|
||||||
|
next_counter(Name) ->
|
||||||
|
Rec = case mnesia:read({id_counter, Name}) of
|
||||||
|
[] -> #id_counter{name=Name, next_value=0};
|
||||||
|
[Val] -> Val
|
||||||
|
end,
|
||||||
|
NextRec = Rec#id_counter{next_value = Rec#id_counter.next_value+ 1},
|
||||||
|
ok = mnesia:write(NextRec),
|
||||||
|
Rec#id_counter.next_value.
|
||||||
|
|
||||||
|
%% Get the next id for a given name
|
||||||
|
dirty_next_counter(Name) ->
|
||||||
|
mnesia:dirty_update_counter(id_counter, Name, 1) - 1.
|
29
src/ts_common.erl
Normal file
29
src/ts_common.erl
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
-module(ts_common).
|
||||||
|
-export([list/3]).
|
||||||
|
|
||||||
|
-include_lib("stdlib/include/qlc.hrl").
|
||||||
|
|
||||||
|
%% list <Length> number of records, skipping the first <Start>
|
||||||
|
list(Table, Start, Length)
|
||||||
|
when is_atom(Table) and is_integer(Start) and is_integer(Length) ->
|
||||||
|
list(qlc:q([A || A <- mnesia:table(Table)]), Start, Length);
|
||||||
|
|
||||||
|
list(Query, Start, Length) ->
|
||||||
|
{atomic, Result} = mnesia:transaction(fun() ->
|
||||||
|
% create a cursor for the query
|
||||||
|
C = qlc:cursor(Query),
|
||||||
|
|
||||||
|
% skip the first Start records
|
||||||
|
if Start > 0 -> qlc:next_answers(C, Start);
|
||||||
|
true -> ok
|
||||||
|
end,
|
||||||
|
|
||||||
|
% return Length records
|
||||||
|
List = qlc:next_answers(C, Length),
|
||||||
|
|
||||||
|
% free cursor
|
||||||
|
ok = qlc:delete_cursor(C),
|
||||||
|
|
||||||
|
List
|
||||||
|
end),
|
||||||
|
Result.
|
12
src/ts_db_records.hrl
Normal file
12
src/ts_db_records.hrl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-record(ts_timeline, {
|
||||||
|
ref, % {username, timelineid}
|
||||||
|
created,% {{year, month, day}, {hour, minute, second}}
|
||||||
|
desc
|
||||||
|
}).
|
||||||
|
|
||||||
|
-record(ts_entry, {
|
||||||
|
ref, % {username, timelineid, eventid}
|
||||||
|
timestamp, % {{year, month, day}, {hour, minute, second}}
|
||||||
|
mark, % String description of entry
|
||||||
|
notes % String with further notes about the entry
|
||||||
|
}).
|
19
src/ts_entry.erl
Normal file
19
src/ts_entry.erl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-module(ts_entry).
|
||||||
|
-export([create_table/1, new/1, update/1, list/3]).
|
||||||
|
|
||||||
|
-include("ts_db_records.hrl").
|
||||||
|
-include_lib("stdlib/include/qlc.hrl").
|
||||||
|
|
||||||
|
create_table(TableOpts) ->
|
||||||
|
mnesia:create_table(ts_entry,
|
||||||
|
TableOpts ++ [{attributes, record_info(fields, ts_entry)},
|
||||||
|
{type, ordered_set}, {index, timestamp}]).
|
||||||
|
|
||||||
|
new(ER = #ts_entry()) ->
|
||||||
|
{atmoic, NewRow) = mnesia:transaction(fun() ->
|
||||||
|
{Username, TimelineId, _} = ER#ts_entry.ref,
|
||||||
|
NextId = id_counter:next_counter(ts_entry_id),
|
||||||
|
NewRow = ER#ts_entry{ref = {Username, TimelineId, NextId}},
|
||||||
|
ok = mnesia:write(NewRow),
|
||||||
|
NewRow end),
|
||||||
|
{ok, NewRow}.
|
34
src/ts_timeline.erl
Normal file
34
src/ts_timeline.erl
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
-module(ts_timeline).
|
||||||
|
-export([create_table/1, new/1, update/1, list/3]).
|
||||||
|
|
||||||
|
-include("ts_db_records.hrl").
|
||||||
|
-include_lib("stdlib/include/qlc.hrl").
|
||||||
|
|
||||||
|
create_table(TableOpts) ->
|
||||||
|
mnesia:create_table(ts_timeline,
|
||||||
|
TableOpts ++ [{attributes, record_info(fields, ts_timeline)},
|
||||||
|
{type, ordered_set}]).
|
||||||
|
|
||||||
|
new(TR = #ts_timeline{}) ->
|
||||||
|
case mnesia:dirty_read(ts_timeline, TR#ts_timeline.ref) of
|
||||||
|
[ExistingRecord] -> {error, {record_exists, ExistingRecord}};
|
||||||
|
[] -> mnesia:dirty_write(TR)
|
||||||
|
end.
|
||||||
|
|
||||||
|
update(TR = #ts_timeline{}) ->
|
||||||
|
|
||||||
|
% look for the existing record
|
||||||
|
case mnesia:dirty_read(ts_timeline, TR#ts_timeline.ref) of
|
||||||
|
% record does not exist
|
||||||
|
[] -> no_record;
|
||||||
|
% record exists, update
|
||||||
|
[Record] -> mnesia:dirty_write(TR)
|
||||||
|
end.
|
||||||
|
|
||||||
|
list(Username, Start, Length) ->
|
||||||
|
ts_common:list(
|
||||||
|
qlc:q([T || T <- mnesia:table(ts_timeline),
|
||||||
|
T#ts_timeline.ref = {Username, _}]),
|
||||||
|
Start, Length).
|
||||||
|
|
||||||
|
|
10
yaws.conf
Normal file
10
yaws.conf
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ebin_dir = /home/jdbernard/projects/timestamper/web-app/ebin
|
||||||
|
#include_dir = /home/jdbernard/projects/timestamper/web-app/src
|
||||||
|
|
||||||
|
runmod = timestamper
|
||||||
|
|
||||||
|
<server timestamper-test>
|
||||||
|
port = 8000
|
||||||
|
listen = /home/jdbernard/projects/timestamper/web-app/www
|
||||||
|
appmods = timestamper_api
|
||||||
|
</server>
|
Loading…
x
Reference in New Issue
Block a user