diff --git a/src/modules/kvs/kvs.c b/src/modules/kvs/kvs.c index 33157c6d4cda..f6a97c1a8ad7 100644 --- a/src/modules/kvs/kvs.c +++ b/src/modules/kvs/kvs.c @@ -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; @@ -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; diff --git a/src/modules/kvs/libkvs.c b/src/modules/kvs/libkvs.c index 77d361b94e9c..a66f446a361b 100644 --- a/src/modules/kvs/libkvs.c +++ b/src/modules/kvs/libkvs.c @@ -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; @@ -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; @@ -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)); @@ -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, ...) @@ -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; @@ -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; @@ -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); @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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); diff --git a/src/modules/kvs/proto.c b/src/modules/kvs/proto.c index 4bc9d1e69e57..e8abf6468a47 100644 --- a/src/modules/kvs/proto.c +++ b/src/modules/kvs/proto.c @@ -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; @@ -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; @@ -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; diff --git a/src/modules/kvs/proto.h b/src/modules/kvs/proto.h index 03ab7f001d5e..d892bfb4fc29 100644 --- a/src/modules/kvs/proto.h +++ b/src/modules/kvs/proto.h @@ -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); diff --git a/src/modules/kvs/test/proto.c b/src/modules/kvs/test/proto.c index e6c3acadcf41..cdb4d2a19d04 100644 --- a/src/modules/kvs/test/proto.c +++ b/src/modules/kvs/test/proto.c @@ -1,30 +1,48 @@ #include #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);