最后,进入最重要的主题,就是实际执行分页查询的模块。
-module(sc_element).
-behaviour(gen_server).
-export([
start_link/2,
create/2,
create/1,
fetch/1,
replace/2,
delete/1
]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include_lib("stdlib/include/qlc.hrl").
-define(SERVER, ?MODULE).
-define(DEFAULT_LEASE_TIME, 60).
-record(state, {value, lease_time, start_time, cursor}).
-record(user_data,{acc,icon,sex,calendar,year,month,day,nation,province,city,question1,question2,question3,answer1,answer2,answer3,nickname,signature=1}).
-record(available_acc,{acc,is_available}).
start_link(Value, LeaseTime) ->
gen_server:start_link(?MODULE, [Value, LeaseTime], []).
create(Value, LeaseTime) ->
sc_element_sup:start_child(Value, LeaseTime).
create(Value) ->
create(Value, ?DEFAULT_LEASE_TIME).
fetch(Pid) ->
gen_server:call(Pid, fetch).
replace(Pid, Value) ->
gen_server:cast(Pid, {replace, Value}).
delete(Pid) ->
gen_server:cast(Pid, delete).
init([Value, LeaseTime]) ->
Now = calendar:local_time(),
StartTime = calendar:datetime_to_gregorian_seconds(Now),
Cursor=make_cursor(),
{ok,
#state{value = Value,
lease_time = LeaseTime,
start_time = StartTime,
cursor=Cursor},
time_left(StartTime, LeaseTime)}.
time_left(_StartTime, infinity) ->
infinity;
time_left(StartTime, LeaseTime) ->
Now = calendar:local_time(),
CurrentTime = calendar:datetime_to_gregorian_seconds(Now),
TimeElapsed = CurrentTime - StartTime,
case LeaseTime - TimeElapsed of
Time when Time =< 0 -> 0;
Time -> Time * 1000
end.
handle_call(fetch, _From, State) ->
#state{
lease_time = LeaseTime,
start_time = StartTime,
cursor = Cursor} = State,
TimeLeft = time_left(StartTime, LeaseTime),
Value = get_next(Cursor),
{reply, {ok, Value}, State, TimeLeft}.
handle_cast({replace, Value}, State) ->
#state{lease_time = LeaseTime,
start_time = StartTime} = State,
TimeLeft = time_left(StartTime, LeaseTime),
{noreply, State#state{value = Value}, TimeLeft};
handle_cast(delete, State) ->
{stop, normal, State}.
handle_info(timeout, State) ->
{stop, normal, State}.
terminate(_Reason, _State) ->
sc_store:delete(self()),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%Internal Functions
make_cursor()->
Q=qlc:q([X||X<-mnesia:table(available_acc)]),
mnesia:activity(async_dirty,
fun()->qlc:cursor(Q,[]) end,
mnesia_frag).
get_next(Cursor)->
Get=fun()->
qlc:next_answers(Cursor,5)
end,
mnesia:activity(async_dirty,Get,mnesia_frag).