|
| 1 | +open Picos_io |
| 2 | +open Picos_io_cohttp |
| 3 | +open Picos_std_finally |
| 4 | +open Picos_std_structured |
| 5 | + |
| 6 | +module String_ext = struct |
| 7 | + let drop_prefix_opt ~prefix s = |
| 8 | + if String.starts_with ~prefix s then |
| 9 | + let i = String.length prefix in |
| 10 | + Some (String.sub s i (String.length s - i)) |
| 11 | + else None |
| 12 | +end |
| 13 | + |
| 14 | +module Option_ext = struct |
| 15 | + let ( >>= ) = Option.bind |
| 16 | + let ( >>- ) xO xy = Option.map xy xO |
| 17 | + |
| 18 | + let ( <|> ) xyO1 xyO2 x = |
| 19 | + match xyO1 x with Some _ as some -> some | None -> xyO2 x |
| 20 | + |
| 21 | + let filter p x = if p x then Some x else None |
| 22 | +end |
| 23 | + |
| 24 | +module Scheduler = struct |
| 25 | + open Option_ext |
| 26 | + |
| 27 | + let parse = |
| 28 | + let parse_0 name con s = |
| 29 | + String_ext.drop_prefix_opt ~prefix:name s |
| 30 | + >>- String.trim |
| 31 | + >>= filter (( = ) "") |
| 32 | + >>- fun _ -> con |
| 33 | + and parse_1 name con s = |
| 34 | + String_ext.drop_prefix_opt ~prefix:name s |
| 35 | + >>- String.trim >>= int_of_string_opt |
| 36 | + >>= filter (fun n -> 1 <= n && n <= Domain.recommended_domain_count ()) |
| 37 | + >>- con |
| 38 | + in |
| 39 | + fun s -> |
| 40 | + match |
| 41 | + String.trim s |
| 42 | + |> (parse_0 "fifo" `Fifo <|> parse_0 "thread" `Thread |
| 43 | + <|> parse_1 "multififo" (fun n -> `Multififo n) |
| 44 | + <|> parse_1 "random" (fun n -> `Random n)) |
| 45 | + with |
| 46 | + | None -> failwith "Unknown or unacceptable scheduler" |
| 47 | + | Some s -> s |
| 48 | +end |
| 49 | + |
| 50 | +let main ~port ~n_connections ~n_servers () = |
| 51 | + let@ server_socket = |
| 52 | + finally Unix.close @@ fun () -> |
| 53 | + Unix.socket ~cloexec:true PF_INET SOCK_STREAM 0 |
| 54 | + in |
| 55 | + Unix.set_nonblock server_socket; |
| 56 | + Unix.bind server_socket Unix.(ADDR_INET (inet_addr_loopback, port)); |
| 57 | + Unix.listen server_socket n_connections; |
| 58 | + let callback _conn _req _req_body = |
| 59 | + let res_body = "Hello world!\n" in |
| 60 | + Server.respond_string ~status:`OK ~body:res_body () |
| 61 | + in |
| 62 | + Flock.join_after @@ fun () -> |
| 63 | + for _ = 1 to n_servers do |
| 64 | + Flock.fork @@ fun () -> Server.run (Server.make ~callback ()) server_socket |
| 65 | + done |
| 66 | + |
| 67 | +let () = |
| 68 | + let port = ref 8082 |
| 69 | + and n_connections = ref 300 |
| 70 | + and scheduler = ref `Fifo |
| 71 | + and n_servers = ref 1 in |
| 72 | + let specs = |
| 73 | + [ |
| 74 | + ("-port", Arg.Set_int port, "\t Port"); |
| 75 | + ("-conns", Arg.Set_int n_connections, "\t Connections"); |
| 76 | + ("-servers", Arg.Set_int n_servers, "\t Server fibers"); |
| 77 | + ( "-scheduler", |
| 78 | + Arg.String (fun s -> scheduler := Scheduler.parse s), |
| 79 | + "\t Scheduler ('fifo' | 'thread' | 'multififo n' | 'random n')" ); |
| 80 | + ] |
| 81 | + in |
| 82 | + Arg.parse specs ignore ""; |
| 83 | + let main = |
| 84 | + main ~port:!port ~n_connections:!n_connections ~n_servers:!n_servers |
| 85 | + in |
| 86 | + match !scheduler with |
| 87 | + | `Fifo -> |
| 88 | + Printf.printf "Fifo\n%!"; |
| 89 | + Picos_mux_fifo.run main |
| 90 | + | `Thread -> |
| 91 | + Printf.printf "Thread\n%!"; |
| 92 | + Picos_mux_thread.run main |
| 93 | + | `Multififo n_domains -> |
| 94 | + Printf.printf "Multififo %d\n%!" n_domains; |
| 95 | + Picos_mux_multififo.run_on ~n_domains main |
| 96 | + | `Random n_domains -> |
| 97 | + Printf.printf "Random %d\n%!" n_domains; |
| 98 | + Picos_mux_random.run_on ~n_domains main |
0 commit comments