Skip to content

Commit ec7baa3

Browse files
authored
xapi_message: Implement proper expression handling in get_all_records_where (xapi-project#6411)
Messages are not stored in the database, so their handling is done through Custom_actions. The custom implementation of get_all_records_where, in particular, used to ignore the query expression altogether (as if expr = true). Expand the existing handler to evaluate the query and match against the messages retrieved and parsed from disk. An alternative approach would have instead special cased filtering code in the database itself, but in my attempts this was awkward and duplicated quite a lot of code. With this it is possible to filter messages properly now: ``` >>> session.xenapi.message.get_all_records_where('field "name" = "VM_STARTED"') <list of messages with name = VM_STARTED> >>> session.xenapi.message.get_all_records_where('field "name" = "VM_STARTED" and field "obj_uuid" = "3c61111f-1d67-7db4-95a5-f0287aff57bf"') <list of messages with name = VM_STARTED and obj_uuid with such value> ``` Also update the documentation to match new behaviour. Closes xapi-project#6340
2 parents 94f1f81 + ffda08e commit ec7baa3

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

ocaml/idl/datamodel.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -8976,7 +8976,7 @@ module Message = struct
89768976
let get_all_records_where =
89778977
call ~name:"get_all_records_where"
89788978
~lifecycle:[(Published, rel_orlando, "")]
8979-
~params:[(String, "expr", "The expression to match (not currently used)")]
8979+
~params:[(String, "expr", "The expression to match")]
89808980
~flags:[`Session]
89818981
~result:(Map (Ref _message, Record _message), "The messages")
89828982
~allowed_roles:_R_READ_ONLY ()
@@ -10543,12 +10543,12 @@ let all_system =
1054310543
(**
1054410544
These are the pairs of (object, field) which are bound together in
1054510545
the database schema.
10546-
10546+
1054710547
It is assumed that, for any entry (p, p'), neither p nor p'
1054810548
appears in any other entry. It may be the case that p = p', which
1054910549
is the only instance where some object-field pair may appear more
1055010550
than once.
10551-
10551+
1055210552
This is implicitly assumed by other code which treats this list -
1055310553
and its symmetric closure - as an association list
1055410554
without duplicate keys. *)

ocaml/xapi/xapi_message.ml

+48-2
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,54 @@ let get_record ~__context ~self =
730730

731731
let get_all_records ~__context = get_real message_dir (fun _ -> true) 0.0
732732

733-
let get_all_records_where ~__context ~expr:_ =
734-
get_real message_dir (fun _ -> true) 0.0
733+
let get_all_records_where ~__context ~expr =
734+
let open Xapi_database in
735+
let expr = Db_filter.expr_of_string expr in
736+
let eval_val msg expr =
737+
match expr with
738+
| Db_filter_types.Literal x ->
739+
x
740+
| Db_filter_types.Field x -> (
741+
match x with
742+
| "name" ->
743+
msg.API.message_name
744+
| "uuid" ->
745+
msg.API.message_uuid
746+
| "priority" ->
747+
Int64.to_string msg.API.message_priority
748+
| "cls" ->
749+
Record_util.cls_to_string msg.API.message_cls
750+
| "obj_uuid" ->
751+
msg.API.message_obj_uuid
752+
| "timestamp" ->
753+
Date.to_rfc3339 msg.API.message_timestamp
754+
| "body" ->
755+
msg.API.message_body
756+
| any_other_key ->
757+
raise (Db_exn.DBCache_NotFound ("missing field", any_other_key, ""))
758+
)
759+
in
760+
let eval_expr (lookup_val : API.message_t -> Db_filter_types._val -> string)
761+
(msg : API.message_t) =
762+
let lookup_val = lookup_val msg in
763+
let compare _a _b = lookup_val _a = lookup_val _b in
764+
let rec f = function
765+
| Db_filter_types.True ->
766+
true
767+
| Db_filter_types.False ->
768+
false
769+
| Db_filter_types.Not x ->
770+
not (f x)
771+
| Db_filter_types.And (a, b) ->
772+
f a && f b
773+
| Db_filter_types.Eq (_a, _b) ->
774+
compare _a _b
775+
| Db_filter_types.Or (a, b) ->
776+
f a || f b
777+
in
778+
f expr
779+
in
780+
get_real message_dir (eval_expr eval_val) 0.0
735781

736782
let repopulate_cache () =
737783
with_lock in_memory_cache_mutex (fun () ->

0 commit comments

Comments
 (0)