Current section
Files
Jump to
Current section
Files
src/elru_srv.erl
-module(elru_srv).
-behaviour(gen_server).
-include("elru.hrl").
-export([start_link/0, init/1, handle_call/3, handle_cast/2, new/1, add/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
new(Size) ->
gen_server:call(?MODULE, {new, Size}).
add(Module, Func, List_Args) ->
gen_server:call(?MODULE, {add, Module, Func, List_Args}).
init([]) ->
{ok, {}}.
handle_call({new , MaxSize}, _From, _State) ->
{reply, ok, {ets:new(elru, [set]),0 ,MaxSize}};
handle_call({add, Module, Func, List_Args}, _From, {Id, Count, MaxSize}) ->
Bin = erlang:term_to_binary([Module, Func, List_Args]),
Hash = crypto:hash(md5, Bin),
case ets:lookup(Id, Hash) of
[{Key, {_ValCount,Value}}] ->
ets:delete(Id, Key),
ets:insert(Id, {Key,{Count, Value}}),
{reply, Value, {Id,Count + 1 ,MaxSize}};
_ ->
Res = Module:Func(List_Args),
ets:insert(Id, {Hash, {Count, Res}}),
gen_server:cast(?MODULE, {check_size}),
{reply, Res, {Id, Count + 1, MaxSize}}
end.
handle_cast({check_size}, {Id, Count, MaxSize}) ->
Size = ets:info(Id, size),
if
Size > MaxSize ->
List = ets:tab2list(Id),
Key = minimum(List),
Val = ets:lookup(Id, Key),
ets:delete(Id, Key),
?LOG("Delete ~p",[Val]),
{noreply, {Id, Count, MaxSize}};
true ->
{noreply, {Id, Count, MaxSize}}
end.
minimum([H|T]) ->
minimum(H,T).
minimum({Key,{Count,Val}}, [{NewKey,{NewCount,NewVal}}|T]) ->
case Count < NewCount of
true -> minimum({Key,{Count,Val}},T);
false -> minimum({NewKey,{NewCount,NewVal}},T)
end;
minimum({Key,{_Count,_}}, []) ->
Key.