从Qt客户端向Erlang服务器发起数据库分页查询的请求(1)

        用户向服务器发出搜索联系人的请求时,搜索结果可能是很大的数据,必须分页传递给客户端。在当前的查询中,负责数据库查询的进程不可中断,用户请求下一页时,仍然必须由该进程来完成。该进程也需维护一个超时,当用户一定时间没新的搜索请求到达,或者查询数据到达数据库末尾,则都应该结束该查询进程。

        每个用户账号唯一地对应于一个查询进程,用ets表管理用户账号Acc及其对应的动态创建的查询数据库的进程Pid之间的映射关系。设计时,考虑过使用用户账号转成原子,再用原子构建注册进程,但考虑到Erlang系统里,原子不会被回收,动态创建大量原子可能造成内存的泄露,所以放弃了这种设计。现在的设计是,将用户账号和对应的查询进程Pid写入ets表,这样当某用户请求到达时,即可从该ets表里查询获取对应的查询进程的Pid。(但此种设计的缺陷是,一旦保存AccPid映射关系的进程崩溃,所有正在搜索联系人的用户都会受到影响,希望以后能有更好的解决方案)

        思路理清,现在开始开工。

此模块既可使用OTP框架,也可以不采用。但为了工程的健壮性,还是采用OTP行为模式,这样可以将其纳入监督者的管理之下。

cs_accToSearchDBPid.erl

-module(cs_accToSearchDBPid).
-behaviour(gen_server).
-export([
	start_link/0,
	insert/2,
	lookup/1,
	delete/1
	]).
-export([
	init/1,
	handle_call/3,
	handle_cast/2,
	handle_info/2,
	terminate/2,
	code_change/3
	]).
-define(SERVER,?MODULE).
-define(TABLE_ID,?MODULE).

start_link()->
    gen_server:start_link({local,?SERVER},?MODULE,[],[]).

insert(Acc,Pid)->
    gen_server:cast(?SERVER,{insert,{Acc,Pid}}).

lookup(Acc)->
    gen_server:call(?SERVER,{lookup,Acc}).

delete(Pid)->
    gen_server:cast(?SERVER,{delete,Pid}).

init([])->
    ets:new(?TABLE_ID,[private,named_table,set]),
    {ok,state}.

handle_call({lookup,Acc},_,State)->
    Value=ets:lookup(?TABLE_ID,Acc),
    {reply,{ok,Value},State}.

handle_cast({insert,{Acc,Pid}},State)->
    ets:insert(?TABLE_ID,{Acc,Pid}),
    {noreply,State};
handle_cast({delete,Pid},State)->
    ets:match_delete(?TABLE_ID,{'_',Pid}),
    {noreply,State}.

handle_info(_,State)->
    {noreply,State}.

terminate(_Reason,_State)->
    ok.

code_change(_OldVsn,State,_Extra)->
    {ok,State}.

cs_accToSearchDBPid模块中导出了3个接口函数:insert是插入新的Acc-Pid对,lookup是通过Acc查询对应的进程Pid,delete是删除一个Acc-Pid对。

具体的查询进程模块,请见下篇文章。

你可能感兴趣的:(erlang,pid,ets)