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

kvs: support symlinks with namespaces within them #1949

Merged
merged 10 commits into from
Jan 29, 2019
13 changes: 9 additions & 4 deletions doc/man1/flux-kvs.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,20 @@ Remove 'key' from the KVS and commit the change. If 'key' represents
a directory, specify '-R' to remove all keys underneath it. If '-f' is
specified, ignore nonexistent files.

*link* 'target' 'linkname'::
*link* [-T ns] 'target' 'linkname'::
Create a new name for 'target', similar to a symbolic link, and commit
the change. 'target' does not have to exist. If 'linkname' exists,
it is overwritten.
it is overwritten. Optionally, specify a namespace the target is in.
This namespace can be different that the one the linkname is being
written to.

*readlink* [-a treeobj] 'key' ['key...']::
*readlink* [-a treeobj] [ -o | -k ] 'key' ['key...']::
Retrieve the key a link refers to rather than its value, as would be
returned by *get*. '-a treeobj' causes the lookup to be relative to
an RFC 11 snapshot reference.
an RFC 11 snapshot reference. If the link points to a namespace, the
namespace and key will be output in the format '<namespace>::<key>'.
The '-o' can be used to only output namespaces and the '-k' can be
used to only output keys.

*mkdir* 'key' ['key...']::
Create an empty directory and commit the change. If 'key' exists,
Expand Down
7 changes: 5 additions & 2 deletions doc/man3/flux_kvs_lookup.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ SYNOPSIS

int flux_kvs_lookup_get_treeobj (flux_future_t *f, const char **treeobj);

int flux_kvs_lookup_get_symlink (flux_future_t *f, const char **target);
int flux_kvs_lookup_get_symlink (flux_future_t *f, const char **ns,
const char **target);

const char *flux_kvs_lookup_get_key (flux_future_t *f);

Expand Down Expand Up @@ -87,7 +88,9 @@ function should work on all.

`flux_kvs_lookup_get_symlink()` interprets the result as a symlink target,
e.g. in response to a lookup with the FLUX_KVS_READLINK flag set.
The result is parsed and symlink target is assigned to _target_.
The result is parsed and symlink namespace is assigned to _ns_ and
the symlink target is assigned to _target_. If a namespace was not assigned
to the symlink, _ns_ is set to NULL.

`flux_kvs_lookup_get_key()` accesses the key argument from the original
lookup.
Expand Down
9 changes: 6 additions & 3 deletions doc/man3/flux_kvs_txn_create.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ SYNOPSIS
const char *key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not critical but "common" is not that helpful in the commit title. Maybe go with "libkvs/txn:" for this one?


int flux_kvs_txn_symlink (flux_kvs_txn_t *txn, int flags,
const char *key, const char *target);
const char *key, const char *ns,
const char *target);

int flux_kvs_txn_put_raw (flux_kvs_txn_t *txn, int flags,
const char *key, const void *data, int len);
Expand Down Expand Up @@ -71,8 +72,10 @@ from a JSON object built with `json_pack()` style arguments (see below).
`flux_kvs_txn_unlink()` removes _key_. If _key_ is a directory,
all its contents are removed as well.

`flux_kvs_txn_symlink()` sets _key_ to a symbolic link pointing to _target_,
another key. _target_ need not exist.
`flux_kvs_txn_symlink()` sets _key_ to a symbolic link pointing to a
namespace _ns_ and a _target_ key within that namespace. Neither _ns_
nor _target_ must exist. The namespace _ns_ is optional, if set to
NULL the _target_ is assumed to be in the key's current namespace.

`flux_kvs_txn_put_raw()` sets _key_ to a value containing raw data
referred to by _data_ of length _len_.
Expand Down
2 changes: 1 addition & 1 deletion src/bindings/lua/flux-lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ static int l_flux_kvs_type (lua_State *L)
return lua_pusherror (L, "key expected in arg #2");

if ((future = flux_kvs_lookup (f, FLUX_KVS_READLINK, key))
&& flux_kvs_lookup_get_symlink (future, &target) == 0) {
&& flux_kvs_lookup_get_symlink (future, NULL, &target) == 0) {
lua_pushstring (L, "symlink");
lua_pushstring (L, target);
flux_future_destroy (future);
Expand Down
2 changes: 1 addition & 1 deletion src/bindings/python/flux/kvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def put_unlink(flux_handle, key):
def put_symlink(flux_handle, key, target):
if flux_handle.aux_txn is None:
flux_handle.aux_txn = RAW.flux_kvs_txn_create()
return RAW.flux_kvs_txn_symlink(flux_handle.aux_txn, 0, key, target)
return RAW.flux_kvs_txn_symlink(flux_handle.aux_txn, 0, key, None, target)


def commit(flux_handle, flags=0):
Expand Down
60 changes: 48 additions & 12 deletions src/cmd/flux-kvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ static struct optparse_option readlink_opts[] = {
{ .name = "at", .key = 'a', .has_arg = 1,
.usage = "Lookup relative to RFC 11 snapshot reference",
},
{ .name = "namespace-only", .key = 'o', .has_arg = 0,
.usage = "Output only namespace if link points to a namespace",
},
{ .name = "key-only", .key = 'k', .has_arg = 0,
.usage = "Output only key if link points to a namespace",
},
OPTPARSE_TABLE_END
};

Expand Down Expand Up @@ -215,6 +221,13 @@ static struct optparse_option copy_opts[] = {
OPTPARSE_TABLE_END
};

static struct optparse_option link_opts[] = {
{ .name = "target-namespace", .key = 'T', .has_arg = 1,
.usage = "Specify target's namespace",
},
OPTPARSE_TABLE_END
};

static struct optparse_subcommand subcommands[] = {
{ "namespace-create",
"name [name...]",
Expand Down Expand Up @@ -273,14 +286,14 @@ static struct optparse_subcommand subcommands[] = {
unlink_opts
},
{ "link",
"target linkname",
"[-T ns] target linkname",
"Create a new name for target",
cmd_link,
0,
NULL
link_opts
},
{ "readlink",
"[-a treeobj] key [key...]",
"[-a treeobj] [ -o | -k ] key [key...]",
"Retrieve the key a link refers to",
cmd_readlink,
0,
Expand Down Expand Up @@ -911,6 +924,8 @@ int cmd_unlink (optparse_t *p, int argc, char **argv)
int cmd_link (optparse_t *p, int argc, char **argv)
{
flux_t *h = (flux_t *)optparse_get_data (p, "flux_handle");
const char *ns = NULL;
const char *target, *linkname;
int optindex;
flux_kvs_txn_t *txn;
flux_future_t *f;
Expand All @@ -923,10 +938,14 @@ int cmd_link (optparse_t *p, int argc, char **argv)
if (optindex != (argc - 2))
log_msg_exit ("link: specify target and link_name");

ns = optparse_get_str (p, "target-namespace", NULL);
target = argv[optindex];
linkname = argv[optindex + 1];

if (!(txn = flux_kvs_txn_create ()))
log_err_exit ("flux_kvs_txn_create");
if (flux_kvs_txn_symlink (txn, 0, argv[optindex + 1], argv[optindex]) < 0)
log_err_exit ("%s", argv[optindex + 1]);
if (flux_kvs_txn_symlink (txn, 0, linkname, ns, target) < 0)
log_err_exit ("%s", linkname);
if (!(f = flux_kvs_commit (h, 0, txn)) || flux_future_get (f, NULL) < 0)
log_err_exit ("flux_kvs_commit");
flux_future_destroy (f);
Expand All @@ -938,16 +957,21 @@ int cmd_readlink (optparse_t *p, int argc, char **argv)
{
flux_t *h = (flux_t *)optparse_get_data (p, "flux_handle");
int optindex, i;
const char *target;
flux_future_t *f;
bool ns_only;
bool key_only;

optindex = optparse_option_index (p);
if ((optindex - argc) == 0) {
optparse_print_usage (p);
exit (1);
}
ns_only = optparse_hasopt (p, "namespace-only");
key_only = optparse_hasopt (p, "key-only");

for (i = optindex; i < argc; i++) {
const char *ns = NULL;
const char *target = NULL;
if (optparse_hasopt (p, "at")) {
const char *ref = optparse_get_str (p, "at", "");
if (!(f = flux_kvs_lookupat (h, FLUX_KVS_READLINK, argv[i], ref)))
Expand All @@ -957,9 +981,18 @@ int cmd_readlink (optparse_t *p, int argc, char **argv)
if (!(f = flux_kvs_lookup (h, FLUX_KVS_READLINK, argv[i])))
log_err_exit ("%s", argv[i]);
}
if (flux_kvs_lookup_get_symlink (f, &target) < 0)
if (flux_kvs_lookup_get_symlink (f, &ns, &target) < 0)
log_err_exit ("%s", argv[i]);
printf ("%s\n", target);
if (ns_only && ns)
printf ("%s\n", ns);
else if (key_only)
printf ("%s\n", target);
else {
if (ns)
printf ("%s::%s\n", ns, target);
else
printf ("%s\n", target);
}
flux_future_destroy (f);
}
return (0);
Expand Down Expand Up @@ -1241,13 +1274,16 @@ static void dump_kvs_dir (const flux_kvsdir_t *dir, int maxcol,
while ((name = flux_kvsitr_next (itr))) {
key = flux_kvsdir_key_at (dir, name);
if (flux_kvsdir_issymlink (dir, name)) {
const char *link;
const char *ns = NULL;
const char *target = NULL;
if (!(f = flux_kvs_lookupat (h, FLUX_KVS_READLINK, key, rootref))
|| flux_kvs_lookup_get_symlink (f, &link) < 0)
|| flux_kvs_lookup_get_symlink (f, &ns, &target) < 0)
log_err_exit ("%s", key);
printf ("%s -> %s\n", key, link);
if (ns)
printf ("%s -> %s::%s\n", key, ns, target);
else
printf ("%s -> %s\n", key, target);
flux_future_destroy (f);

} else if (flux_kvsdir_isdir (dir, name)) {
if (Ropt) {
const flux_kvsdir_t *ndir;
Expand Down
2 changes: 1 addition & 1 deletion src/common/libkvs/kvs_classic.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ int flux_kvs_symlink (flux_t *h, const char *key, const char *target)
flux_kvs_txn_t *txn = get_default_txn (h);
if (!txn)
return -1;
return flux_kvs_txn_symlink (txn, 0, key, target);
return flux_kvs_txn_symlink (txn, 0, key, NULL, target);
}

int flux_kvs_mkdir (flux_t *h, const char *key)
Expand Down
16 changes: 8 additions & 8 deletions src/common/libkvs/kvs_lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,12 @@ int flux_kvs_lookup_get_dir (flux_future_t *f, const flux_kvsdir_t **dirp)
return 0;
}

int flux_kvs_lookup_get_symlink (flux_future_t *f, const char **target)
int flux_kvs_lookup_get_symlink (flux_future_t *f,
const char **ns,
const char **target)
{
struct lookup_ctx *ctx;
json_t *str;
const char *s;
const char *n = NULL, *t = NULL;

if (!(ctx = get_lookup_ctx (f)))
return -1;
Expand All @@ -386,13 +387,12 @@ int flux_kvs_lookup_get_symlink (flux_future_t *f, const char **target)
errno = EINVAL;
return -1;
}
if (!(str = treeobj_get_data (ctx->treeobj))
|| !(s = json_string_value (str))) {
errno = EINVAL;
if (treeobj_get_symlink (ctx->treeobj, &n, &t) < 0)
return -1;
}
if (ns)
*ns = n;
if (target)
*target = s;
*target = t;
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion src/common/libkvs/kvs_lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ int flux_kvs_lookup_get_unpack (flux_future_t *f, const char *fmt, ...);
int flux_kvs_lookup_get_raw (flux_future_t *f, const void **data, int *len);
int flux_kvs_lookup_get_treeobj (flux_future_t *f, const char **treeobj);
int flux_kvs_lookup_get_dir (flux_future_t *f, const flux_kvsdir_t **dir);
int flux_kvs_lookup_get_symlink (flux_future_t *f, const char **target);
int flux_kvs_lookup_get_symlink (flux_future_t *f,
const char **ns,
const char **target);

const char *flux_kvs_lookup_get_key (flux_future_t *f);

Expand Down
5 changes: 3 additions & 2 deletions src/common/libkvs/kvs_txn.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ int flux_kvs_txn_unlink (flux_kvs_txn_t *txn, int flags,
}

int flux_kvs_txn_symlink (flux_kvs_txn_t *txn, int flags,
const char *key, const char *target)
const char *key, const char *ns,
const char *target)
{
json_t *dirent = NULL;
int saved_errno;
Expand All @@ -296,7 +297,7 @@ int flux_kvs_txn_symlink (flux_kvs_txn_t *txn, int flags,
}
if (validate_flags (flags, 0) < 0)
goto error;
if (!(dirent = treeobj_create_symlink (target)))
if (!(dirent = treeobj_create_symlink (ns, target)))
goto error;
if (append_op_to_txn (txn, flags, key, dirent) < 0)
goto error;
Expand Down
3 changes: 2 additions & 1 deletion src/common/libkvs/kvs_txn.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ int flux_kvs_txn_unlink (flux_kvs_txn_t *txn, int flags,
const char *key);

int flux_kvs_txn_symlink (flux_kvs_txn_t *txn, int flags,
const char *key, const char *target);
const char *key, const char *ns,
const char *target);

#ifdef __cplusplus
}
Expand Down
Loading