;;
let code (c,_,_) = c
type quote
= { price
:int; } ;;
type response = {
req: request;
body: quote;
}
;;
(* 再送信要求のレスポンスは送信idと紐付けられていない(!)ため、
一度に多くのリクエストを投げた後は、レスポンスを整列させる必要がある。 *)
struct
type t = request
end)
;;
(* メッセージを整列させつつ格納するバッファ。
(通貨ペア, 問い合わせfrom, to) をキーとして
(受信した数, メッセージの配列) のリストで管理する。
リストになっているのは、重複するキーを持つレスポンスに対応するためである。
*)
let buf
: (int * quote
option array) list M
.t
ref = ref M
.empty
;;
(* 株価のリストをデータベースに保存する. ダミーで画面への出力関数にしてある *)
| Some q
-> Printf.printf
"%d;" q
.price
| None -> failwith "impossible"
end quotes;
;;
(*
メッセージrをバッファに格納する。 レスポンス全体が得られたら、saveで保存する。
*)
let receive_quote
(r
:response
) : unit = if r.total=1 then save (code r.req) [Some r.body] (* 総レコードが1件のみであればすぐに保存 *)
else begin
let map = !buf in
(* このリクエストに対するレスポンスのリスト(更新前) *)
let all = try M.find r.req map with Not_found -> [] in
(* バッファに新しいレスポンスを追加 *)
let newentry () =
let arr
= Array.make r
.total None
in arr.(r.seq) <- Some r.body;
buf := M.add r.req ((1, arr)::all) map
in
(* レスポンスのリストを走査し適切な位置に格納 / レスポンス全体が満たされたら保存 *)
let rec addentry rest = function
| [] -> newentry ()
| (cnt, arr) as y::ys ->
match arr.(r.seq) with
| None ->
arr.(r.seq) <- Some r.body; (* レスポンスの該当する連番を満たす *)
if cnt+1=r.total then begin
(* レスポンス全体が満たされた. 保存後、この配列をバッファから除く *)
save
(code r
.req
) (Array.to_list arr
) (* 保存 *); buf
:= M
.add r
.req
(List.rev_append rest ys
) map
end else
(* また足りない.受信済み数をインクリメントしバッファを更新 *)
buf
:= M
.add r
.req
(List.rev_append rest
((cnt
+1, arr
)::ys
)) map
| Some q -> (* このレスポンスでは格納済み. 次のレスポンスを見る *)
addentry (y::rest) ys
in
addentry [] all
end
;;
let test =
let a="A","1","4" and b = "B","1","2" in
let resps = [
{req=a; body={price=1100}; total=4; seq=0};
{req=a; body={price=1098}; total=4; seq=1};
{req=a; body={price=1100}; total=4; seq=0};
{req=b; body={price=910}; total=2; seq=0};
{req=a; body={price=1098}; total=4; seq=1};
{req=a; body={price=1081}; total=4; seq=2};
{req=a; body={price=1081}; total=4; seq=2};
{req=a; body={price=1120}; total=4; seq=3};
{req=b; body={price=940}; total=2; seq=1};
{req=a; body={price=1120}; total=4; seq=3};
] in
List.iter receive_quote resps