-
Notifications
You must be signed in to change notification settings - Fork 292
CA-171948: Adjust semantics of 'add_to_<map>' in Db layer #3001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Jon Ludlam <jonathan.ludlam@citrix.com>
Signed-off-by: Jon Ludlam <jonathan.ludlam@citrix.com>
* Xapi code must assume idempotency of 'add_to_<map>' calls * Remote DB calls will _always_ be idempotent * DB calls on the master are controlled by the switch, defaulting to the original behaviour (non idempotent) * API calls follow the master DB behaviour Signed-off-by: Jon Ludlam <jonathan.ludlam@citrix.com>
Minor quibble: |
all map operations are idempotent after this c/s, because 'remove' already was. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small comments.
let t = Schema.Value.Unsafe_cast.pairs t in | ||
if List.mem key (List.map fst t) then raise Duplicate; | ||
Schema.Value.Pairs ((key, value) :: t) | ||
if List.mem_assoc key t && (not idempotent || List.assoc key t <> value) then raise Duplicate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for performance it would be best to check the cheapest conditions first - that would be idempotent
and List.assoc
next (I assume).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's quite so clear cut here - checking the idempotent
condition is only relevant if the mem_assoc
test is true, and that's expected to be quite rare. Also, in the default case here idempotent
is false, hence we don't do the List.assoc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right - I now realise that you do List.mem
to avoid a Not_found
exception. This can stay as it is. But I think the best performance would have this:
try if not idempotent && List.assoc key t <> value then raise Duplicate
with Not_found -> ()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't have the same semantics - it doesn't raise any exception if idempotent is true, which isn't the same as the current change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last try - not better performance but easier to read maybe:
if List.mem_assoc key t && idempotent && List.assoc key t = value then raise Duplicate;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that has wrong semantics too.
If idempotent
then we shouldn't raise an exception when List.assoc key t = value
,
and otherwise we should raise an exception if List.mem_assoc key t
regardless of the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I wanted to use: !a || !b = !(a && b)
but forgot the outer negation. So it probably should stay the way it is.
ocaml/database/db_cache_types.ml
Outdated
|
||
exception Duplicate | ||
let add_to_map key value t = | ||
let add_to_map idempotent key value t = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd consider givingidempotent
a label because at a call site true
/false
isn't very descriptive and easy to mix up. You could even provide a default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
Suggested by @lindig in PR#3001 Signed-off-by: Jon Ludlam <jonathan.ludlam@citrix.com>
This allows the DB add_to_map calls to be idempotent. So if a map contains:
then
will succeed if idempotency is enabled, and fail with
Duplicate_key
if not.will always fail with a
Duplicate_key
exception.By default, this behaviour is turned on when xapi uses the remote DB access from slaves, but turned off on the master. This has the effect of ensuring that the Xen API calls retain their current semantics for now.
The behaviour can be normalised across master/slave via the config file parameter
which currently defaults to
false
. This default will change at some point in the future.