Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@
; because it is not in xs-opam yet
rrd-transport
rrdd-plugin
xapi-stdext-std
xapi-tracing-export
xen-api-client
(alcotest :with-test)
Expand Down
6 changes: 5 additions & 1 deletion ocaml/database/db_cache_impl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,11 @@ let sync conns db =
let flush_dirty dbconn = Db_connections.flush_dirty_and_maybe_exit dbconn None

let flush_and_exit dbconn ret_code =
ignore (Db_connections.flush_dirty_and_maybe_exit dbconn (Some ret_code))
match dbconn with
| Some dbconn ->
ignore (Db_connections.flush_dirty_and_maybe_exit dbconn (Some ret_code))
| None ->
raise Db_not_initialized

let spawn_db_flush_threads () =
(* Spawn threads that flush cache to db connections at regular intervals *)
Expand Down
6 changes: 3 additions & 3 deletions ocaml/database/db_cache_impl.mli
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ include Db_interface.DB_ACCESS2
val make : Db_ref.t -> Parse_db_conf.db_connection list -> Schema.t -> unit
(** [make t connections default_schema] initialises the in-memory cache *)

val flush_and_exit : Parse_db_conf.db_connection -> int -> unit
(** [flush_and_exit db code] flushes the specific backend [db] and exits
xapi with [code] *)
val flush_and_exit : Parse_db_conf.db_connection option -> int -> unit
(** [flush_and_exit db code] flushes the specific backend [db] and exits xapi
with [code]. Raises Db_not_initialized if db is None *)

val sync : Parse_db_conf.db_connection list -> Db_cache_types.Database.t -> unit
(** [sync db] forcibly flushes the database to disk *)
Expand Down
16 changes: 10 additions & 6 deletions ocaml/database/db_connections.ml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ let choose connections =
most_recent.Parse_db_conf.path gen ;
Some most_recent

let preferred_write_db () = List.hd (Db_conn_store.read_db_connections ())
let preferred_write_db () =
Xapi_stdext_std.Listext.List.head (Db_conn_store.read_db_connections ())

(* !!! FIX ME *)

Expand All @@ -75,14 +76,17 @@ let pre_exit_hook () =
R.debug "Closed all active redo logs."

(* The connection flushing calls each lock the connection they're flushing to.
The backend flush calls have to do enough locking (i.e. with the db_lock) to ensure that they
flush a consistent snapshot. Backends must also ensure that they do not hold the global db_lock
whilst they are writing to non-local storage.
The backend flush calls have to do enough locking (i.e. with the db_lock) to
ensure that they flush a consistent snapshot. Backends must also ensure that
they do not hold the global db_lock whilst they are writing to non-local
storage.
*)
let flush_dirty_and_maybe_exit dbconn exit_spec =
Db_conn_store.with_db_conn_lock dbconn (fun () ->
(* if we're being told to shutdown by signal handler then flush every connection
- the rationale is that we're not sure which db connections will be available on next restart *)
(* if we're being told to shutdown by signal handler then flush every
connection
- the rationale is that we're not sure which db connections will be
available on next restart *)
( if !exit_on_next_flush then
let (_ : bool) = Backend_xml.flush_dirty dbconn in
let refcount = dec_and_read_db_flush_thread_refcount () in
Expand Down
2 changes: 1 addition & 1 deletion ocaml/database/db_connections.mli
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ val get_dbs_and_gen_counts : unit -> (int64 * Parse_db_conf.db_connection) list
val choose :
Parse_db_conf.db_connection list -> Parse_db_conf.db_connection option

val preferred_write_db : unit -> Parse_db_conf.db_connection
val preferred_write_db : unit -> Parse_db_conf.db_connection option

val exit_on_next_flush : bool ref

Expand Down
2 changes: 2 additions & 0 deletions ocaml/database/db_exn.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ exception Remote_db_server_returned_bad_message
exception Empty_key_in_map

exception Invalid_value

exception Db_not_initialized
2 changes: 2 additions & 0 deletions ocaml/database/db_exn.mli
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ exception Remote_db_server_returned_bad_message
exception Empty_key_in_map

exception Invalid_value

exception Db_not_initialized
3 changes: 3 additions & 0 deletions ocaml/idl/datamodel_types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ let release_order_full =
let release_order =
List.filter (fun x -> x.code_name <> None) release_order_full

let latest_release =
Xapi_stdext_std.Listext.List.last release_order |> Option.get

exception Unknown_release of string

exception UnspecifiedRelease
Expand Down
2 changes: 2 additions & 0 deletions ocaml/idl/datamodel_types.mli
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ val release_order_full : api_release list

val release_order : api_release list

val latest_release : api_release

exception Unknown_release of string

exception UnspecifiedRelease
Expand Down
4 changes: 2 additions & 2 deletions ocaml/idl/dm_api.ml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ let check api emergency_calls =
let are_in_vsn_order ps =
let release_lt x y = release_leq x y && x <> y in
let in_since releases =
let last = code_name_of_release latest_release in
(* been in since the lowest of releases *)
List.fold_left
(fun sofar r ->
Expand All @@ -378,8 +379,7 @@ let check api emergency_calls =
| r ->
if release_lt r sofar then r else sofar
)
(Xapi_stdext_std.Listext.List.last release_order |> code_name_of_release)
releases
last releases
in
let rec check_vsns max_release_sofar ps =
match ps with
Expand Down
4 changes: 1 addition & 3 deletions ocaml/libs/http-lib/http_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ let response_of_fd_exn_slow fd =
let line = input_line_fd fd in
let bits = Astring.String.fields ~empty:false line in
(* We just ignore the initial "FRAME xxxxx" *)
let bits =
if bits <> [] && List.hd bits = "FRAME" then List.tl bits else bits
in
let bits = match bits with "FRAME" :: bits -> bits | _ -> bits in
match bits with
| http_version :: code :: rest ->
let version =
Expand Down
1 change: 1 addition & 0 deletions ocaml/libs/pciutil/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
(libraries
threads
unix
xapi-stdext-std
xapi-stdext-unix
)
)
Expand Down
19 changes: 10 additions & 9 deletions ocaml/libs/pciutil/pciutil.ml
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ let parse vendor device =
(fun path -> try Unix.access path perms ; true with _ -> false)
l
in
try
(* is that the correct path ? *)
let l =
access_list
["/usr/share/hwdata/pci.ids"; "/usr/share/misc/pci.ids"]
[Unix.R_OK]
in
parse_from (List.hd l) vendor device
with _ -> (unknown_vendor vendor, unknown_device device)
access_list
["/usr/share/hwdata/pci.ids"; "/usr/share/misc/pci.ids"]
[Unix.R_OK]
|> Xapi_stdext_std.Listext.List.head
|> Option.map (fun path -> parse_from path vendor device)
|> function
| Some vd ->
vd
| None ->
(unknown_vendor vendor, unknown_device device)
7 changes: 3 additions & 4 deletions ocaml/libs/stunnel/stunnel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ module Unsafe = struct
(* Low-level (unsafe) function which forks, runs a 'pre_exec' function and
then executes some other binary. It makes sure to catch any exception thrown by
exec* so that we don't end up with two ocaml processes. *)
let fork_and_exec ?(pre_exec = fun () -> ()) ?env (cmdline : string list) =
let args = Array.of_list cmdline in
let argv0 = List.hd cmdline in
let fork_and_exec ?(pre_exec = fun () -> ()) ?env argv0 (args : string list) =
let args = Array.of_list (argv0 :: args) in
let pid = Unix.fork () in
if pid = 0 then
try
Expand Down Expand Up @@ -342,7 +341,7 @@ let attempt_one_connect ?(use_fork_exec_helper = true)
List.iter Unsafe.do_fd_operation fdops ;
Unixext.close_all_fds_except fds_needed
)
(path :: args)
path args
)
in
Unixfd.safe_close config_out ;
Expand Down
20 changes: 13 additions & 7 deletions ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ module List = struct

let mapi_tr f l = rev (rev_mapi f l)

let try_map f l =
let rec loop acc = function
| [] ->
Ok (List.rev acc)
| x :: xs -> (
match f x with Ok x -> loop (x :: acc) xs | Error _ as e -> e
)
in
loop [] l

let take n list =
let rec loop i acc = function
| x :: xs when i < n ->
Expand All @@ -75,13 +85,9 @@ module List = struct
in
loop 0 list

let rec last = function
| [] ->
invalid_arg "last: empty list"
| [x] ->
x
| _ :: xs ->
last xs
let head = function [] -> None | x :: _ -> Some x

let rec last = function [] -> None | [x] -> Some x | _ :: xs -> last xs

let split_at n list =
let rec loop i acc = function
Expand Down
12 changes: 9 additions & 3 deletions ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.mli
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,15 @@ module List : sig
element being the rest of elements of the list (or [] if the list is
shorter). The results with negative values of [n] are the same as using 0. *)

val last : 'a list -> 'a
(** [last l] returns the last element of a list or raise Invalid_argument if
the list is empty *)
val head : 'a list -> 'a option
(** [head l] returns the first element of [lst] or None if [lst] is empty *)

val last : 'a list -> 'a option
(** [last lst] returns the last element of [lst] or None if [lst] is empty *)

val try_map : ('a -> ('b, 'c) result) -> 'a list -> ('b list, 'c) result
(** [try_map f l] applies f to all elements of l, in turn and returns the
first [error]. If none were return, returns the [Ok results] *)

val rev_mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
(** [rev_map f l] gives the same result as {!Stdlib.List.rev}[ (]
Expand Down
46 changes: 31 additions & 15 deletions ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
module Listext = Xapi_stdext_std.Listext.List

let test_last_list tested_f (name, case, expected) =
let check () = Alcotest.(check @@ int) name expected (tested_f case) in
let check () = Alcotest.(check @@ option int) name expected (tested_f case) in
(name, `Quick, check)

let test_list tested_f (name, case, expected) =
Expand All @@ -31,8 +31,10 @@ let test_split_at_list tested_f (name, case, expected) =
in
(name, `Quick, check)

let test_error tested_f (name, case, expected) =
let check () = Alcotest.check_raises name expected (tested_f case) in
let test_try_map tested_f (name, case, expected) =
let check () =
Alcotest.(check @@ result (list int) int) name expected (tested_f case)
in
(name, `Quick, check)

let test_iteri_right =
Expand Down Expand Up @@ -114,8 +116,7 @@ let test_drop =
("drop", tests)

let test_last =
let specs = [([1], 0, 1); ([1; 2; 3], 1, 3)] in
let error_specs = [([], -1, Invalid_argument "last: empty list")] in
let specs = [([1], 0, Some 1); ([1; 2; 3], 1, Some 3); ([], -1, None)] in
let test_good (whole, number, expected) =
let name =
Printf.sprintf "get last %i from [%s]" number
Expand All @@ -124,16 +125,7 @@ let test_last =
test_last_list Listext.last (name, whole, expected)
in
let tests = List.map test_good specs in
let error_test (whole, number, error) =
let name =
Printf.sprintf "last [%s] with %i fails"
(String.concat "; " (List.map string_of_int whole))
number
in
test_error (fun ls () -> ignore (Listext.last ls)) (name, whole, error)
in
let error_tests = List.map error_test error_specs in
("last", tests @ error_tests)
("last", tests)

let test_split_at =
let specs =
Expand All @@ -160,6 +152,29 @@ let test_split_at =
let tests = List.map test specs in
("split_at", tests)

let test_try_map =
let only_positive = function i when i >= 0 -> Ok i | i -> Error i in
let specs =
[
([], Ok [])
; ([0; 1], Ok [0; 1])
; ([-1], Error (-1))
; ([-2; 0], Error (-2))
; ([0; -3], Error (-3))
; ([-4; -3], Error (-4))
]
in
let test (lst, expected) =
let name =
Printf.sprintf "try_map only_positive [%s]"
(String.concat "; " (List.map string_of_int lst))
in
test_try_map (Listext.try_map only_positive) (name, lst, expected)
in

let tests = List.map test specs in
("try_map", tests)

let test_find_minimum (name, pp, typ, specs) =
let test ((cmp, cmp_name), input, expected) =
let name = Printf.sprintf "%s of [%s]" cmp_name (pp input) in
Expand Down Expand Up @@ -215,6 +230,7 @@ let () =
; test_drop
; test_last
; test_split_at
; test_try_map
; test_find_minimum_int
; test_find_minimum_tuple
]
1 change: 1 addition & 0 deletions ocaml/xapi-aux/dune
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
xapi-idl.network
xapi-inventory
xapi-log
xapi-stdext-std
xapi-stdext-threads
xapi-stdext-unix
xml-light2
Expand Down
6 changes: 4 additions & 2 deletions ocaml/xapi-aux/networking_info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ module Net = Network_client.Client

module L = Debug.Make (struct let name = __MODULE__ end)

module Listext = Xapi_stdext_std.Listext.List

let get_hostname () = try Unix.gethostname () with _ -> ""

type management_ip_error =
Expand Down Expand Up @@ -99,7 +101,7 @@ let get_management_ip_addrs ~dbg =
let get_management_ip_addr ~dbg =
match get_management_ip_addrs ~dbg with
| Ok (preferred, _) ->
List.nth_opt preferred 0 |> Option.map Ipaddr.to_string
Listext.head preferred |> Option.map Ipaddr.to_string
| Error _ ->
None

Expand All @@ -113,7 +115,7 @@ let get_host_certificate_subjects ~dbg =
let ips = List.(rev_append (rev preferred) others) in
Option.fold ~none:(Error IP_missing)
~some:(fun ip -> Ok (List.map ipaddr_to_octets ips, ip))
(List.nth_opt ips 0)
(Listext.head ips)
in
let dns_names = dns_names () in
let name =
Expand Down
3 changes: 1 addition & 2 deletions ocaml/xapi/import.ml
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,8 @@ module VM : HandlerTools = struct
in

let maybe_template =
List.nth_opt
Listext.List.head
(Db.VM.get_by_name_label ~__context ~label:vm_record.API.vM_name_label)
0
in
match (is_default_template, maybe_template) with
| true, Some template ->
Expand Down
5 changes: 1 addition & 4 deletions ocaml/xapi/map_check.ml
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ let with_ks ~kss ~fn =
let corrected_values =
List.filter (fun cv -> cv <> None) (List.map (fun ks -> fn field ks) kss)
in
if corrected_values = [] then
[]
else
match List.hd corrected_values with None -> [] | Some cv -> cv
match corrected_values with [] | None :: _ -> [] | Some cv :: _ -> cv

let assert_req_values ~field ~ks ~vs =
(* each required values in this ks must match the one in the vs map this key/value belongs to *)
Expand Down
Loading
Loading