Skip to content

Commit 6e1c8a6

Browse files
author
Gabriel Buica
committed
CP-53843: reusable session for sm_exec
The session reuse logic in `xapi_session.ml` does work in this usecase, sm calls are made with `pool=false`. So reimplement the logic so that we use a single session for `sm_exec` per sr. This should help with session count inside xapi. Signed-off-by: Gabriel Buica <danutgabriel.buica@citrix.com>
1 parent 7466e5f commit 6e1c8a6

1 file changed

Lines changed: 62 additions & 14 deletions

File tree

ocaml/xapi/sm_exec.ml

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,32 @@ let methodResponse xml =
317317
| xml ->
318318
XMLRPC.From.methodResponse xml
319319

320-
(****************************************************************************************)
321-
(* Functions that actually execute the python backends *)
320+
let reusable_sessions : (string option, API.ref_session) Hashtbl.t =
321+
Hashtbl.create 5
322+
323+
let sm_sessions_m = Mutex.create ()
324+
325+
let with_sm_sessions_lock f =
326+
Xapi_stdext_threads.Threadext.Mutex.execute sm_sessions_m f
327+
328+
let is_valid_session ~__context session_id =
329+
try
330+
(* Call an API function to check the session is still valid *)
331+
let rpc = Helpers.make_rpc ~__context in
332+
ignore (Client.Client.Pool.get_all ~rpc ~session_id) ;
333+
true
334+
with Api_errors.Server_error (err, _) ->
335+
debug "%s: Invalid session: %s" __FUNCTION__ err ;
336+
false
337+
338+
let session_access ~__context session sr =
339+
(* Give this session access to this particular SR *)
340+
Option.iter
341+
(fun sr ->
342+
Db.Session.add_to_other_config ~__context ~self:session
343+
~key:Xapi_globs._sm_session ~value:(Ref.string_of sr)
344+
)
345+
sr
322346

323347
let create_session ~__context sr =
324348
let host = !Xapi_globs.localhost_ref in
@@ -327,25 +351,49 @@ let create_session ~__context sr =
327351
~is_local_superuser:true ~subject:Ref.null ~auth_user_sid:""
328352
~auth_user_name:sm_username ~rbac_permissions:[]
329353
in
330-
(* Give this session access to this particular SR *)
331-
Option.iter
332-
(fun sr ->
333-
Db.Session.add_to_other_config ~__context ~self:session
334-
~key:Xapi_globs._sm_session ~value:(Ref.string_of sr)
335-
)
336-
sr ;
354+
session_access ~__context session sr ;
337355
session
338356

357+
let rec get_session ~__context sr =
358+
let sr_key = Option.map Ref.string_of sr in
359+
let session = Hashtbl.find_opt reusable_sessions sr_key in
360+
match session with
361+
| Some session ->
362+
if is_valid_session ~__context session then
363+
session
364+
else (
365+
with_sm_sessions_lock (fun () -> Hashtbl.remove reusable_sessions sr_key) ;
366+
(get_session [@tailcall]) ~__context sr
367+
)
368+
| None ->
369+
let new_session = create_session ~__context sr in
370+
with_sm_sessions_lock (fun () ->
371+
match Hashtbl.find_opt reusable_sessions sr_key with
372+
| None ->
373+
Hashtbl.add reusable_sessions sr_key new_session ;
374+
new_session
375+
| Some session ->
376+
Xapi_session.destroy_db_session ~__context ~self:new_session ;
377+
session
378+
)
379+
339380
let with_session ~traceparent sr f =
340381
Server_helpers.exec_with_new_task "sm_exec"
341382
~origin:(Internal_Traced traceparent) (fun __context ->
342-
let session_id = create_session ~__context sr in
343-
let destroy_session () =
344-
Xapi_session.destroy_db_session ~__context ~self:session_id
345-
in
346-
finally (fun () -> f session_id) destroy_session
383+
if !Xapi_globs.reuse_pool_sessions then
384+
let session_id = get_session ~__context sr in
385+
f session_id
386+
else
387+
let session_id = create_session ~__context sr in
388+
let destroy_session () =
389+
Xapi_session.destroy_db_session ~__context ~self:session_id
390+
in
391+
finally (fun () -> f session_id) destroy_session
347392
)
348393

394+
(****************************************************************************************)
395+
(* Functions that actually execute the python backends *)
396+
349397
let exec_xmlrpc ~dbg ?context:_ ?(needs_session = true) (driver : string)
350398
(call : call) =
351399
with_dbg ~name:call.cmd ~dbg @@ fun di ->

0 commit comments

Comments
 (0)