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