@@ -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
323347let 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+
339380let 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+
349397let exec_xmlrpc ~dbg ?context :_ ?(needs_session = true ) (driver : string )
350398 (call : call ) =
351399 with_dbg ~name: call.cmd ~dbg @@ fun di ->
0 commit comments