Skip to content

Instantly share code, notes, and snippets.

@lyagusha
Last active January 13, 2017 22:36
Show Gist options
  • Select an option

  • Save lyagusha/d8a61c33313c4ac489f7de1b261c0cc1 to your computer and use it in GitHub Desktop.

Select an option

Save lyagusha/d8a61c33313c4ac489f7de1b261c0cc1 to your computer and use it in GitHub Desktop.
-module(cache_server).
-behaviour(gen_server).
-export([start_link/1,insert/3,lookup/1,lookup_by_date/2]).%,lookup_by_date/2]).
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-export([test/0,ets_list/0]).
-export([delete/1]).
-record(string,{key,value,life_time,valid_time,add_date}).
%------------------------------------------------------------------------------------------
test()->
start_link([{drop_interval, 10000}]),
insert(1,test_value1,0),
insert(2,test_value2,15),
insert(3,test_value3,25),
insert(4,test_value4,35),
insert(5,test_value5,45),
insert(6,test_value6,55),
insert(7,test_value7,65),
insert(8,test_value8,75),
insert(9,test_value9,85).
ets_list()->
List=ets:select(table,[{{'$1','$2','$3','$4','$5','$6'},[],['$2']}]),
io:format(List).
%-----------------------------------------------------------------------------------------
start_link([{drop_interval, Time}]) ->
gen_server:start_link({global, ?MODULE}, ?MODULE, [Time], []).
insert(Key,Value,Life_time) ->
S=#string{key=Key,
value=Value,
life_time=Life_time,
valid_time=valid_time(Life_time),
add_date=calendar:local_time()},
gen_server:call({global, ?MODULE}, {insert,S}).
lookup(Key) ->
gen_server:call({global, ?MODULE}, {lookup,Key}).
lookup_by_date(DateFrom, DateTo)->
gen_server:call({global, ?MODULE}, {lookup_by_date,DateFrom,DateTo}).
%-------------------------------------------------------------------------------------------
valid_time(Life_time)->
DateTime=calendar:local_time(),
DateTimeSec = calendar:datetime_to_gregorian_seconds(DateTime),
DateTimeSec+Life_time.
delete('$end_of_table')->
ok;
delete(Key)->Key,
[S]=ets:lookup(table,Key),
Valid_time=S#string.valid_time,
case Valid_time > calendar:datetime_to_gregorian_seconds(calendar:local_time()) of
true -> delete(ets:next(table,Key));
false-> ets:delete(table,Key), delete(ets:next(table,Key))
end,
ok.
is_old(Valid_time)->
calendar:datetime_to_gregorian_seconds(calendar:local_time())>Valid_time.
list_by_date('$end_of_table', _DateFrom, _DateTo,List)->
List;
list_by_date(Key, DateFrom, DateTo,List)->
A=ets:lookup(table,Key),
case A of
[]->list_by_date(ets:next(table,Key), DateFrom, DateTo,List);
_->
[S]=A,
Valid_time=S#string.valid_time,
Date=S#string.add_date,
case {is_old(Valid_time),(Date>=DateFrom) and (Date=<DateTo)} of
{false,true}->list_by_date(ets:next(table,Key), DateFrom, DateTo,[Key|List]);
_->list_by_date(ets:next(table,Key), DateFrom, DateTo,List)
end
end.
%-------------------------------------------------------------------------------------------
init([Time]) ->
ets:new(table,[ordered_set,public,{keypos,2}, named_table]),
Timer = erlang:send_after(Time, self(), start),
{ok,Timer}.
handle_call({insert,S}, _From,State) ->
ets:insert(table,S),
{ reply,ok, State };
handle_call({lookup,Key}, _From,State) ->
A=ets:lookup(table,Key),
Rez=case A of
[] ->{undefined};
_ ->
[S]=A,
Valid_time=S#string.valid_time,
Value=S#string.value,
case is_old(Valid_time) of
true -> {undefined};
false -> {ok,Value}
end
end,
{reply,Rez,State};
handle_call({lookup_by_date, DateFrom, DateTo}, _From,State) ->
Key=ets:first(table),
Rez=list_by_date(Key, DateFrom, DateTo,[]),
{reply,Rez,State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(start, OldTimer) ->
erlang:cancel_timer(OldTimer),
delete(ets:first(table)),
Timer = erlang:send_after(1000, self(), start),
{noreply, Timer}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment