Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

[new-backend] Extend kdbOpen contracts for adding mountpoints #4442

Closed
kodebach opened this issue Aug 22, 2022 · 5 comments
Closed

[new-backend] Extend kdbOpen contracts for adding mountpoints #4442

kodebach opened this issue Aug 22, 2022 · 5 comments
Assignees
Labels

Comments

@kodebach
Copy link
Member

kodebach commented Aug 22, 2022

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.

static bool ensureContract (KDB * handle, const KeySet * contract, Key * parentKey)
{
// TODO (kodebach): tests
// deep dup, so modifications to the keys in contract after kdbOpen() cannot modify the contract
KeySet * dup = ksDeepDup (contract);
ensureContractGlobalKs (handle, dup);
int ret = ensureContractMountGlobal (handle, dup, parentKey);
ksDel (dup);
return ret == 0;
}

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 master too. There the KeySet is simply called keys in kdbOpen. However, I'm not 100% sure if the surrounding code needs changes or not. Obviously, on master the contract would look different, since it would have to match the old system:/elektra/mountpoints structure and specload couldn't be used in the new "backend plugin" form.

@kodebach

This comment was marked as off-topic.

@markus2330
Copy link
Contributor

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

👍

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! 💟

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?

@kodebach
Copy link
Member Author

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

  1. Find the keys directly below mountpointsRoot in mountpoints.
  2. Do a ksDel (ksCut (elektraKs, keyFrom1)) for each of those.
  3. Then do the ksAppend (elektraKs, mountpoints).

@github-actions
Copy link

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 29, 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 Sep 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants