step by step开发一个简易股票交易系统(五)---数据库使用

Step5:使用mnesia代替进程字典
1.创建mnesia表init_db.erl

-module(init_db).
-import(lists, [foreach/2]).
-compile(export_all).

-include_lib("stdlib/include/qlc.hrl").
-record(stock,{id,pid}).

do_this_once() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(stock,[{ram_copies, [node()]},{attributes, record_info(fields,stock)}]),
mnesia:stop().


2.stock_server.erl

-module(stock_server).

-behaviour(gen_server).

-export([list/1, sell/2, buy/2, start/0,stop/0,start_trade/1,stop_trade/1]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(stock,{id,pid}).

-import(lists, [foreach/2]).
-import(stock,[start/1,stop/1]).

-include_lib("stdlib/include/qlc.hrl").

start()->gen_server:start_link({local,stock_server},stock_server,[],[]).
stop()->gen_server:cast(?MODULE,stop).
sell(Id,Trade)->gen_server:cast(?MODULE,{sell,Id,Trade}).
buy(Id,Trade)->gen_server:cast(?MODULE,{buy,Id,Trade}).
list(Id)->gen_server:cast(?MODULE,{list,Id}).
start_trade(Id)->gen_server:cast(?MODULE,{start_trade,Id}).
stop_trade(Id)->gen_server:cast(?MODULE,{stop_trade,Id}).

init([]) ->
mnesia:start(),
mnesia:wait_for_tables([stock], 20000),
foreach(fun start_stock/1,getStock()),
{ok, []}.

handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.


handle_cast(stop,State) ->
{stop,normal,State};

handle_cast({start_trade,Id},State) ->
start_stock(Id),
{noreply, State};
handle_cast({stop_trade,Id},State) ->
case getPid(Id) of
[]->
io:format("stock Id=~w no such stock~n",[Id]);
[stop]->
io:format("stock Id=~w have no start trade~n",[Id]);

[Pid]->
gen_server:cast(Pid,stop),
removeId(Id)
end,
{noreply, State};

handle_cast({list,Id}, State) ->
case getPid(Id) of
[]->
io:format("stock Id=~w no such stock~n",[Id]);
[stop]->
io:format("stock Id=~w have no start trade~n",[Id]);
[Pid]->
gen_server:cast(Pid,{list,5})
end,
{noreply, State};

handle_cast({buy,Id,Trade}, State) ->
case getPid(Id) of
[]->
io:format("stock Id=~w no such stock~n",[Id]);
[stop]->
io:format("stock Id=~w have no start trade~n",[Id]);
[Pid]->

gen_server:cast(Pid,{buy,Trade})
end,
{noreply, State};

handle_cast({sell,Id,Trade}, State) ->
case getPid(Id) of
[]->
io:format("stock Id=~w no such stock~n",[Id]);
[stop]->
io:format("stock Id=~w have no start trade~n",[Id]);
[Pid]->

gen_server:cast(Pid,{sell,Trade})
end,
{noreply, State};

handle_cast({ok,Msg}, State) ->
io:format("ok: ~w~n",[Msg]),
{noreply, State};

handle_cast(_Msg, State) ->
{noreply, State}.

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

terminate(_Reason, _State) ->
foreach(fun stop_stock/1,getStock()),
mnesia:stop(),
ok.

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

%% --------------------------------------------------------------------
%%% Internal functions
%% --------------------------------------------------------------------
removeId(Item) ->
Oid = {stock, Item},
F = fun() ->
mnesia:delete(Oid)
end,
mnesia:transaction(F).

saveId(Id,Pid)->
Row = #stock{id=Id,pid=Pid},
F = fun() ->
mnesia:write(Row)
end,
mnesia:transaction(F).

getStock()->
do(qlc:q([{X#stock.id,X#stock.pid} || X <- mnesia:table(stock)])).

getPid(Id)->
do(qlc:q([X#stock.pid || X <- mnesia:table(stock),
X#stock.id =:=Id])).

do(Q) ->
F = fun() -> qlc:e(Q) end,
{atomic, Val} = mnesia:transaction(F),
Val.

start_stock({Id,_})->
case gen_server:start(stock,[],[]) of
{ok,Pid}->saveId(Id,Pid);
Any->
io:format("start_trade error:~w~n",[Any])
end.

stop_stock({Id,Pid})->
case Pid of
stop->
ok;
Pid->
gen_server:cast(Pid, stop)
end,
saveId(Id,stop).

3.stock.erl
-module(stock).

-behaviour(gen_server).
-export([start/0,stop/0]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).


start()->gen_server:start_link({local,?MODULE},?MODULE,[],[]).
stop()->gen_server:cast(?MODULE,stop).
init([]) ->
{ok, {[],[],1}}.

handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.


handle_cast({sell,{Price,Number,Name}}, {BuyL,SellL,TradeId}) ->
case lookup(buy,{Price,none},BuyL) of
{_,Price,0,none}->
L2=add(sell,{TradeId,Price,Number,Name},SellL),
gen_server:cast(stock_server,{ok,hangup}),
{noreply,{BuyL,L2,TradeId+1}};
{TradeId1,Price1,Number1,Buy}->
if Number1=:=Number->
L2=remove({TradeId1,Price1,Number1,Buy},BuyL),
gen_server:cast(stock_server,{ok,Buy}),
{noreply,{L2,SellL,TradeId}};
Number1<Number->
L2=remove({TradeId1,Price1,Number1,Buy},BuyL),
gen_server:cast(stock_server,{ok,Buy}),
handle_cast({sell,{Price,Number-Number1,Name}},{L2,SellL,TradeId});
Number1>Number->
L2=[replace(X,{TradeId1,Price1,Number1,Buy},Number1-Number)||X<-BuyL],
gen_server:cast(stock_server,{ok,Buy}),
{noreply,{L2,SellL,TradeId}}
end

end;


handle_cast({buy,{Price,Number,Name}}, {BuyL,SellL,TradeId}) ->
case lookup(sell,{Price,none},SellL) of
{_,Price,0,none}->
L2=add(buy,{TradeId,Price,Number,Name},BuyL),
gen_server:cast(stock_server,{ok,hangup}),
{noreply,{L2,SellL,TradeId+1}};
{TradeId1,Price1,Number1,Sell}->
if Number1=:=Number->
L2=remove({TradeId1,Price1,Number1,Sell},SellL),
gen_server:cast(stock_server,{ok,Sell}),
{noreply,{BuyL,L2,TradeId}};
Number1<Number->
L2=remove({TradeId1,Price1,Number1,Sell},SellL),
gen_server:cast(stock_server,{ok,Sell}),
handle_cast({buy,{Price,Number-Number1,Name}},{BuyL,L2,TradeId});
Number1>Number->
L2=[replace(X,{TradeId1,Price1,Number1,Sell},Number1-Number)||X<-SellL],
gen_server:cast(stock_server,{ok,Sell}),
{noreply,{BuyL,L2,TradeId}}
end

end;

handle_cast({list,Count}, {BuyL,SellL,TradeId}) ->
X = getList(Count,BuyL),
gen_server:cast(stock_server,{ok,{buy_list,X}}),
Y = getList(Count,SellL),
gen_server:cast(stock_server,{ok,{sell_list,Y}}),
{noreply,{BuyL,SellL,TradeId}};

handle_cast(stop,State) ->
{stop,normal,State};

handle_cast(_Msg, State) ->
{noreply, State}.

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

terminate(_Reason, _State) ->
ok.

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

lookup(sell,{Price,Buy},[{TradeId,Price1,Number,Name}|_T]) ->
if
Price>=Price1 -> {TradeId,Price1,Number,Name};
true->{0,Price,0,Buy}
end;

lookup(buy,{Price,Sell},[{TradeId,Price1,Number,Name}|_T]) ->
if
Price=<Price1 -> {TradeId,Price1,Number,Name};
true->{0,Price,0,Sell}
end;
lookup(_,{Price,Name},[])->{0,Price,0,Name}.

add(sell,{TradeId,Price,Number,Name},[{TradeId1,Price1,Number1,Name1}|T]) ->
if
Price>=Price1 -> [{TradeId1,Price1,Number1,Name1}|add(sell,{TradeId,Price,Number,Name},T)];
true->[{TradeId,Price,Number,Name}|[{TradeId1,Price1,Number1,Name1}|T]]
end;

add(buy,{TradeId,Price,Number,Name},[{TradeId1,Price1,Number1,Name1}|T]) ->
if
Price=<Price1 -> [{TradeId1,Price1,Number1,Name1}|add(buy,{TradeId,Price,Number,Name},T)];
true->[{TradeId,Price,Number,Name}|[{TradeId1,Price1,Number1,Name1}|T]]
end;
add(_,{TradeId,Price,Number,Name},[])->[{TradeId,Price,Number,Name}].

remove(Trade,L)-> [X||X<-L,X/=Trade].

replace({TradeId,Price,Number,Name},{TradeId1,Price1,Number1,Name1},Number2)->
if
{TradeId1,Price1,Number1,Name1}=:={TradeId,Price,Number,Name}->
{TradeId,Price,Number2,Name};
true->{TradeId,Price,Number,Name}
end.

getList(_,[])->[];
getList(0,_)->[];
getList(Count,[{_,Price,Number,Name}|T])->
[{Price,Number,Name}|getList(Count-1,T)].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值