Skip to content
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

origvalue #3626

Closed
kodebach opened this issue Jan 18, 2021 · 10 comments
Closed

origvalue #3626

kodebach opened this issue Jan 18, 2021 · 10 comments
Labels
Milestone

Comments

@kodebach
Copy link
Member

The current solution with origvalue metadata is far from ideal.

The root cause of all the problems is that we wanted a solution that fulfils two properties:

  1. If the key is not modified between kdbGet() and kdbSet() the value in the storage file should not change.
  2. Executing kdb set /some/key myvalue should put the exact string myvalue into the storage file (assuming it is a valid value for the key).

IMO a much better solution would be a flag similar to KEY_FLAG_SYNC that is set by keySetRaw (called by keySetString and keySetBinary) [1] and only cleared at the end of kdbGet (and maybe kdbSet). That way a storage plugin could reliably detect, when a key value was actively modified (even if the new value is the same as the old one).

The second property would be solved automatically. The plugin would know that the key value is different than during kdbGet() and could skip any restore procedures and only do validation.

The first property can be solved multiple ways. One solution is that plugins don't do anything during kdbSet(), if the flag is not set (i.e. key wasn't modified since kdbGet()). To restore the original value we would have general logic in kdbGet() and kdbSet(). The part in kdbGet() copies the value received from the storage plugin into a meta key (e.g. reuse origvalue). In kdbSet() we restore all unmodified keys to this backup before calling the storage plugin.

Another (possibly more flexible) solution would be that plugins create internal meta keys to remember what representation [2] the value had before it was transformed in kdbGet(). In kdbSet() the plugin would reverse this transformation again.


[1] Functions that modify the key value directly must set the flag as well. This includes keyCopy, but also keyVNew. We need to set the flag on newly created keys, so that fully replacing a key also counts as modifying the value.

[2] The advantage of storing the kind of representation instead of the exact value (e.g. storing hex instead of 0xA3) is that with very little extra work, the plugin could allow admins to define in a spec what representation should be used in a storage file and always transform into that representation in kdbSet() regardless of whether the key was modified. The disadvantage is that there might be ambiguous cases and values that cannot be restored exactly (e.g. 0xaf vs. 0xaF vs. 0xAF) without storing the exact value. But in the end that doesn't matter, since it is up to the plugin to define how values are restored and it is an implementation detail how that is accomplished.

@markus2330
Copy link
Contributor

I fully agree that we need to rethink KEY_FLAG_SYNC. How can we proceed in that matter?

solution would be that plugins create internal

Yes, probably it was a mistake from the beginning to use origvalue for that. The values should be internal as they actually are specific to the plugins.

@kodebach
Copy link
Member Author

I fully agree that we need to rethink KEY_FLAG_SYNC. How can we proceed in that matter?

I didn't suggest any changes to KEY_FLAG_SYNC and I think there have to be (at least) two different flags. The replacement for origvalue suggested above needs a flag that exclusively indicates, when the value has changed/is new.
KEY_FLAG_SYNC indicates when a key has changed in any way, such that it has to be written out during kdbSet.

The values should be internal as they actually are specific to the plugins.

The problem, was that the current solution needs the core to remove origvalue on keySetString. It would be weird if the core was aware of internal metakeys for certain plugins. The new solution avoids this.

@markus2330
Copy link
Contributor

suggested above needs a flag that exclusively indicates, when the value has changed/is new.

This was the initial purpose of KEY_FLAG_SYNC, too. Then renaming and metadata got added and now we found a situation where we again need the pure initial meaning. We could separate the 3 different sync flags, like we have for locking.

The new solution avoids this.

Good. 👍

@markus2330
Copy link
Contributor

Do we have an agreement to get rid of meta:/origvalue and instead only using meta:/internal/* instead?

@kodebach
Copy link
Member Author

Yes, origvalue is broken and should not be recommended anymore. BUT only using meta:/internal/* is not a replacement. We need a way to let plugins know, when a key's value has changed. For that we need the additional flag.

Also there is this example in the toml plugin README. It uses/abuses origvalue to let users set key to a non-decimal value. The new solution doesn't really have a mechanism for that. You would have to use a kdb set with a decimal value. However, this probably more of a tools issue.

@stale
Copy link

stale bot commented Jul 30, 2022

I mark this issue stale as it did not have any activity for one year. I'll close it in two weeks if no further activity occurs. If you want it to be alive again, ping the issue by writing a message here or create a new issue with the remainder of this issue.
Thank you for your contributions 💖

@stale stale bot added the stale label Jul 30, 2022
@kodebach kodebach removed the stale label Jul 31, 2022
@markus2330
Copy link
Contributor

meta:/internal/* would be a solution if the type plugin is the only plugin that rewrites values. Then the one way how the type plugin saves the original value would be the only relevant place.

I agree that tooling might be interested in what the original value was. So maybe we should not make it internal and use meta:/value/original to store the original value? But still, only the type plugin would be responsible, otherwise there would be a mess like it is now.

We should even make a check in the contract that only one plugin writes a certain meta-value (it is okay if many read it).

@markus2330 markus2330 added this to the 0.9.* milestone Aug 1, 2022
@kodebach
Copy link
Member Author

kodebach commented Aug 1, 2022

So maybe we should not make it internal and use meta:/value/original to store the original value? But still, only the type plugin would be responsible, otherwise there would be a mess like it is now.

Yes, we definitely need a public "contract" to define how this kind of value conversion should be done. Ideally there would be library functions that handle everything except the actual conversion. But I'm not sure how feasible that is.

Only type doing any conversion is a definite no-go, because there are things like color and hexnumber that do valuable conversions. We cannot possible integrate all of this into type. Also there are plugins like toml that do direct conversion from the storage file and only use type for additional checking.

The basic problem here is just that some "internal" values have multiple "external" representations and we need to remember which one was used. So we broadly need two things:

  1. When the first conversion happens, we need to remember the original value.
  2. We need a way to check, if a key value changed between kdbGet and kdbSet.

How this is best achieved, I don't know. Unless we find a simple solution, fixing this issue should probably be part of #4424, since it is kind of related to the whole specification system.

We should even make a check in the contract that only one plugin writes a certain meta-value (it is okay if many read it).

How would you check/enforce that?

@github-actions
Copy link

github-actions bot commented Aug 2, 2023

I mark this stale as it did not have any activity for one year. I'll close it in two weeks if no further activity occurs. If you want it to be alive again, ping by writing a message here or create a new issue with the remainder of this issue.
Thank you for your contributions 💖

@github-actions github-actions bot added the stale label Aug 2, 2023
@github-actions
Copy link

I closed this now because it has been inactive for more than one year. If I closed it by mistake, please do not hesitate to reopen it or create a new issue with the remainder of this issue.
Thank you for your contributions 💖

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants