Skip to content

Commit d603928

Browse files
authored
Merge feature/perf to master (#6229)
Relevant feature flags are off by default/match previous values: ``` coordinator_max_stunnel_cache member_max_stunnel_cache stunnel_cache_max_age member_max_stunnel_cache event_from_delay event_from_task_delay event_next_delay use-event-next use-xmlrpc tgroups-enabled timeslice ``` Draft PR to check conflicts, waiting for testing to complete.
2 parents 104efe9 + e39baa6 commit d603928

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1592
-229
lines changed

dune-project

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
)
3838
)
3939

40+
(package
41+
(name tgroup)
42+
(depends
43+
xapi-log
44+
xapi-stdext-unix)
45+
)
46+
4047
(package
4148
(name xml-light2)
4249
)
@@ -321,6 +328,7 @@
321328
(synopsis "The toolstack daemon which implements the XenAPI")
322329
(description "This daemon exposes the XenAPI and is used by clients such as 'xe' and 'XenCenter' to manage clusters of Xen-enabled hosts.")
323330
(depends
331+
(ocaml (>= 4.09))
324332
(alcotest :with-test)
325333
angstrom
326334
astring
@@ -374,6 +382,7 @@
374382
tar
375383
tar-unix
376384
uri
385+
tgroup
377386
(uuid (= :version))
378387
uutf
379388
uuidm
@@ -587,6 +596,7 @@ This package provides an Lwt compatible interface to the library.")
587596
(safe-resources(= :version))
588597
sha
589598
(stunnel (= :version))
599+
tgroup
590600
uri
591601
(uuid (= :version))
592602
xapi-backtrace

http-lib.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ depends: [
2222
"safe-resources" {= version}
2323
"sha"
2424
"stunnel" {= version}
25+
"tgroup"
2526
"uri"
2627
"uuid" {= version}
2728
"xapi-backtrace"

ocaml/idl/datamodel.ml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8517,11 +8517,18 @@ module Event = struct
85178517
]
85188518
~doc:
85198519
"Blocking call which returns a (possibly empty) batch of events. This \
8520-
method is only recommended for legacy use. New development should use \
8521-
event.from which supersedes this method."
8520+
method is only recommended for legacy use.It stores events in a \
8521+
buffer of limited size, raising EVENTS_LOST if too many events got \
8522+
generated. New development should use event.from which supersedes \
8523+
this method."
85228524
~custom_marshaller:true ~flags:[`Session]
85238525
~result:(Set (Record _event), "A set of events")
8524-
~errs:[Api_errors.session_not_registered; Api_errors.events_lost]
8526+
~errs:
8527+
[
8528+
Api_errors.session_not_registered
8529+
; Api_errors.events_lost
8530+
; Api_errors.event_subscription_parse_failure
8531+
]
85258532
~allowed_roles:_R_ALL ()
85268533

85278534
let from =
@@ -8551,7 +8558,8 @@ module Event = struct
85518558
~doc:
85528559
"Blocking call which returns a new token and a (possibly empty) batch \
85538560
of events. The returned token can be used in subsequent calls to this \
8554-
function."
8561+
function. It eliminates redundant events (e.g. same field updated \
8562+
multiple times)."
85558563
~custom_marshaller:true ~flags:[`Session]
85568564
~result:
85578565
( Set (Record _event)
@@ -8562,7 +8570,11 @@ module Event = struct
85628570
(*In reality the event batch is not a set of records as stated here.
85638571
Due to the difficulty of representing this in the datamodel, the doc is generated manually,
85648572
so ensure the markdown_backend.ml and gen_json.ml is updated if something changes. *)
8565-
~errs:[Api_errors.session_not_registered; Api_errors.events_lost]
8573+
~errs:
8574+
[
8575+
Api_errors.event_from_token_parse_failure
8576+
; Api_errors.event_subscription_parse_failure
8577+
]
85668578
~allowed_roles:_R_ALL ()
85678579

85688580
let get_current_id =

ocaml/libs/http-lib/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
http_lib
4444
ipaddr
4545
polly
46+
tgroup
4647
threads.posix
4748
tracing
4849
tracing_propagator

ocaml/libs/http-lib/http.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ module Hdr = struct
132132

133133
let location = "location"
134134

135+
let originator = "originator"
136+
135137
let hsts = "strict-transport-security"
136138
end
137139

@@ -674,6 +676,14 @@ module Request = struct
674676
let headers, body = to_headers_and_body x in
675677
let frame_header = if x.frame then make_frame_header headers else "" in
676678
frame_header ^ headers ^ body
679+
680+
let with_originator_of req f =
681+
Option.iter
682+
(fun req ->
683+
let originator = List.assoc_opt Hdr.originator req.additional_headers in
684+
f originator
685+
)
686+
req
677687
end
678688

679689
module Response = struct

ocaml/libs/http-lib/http.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ module Request : sig
126126

127127
val to_wire_string : t -> string
128128
(** [to_wire_string t] returns a string which could be sent to a server *)
129+
130+
val with_originator_of : t option -> (string option -> unit) -> unit
129131
end
130132

131133
(** Parsed form of the HTTP response *)

ocaml/libs/http-lib/http_svr.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ let handle_connection ~header_read_timeout ~header_total_timeout
574574
~max_length:max_header_length ss
575575
in
576576

577+
Http.Request.with_originator_of req Tgroup.of_req_originator ;
578+
577579
(* 2. now we attempt to process the request *)
578580
let finished =
579581
Option.fold ~none:true

ocaml/libs/stunnel/stunnel_cache.ml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,19 @@ let debug = if debug_enabled then debug else ignore_log
4040
type endpoint = {host: string; port: int}
4141

4242
(* Need to limit the absolute number of stunnels as well as the maximum age *)
43-
let max_stunnel = 70
43+
let max_stunnel = Atomic.make 70
4444

45-
let max_age = 180. *. 60. (* seconds *)
45+
let set_max_stunnel n =
46+
D.info "Setting max_stunnel = %d" n ;
47+
Atomic.set max_stunnel n
4648

47-
let max_idle = 5. *. 60. (* seconds *)
49+
let max_age = ref (180. *. 60.) (* seconds *)
50+
51+
let max_idle = ref (5. *. 60.) (* seconds *)
4852

4953
(* The add function adds the new stunnel before doing gc, so the cache *)
5054
(* can briefly contain one more than maximum. *)
51-
let capacity = max_stunnel + 1
55+
let capacity = Atomic.get max_stunnel + 1
5256

5357
(** An index of endpoints to stunnel IDs *)
5458
let index : (endpoint, int list) Hashtbl.t ref = ref (Hashtbl.create capacity)
@@ -104,6 +108,7 @@ let unlocked_gc () =
104108
let to_gc = ref [] in
105109
(* Find the ones which are too old *)
106110
let now = Unix.gettimeofday () in
111+
let max_age = !max_age and max_idle = !max_idle in
107112
Tbl.iter !stunnels (fun idx stunnel ->
108113
match Hashtbl.find_opt !times idx with
109114
| Some time ->
@@ -122,6 +127,7 @@ let unlocked_gc () =
122127
debug "%s: found no entry for idx=%d" __FUNCTION__ idx
123128
) ;
124129
let num_remaining = List.length all_ids - List.length !to_gc in
130+
let max_stunnel = Atomic.get max_stunnel in
125131
if num_remaining > max_stunnel then (
126132
let times' = Hashtbl.fold (fun k v acc -> (k, v) :: acc) !times [] in
127133
let times' =

ocaml/libs/stunnel/stunnel_cache.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
HTTP 1.1 should be used and the connection should be kept-alive.
2020
*)
2121

22+
val set_max_stunnel : int -> unit
23+
(** [set_max_stunnel] set the maximum number of unusued, but cached client stunnel connections.
24+
This should be a low number on pool members, to avoid hitting limits on the coordinator with large pools.
25+
*)
26+
2227
val with_connect :
2328
?use_fork_exec_helper:bool
2429
-> ?write_to_log:(string -> unit)
@@ -46,3 +51,9 @@ val flush : unit -> unit
4651

4752
val gc : unit -> unit
4853
(** GCs old stunnels *)
54+
55+
val max_age : float ref
56+
(** maximum time a connection is kept in the stunnel cache, counted from the time it got initially added to the cache *)
57+
58+
val max_idle : float ref
59+
(** maximum time a connection is kept in the stunnel cache, counted from the most recent time it got (re)added to the cache. *)

ocaml/libs/tgroup/dune

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(library
2+
(name tgroup)
3+
(modules tgroup)
4+
(public_name tgroup)
5+
(libraries xapi-log xapi-stdext-unix xapi-stdext-std))
6+
7+
(test
8+
(name test_tgroup)
9+
(modules test_tgroup)
10+
(package tgroup)
11+
(libraries tgroup alcotest xapi-log))

ocaml/libs/tgroup/test_tgroup.ml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module D = Debug.Make (struct let name = __MODULE__ end)
2+
3+
let test_identity () =
4+
let specs =
5+
[
6+
((Some "XenCenter2024", "u1000"), "u1000/XenCenter2024")
7+
; ((None, "u1001"), "u1001")
8+
; ((None, "Special!@#"), "Special")
9+
; ((Some "With-Hyphen", "123"), "123/WithHyphen")
10+
; ((Some "", ""), "root")
11+
; ((Some " Xen Center 2024 ", ", u 1000 "), "u1000/XenCenter2024")
12+
; ((Some "Xen Center ,/@.~# 2024", "root"), "root/XenCenter2024")
13+
; ((Some "XenCenter 2024.3.18", ""), "root/XenCenter2024318")
14+
; ((Some "", "S-R-X-Y1-Y2-Yn-1-Yn"), "SRXY1Y2Yn1Yn")
15+
; ( (Some "XenCenter2024", "S-R-X-Y1-Y2-Yn-1-Yn")
16+
, "SRXY1Y2Yn1Yn/XenCenter2024"
17+
)
18+
]
19+
in
20+
21+
let test_make ((user_agent, subject_sid), expected_identity) =
22+
let actual_identity =
23+
Tgroup.Group.Identity.(make ?user_agent subject_sid |> to_string)
24+
in
25+
Alcotest.(check string)
26+
"Check expected identity" expected_identity actual_identity
27+
in
28+
List.iter test_make specs
29+
30+
let test_of_creator () =
31+
let dummy_identity =
32+
Tgroup.Group.Identity.make ~user_agent:"XenCenter2024" "root"
33+
in
34+
let specs =
35+
[
36+
((None, None, None, None), "external/unauthenticated")
37+
; ((Some true, None, None, None), "external/intrapool")
38+
; ( ( Some true
39+
, Some Tgroup.Group.Endpoint.External
40+
, Some dummy_identity
41+
, Some "sm"
42+
)
43+
, "external/intrapool"
44+
)
45+
; ( ( Some true
46+
, Some Tgroup.Group.Endpoint.Internal
47+
, Some dummy_identity
48+
, Some "sm"
49+
)
50+
, "external/intrapool"
51+
)
52+
; ( ( None
53+
, Some Tgroup.Group.Endpoint.Internal
54+
, Some dummy_identity
55+
, Some "cli"
56+
)
57+
, "internal/cli"
58+
)
59+
; ( (None, None, Some dummy_identity, Some "sm")
60+
, "external/authenticated/root/XenCenter2024"
61+
)
62+
]
63+
in
64+
let test_make ((intrapool, endpoint, identity, originator), expected_group) =
65+
let originator = Option.map Tgroup.Group.Originator.of_string originator in
66+
let actual_group =
67+
Tgroup.Group.(
68+
Creator.make ?intrapool ?endpoint ?identity ?originator ()
69+
|> of_creator
70+
|> to_string
71+
)
72+
in
73+
Alcotest.(check string) "Check expected group" expected_group actual_group
74+
in
75+
List.iter test_make specs
76+
77+
let tests =
78+
[
79+
("identity make", `Quick, test_identity)
80+
; ("group of creator", `Quick, test_of_creator)
81+
]
82+
83+
let () = Alcotest.run "Tgroup library" [("Thread classification", tests)]

ocaml/libs/tgroup/test_tgroup.mli

Whitespace-only changes.

0 commit comments

Comments
 (0)