-module(timed_cache). -behavior(gen_server). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% 'gen_server' Exports -export ( [ init/1, handle_cast/2, handle_call/3, %% No reply will ever be given. terminate/2, code_change/3, format_status/2, handle_info/2 ] ). %%%% Actual Interface -export ( [ fetch/2, invalidate/2 ] ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% add_to_cache (DB, ObjectID) -> {ok, TimerPID} = gen_server:start(?MODULE, {DB, ObjectID}, []), {ok, Data} = database_shim:fetch(DB, ObjectID), ets:insert(DB, {ObjectID, TimerPID, Data}), Data. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% 'gen_server' functions init ({DB, ObjectID}) -> {ok, {DB, ObjectID}}. handle_call (invalidate, _, State) -> {stop, normal, State}. handle_cast (invalidate, State) -> {stop, normal, State}. terminate (_, {DB, ObjectID}) -> io:format("~nCache entry timed out: ~p.~n", [{DB, ObjectID}]), ets:delete(DB, ObjectID). code_change (_, State, _) -> {ok, State}. format_status (_, [_, State]) -> [{data, [{"State", State}]}]. handle_info(timeout, State) -> {stop, normal, State}; handle_info(_, {DB, ObjectID}) -> {noreply, {DB, ObjectID}, timed_caches_manager:get_timeout(DB)}. %%%% Interface Functions fetch (DB, ObjectID) -> io:format("~nfetch from cache: ~p.~n", [{DB, ObjectID}]), case ets:lookup(DB, ObjectID) of [] -> add_to_cache(DB, ObjectID); [{_, TimerPID, Data}] -> Data end. invalidate (DB, ObjectID) -> case ets:lookup(DB, ObjectID) of [] -> ok; [{_, TimerPID, _}] -> gen_server:stop(TimerPID) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Notes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%