P2P: Introduce a worker dedicated to user events

This commit is contained in:
Vincent Bernardoff 2016-11-30 16:29:11 +01:00 committed by Grégoire Henry
parent a832c2069f
commit bdb2d20f05

View File

@ -1061,35 +1061,44 @@ module Make (P: PARAMS) = struct
(fun (n, l) (point, _, _) -> if n = 0 then (n, l) else (n - 1, point :: l)) (fun (n, l) (point, _, _) -> if n = 0 then (n, l) else (n - 1, point :: l))
(50, []) |> snd (50, []) |> snd
in in
let rec available_events () = let next_peer_event () =
let peers = PeerMap.bindings !connected in let rec peer_events () =
let current_peers_evts = let peers = PeerMap.bindings !connected in
List.map (fun (_, gid, p) -> let current_peers_evts =
Lwt_pipe.values_available p.reader >|= fun () -> gid, p.reader) List.map begin function
peers | _, Some gid, p -> Lwt_pipe.values_available p.reader >|= fun () -> gid, p.reader
| _ -> Lwt_utils.never_ending
end peers
in
Lwt.choose [
(LC.wait new_peer >>= fun _p -> peer_events ());
Lwt.nchoose current_peers_evts;
]
in in
Lwt.choose [ peer_events () >>= fun evts ->
(LC.wait new_peer >>= fun _p -> available_events ());
Lwt.nchoose @@
(Lwt_pipe.values_available events >|= fun () -> None, events) :: current_peers_evts
]
in
let rec choose_event () =
available_events () >>= fun evts ->
let nb_evts = List.length evts in let nb_evts = List.length evts in
let gid, evtqueue = List.nth evts (Random.int nb_evts) in let gid, evtqueue = List.nth evts (Random.int nb_evts) in
begin match gid with lwt_debug "(%a) Processing event from %a" pp_gid my_gid pp_gid gid >|= fun () ->
| None -> lwt_debug "(%a) Processing event from main" pp_gid my_gid
| Some remote_gid -> lwt_debug "(%a) Processing event from %a" pp_gid my_gid pp_gid remote_gid
end >|= fun () ->
Lwt_pipe.pop_now_exn evtqueue Lwt_pipe.pop_now_exn evtqueue
in in
(* main internal event handling worker *) let rec peers () =
let rec main () = (* user event handling worker *)
Lwt.pick [
next_peer_event () ;
cancelation () >>= fun () -> Lwt.return Shutdown ;
] >>= fun event -> match event with
| Recv (peer, msg) -> Lwt_pipe.push messages (peer, msg) >>= peers
| msg -> Lwt_pipe.push events msg >>= peers
in
(* internal event handling worker *)
let rec admin () =
Lwt.pick Lwt.pick
[ choose_event () ; [ Lwt_pipe.pop events ;
cancelation () >>= fun () -> Lwt.return Shutdown ] >>= fun event -> cancelation () >>= fun () -> Lwt.return Shutdown ] >>= fun event ->
match event with match event with
| Recv _ ->
(* Invariant broken *)
Lwt.fail_with "admin: got a Recv message (broken invariant)"
| Disconnected peer -> | Disconnected peer ->
debug "(%a) disconnected peer %a" pp_gid my_gid pp_gid peer.gid ; debug "(%a) disconnected peer %a" pp_gid my_gid pp_gid peer.gid ;
(* remove it from the tables *) (* remove it from the tables *)
@ -1097,7 +1106,7 @@ module Make (P: PARAMS) = struct
if PeerMap.cardinal !connected < limits.min_connections then if PeerMap.cardinal !connected < limits.min_connections then
LC.broadcast too_few_peers () ; LC.broadcast too_few_peers () ;
incoming := PointMap.remove peer.point !incoming ; incoming := PointMap.remove peer.point !incoming ;
main () admin ()
| Connected peer -> | Connected peer ->
incoming := PointMap.remove peer.point !incoming ; incoming := PointMap.remove peer.point !incoming ;
let update_infos () = let update_infos () =
@ -1162,7 +1171,7 @@ module Make (P: PARAMS) = struct
LC.broadcast too_many_peers () ; LC.broadcast too_many_peers () ;
LC.broadcast new_peer peer LC.broadcast new_peer peer
end ; end ;
main () admin ()
| Contact ((addr, port), socket) -> | Contact ((addr, port), socket) ->
(* we do not check the credentials at this stage, since they (* we do not check the credentials at this stage, since they
could change from one connection to the next *) could change from one connection to the next *)
@ -1170,7 +1179,7 @@ module Make (P: PARAMS) = struct
|| PeerMap.mem_by_point (addr, port) !connected || PeerMap.mem_by_point (addr, port) !connected
|| BlackList.mem addr !black_list then || BlackList.mem addr !black_list then
LU.close socket >>= fun () -> LU.close socket >>= fun () ->
main () admin ()
else else
let canceler = let canceler =
connect_to_peer connect_to_peer
@ -1179,14 +1188,11 @@ module Make (P: PARAMS) = struct
debug "(%a) incoming peer @@ %a:%d" debug "(%a) incoming peer @@ %a:%d"
pp_gid my_gid Ipaddr.pp_hum addr port ; pp_gid my_gid Ipaddr.pp_hum addr port ;
incoming := PointMap.add (addr, port) canceler !incoming ; incoming := PointMap.add (addr, port) canceler !incoming ;
main () admin ()
| Bootstrap peer -> | Bootstrap peer ->
let sample = bootstrap_peers () in let sample = bootstrap_peers () in
Lwt.async (fun () -> peer.send (Advertise sample)) ; Lwt.async (fun () -> peer.send (Advertise sample)) ;
main () admin ()
| Recv (peer, msg) ->
Lwt_pipe.push messages (peer, msg) >>=
main
| Peers peers -> | Peers peers ->
List.iter List.iter
(fun point -> (fun point ->
@ -1199,7 +1205,7 @@ module Make (P: PARAMS) = struct
known_peers := PeerMap.update point source !known_peers ; known_peers := PeerMap.update point source !known_peers ;
LC.broadcast new_contact point) LC.broadcast new_contact point)
peers ; peers ;
main () admin ()
| Shutdown -> | Shutdown ->
Lwt.return_unit Lwt.return_unit
in in
@ -1233,10 +1239,14 @@ module Make (P: PARAMS) = struct
Lwt_utils.worker Lwt_utils.worker
(Format.asprintf "(%a) maintenance" pp_gid my_gid) (Format.asprintf "(%a) maintenance" pp_gid my_gid)
maintenance cancel in maintenance cancel in
let main = let peers_worker =
Lwt_utils.worker Lwt_utils.worker
(Format.asprintf "(%a) reception" pp_gid my_gid) (Format.asprintf "(%a) peers" pp_gid my_gid)
main cancel in peers cancel in
let admin =
Lwt_utils.worker
(Format.asprintf "(%a) admin" pp_gid my_gid)
admin cancel in
let unblock = let unblock =
Lwt_utils.worker Lwt_utils.worker
(Format.asprintf "(%a) unblacklister" pp_gid my_gid) (Format.asprintf "(%a) unblacklister" pp_gid my_gid)
@ -1282,7 +1292,7 @@ module Make (P: PARAMS) = struct
(* stop accepting clients *) (* stop accepting clients *)
cancel () >>= fun () -> cancel () >>= fun () ->
(* wait for both workers to end *) (* wait for both workers to end *)
Lwt.join [ welcome ; main ; maintenance ; unblock ; Lwt.join [ welcome ; peers_worker ; admin ; maintenance ; unblock ;
discovery_answerer ; discovery_sender ] >>= fun () -> discovery_answerer ; discovery_sender ] >>= fun () ->
(* properly shutdown all peers *) (* properly shutdown all peers *)
let cancelers = let cancelers =