最后,进入最重要的主题,就是实际执行分页查询的模块。
-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).