Skip to content

Commit f51e7e7

Browse files
authored
Merge epoll feature branch to master (xapi-project#6005)
Pending some final testing by QA, these commits have already been reviewed on the feature branch. This switches `select` calls to `Unixext.select` (which is implemented using `epoll`), and implements the few performance sensitive parts using epoll directly. It also enables some more tests with >1024 fds.
2 parents bc10ca0 + 8cf7ab2 commit f51e7e7

File tree

27 files changed

+183
-26
lines changed

27 files changed

+183
-26
lines changed

ezxenstore.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ depends: [
1414
"cmdliner" {with-test & >= "1.1.0"}
1515
"logs"
1616
"uuidm"
17+
"xapi-stdext-unix"
1718
"xenctrl"
1819
"xenstore"
1920
"xenstore_transport"

ezxenstore.opam.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ depends: [
1212
"cmdliner" {with-test & >= "1.1.0"}
1313
"logs"
1414
"uuidm"
15+
"xapi-stdext-unix"
1516
"xenctrl"
1617
"xenstore"
1718
"xenstore_transport"

ocaml/database/block_device_io.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ let accept_conn s latest_response_time =
328328
let now = Unix.gettimeofday () in
329329
let timeout = latest_response_time -. now in
330330
(* Await an incoming connection... *)
331-
let ready_to_read, _, _ = Unix.select [s] [] [] timeout in
331+
let ready_to_read, _, _ = Xapi_stdext_unix.Unixext.select [s] [] [] timeout in
332332
R.info "Finished selecting" ;
333333
if List.mem s ready_to_read then
334334
(* We've received a connection. Accept it and return the socket. *)

ocaml/database/master_connection.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,11 @@ let open_secure_connection () =
171171
~write_to_log:(fun x -> debug "stunnel: %s\n" x)
172172
~verify_cert host port
173173
@@ fun st_proc ->
174-
let fd_closed = Thread.wait_timed_read Unixfd.(!(st_proc.Stunnel.fd)) 5. in
174+
let fd_closed =
175+
Xapi_stdext_threads.Threadext.wait_timed_read
176+
Unixfd.(!(st_proc.Stunnel.fd))
177+
5.
178+
in
175179
let proc_quit =
176180
try
177181
Unix.kill (Stunnel.getpid st_proc.Stunnel.pid) 0 ;

ocaml/forkexecd/src/child.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ let handle_comms_sock comms_sock state =
6161

6262
let handle_comms_no_fd_sock2 comms_sock fd_sock state =
6363
debug "Selecting in handle_comms_no_fd_sock2" ;
64-
let ready, _, _ = Unix.select [comms_sock; fd_sock] [] [] (-1.0) in
64+
let ready, _, _ =
65+
Xapi_stdext_unix.Unixext.select [comms_sock; fd_sock] [] [] (-1.0)
66+
in
6567
debug "Done" ;
6668
if List.mem fd_sock ready then (
6769
debug "fd sock" ;
@@ -74,7 +76,9 @@ let handle_comms_no_fd_sock2 comms_sock fd_sock state =
7476

7577
let handle_comms_with_fd_sock2 comms_sock _fd_sock fd_sock2 state =
7678
debug "Selecting in handle_comms_with_fd_sock2" ;
77-
let ready, _, _ = Unix.select [comms_sock; fd_sock2] [] [] (-1.0) in
79+
let ready, _, _ =
80+
Xapi_stdext_unix.Unixext.select [comms_sock; fd_sock2] [] [] (-1.0)
81+
in
7882
debug "Done" ;
7983
if List.mem fd_sock2 ready then (
8084
debug "fd sock2" ;

ocaml/libs/ezxenstore/core/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
(re_export xenstore)
1010
(re_export xenstore_transport)
1111
threads.posix
12+
xapi-stdext-unix
1213
(re_export xenstore.unix))
1314
)

ocaml/libs/ezxenstore/core/watch.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ let wait_for ~xs ?(timeout = 300.) (x : 'a t) =
5050
let thread =
5151
Thread.create
5252
(fun () ->
53-
let r, _, _ = Unix.select [p1] [] [] timeout in
53+
let r, _, _ = Xapi_stdext_unix.Unixext.select [p1] [] [] timeout in
5454
if r <> [] then
5555
()
5656
else

ocaml/libs/http-lib/buf_io.ml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,21 @@ let is_full ic = ic.cur = 0 && ic.max = Bytes.length ic.buf
7474
let fill_buf ~buffered ic timeout =
7575
let buf_size = Bytes.length ic.buf in
7676
let fill_no_exc timeout len =
77-
let l, _, _ = Unix.select [ic.fd] [] [] timeout in
78-
if l <> [] then (
77+
Xapi_stdext_unix.Unixext.with_socket_timeout ic.fd timeout @@ fun () ->
78+
try
7979
let n = Unix.read ic.fd ic.buf ic.max len in
8080
ic.max <- n + ic.max ;
8181
if n = 0 && len <> 0 then raise Eof ;
8282
n
83-
) else
84-
-1
83+
with Unix.Unix_error (Unix.(EAGAIN | EWOULDBLOCK), _, _) -> -1
8584
in
8685
(* If there's no space to read, shift *)
8786
if ic.max = buf_size then shift ic ;
8887
let space_left = buf_size - ic.max in
8988
(* Read byte one by one just do make sure we don't buffer too many chars *)
9089
let n =
91-
fill_no_exc timeout (if buffered then space_left else min space_left 1)
90+
fill_no_exc (Some timeout)
91+
(if buffered then space_left else min space_left 1)
9292
in
9393
(* Select returned nothing to read *)
9494
if n = -1 then raise Timeout ;
@@ -97,7 +97,11 @@ let fill_buf ~buffered ic timeout =
9797
let tofillsz =
9898
if buffered then buf_size - ic.max else min (buf_size - ic.max) 1
9999
in
100-
ignore (fill_no_exc 0.0 tofillsz)
100+
(* cannot use 0 here, for select that'd mean timeout immediately, for
101+
setsockopt it would mean no timeout.
102+
So use a very short timeout instead
103+
*)
104+
ignore (fill_no_exc (Some 1e-6) tofillsz)
101105
)
102106

103107
(** Input one line terminated by \n *)

ocaml/libs/http-lib/http.ml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,14 +320,8 @@ let read_frame_header buf =
320320
let prefix = Bytes.sub_string buf 0 frame_header_length in
321321
try Scanf.sscanf prefix "FRAME %012d" (fun x -> Some x) with _ -> None
322322

323-
let set_socket_timeout fd t =
324-
try Unix.(setsockopt_float fd SO_RCVTIMEO t)
325-
with Unix.Unix_error (Unix.ENOTSOCK, _, _) ->
326-
(* In the unit tests, the fd comes from a pipe... ignore *)
327-
()
328-
329323
let read_http_request_header ~read_timeout ~total_timeout ~max_length fd =
330-
Option.iter (fun t -> set_socket_timeout fd t) read_timeout ;
324+
Unixext.with_socket_timeout fd read_timeout @@ fun () ->
331325
let buf = Bytes.create (Option.value ~default:1024 max_length) in
332326
let deadline =
333327
Option.map
@@ -372,7 +366,6 @@ let read_http_request_header ~read_timeout ~total_timeout ~max_length fd =
372366
check_timeout_and_read 0 length ;
373367
(true, length)
374368
in
375-
set_socket_timeout fd 0. ;
376369
(frame, Bytes.sub_string buf 0 headers_length, proxy)
377370

378371
let read_http_response_header buf fd =

ocaml/libs/xapi-stdext/lib/xapi-stdext-unix/unixext.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,3 +1062,18 @@ module Daemon = struct
10621062
true
10631063
with Unix.Unix_error _ -> false
10641064
end
1065+
1066+
let set_socket_timeout fd t =
1067+
try Unix.(setsockopt_float fd SO_RCVTIMEO t)
1068+
with Unix.Unix_error (Unix.ENOTSOCK, _, _) ->
1069+
(* In the unit tests, the fd comes from a pipe... ignore *)
1070+
()
1071+
1072+
let with_socket_timeout fd timeout_opt f =
1073+
match timeout_opt with
1074+
| Some t ->
1075+
if t < 1e-6 then invalid_arg (Printf.sprintf "Timeout too short: %g" t) ;
1076+
let finally () = set_socket_timeout fd 0. in
1077+
set_socket_timeout fd t ; Fun.protect ~finally f
1078+
| None ->
1079+
f ()

0 commit comments

Comments
 (0)