Skip to content

Commit

Permalink
modules/kvs: allow optional root dirent in kvs.get
Browse files Browse the repository at this point in the history
Allow an optional root dirent to accompany a kvs.get
request.  If present, key will be looked up relative to
this directory.  It is an EINVAL error if the dirent
is invalid or not a directory reference.

Update kvs.get codec and its unit test.
  • Loading branch information
garlick committed Sep 23, 2016
1 parent 400a743 commit 490ab6a
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 22 deletions.
18 changes: 16 additions & 2 deletions src/modules/kvs/kvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,8 @@ static void get_request_cb (flux_t h, flux_msg_handler_t *w,
int flags;
const char *key;
JSON val;
JSON root = NULL;
JSON root_dirent = NULL;
wait_t *wait = NULL;
int lookup_errnum = 0;
int rc = -1;
Expand All @@ -918,11 +920,23 @@ static void get_request_cb (flux_t h, flux_msg_handler_t *w,
errno = EPROTO;
goto done;
}
if (kp_tget_dec (in, &key, &flags) < 0)
if (kp_tget_dec (in, &root_dirent, &key, &flags) < 0)
goto done;
if (!(wait = wait_create_msg_handler (h, w, msg, get_request_cb, arg)))
goto done;
if (!lookup (ctx, NULL, wait, flags, key, &val, &lookup_errnum))
/* If root dirent was specified, lookup will be relative to that.
*/
if (root_dirent) {
const char *ref;

if (!Jget_str (root_dirent, "DIRREF", &ref)) {
errno = EINVAL;
goto done;
}
if (!load (ctx, ref, wait, &root))
goto stall;
}
if (!lookup (ctx, root, wait, flags, key, &val, &lookup_errnum))
goto stall;
if (lookup_errnum != 0) {
errno = lookup_errnum;
Expand Down
27 changes: 14 additions & 13 deletions src/modules/kvs/libkvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ char *kvsdir_key_at (kvsdir_t *dir, const char *name)
** GET
**/

static int getobj (flux_t h, const char *key, int flags, json_object **val)
static int getobj (flux_t h, json_object *rootdir, const char *key,
int flags, json_object **val)
{
flux_rpc_t *rpc = NULL;
const char *json_str;
Expand All @@ -341,7 +342,7 @@ static int getobj (flux_t h, const char *key, int flags, json_object **val)
goto done;
}
k = pathcat (kvs_getcwd (h), key);
if (!(in = kp_tget_enc (k, flags)))
if (!(in = kp_tget_enc (rootdir, k, flags)))
goto done;
if (!(rpc = flux_rpc (h, "kvs.get", Jtostr (in), FLUX_NODEID_ANY, 0)))
goto done;
Expand Down Expand Up @@ -371,7 +372,7 @@ int kvs_get (flux_t h, const char *key, char **val)
{
JSON v;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
return -1;
if (val)
*val = xstrdup (Jtostr (v));
Expand All @@ -382,7 +383,7 @@ int kvs_get (flux_t h, const char *key, char **val)
/* deprecated */
int kvs_get_obj (flux_t h, const char *key, JSON *val)
{
return getobj (h, key, 0, val);
return getobj (h, NULL, key, 0, val);
}

int kvs_get_dir (flux_t h, kvsdir_t **dir, const char *fmt, ...)
Expand All @@ -405,7 +406,7 @@ int kvs_get_dir (flux_t h, kvsdir_t **dir, const char *fmt, ...)
key = xvasprintf (fmt, ap);
va_end (ap);
k = pathcat (kvs_getcwd (h), key);
if (!(in = kp_tget_enc (k, KVS_PROTO_READDIR)))
if (!(in = kp_tget_enc (NULL, k, KVS_PROTO_READDIR)))
goto done;
if (!(rpc = flux_rpc (h, "kvs.get", Jtostr (in), FLUX_NODEID_ANY, 0)))
goto done;
Expand Down Expand Up @@ -435,7 +436,7 @@ int kvs_get_symlink (flux_t h, const char *key, char **val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, KVS_PROTO_READLINK, &v) < 0)
if (getobj (h, NULL, key, KVS_PROTO_READLINK, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_string) {
errno = EPROTO;
Expand All @@ -455,7 +456,7 @@ int kvs_get_treeobj (flux_t h, const char *key, char **val)
const char *s;
int rc = -1;

if (getobj (h, key, KVS_PROTO_TREEOBJ, &v) < 0)
if (getobj (h, NULL, key, KVS_PROTO_TREEOBJ, &v) < 0)
goto done;
if (val) {
s = json_object_to_json_string_ext (v, JSON_C_TO_STRING_PLAIN);
Expand All @@ -472,7 +473,7 @@ int kvs_get_string (flux_t h, const char *key, char **val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_string) {
errno = EPROTO;
Expand All @@ -491,7 +492,7 @@ int kvs_get_int (flux_t h, const char *key, int *val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_int) {
errno = EPROTO;
Expand All @@ -510,7 +511,7 @@ int kvs_get_int64 (flux_t h, const char *key, int64_t *val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_int) {
errno = EPROTO;
Expand All @@ -529,7 +530,7 @@ int kvs_get_double (flux_t h, const char *key, double *val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_double) {
errno = EPROTO;
Expand All @@ -548,7 +549,7 @@ int kvs_get_boolean (flux_t h, const char *key, bool *val)
JSON v = NULL;
int rc = -1;

if (getobj (h, key, 0, &v) < 0)
if (getobj (h, NULL, key, 0, &v) < 0)
goto done;
if (json_object_get_type (v) != json_type_boolean) {
errno = EPROTO;
Expand Down Expand Up @@ -1651,7 +1652,7 @@ int kvsdir_unlink (kvsdir_t *dir, const char *name)
int kvs_copy (flux_t h, const char *from, const char *to)
{
JSON dirent;
if (getobj (h, from, KVS_PROTO_TREEOBJ, &dirent) < 0)
if (getobj (h, NULL, from, KVS_PROTO_TREEOBJ, &dirent) < 0)
return -1;
if (kvs_put_dirent (h, to, dirent) < 0) {
Jput (dirent);
Expand Down
8 changes: 6 additions & 2 deletions src/modules/kvs/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
/* kvs.get
*/

JSON kp_tget_enc (const char *key, int flags)
JSON kp_tget_enc (JSON rootdir, const char *key, int flags)
{
JSON o = NULL;

Expand All @@ -53,13 +53,15 @@ JSON kp_tget_enc (const char *key, int flags)
goto done;
}
o = Jnew ();
if (rootdir)
Jadd_obj (o, "rootdir", rootdir); /* takes a ref on rootdir */
Jadd_str (o, "key", key);
Jadd_int (o, "flags", flags);
done:
return o;
}

int kp_tget_dec (JSON o, const char **key, int *flags)
int kp_tget_dec (JSON o, JSON *rootdir, const char **key, int *flags)
{
int rc = -1;

Expand All @@ -71,6 +73,8 @@ int kp_tget_dec (JSON o, const char **key, int *flags)
errno = EPROTO;
goto done;
}
if (rootdir)
*rootdir = Jobj_get (o, "rootdir");
rc = 0;
done:
return rc;
Expand Down
6 changes: 4 additions & 2 deletions src/modules/kvs/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ enum {

/* kvs.get
*/
json_object *kp_tget_enc (const char *key, int flags);
int kp_tget_dec (json_object *o, const char **key, int *flags);
json_object *kp_tget_enc (json_object *rootdir,
const char *key, int flags);
int kp_tget_dec (json_object *o, json_object **rootdir,
const char **key, int *flags);

json_object *kp_rget_enc (json_object *val);
int kp_rget_dec (json_object *o, json_object **val);
Expand Down
24 changes: 21 additions & 3 deletions src/modules/kvs/test/proto.c
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
#include <string.h>

#include "src/common/libutil/shortjson.h"
#include "src/modules/kvs/proto.h"
#include "src/common/libtap/tap.h"
#include "src/common/libutil/log.h"
#include "src/common/libutil/shortjson.h"
#include "src/common/libutil/xzmalloc.h"

#include "src/modules/kvs/proto.h"
#include "src/modules/kvs/json_dirent.h"

void test_get (void)
{
JSON o;
const char *key = NULL;
JSON val = NULL;
JSON dirent = NULL;
JSON dirent2 = NULL;
int i, flags;

o = kp_tget_enc ("foo", 42);
o = kp_tget_enc (NULL, "foo", 42);
ok (o != NULL,
"kp_tget_enc works");
diag ("get request: %s", Jtostr (o));
flags = 0;
ok (kp_tget_dec (o, &key, &flags) == 0 && flags == 42,
ok (kp_tget_dec (o, NULL, &key, &flags) == 0 && flags == 42,
"kp_tget_dec works");
like (key, "^foo$",
"kp_tget_dec returned encoded key");
Jput (o);

dirent = dirent_create ("DIRREF", "sha1-abcdefabcdef00000");
o = kp_tget_enc (dirent, "foo", 42);
ok (o != NULL,
"kp_tget_enc with optional dirent arg works");
diag ("get request: %s", Jtostr (o));
flags = 0;
ok (kp_tget_dec (o, &dirent2, &key, &flags) == 0 && flags == 42,
"kp_tget_dec works");
ok (dirent_validate (dirent2) && dirent_match (dirent, dirent2),
"kp_tget_dec returned dirent");
Jput (dirent);
Jput (o);


val = Jnew ();
Jadd_int (val, "i", 42);
o = kp_rget_enc (val);
Expand Down

0 comments on commit 490ab6a

Please sign in to comment.