libelektra
libelektra copied to clipboard
[new-backend] Extend kdbOpen contracts for adding mountpoints
The contract KeySet passed to kdbOpen currently supports only two types of contract: adding global plugins and adding keys to the global keyset (see docs)
This is enough for the currently supported use cases of: configuring gopts and setting up I/O bindings and notifications. However, another use case is the new kdb (and possibly other applications). There we want to embed its specification into the application itself to ensure the tool always works and isn't dependent on files/mountpoints being present on the system.
To solve this a new type of contract mountpoint shall be added, i.e. keys below system:/elektra/contract/mountpoint can be used to define an in-process mountpoint. This mountpoint acts like any other mountpoint present on disk. It is added after the boostrap kdbGet, i.e. mountpoints defined in the contract override the ones present on disk.
Because this issue is concerned with mountpoints, it should only be implemented on the new-backend branch.
Proposal for structure
This is a proposal for the structure of the mountpoints contract. IMO the simplest solution would be to use system:/elektra/contract/mountpoint/<mountpointkey>/... where <mountpointkey> is the escaped form of the key at which the backend will be mounted and ... is the definition of the mountpoint. In other words, the contract would be exactly the same as a real mountpoint at system:/elektra/mountpoints, but moved to system:/elektra/contract/mountpoint.
For example to add a modified specload as a new backend at spec:/sw/myapp:
int main (void)
{
KeySet * contract = ksNew (2,
keyNew ("system:/elektra/contract/mountpoint/spec:\\/sw\\/myapp/plugins/backend/name", KEY_VALUE, "specload", KEY_END),
keyNew ("system:/elektra/contract/mountpoint/spec:\\/sw\\/myapp/definition/symbol", KEY_VALUE, "myappGetSpec", KEY_END),
KS_END
);
Key * parent = keyNew ("/sw/myapp", KEY_END);
KDB * handle = kdbOpen (contract, parent);
// ...
}
Note See #4444 for the required changes to
specload
Required changes to libelektra-kdb
To make this new contract work, a few changes need to be made to libelektra-kdb.
The starting point is ensureContract, the helper function responsible for processing contracts.
https://github.com/ElektraInitiative/libelektra/blob/5f0895bc88c92c623d9e2147cdaf12f77cb4db68/src/libs/elektra/kdb.c#L343-L355
Since the new contract shouldn't have any interaction with the previous ones, we can just add a new ensureContractMountpoint call in line 351.
Since ensureContract is already called at the right place in kdbOpen (after the bootstrap kdbGet, but before mountpoints are processed into the internal structure), this new ensureContractMountpoint is very simple. It basically boils down to: 1) move the keys from system:/elektra/contract/mountpoint to system:/elektra/mountpoints & 2) add them to the existing mountpoints keyset to override.
For the second point we need to pass elektraKs from kdbOpen to ensureContract and then ensureContractMountpoint. Then it should simply be a case of:
static void ensureContractMountpoint (KeySet * elektraKs, KeySet * contract)
{
Key * mountpointContractsRoot = keyNew ("system:/elektra/contract/mountpoint", KEY_END);
Key * mountpointsRoot = keyNew ("system:/elektra/mountpoints", KEY_END);
KeySet * mountpoints = ksCut (contract, mountpointContractsRoot);
ksRename (mountpoints, mountpointContractsRoot, mountpointsRoot);
// TODO: ksDel(ksCut(...)) the overlapping parts from elektraKs
ksAppend (elektraKs, mountpoints);
ksDel (mountpoints);
keyDel (mountpointContractsRoot);
keyDel (mountpointsRoot);
}
Note: This may work on
mastertoo. There theKeySetis simply calledkeysinkdbOpen. However, I'm not 100% sure if the surrounding code needs changes or not. Obviously, onmasterthe contract would look different, since it would have to match the oldsystem:/elektra/mountpointsstructure andspecloadcouldn't be used in the new "backend plugin" form.
cc @hannes99 @markus2330
system:/elektra/mountpoints
This should be changed to system:/elektra/mountpoint as we have in doc/DESIGN.md "We use singular for all names.". Do we need an extra issue for that?
system:/elektra/contract/mountpoint
:+1:
To make this new contract work, a few changes need to be made to libelektra-kdb.
Thank you, for so carefully investigating what is to be done! :heart_decoration:
I am missing the information what should be done if such a mountpoint already exists. Are you sure that simply inserting the keys, possibly kicking out other keys that were there, is safe with our definition of backends in the new-backend branch?
Are you sure that simply inserting the keys, possibly kicking out other keys that were there, is safe with our definition of backends in the new-backend branch?
It would probably be safer, to do appropriate ksCuts before the ksAppend in ensureContractMountpoint. This is more complex than I can quickly write up here, but the basic idea would be to
- Find the keys directly below
mountpointsRootinmountpoints. - Do a
ksDel (ksCut (elektraKs, keyFrom1))for each of those. - Then do the
ksAppend (elektraKs, mountpoints).
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 :sparkling_heart:
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 :sparkling_heart: