forked from consensus-oracle/coracle
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_proxy.ml
More file actions
77 lines (69 loc) · 2.59 KB
/
Copy pathclient_proxy.ml
File metadata and controls
77 lines (69 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
open Common
open Rpcs
open Io
open Yojson.Safe
type state = {
id: id;
last_leader: id option;
servers: int;
outstanding: (int * cmd) option;
seq_num: int;
timeout: int option;
}
let try_next state =
match state.last_leader with
| Some id -> id
| None -> Numbergen.uniform 1 state.servers
let init id (config:State.config) = {
id=id;
last_leader=None;
servers = config.servers;
outstanding =None;
seq_num = 1;
timeout = config.client_timer;
}
let state_to_json state : json =
`Assoc [
("type", `String "state update");
("data", `Assoc [
("last leader", match state.last_leader with None -> `String "none" | Some id -> `Int id);
("outstanding", match state.outstanding with None -> `String "none" | Some (id,cmd) -> `Int id);
("next sequence number", `Int state.seq_num);
]);
]
let receive_timeout timer state global =
match timer, state.outstanding with
| Client n, Some (seq_num,cmd) ->
let pkt = CRA ClientArg.({seq_num;cmd}) in
let state = {state with last_leader=None} in
(Some state,
[PacketDispatch (try_next state,pkt);
SetTimeout (pull state.timeout,Client state.seq_num);
],Global.update (`CL `ARG_SND) global)
| _ -> (* ignore *) (None,[],global)
let receive_client_request_reply id (pkt:ClientRes.t) state global =
let global = Global.update (`CL `RES_RCV) global in
match state.outstanding with
| None -> (* ignore it *) (None,[],global)
| Some (n,_) when n<>pkt.seq_num -> (* ignore it *) (None,[],global)
| Some (seq_num,cmd) -> (
match pkt.success with
| Some result ->
(Some {state with outstanding=None; last_leader=Some id},
[LocalDispatch (Outcome result); CancelTimeout (Client seq_num)],global)
| None ->
let new_pkt = CRA ClientArg.({seq_num;cmd}) in
let state = {state with last_leader= pkt.leader_hint} in
(Some state,[PacketDispatch (try_next state, new_pkt); ResetTimeout (pull state.timeout,Client seq_num)],
Global.update (`CL `ARG_SND) global))
let recieve_client_request client_cmd (state:state) global =
match state.outstanding with
| None ->
let pkt = CRA ClientArg.({seq_num = state.seq_num; cmd = client_cmd}) in
(Some {state with outstanding = Some (state.seq_num, client_cmd); seq_num=state.seq_num+1},
[PacketDispatch (try_next state,pkt);
SetTimeout (pull state.timeout,Client state.seq_num)],
Global.update (`CL `ARG_SND) global)
| Some _ -> (* can only had one request at a time *)
(* TODO: remove hard coding *)
(None, [LocalDispatch (Outcome Failure)],global)