Much cleaner, but not working, because I have a circular loop

This commit is contained in:
lsowen
2012-12-04 21:36:44 -05:00
parent 676e112600
commit 4f3364a76d
10 changed files with 353 additions and 371 deletions

View File

@@ -36,7 +36,7 @@ localtime(TzName) ->
utc_to_local(UTCDatetime, TzName) -> utc_to_local(UTCDatetime, TzName) ->
NormalDatetime= ezic_date:normalize(UTCDatetime, u), NormalDatetime= ezic_date:normalize(UTCDatetime, u),
#flatzone{offset=Offset, dstoffset=DSTOffset}= ezic_db_ets:flatzone(NormalDatetime, TzName), #flatzone{offset=Offset, dstoffset=DSTOffset}= ezic_db:flatzone(NormalDatetime, TzName),
ezic_date:add_offset( ezic_date:add_offset(
ezic_date:add_offset( ezic_date:add_offset(
@@ -47,7 +47,7 @@ utc_to_local(UTCDatetime, TzName) ->
local_to_utc(LocalDatetime, TzName) -> local_to_utc(LocalDatetime, TzName) ->
NormalDatetime= ezic_date:normalize(LocalDatetime, w), NormalDatetime= ezic_date:normalize(LocalDatetime, w),
#flatzone{offset=Offset, dstoffset=DSTOffset}= ezic_db_ets:flatzone(NormalDatetime, TzName), #flatzone{offset=Offset, dstoffset=DSTOffset}= ezic_db:flatzone(NormalDatetime, TzName),
ezic_date:add_offset( ezic_date:add_offset(
ezic_date:add_offset( ezic_date:add_offset(
@@ -84,7 +84,7 @@ dev() ->
% ezic_flatten:flatten_all_zones(Zones), % ezic_flatten:flatten_all_zones(Zones),
application:start(ezic), application:start(ezic),
ezic_db_ets:flatzone({{2010,11,17}, #tztime{time={23,42,0}}}, "America/Los_Angeles"), ezic_db:flatzone({{2010,11,17}, #tztime{time={23,42,0}}}, "America/Los_Angeles"),
ok. ok.
@@ -94,8 +94,8 @@ zf() ->
reflatten() -> reflatten() ->
ezic_db_ets:wipe(flatzone), ezic_db:wipe(flatzone),
ezic_db_ets:flatten(). ezic_db:flatten().
@@ -113,20 +113,20 @@ test() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
current_as_of_utc(UTCDatetime, TzName) -> %current_as_of_utc(UTCDatetime, TzName) ->
CZone= ezic_zone:current_as_of_utc(UTCDatetime, TzName), % CZone= ezic_zone:current_as_of_utc(UTCDatetime, TzName),
RuleName= CZone#zone.rule, % RuleName= CZone#zone.rule,
Rules= ezic_db_ets:rules(RuleName), % Rules= ezic_db:rules(RuleName),
CRule= ezic_rule:current_as_of_utc(UTCDatetime, Rules), % CRule= ezic_rule:current_as_of_utc(UTCDatetime, Rules),
{ok, CZone, CRule}. % {ok, CZone, CRule}.
%%current_as_of_local(Datetime, TzName) -> %%current_as_of_local(Datetime, TzName) ->
%% not_done. %% not_done.
time_offset(Zone, Rule) -> %time_offset(Zone, Rule) ->
OffsetSec= ezic_zone:offset_sec(Zone), % OffsetSec= ezic_zone:offset_sec(Zone),
DSTSec= ezic_rule:dst_sec(Rule), % DSTSec= ezic_rule:dst_sec(Rule),
OffsetSec + DSTSec. % OffsetSec + DSTSec.

View File

@@ -251,7 +251,7 @@ when is_integer(Y1), is_integer(Y2)
compare({Date1, #tztime{time=Time1, flag=F}} compare({Date1, #tztime{time=Time1, flag=F}}
, {Date2, #tztime{time=Time2, flag=F}}) -> , {Date2, #tztime{time=Time2, flag=F}}) ->
Date1 =< Date2 orelse Time1 =< time2; Date1 =< Date2 orelse Time1 =< Time2;
compare(X,Y) -> compare(X,Y) ->
erlang:error(bad_dates, [X,Y]). erlang:error(bad_dates, [X,Y]).

View File

@@ -1,149 +1,125 @@
-module(ezic_db). -module(ezic_db).
-include("include/ezic.hrl"). -include("include/ezic.hrl").
-include_lib("stdlib/include/qlc.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-behaviour(gen_server).
-export([ -export([
zones/1 zones/1
, rules/1 , rules/1
, flatzone/2 , flatzone/2
%, insert/2
, get_all/1
, insert_all/1
, wipe/1
, flatten/0
]). ]).
-export([ -export([
wipe/0 start_link/0
, wipe/1 , init/1
, init/0 , code_change/3
, insert_all/1 , handle_call/3
, get_all/1 , handle_cast/2
, handle_info/2
, terminate/2
]). ]).
-define(create(Record), %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{atomic, ok} = mnesia:create_table(Record, % PUBLIC API
[{type, bag} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
, {disc_copies, [node()]}
, {attributes, record_info(fields, Record)}
])).
zones(TzName) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_server:call(?MODULE, {zones, TzName}).
% READ - db reading methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rules(TzName) ->
gen_server:call(?MODULE, {rules, TzName}).
% retrieve all zones by name
zones(Name) ->
F = fun()->
Q = qlc:q([Z || Z=#zone{name=N} <- mnesia:table(zone), N=:=Name]),
qlc:e(Q)
end,
{atomic, Zones}= mnesia:transaction(F),
Zones.
% retrieve all rules by name
rules(Name) ->
F = fun()->
Q = qlc:q([R || R=#rule{name=N} <- mnesia:table(rule), N=:=Name]),
qlc:e(Q)
end,
{atomic, Rules}= mnesia:transaction(F),
Rules.
% get all records from table
get_all(Tab) when is_atom(Tab) ->
F = fun() ->
Q = qlc:q([R || R<- mnesia:table(Tab)]),
qlc:e(Q)
end,
{atomic, Ret}= mnesia:transaction(F),
Ret.
%% get a flatzone for a specific date
%% Date :: {date(), #tztime{}}
%% returns #flatzone{}
%% or throws either error:
%% * {ambiguous_zone, [Z1,Z2,...]}
%% * {no_zone}
flatzone(Date, TzName) -> flatzone(Date, TzName) ->
%% @todo validate Date gen_server:call(?MODULE, {flatzone, Date, TzName}).
F = fun()->
Q = qlc:q(
[Fz || Fz=#flatzone{tzname=N} <- mnesia:table(flatzone)
, N=:=TzName
, ezic_flatten:contains_date(Fz, Date)]),
qlc:e(Q)
end,
{atomic, FlatZones}= mnesia:transaction(F),
case length(FlatZones) of
1 ->
hd(FlatZones);
2 ->
erlang:error(ambiguous_zone, FlatZones);
0 ->
erlang:error(no_zone);
_ ->
erlang:error(should_not_happen, {FlatZones, Date, TzName})
end.
get_all(Tab) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_server:call(?MODULE, {all, Tab}).
% ADMIN - initialization and administration methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initialize the db
init() ->
create_tabs(mnesia:create_schema([node()])),
mnesia:wait_for_tables([rule, zone, link, leap, flatzone], 3000).
% WARNING: deletes all db files
wipe() ->
mnesia:stop(),
mnesia:delete_schema([node()]).
% WARNING: deletes all entries in table Tab
wipe(Tab) ->
mnesia:transaction(
fun()->
mnesia:delete(Tab, '_', write)
end).
create_tabs(ok) ->
mnesia:start(),
?create(rule),
?create(zone),
?create(link),
?create(leap),
?create(flatzone),
ok;
create_tabs({error, {_, {already_exists,_}}}) ->
mnesia:start(),
ok;
create_tabs(E) ->
?debugVal(E).
insert_all(Records) -> insert_all(Records) ->
mnesia:transaction( gen_server:call(?MODULE, {insert_all, Records}).
fun() ->
lists:foreach(
fun(R)-> mnesia:write(R) end,
Records)
end).
%wipe() ->
% gen_server:call(?MODULE, {wipe}).
wipe(Tab) ->
gen_server:call(?MODULE, {wipe, Tab}).
flatten() ->
gen_server:call(?MODULE, {flatten}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% GEN_SERVER
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_) ->
ezic_db_ets:init(),
{ok, []}.
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%% DB Lookup
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
handle_call({zones, Name}, _, State) ->
Matches= ezic_db_ets:zones(Name),
{reply, Matches, State};
handle_call({rules, Name}, _, State) ->
Matches= ezic_db_ets:rules(Name),
{reply, Matches, State};
handle_call({all, Tab}, _, State) ->
Matches= ezic_db_ets:get_all(Tab),
{reply, Matches, State};
handle_call({flatzone, Date, Name}, _, State) ->
Result= ezic_db_ets:flatzone(Date, Name),
{reply, Result, State};
handle_call({insert_all, Records}, _, State) ->
ezic_db_ets:insert_all(Records),
{noreply, State};
handle_call({wipe, Tab}, _, State) ->
Result= ezic_db_ets:wipe(Tab),
{reply, Result, State};
handle_call({flatten}, _, State) ->
Result= ezic_flatten:flatten(),
{reply, Result, State};
handle_call(_, _, State) ->
{noreply, State}.
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%% Other gen_server
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
code_change(_, State, _) ->
{ok, State}.
handle_cast(_, State) ->
{noreply, State}.
handle_info(_, State) ->
{noreply, State}.
terminate(_, _State) ->
ok.

View File

@@ -2,96 +2,35 @@
-include("include/ezic.hrl"). -include("include/ezic.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-behaviour(gen_server). -define(DB_FILENAME, "db.e2f").
-export([ -export([
zones/1 init/0
, zones/1
, rules/1 , rules/1
, flatzone/2 , flatzone/2
, all/1 %, insert/2
%, insert_all/1 , get_all/1
, insert_all/1
, wipe/1 , wipe/1
, flatten/0
]). ]).
-export([
start_link/0
, init/1
, code_change/3
, handle_call/3
, handle_cast/2
, handle_info/2
, terminate/2
]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PUBLIC API % PUBLIC API
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
zones(TzName) -> zones(TzName) ->
gen_server:call(?MODULE, {zones, TzName}). ets:select(zone, [{#zone{name=TzName, _='_'}, [], ['$_']}]).
rules(TzName) -> rules(TzName) ->
gen_server:call(?MODULE, {rules, TzName}). ets:select(rule, [{#rule{name=TzName, _='_'}, [], ['$_']}]).
flatzone(Date, TzName) -> flatzone(Date, TzName) ->
gen_server:call(?MODULE, {flatzone, Date, TzName}). FlatZones= ets:select(flatzone, ezic_flatten:ms(Date, TzName)),
case length(FlatZones) of
all(Tab) ->
gen_server:call(?MODULE, {all, Tab}).
%insert_all(Records) ->
% gen_server:call(?MODULE, {insert_all, Records}).
%wipe() ->
% gen_server:call(?MODULE, {wipe}).
wipe(Tab) ->
gen_server:call(?MODULE, {wipe, Tab}).
flatten() ->
gen_server:call(?MODULE, {flatten}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% GEN_SERVER
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_) ->
ezic_db_ets_admin:init().
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%% DB Lookup
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
handle_call({zones, Name}, _, State) ->
Matches= ets:select(zone, [{#zone{name=Name, _='_'}, [], ['$_']}]),
{reply, Matches, State};
handle_call({rules, Name}, _, State) ->
Matches= ets:select(rule, [{#rule{name=Name, _='_'}, [], ['$_']}]),
{reply, Matches, State};
handle_call({all, Tab}, _, State) ->
Matches= ets:lookup(Tab, Tab),
{reply, Matches, State};
handle_call({flatzone, Date, Name}, _, State) ->
FlatZones= ets:select(flatzone, ezic_flatten:ms(Date, Name)),
Result= case length(FlatZones) of
1 -> 1 ->
hd(FlatZones); hd(FlatZones);
2 -> 2 ->
@@ -99,39 +38,100 @@ handle_call({flatzone, Date, Name}, _, State) ->
0 -> 0 ->
erlang:error(no_zone); erlang:error(no_zone);
_ -> _ ->
erlang:error(should_not_happen, {FlatZones, Date, Name}) erlang:error(should_not_happen, {FlatZones, Date, TzName})
end.
get_all(Tab) ->
ets:lookup(Tab, Tab).
insert_all(Records) ->
Zones= [ZI || ZI <- Records, ZI = #zone{}],
ets:insert(zone, Zones),
Rules= [RI || RI <- Records, RI = #rule{}],
ets:insert(rule, Rules),
FlatZones= [FZ || FZ <- Records, FZ = #flatzone{}],
ets:insert(flatzone, FlatZones).
%wipe() ->
% gen_server:call(?MODULE, {wipe}).
wipe(Tab) ->
ets:delete(Tab, Tab).
init() ->
{ok, DbDir}= application:get_env(db_dir),
Filename= filename:join(DbDir, ?DB_FILENAME),
case db_sane(Filename) of
true -> load_tabfile(Filename);
false -> create_tables(Filename)
end, end,
{reply, Result, State}; {ok, []}.
%handle_call({insert_all, Records}, _, Ets) ->
% Result= ets:insert(Ets, Records),
% {reply, Result, Ets};
%handle_call({wipe}, _, Ets) ->
% Result= ets:delete(Ets),
% {reply, Result, Ets};
handle_call({wipe, Tab}, _, State) ->
Result= ets:delete(Tab, Tab),
{reply, Result, State};
handle_call({flatten}, _, State) ->
Result= ezic_flatten:flatten(),
{reply, Result, State};
handle_call(_, _, State) ->
{noreply, State}.
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%% Other gen_server %% Private functions for initializing ets
%%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
code_change(_, State, _) -> %% -> true if table exists
{ok, State}. db_sane(Filename) ->
%% @todo ensure data is present for each record type.
case ets:tabfile_info(Filename) of
{ok, _} -> true;
{error, _} -> false
end.
handle_cast(_, State) ->
{noreply, State}.
handle_info(_, State) -> %% creates the dets table and populates it.
{noreply, State}. create_tables(Filename) ->
{ok, Zones, Rules, _, _} = ezic_record:separate(ezic_loader:load()),
ets:new(zone, [duplicate_bag, named_table]),
true = ets:insert(zone, Zones),
ets:new(rule, [duplicate_bag, named_table]),
true = ets:insert(rule, Rules),
ets:new(flatzone, [duplicate_bag, named_table]),
io:format("~p~n", [Rules]),
ezic_flatten:flatten(),
% combine into one ets
Ets= ets:new(ezic_db_ets, [duplicate_bag]),
ets:insert(Ets, ets:lookup(zone, zone)),
ets:insert(Ets, ets:lookup(rule, rule)),
ets:insert(Ets, ets:lookup(flatzone, flatzone)),
% save to disk
ets:tab2file(Ets, Filename),
ets:delete(Ets),
terminate(_, State) -> ok.
%% loads or creates the dets table.
load_tabfile(Filename) ->
{ok, Ets}= ets:file2tab(Filename),
Zones= ets:lookup(Ets, zone),
ets:new(zone, [duplicate_bag, named_table]),
ets:insert(zone, Zones),
Rules= ets:lookup(Ets, rule),
ets:new(rule, [duplicate_bag, named_table]),
ets:insert(rule, Rules),
FlatZones= ets:lookup(Ets, flatzone),
ets:new(flatzone, [duplicate_bag, named_table]),
ets:insert(flatzone, FlatZones),
ets:delete(Ets),
ok. ok.

View File

@@ -1,137 +0,0 @@
-module(ezic_db_ets_admin).
-include("include/ezic.hrl").
-include_lib("eunit/include/eunit.hrl").
-define(TABS, [rule, zone, leap, flatzone]).
-define(DB_FILENAME, "db.e2f").
-define(DETS_OPTS, []).
-define(ETS_OPTS, [named_table]).
-export([
init/0
, wipe/0
, insert_all/1
, wipe/1
]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ADMIN API
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Entire DB
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%% if dets tables exist,
%% load stored tables
%% else
%% create all ets tables as named tables
%% load data
init() ->
{ok, DbDir}= application:get_env(db_dir),
Filename= filename:join(DbDir, ?DB_FILENAME),
case db_sane(Filename) of
true -> load_tabfile(Filename);
false -> create_tables(Filename)
end,
{ok, []}.
% erases all data
wipe() ->
not_done.
% inserts all records into the appropriate db
insert_all(Record) ->
not_done.
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% Single Table
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% erases date for one table
wipe(Tab) ->
ezic_db_ets:wipe(Tab).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% PRIVATE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% -> true if table exists
db_sane(Filename) ->
%% @todo ensure data is present for each record type.
case ets:tabfile_info(Filename) of
{ok, _} -> true;
{error, _} -> false
end.
%% creates the dets table and populates it.
create_tables(Filename) ->
{ok, Zones, Rules, _, _} = ezic_record:separate(ezic_loader:load()),
ets:new(zone, [duplicate_bag, named_table]),
ets:insert(zone, Zones),
ets:new(rule, [duplicate_bag, named_table]),
ets:insert(rule, Rules),
ets:new(flatzone, [duplicate_bag, named_table]),
ezic_flatten:flatten(),
% combine into one ets
Ets= ets:new(ezic_db_ets, [duplicate_bag]),
ets:insert(Ets, ets:lookup(zone, zone)),
ets:insert(Ets, ets:lookup(rule, rule)),
ets:insert(Ets, ets:lookup(flatzone, flatzone)),
% save to disk
ets:tab2file(Ets, Filename),
ets:delete(Ets),
ok.
%% loads or creates the dets table.
load_tabfile(Filename) ->
{ok, Ets}= ets:file2tab(Filename),
Zones= ets:lookup(Ets, zone),
ets:new(zone, [duplicate_bag, named_table]),
ets:insert(zone, Zones),
Rules= ets:lookup(Ets, rule),
ets:new(rule, [duplicate_bag, named_table]),
ets:insert(rule, Rules),
FlatZones= ets:lookup(Ets, flatzone),
ets:new(flatzone, [duplicate_bag, named_table]),
ets:insert(flatzone, FlatZones),
ets:delete(Ets),
ok.
%% takes a populated dets table and converts it to an ets table.
ets_from_dets(Dets) ->
Ets= ets:new(tzdb, ?ETS_OPTS),
dets:to_ets(Dets, Ets).

145
src/ezic_db_mnesia.erl Normal file
View File

@@ -0,0 +1,145 @@
-module(ezic_db_mnesia).
-include("include/ezic.hrl").
-include_lib("stdlib/include/qlc.hrl").
-include_lib("eunit/include/eunit.hrl").
-export([
init/0
, zones/1
, rules/1
, flatzone/2
%, insert/2
, get_all/1
, insert_all/1
, wipe/1
]).
-define(create(Record),
{atomic, ok} = mnesia:create_table(Record,
[{type, bag}
, {disc_copies, [node()]}
, {attributes, record_info(fields, Record)}
])).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% READ - db reading methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% retrieve all zones by name
zones(Name) ->
F = fun()->
Q = qlc:q([Z || Z=#zone{name=N} <- mnesia:table(zone), N=:=Name]),
qlc:e(Q)
end,
{atomic, Zones}= mnesia:transaction(F),
Zones.
% retrieve all rules by name
rules(Name) ->
F = fun()->
Q = qlc:q([R || R=#rule{name=N} <- mnesia:table(rule), N=:=Name]),
qlc:e(Q)
end,
{atomic, Rules}= mnesia:transaction(F),
Rules.
% get all records from table
get_all(Tab) when is_atom(Tab) ->
F = fun() ->
Q = qlc:q([R || R<- mnesia:table(Tab)]),
qlc:e(Q)
end,
{atomic, Ret}= mnesia:transaction(F),
Ret.
%% get a flatzone for a specific date
%% Date :: {date(), #tztime{}}
%% returns #flatzone{}
%% or throws either error:
%% * {ambiguous_zone, [Z1,Z2,...]}
%% * {no_zone}
flatzone(Date, TzName) ->
%% @todo validate Date
F = fun()->
Q = qlc:q(
[Fz || Fz=#flatzone{tzname=N} <- mnesia:table(flatzone)
, N=:=TzName
, ezic_flatten:contains_date(Fz, Date)]),
qlc:e(Q)
end,
{atomic, FlatZones}= mnesia:transaction(F),
case length(FlatZones) of
1 ->
hd(FlatZones);
2 ->
erlang:error(ambiguous_zone, FlatZones);
0 ->
erlang:error(no_zone);
_ ->
erlang:error(should_not_happen, {FlatZones, Date, TzName})
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ADMIN - initialization and administration methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initialize the db
init() ->
create_tabs(mnesia:create_schema([node()])),
mnesia:wait_for_tables([rule, zone, link, leap, flatzone], 3000).
% WARNING: deletes all db files
%wipe() ->
% mnesia:stop(),
% mnesia:delete_schema([node()]).
% WARNING: deletes all entries in table Tab
wipe(Tab) ->
mnesia:transaction(
fun()->
mnesia:delete(Tab, '_', write)
end).
create_tabs(ok) ->
mnesia:start(),
?create(rule),
?create(zone),
?create(link),
?create(leap),
?create(flatzone),
{ok, Zones, Rules, _, _} = ezic_record:separate(ezic_loader:load()),
insert_all(Zones),
insert_all(Rules),
ezic_flatten:flatten(),
ok;
create_tabs({error, {_, {already_exists,_}}}) ->
mnesia:start(),
ok;
create_tabs(E) ->
?debugVal(E).
insert_all(Records) ->
mnesia:transaction(
fun() ->
lists:foreach(
fun(R)-> mnesia:write(R) end,
Records)
end).

View File

@@ -1,6 +1,5 @@
-module(ezic_flatten). -module(ezic_flatten).
-include("include/ezic.hrl"). -include("include/ezic.hrl").
-define(NODEBUG, true).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@@ -22,7 +21,7 @@
flatten() -> flatten() ->
AllZones= ets:lookup(zone, zone), AllZones= ezic_db:get_all(zone),
flatten_all_zones(AllZones), flatten_all_zones(AllZones),
done. done.
@@ -45,7 +44,7 @@ ms(Date, Name) ->
{D, #tztime{time=T, flag=F}}=Date, {D, #tztime{time=T, flag=F}}=Date,
SDate= {D,T}, %SDate= {D,T},
DComp= {{{D},{T}}}, DComp= {{{D},{T}}},
G= ms_guards(F, DComp), G= ms_guards(F, DComp),
@@ -82,22 +81,22 @@ flatten_all_zones([Z1|_]= AllZones) ->
{CurrentZones, RestZones}= ezic_zone:split_by_name(Z1, AllZones), {CurrentZones, RestZones}= ezic_zone:split_by_name(Z1, AllZones),
Flats= flatten_zone_set(CurrentZones), Flats= flatten_zone_set(CurrentZones),
ets:insert(flatzone, Flats), ezic_db:insert_all(Flats),
flatten_all_zones(RestZones). flatten_all_zones(RestZones).
contains_date2(FlatZone=#flatzone{utc_from=From, utc_to=To}, {Dt,#tztime{time=T, flag=F}}) contains_date2(#flatzone{utc_from=From, utc_to=To}, {Dt,#tztime{time=T, flag=F}})
when F=:= u; F=:= g; F=:=z -> when F=:= u; F=:= g; F=:=z ->
Date={Dt, T}, Date={Dt, T},
ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To); ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To);
contains_date2(FlatZone=#flatzone{std_from=From, std_to=To}, {Dt,#tztime{time=T, flag=s}}) -> contains_date2(#flatzone{std_from=From, std_to=To}, {Dt,#tztime{time=T, flag=s}}) ->
Date={Dt, T}, Date={Dt, T},
ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To); ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To);
contains_date2(FlatZone=#flatzone{wall_from=From, wall_to=To}, {Dt,#tztime{time=T, flag=F}}) contains_date2(#flatzone{wall_from=From, wall_to=To}, {Dt,#tztime{time=T, flag=F}})
when F=:=w; F=:=undefined -> when F=:=w; F=:=undefined ->
Date={Dt, T}, Date={Dt, T},
ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To). ezic_date:compare(From, Date) andalso ezic_date:compare(Date, To).
@@ -141,7 +140,7 @@ flatten_zone_set(FromTimeStub=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset}
%% we gather all rules that _may_ apply %% we gather all rules that _may_ apply
Rules= ets:select(rule, [{#rule{name=RuleName, _='_'}, [], ['$_']}]), Rules= ezic_db:rules(RuleName),
?debugVal(FromTime), ?debugVal(FromTime),

View File

@@ -58,7 +58,7 @@ years(#rule{from=From, to=To}) ->
%% calculation stops after a fixed year, configurable above. %% calculation stops after a fixed year, configurable above.
years_after(Y, {F,M}) when M=:=max; M=:=maximum -> years_after(Y, {F,M}) when M=:=max; M=:=maximum ->
{erlang:max(Y,F), M}; {erlang:max(Y,F), M};
years_after(Y, {From, To}) when Y > To -> years_after(Y, {_From, To}) when Y > To ->
none; none;
years_after(Y, {From, To}) -> years_after(Y, {From, To}) ->
{erlang:max(Y,From), To}. {erlang:max(Y,From), To}.

View File

@@ -40,7 +40,7 @@ start_link(_) ->
%% specifications. %% specifications.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
init(_) -> init(_) ->
EzicDb = {ezic_db_ets,{ezic_db_ets, start_link, []}, EzicDb = {ezic_db,{ezic_db, start_link, []},
permanent,2000,worker,[ezic_db_ets]}, permanent,2000,worker,[ezic_db_ets]},
{ok,{{one_for_all,3,30}, [EzicDb]}}. {ok,{{one_for_all,3,30}, [EzicDb]}}.

View File

@@ -1,6 +1,5 @@
-module(ezic_zone). -module(ezic_zone).
-include("include/ezic.hrl"). -include("include/ezic.hrl").
-define(NODEBUG, true).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-export([ -export([
@@ -42,7 +41,7 @@ current(TzName) ->
current_as_of_utc(erlang:universaltime(), TzName). current_as_of_utc(erlang:universaltime(), TzName).
current_as_of_utc(UTCDatetime, TzName) -> current_as_of_utc(UTCDatetime, TzName) ->
Zones= ezic_db_ets:zones(TzName), Zones= ezic_db:zones(TzName),
get_zone_utc(UTCDatetime, Zones). get_zone_utc(UTCDatetime, Zones).