Skip to content

Commit 42e47b6

Browse files
authored
xapi-stdext: remove unused functions from listext, and replace chop with split_at (#6733)
Although I doubt it, please check whether Xenserver's proprietary code uses these functions. I took the chance to consolidate some functions in `ocaml/xapi/db_gc_util.ml` as well.
2 parents 18e90e0 + e90a901 commit 42e47b6

File tree

10 files changed

+49
-188
lines changed

10 files changed

+49
-188
lines changed

dune-project

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,8 @@
612612
(= :version))
613613
(xapi-stdext-pervasives
614614
(= :version))
615+
(xapi-stdext-std
616+
(= :version))
615617
(xapi-stdext-threads
616618
(= :version))
617619
(xapi-stdext-unix

ocaml/libs/stunnel/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
xapi-inventory
1414
xapi-log
1515
xapi-stdext-pervasives
16+
xapi-stdext-std
1617
xapi-stdext-threads
1718
xapi-stdext-unix
1819
)

ocaml/libs/stunnel/stunnel_cache.ml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ open Safe_resources
2727

2828
let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute
2929

30+
let list_drop = Xapi_stdext_std.Listext.List.drop
31+
3032
(* Disable debug-level logging but leave higher-priority enabled. It would be
3133
* better to handle this sort of configuration in the Debug module itself.
3234
*)
@@ -93,17 +95,6 @@ let unlocked_gc () =
9395
!index ""
9496
)
9597
) ;
96-
(* Split a list at the given index to give a pair of lists.
97-
* From Xapi_stdext_std.Listext *)
98-
let rec chop i l =
99-
match (i, l) with
100-
| 0, l ->
101-
([], l)
102-
| i, h :: t ->
103-
(fun (fr, ba) -> (h :: fr, ba)) (chop (i - 1) t)
104-
| _ ->
105-
invalid_arg "chop"
106-
in
10798
let all_ids = Tbl.fold !stunnels (fun k _ acc -> k :: acc) [] in
10899
let to_gc = ref [] in
109100
(* Find the ones which are too old *)
@@ -134,8 +125,8 @@ let unlocked_gc () =
134125
List.filter (fun (idx, _) -> not (List.mem idx !to_gc)) times'
135126
in
136127
(* Sort into descending order of donation time, ie youngest first *)
137-
let times' = List.sort (fun x y -> compare (fst y) (fst x)) times' in
138-
let _youngest, oldest = chop max_stunnel times' in
128+
let times' = List.sort (fun (_, x) (_, y) -> Float.compare y x) times' in
129+
let oldest = list_drop max_stunnel times' in
139130
let oldest_ids = List.map fst oldest in
140131
List.iter
141132
(fun x ->

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
(names xstringext_test listext_test)
88
(package xapi-stdext-std)
99
(modules xstringext_test listext_test)
10-
(libraries xapi_stdext_std alcotest)
10+
(libraries xapi_stdext_std fmt alcotest)
1111
)

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.ml

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ module List = struct
2222
| x :: xs ->
2323
if mem x xs then setify xs else x :: setify xs
2424

25-
let subset s1 s2 =
26-
List.fold_left ( && ) true (List.map (fun s -> List.mem s s2) s1)
25+
let subset s1 s2 = List.for_all (fun s -> List.mem s s2) s1
2726

2827
let set_equiv s1 s2 = subset s1 s2 && subset s2 s1
2928

@@ -84,61 +83,14 @@ module List = struct
8483
| _ :: xs ->
8584
last xs
8685

87-
let sub i j l = drop i l |> take (j - max i 0)
88-
89-
let rec chop i l =
90-
match (i, l) with
91-
| j, _ when j < 0 ->
92-
invalid_arg "chop: index cannot be negative"
93-
| 0, l ->
94-
([], l)
95-
| _, h :: t ->
96-
(fun (fr, ba) -> (h :: fr, ba)) (chop (i - 1) t)
97-
| _, [] ->
98-
invalid_arg "chop: index not in list"
99-
100-
let rev_chop i l =
101-
let rec aux i fr ba =
102-
match (i, fr, ba) with
103-
| i, _, _ when i < 0 ->
104-
invalid_arg "rev_chop: index cannot be negative"
105-
| 0, fr, ba ->
106-
(fr, ba)
107-
| i, fr, h :: t ->
108-
aux (i - 1) (h :: fr) t
109-
| _ ->
110-
invalid_arg "rev_chop"
86+
let split_at n list =
87+
let rec loop i acc = function
88+
| x :: xs when i < n ->
89+
loop (i + 1) (x :: acc) xs
90+
| xs ->
91+
(List.rev acc, xs)
11192
in
112-
aux i [] l
113-
114-
let chop_tr i l = (fun (fr, ba) -> (rev fr, ba)) (rev_chop i l)
115-
116-
let rec dice m l =
117-
match chop m l with l, [] -> [l] | l1, l2 -> l1 :: dice m l2
118-
119-
let remove i l =
120-
match rev_chop i l with
121-
| rfr, _ :: t ->
122-
rev_append rfr t
123-
| _ ->
124-
invalid_arg "remove"
125-
126-
let insert i e l =
127-
match rev_chop i l with rfr, ba -> rev_append rfr (e :: ba)
128-
129-
let replace i e l =
130-
match rev_chop i l with
131-
| rfr, _ :: t ->
132-
rev_append rfr (e :: t)
133-
| _ ->
134-
invalid_arg "replace"
135-
136-
let morph i f l =
137-
match rev_chop i l with
138-
| rfr, h :: t ->
139-
rev_append rfr (f h :: t)
140-
| _ ->
141-
invalid_arg "morph"
93+
loop 0 [] list
14294

14395
let rec between e = function
14496
| [] ->

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.mli

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ module List : sig
2727
(** [drop n list] returns the list without the first [n] elements of [list]
2828
(or [] if list is shorter). *)
2929

30+
val split_at : int -> 'a list -> 'a list * 'a list
31+
(** [split_at n list] returns a tuple with the first element being the first
32+
[n] elements of [list] (or less if the list is shorter); and the second
33+
element being the rest of elements of the list (or [] if the list is
34+
shorter). The results with negative values of [n] are the same as using 0. *)
35+
3036
val last : 'a list -> 'a
3137
(** [last l] returns the last element of a list or raise Invalid_argument if
3238
the list is empty *)
@@ -67,42 +73,6 @@ module List : sig
6773
When using OCaml compilers 5.1 or later, please use the standard library
6874
instead. *)
6975

70-
(** {1 Using indices to manipulate lists} *)
71-
72-
val chop : int -> 'a list -> 'a list * 'a list
73-
(** [chop k l] splits [l] at index [k] to return a pair of lists. Raises
74-
invalid_arg when [i] is negative or greater than the length of [l]. *)
75-
76-
val rev_chop : int -> 'a list -> 'a list * 'a list
77-
(** [rev_chop k l] splits [l] at index [k] to return a pair of lists, the
78-
first in reverse order. Raises invalid_arg when [i] is negative or
79-
greater than the length of [l]. *)
80-
81-
val chop_tr : int -> 'a list -> 'a list * 'a list
82-
(** Tail-recursive {!chop}. *)
83-
84-
val dice : int -> 'a list -> 'a list list
85-
(** [dice k l] splits [l] into lists with [k] elements each. Raises
86-
{!Invalid_arg} if [List.length l] is not divisible by [k]. *)
87-
88-
val sub : int -> int -> 'a list -> 'a list
89-
(** [sub from to l] returns the sub-list of [l] that starts at index [from]
90-
and ends at [to] or an empty list if [to] is equal or less than [from].
91-
Negative indices are treated as 0 and indeces higher than [List.length l
92-
- 1] are treated as [List.length l - 1]. *)
93-
94-
val remove : int -> 'a list -> 'a list
95-
(** Remove the element at the given index. *)
96-
97-
val insert : int -> 'a -> 'a list -> 'a list
98-
(** Insert the given element at the given index. *)
99-
100-
val replace : int -> 'a -> 'a list -> 'a list
101-
(** Replace the element at the given index with the given value. *)
102-
103-
val morph : int -> ('a -> 'a) -> 'a list -> 'a list
104-
(** Apply the given function to the element at the given index. *)
105-
10676
(** {1 Association Lists} *)
10777

10878
val make_assoc : ('a -> 'b) -> 'a list -> ('a * 'b) list

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext_test.ml

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ let test_option typ tested_f (name, case, expected) =
2525
let check () = Alcotest.(check @@ option typ) name expected (tested_f case) in
2626
(name, `Quick, check)
2727

28-
let test_chopped_list tested_f (name, case, expected) =
28+
let test_split_at_list tested_f (name, case, expected) =
2929
let check () =
3030
Alcotest.(check @@ pair (list int) (list int)) name expected (tested_f case)
3131
in
@@ -135,7 +135,7 @@ let test_last =
135135
let error_tests = List.map error_test error_specs in
136136
("last", tests @ error_tests)
137137

138-
let test_chop =
138+
let test_split_at =
139139
let specs =
140140
[
141141
([], 0, ([], []))
@@ -144,67 +144,21 @@ let test_chop =
144144
; ([0; 1], 0, ([], [0; 1]))
145145
; ([0; 1], 1, ([0], [1]))
146146
; ([0; 1], 2, ([0; 1], []))
147-
]
148-
in
149-
let error_specs =
150-
[
151-
([0], -1, Invalid_argument "chop: index cannot be negative")
152-
; ([0], 2, Invalid_argument "chop: index not in list")
147+
(* test invalid arguments *) [@ocamlformat "disable"]
148+
; ([0], -1, ([], [0]))
149+
; ([0], 2, ([0], []))
153150
]
154151
in
155152
let test (whole, number, expected) =
156153
let name =
157-
Printf.sprintf "chop [%s] with %i"
158-
(String.concat "; " (List.map string_of_int whole))
159-
number
160-
in
161-
test_chopped_list (Listext.chop number) (name, whole, expected)
162-
in
163-
let tests = List.map test specs in
164-
let error_test (whole, number, error) =
165-
let name =
166-
Printf.sprintf "chop [%s] with %i fails"
154+
Printf.sprintf "split_at [%s] with %i"
167155
(String.concat "; " (List.map string_of_int whole))
168156
number
169157
in
170-
test_error
171-
(fun ls () -> ignore (Listext.chop number ls))
172-
(name, whole, error)
173-
in
174-
let error_tests = List.map error_test error_specs in
175-
("chop", tests @ error_tests)
176-
177-
let test_sub =
178-
let specs =
179-
[
180-
([], 0, 0, [])
181-
; ([], 0, 1, [])
182-
; ([0], 0, 0, [])
183-
; ([0], 0, 1, [0])
184-
; ([0], 1, 1, [])
185-
; ([0], 0, 2, [0])
186-
; ([0; 1], 0, 0, [])
187-
; ([0; 1], 0, 1, [0])
188-
; ([0; 1], 0, 2, [0; 1])
189-
; ([0; 1], 1, 1, [])
190-
; ([0; 1], 1, 2, [1])
191-
; ([0; 1], 2, 2, [])
192-
(* test_cases below used to fail *) [@ocamlformat "disable"]
193-
; ([0], -1, 0, [])
194-
; ([0], 0, -1, [])
195-
; ([0; 1], 1, 0, [])
196-
]
197-
in
198-
let test (whole, from, until, expected) =
199-
let name =
200-
Printf.sprintf "sub [%s] from %i to %i"
201-
(String.concat "; " (List.map string_of_int whole))
202-
from until
203-
in
204-
test_list (Listext.sub from until) (name, whole, expected)
158+
test_split_at_list (Listext.split_at number) (name, whole, expected)
205159
in
206160
let tests = List.map test specs in
207-
("sub", tests)
161+
("split_at", tests)
208162

209163
let test_find_minimum (name, pp, typ, specs) =
210164
let test ((cmp, cmp_name), input, expected) =
@@ -260,8 +214,7 @@ let () =
260214
; test_take
261215
; test_drop
262216
; test_last
263-
; test_chop
264-
; test_sub
217+
; test_split_at
265218
; test_find_minimum_int
266219
; test_find_minimum_tuple
267220
]

ocaml/xapi/binpack.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ let choose l n =
9898
(** Return all permutations of a list *)
9999
let rec permutations : 'a list -> 'a list list =
100100
let rotate n xs =
101-
let a, b = Xapi_stdext_std.Listext.List.chop n xs in
101+
let a, b = Xapi_stdext_std.Listext.List.split_at n xs in
102102
b @ a
103103
in
104104
let insert_at n x xs = rotate (List.length xs - n + 1) (x :: rotate n xs) in

ocaml/xapi/db_gc_util.ml

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,12 @@ let gc_vtpms ~__context =
293293

294294
let probation_pending_tasks = Hashtbl.create 53
295295

296+
let sort_and_split compare n tasks =
297+
if List.length tasks <= n then
298+
(tasks, [])
299+
else
300+
Listext.List.split_at n (List.sort compare tasks)
301+
296302
let timeout_tasks ~__context =
297303
let all_tasks =
298304
Db.Task.get_internal_records_where ~__context
@@ -368,32 +374,20 @@ let timeout_tasks ~__context =
368374
let lucky, unlucky =
369375
if List.length young <= Xapi_globs.max_tasks then
370376
(young, []) (* keep them all *)
371-
else (* Compute how many we'd like to delete *)
372-
let overflow = List.length young - Xapi_globs.max_tasks in
373-
(* We only consider deleting completed tasks *)
377+
else (* We only consider deleting completed tasks *)
374378
let completed, pending =
375379
List.partition
376380
(fun (_, t) -> TaskHelper.status_is_completed t.Db_actions.task_status)
377381
young
378382
in
379-
(* Sort the completed tasks so we delete oldest tasks in preference *)
380-
let completed =
381-
List.sort
382-
(fun (_, t1) (_, t2) ->
383-
compare
384-
(Date.to_unix_time t1.Db_actions.task_finished)
385-
(Date.to_unix_time t2.Db_actions.task_finished)
386-
)
387-
completed
388-
in
389-
(* From the completes set, choose up to 'overflow' *)
390-
let unlucky, lucky =
391-
if List.length completed > overflow then
392-
Listext.List.chop overflow completed
393-
else
394-
(completed, [])
383+
(* pending tasks limit the amount of completed tasks to keep, negatives
384+
values are equivalent to 0 *)
385+
let limit = Xapi_globs.max_tasks - List.length completed in
386+
(* Reverse compare order so oldest dates (earliest) are sorted last *)
387+
let compare (_, t1) (_, t2) =
388+
Date.compare t2.Db_actions.task_finished t1.Db_actions.task_finished
395389
in
396-
(* not enough to delete, oh well *)
390+
let lucky, unlucky = sort_and_split compare limit completed in
397391
(* Keep all pending and any which were not chosen from the completed set *)
398392
(pending @ lucky, unlucky)
399393
in
@@ -456,11 +450,8 @@ let timeout_sessions_common ~__context sessions limit session_group =
456450
in
457451
(* If there are too many young sessions then we need to delete the oldest *)
458452
let _, unlucky =
459-
if List.length young <= limit then
460-
(young, []) (* keep them all *)
461-
else (* Need to reverse sort by last active and drop the oldest *)
462-
Listext.List.chop limit
463-
(List.sort (fun (_, a, _) (_, b, _) -> compare b a) young)
453+
let compare (_, a, _) (_, b, _) = compare b a in
454+
sort_and_split compare limit young
464455
in
465456
let cancel doc sessions =
466457
List.iter

opam/stunnel.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ depends: [
1818
"xapi-inventory"
1919
"xapi-log" {= version}
2020
"xapi-stdext-pervasives" {= version}
21+
"xapi-stdext-std" {= version}
2122
"xapi-stdext-threads" {= version}
2223
"xapi-stdext-unix" {= version}
2324
"odoc" {with-doc}

0 commit comments

Comments
 (0)