Skip to content

Commit

Permalink
Precompute symmetric closure table
Browse files Browse the repository at this point in the history
To avoid recomputing the symmetric closure several times during module
initialisation for Eventgen, we introduce a hashtable that stores the
relation.

Signed-off-by: Colin James <[email protected]>
  • Loading branch information
contificate committed Dec 18, 2024
1 parent ed2e502 commit d622dd8
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions ocaml/xapi/eventgen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ let find_get_record obj_name ~__context ~self () : Rpc.t option =
(fun f -> f ~__context ~self ())
(Hashtbl.find_opt get_record_table obj_name)

(* Bidirectional lookup for relations encoded in all_relations. *)
let lookup_object_relation =
(* Precompute the symmetric closure of all_relations and store it as
a hash table. *)
let symmetric_table =
let table = Hashtbl.create 128 in
let relate = Hashtbl.replace table in
let api = Datamodel.all_api in
let close (p, p') =
(* R U= { (p, p'), (p', p) } where p, p' are of the form
(object, field) *)
relate p p' ; relate p' p
in
Dm_api.relations_of_api api |> List.iter close ;
table
in
Hashtbl.find_opt symmetric_table

(* If a record is modified, events must be emitted for related objects' records.
We collect a list of related objects by querying the (Ref _)-typed
fields of the input object against the relations encoded by the datamodel.
Expand All @@ -37,16 +55,11 @@ let compute_object_references_to_follow (obj_name : string) =
let module DT = Datamodel_types in
let api = Datamodel.all_api in
let obj = Dm_api.get_obj_by_name api ~objname:obj_name in
let symmetric =
(* Symmetric closure of the field relation set. *)
Dm_api.relations_of_api api
|> List.concat_map (fun (a, b) -> [(a, b); (b, a)])
in
(* Find an object related to the input field using the datamodel. *)
let find_related_object = function
| DT.{field_name; ty= Ref _; _} ->
let this_end = (obj_name, field_name) in
List.assoc_opt this_end symmetric
lookup_object_relation this_end
|> Option.map (fun (other_object, _) -> (other_object, field_name))
| _ ->
None
Expand Down

0 comments on commit d622dd8

Please sign in to comment.