fork(1) download
  1. type request = string * string * string
  2. ;;
  3. let code (c,_,_) = c
  4.  
  5. type quote = { price:int; }
  6. ;;
  7.  
  8. type response = {
  9. req: request;
  10. body: quote;
  11. seq:int;
  12. total:int;
  13. }
  14. ;;
  15.  
  16. (* 再送信要求のレスポンスは送信idと紐付けられていない(!)ため、
  17.   一度に多くのリクエストを投げた後は、レスポンスを整列させる必要がある。 *)
  18.  
  19. module M = Map.Make (
  20. struct
  21. type t = request
  22. end)
  23. ;;
  24.  
  25. (* メッセージを整列させつつ格納するバッファ。
  26.   (通貨ペア, 問い合わせfrom, to) をキーとして
  27.   (受信した数, メッセージの配列) のリストで管理する。
  28.   リストになっているのは、重複するキーを持つレスポンスに対応するためである。
  29. *)
  30. let buf : (int * quote option array) list M.t ref = ref M.empty
  31. ;;
  32.  
  33. (* 株価のリストをデータベースに保存する. ダミーで画面への出力関数にしてある *)
  34. let save (code:string) (quotes:quote option list) : unit =
  35. print_string (code ^ " ");
  36. List.iter begin function
  37. | Some q -> Printf.printf "%d;" q.price
  38. | None -> failwith "impossible"
  39. end quotes;
  40. ;;
  41.  
  42. (*
  43.   メッセージrをバッファに格納する。 レスポンス全体が得られたら、saveで保存する。
  44. *)
  45. let receive_quote (r:response) : unit =
  46. if r.total=1 then save (code r.req) [Some r.body] (* 総レコードが1件のみであればすぐに保存 *)
  47. else begin
  48. let map = !buf in
  49. (* このリクエストに対するレスポンスのリスト(更新前) *)
  50. let all = try M.find r.req map with Not_found -> [] in
  51.  
  52. (* バッファに新しいレスポンスを追加 *)
  53. let newentry () =
  54. let arr = Array.make r.total None in
  55. arr.(r.seq) <- Some r.body;
  56. buf := M.add r.req ((1, arr)::all) map
  57. in
  58.  
  59. (* レスポンスのリストを走査し適切な位置に格納 / レスポンス全体が満たされたら保存 *)
  60. let rec addentry rest = function
  61. | [] -> newentry ()
  62. | (cnt, arr) as y::ys ->
  63. match arr.(r.seq) with
  64. | None ->
  65. arr.(r.seq) <- Some r.body; (* レスポンスの該当する連番を満たす *)
  66. if cnt+1=r.total then begin
  67. (* レスポンス全体が満たされた. 保存後、この配列をバッファから除く *)
  68. save (code r.req) (Array.to_list arr) (* 保存 *);
  69. buf := M.add r.req (List.rev_append rest ys) map
  70. end else
  71. (* また足りない.受信済み数をインクリメントしバッファを更新 *)
  72. buf := M.add r.req (List.rev_append rest ((cnt+1, arr)::ys)) map
  73. | Some q -> (* このレスポンスでは格納済み. 次のレスポンスを見る *)
  74. addentry (y::rest) ys
  75. in
  76. addentry [] all
  77. end
  78. ;;
  79.  
  80.  
  81. let test =
  82. let a="A","1","4" and b = "B","1","2" in
  83. let resps = [
  84. {req=a; body={price=1100}; total=4; seq=0};
  85. {req=a; body={price=1098}; total=4; seq=1};
  86. {req=a; body={price=1100}; total=4; seq=0};
  87. {req=b; body={price=910}; total=2; seq=0};
  88. {req=a; body={price=1098}; total=4; seq=1};
  89. {req=a; body={price=1081}; total=4; seq=2};
  90. {req=a; body={price=1081}; total=4; seq=2};
  91. {req=a; body={price=1120}; total=4; seq=3};
  92. {req=b; body={price=940}; total=2; seq=1};
  93. {req=a; body={price=1120}; total=4; seq=3};
  94. ] in
  95. List.iter receive_quote resps
  96.  
Success #stdin #stdout 0.02s 2736KB
stdin
Standard input is empty
stdout
A 1100;1098;1081;1120;
B 910;940;
A 1100;1098;1081;1120;