Skip to content

Commit

Permalink
Merge abc0595 into a3add43
Browse files Browse the repository at this point in the history
  • Loading branch information
chu11 committed Jul 18, 2017
2 parents a3add43 + abc0595 commit 17aba0e
Show file tree
Hide file tree
Showing 27 changed files with 1,313 additions and 806 deletions.
13 changes: 11 additions & 2 deletions src/common/libkvs/Makefile.am
Expand Up @@ -16,11 +16,14 @@ libkvs_la_SOURCES = \
kvs_lookup.c \
proto.c \
proto.h \
proto_functions.h \
json_dirent.c \
json_dirent.h \
kvs_dir.c \
kvs_classic.c \
kvs_watch.c
kvs_watch.c \
jansson_dirent.c \
jansson_dirent.h


fluxcoreinclude_HEADERS = \
Expand All @@ -32,7 +35,8 @@ fluxcoreinclude_HEADERS = \

TESTS = \
test_proto.t \
test_dirent.t
test_dirent.t \
test_jansson_dirent.t

check_PROGRAMS = \
$(TESTS)
Expand All @@ -45,6 +49,7 @@ test_ldadd = \
$(top_builddir)/src/common/libflux-internal.la \
$(top_builddir)/src/common/libkvs/proto.o \
$(top_builddir)/src/common/libkvs/json_dirent.o \
$(top_builddir)/src/common/libkvs/jansson_dirent.o \
$(top_builddir)/src/common/libflux-core.la \
$(top_builddir)/src/common/libtap/libtap.la

Expand All @@ -59,3 +64,7 @@ test_proto_t_LDADD = $(test_ldadd)
test_dirent_t_SOURCES = test/dirent.c
test_dirent_t_CPPFLAGS = $(test_cppflags)
test_dirent_t_LDADD = $(test_ldadd)

test_jansson_dirent_t_SOURCES = test/jansson_dirent.c
test_jansson_dirent_t_CPPFLAGS = $(test_cppflags)
test_jansson_dirent_t_LDADD = $(test_ldadd)
157 changes: 157 additions & 0 deletions src/common/libkvs/jansson_dirent.c
@@ -0,0 +1,157 @@
/*****************************************************************************\
* Copyright (c) 2014 Lawrence Livermore National Security, LLC. Produced at
* the Lawrence Livermore National Laboratory (cf, AUTHORS, DISCLAIMER.LLNS).
* LLNL-CODE-658032 All rights reserved.
*
* This file is part of the Flux resource manager framework.
* For details, see https://github.com/flux-framework.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the license, or (at your option)
* any later version.
*
* Flux is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the terms and conditions of the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
* See also: http://www.gnu.org/licenses/
\*****************************************************************************/

#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <jansson.h>

#include "src/common/libutil/blobref.h"
#include "src/common/libutil/oom.h"

#include "jansson_dirent.h"

json_t *j_dirent_create (const char *type, void *arg)
{
json_t *dirent;
bool valid_type = false;

if (!(dirent = json_object ()))
oom ();

if (!strcmp (type, "FILEREF") || !strcmp (type, "DIRREF")) {
char *ref = arg;
json_t *o;

if (!(o = json_string (ref)))
oom ();
if (json_object_set_new (dirent, type, o) < 0)
oom ();

valid_type = true;
} else if (!strcmp (type, "FILEVAL") || !strcmp (type, "DIRVAL")
|| !strcmp (type, "LINKVAL")) {
json_t *val = arg;

if (val)
json_incref (val);
else {
if (!(val = json_object ()))
oom ();
}
if (json_object_set_new (dirent, type, val) < 0)
oom ();
valid_type = true;
}
assert (valid_type == true);

return dirent;
}

bool j_dirent_match (json_t *dirent1, json_t *dirent2)
{
if (!dirent1 && !dirent2)
return true;
if ((dirent1 && !dirent2) || (!dirent1 && dirent2))
return false;
if (json_equal (dirent1, dirent2))
return true;
return false;
}

void j_dirent_append (json_t **array, const char *key, json_t *dirent)
{
json_t *op;
json_t *o;

if (!(op = json_object ()))
oom ();

if (!(o = json_string (key)))
oom ();
if (json_object_set_new (op, "key", o) < 0)
oom ();
if (dirent) {
if (json_object_set (op, "dirent", dirent) < 0)
oom ();
}
else {
json_t *null;
if (!(null = json_null ()))
oom ();
if (json_object_set_new (op, "dirent", null) < 0)
oom ();
}
if (!*array) {
if (!(*array = json_array ()))
oom ();
}
if (json_array_append (*array, op) < 0)
oom ();
}

int j_dirent_validate (json_t *dirent)
{
json_t *o;

if (!dirent)
goto error;
if ((o = json_object_get (dirent, "DIRVAL"))) {
const char *key;
json_t *val;
json_object_foreach (o, key, val) {
if (j_dirent_validate (val) < 0)
goto error;
}
}
else if ((o = json_object_get (dirent, "FILEVAL"))) {
/* Any json type is valid here */
}
else if ((o = json_object_get (dirent, "LINKVAL"))) {
if (json_typeof (o) != JSON_STRING)
goto error;
}
else if ((o = json_object_get (dirent, "DIRREF"))
|| (o = json_object_get (dirent, "FILEREF"))) {
if (json_typeof (o) != JSON_STRING)
goto error;
const char *s = json_string_value (o);
uint8_t hash[BLOBREF_MAX_DIGEST_SIZE];
if (blobref_strtohash (s, hash, sizeof (hash)) < 0)
goto error;
}
else
goto error;
return 0;
error:
errno = EINVAL;
return -1;
}

/*
* vi:tabstop=4 shiftwidth=4 expandtab
*/
63 changes: 63 additions & 0 deletions src/common/libkvs/jansson_dirent.h
@@ -0,0 +1,63 @@
#include <stdbool.h>
#include <jansson.h>

/* JSON directory object:
* list of key-value pairs where key is a name, value is a dirent
*
* JSON dirent objects:
* object containing one key-value pair where key is one of
* "FILEREF", "DIRREF", "FILEVAL", "DIRVAL", "LINKVAL", and value is a
* blobref key into ctx->store (FILEREF, DIRREF), an actual directory, file
* (value), or link target JSON object (FILEVAL, DIRVAL, LINKVAL).
*
* For example, consider KVS containing:
* a="foo"
* b="bar"
* c.d="baz"
* X -> c.d
*
* Root directory:
* {"a":{"FILEREF":"f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"},
* "b":{"FILEREF","8714e0ef31edb00e33683f575274379955b3526c"},
* "c":{"DIRREF","6eadd3a778e410597c85d74c287a57ad66071a45"},
* "X":{"LINKVAL","c.d"}}
*
* Deep copy of root directory:
* {"a":{"FILEVAL":"foo"},
* "b":{"FILEVAL","bar"},
* "c":{"DIRVAL",{"d":{"FILEVAL":"baz"}}},
* "X":{"LINKVAL","c.d"}}
*
* On LINKVAL's:
* - target is always fully qualified key name
* - links are always followed in path traversal of intermediate directories
* - for kvs_get, terminal links are only followed if 'readlink' flag is set
* - for kvs_put, terminal links are never followed
*/

/* Create a KVS dirent.
* 'type' is one of { "FILEREF", "DIRREF", "FILEVAL", "DIRVAL", "LINKVAL" }.
* 'arg' is dependent on the type. This function asserts on failure.
*/
json_t *j_dirent_create (const char *type, void *arg);

/* Append a JSON object containing
* { "key" : key, "dirent" : dirent }
* { "key" : key, "dirent" : nil }
* to a json array, creating '*array' if necessary. This is used to build
* a KVS commit, where each new object is an ordered operation that adds/
* changes/unlinks a key in KVS namespace. This function asserts on failure.
*/
void j_dirent_append (json_t **array, const char *key, json_t *dirent);

/* Compare two dirents.
* N.B. The serialize/strcmp method used here can return false negatives,
* but a positive can be relied on.
*/
bool j_dirent_match (json_t *dirent1, json_t *dirent2);

int j_dirent_validate (json_t *dirent);

/*
* vi:tabstop=4 shiftwidth=4 expandtab
*/
1 change: 1 addition & 0 deletions src/common/libkvs/kvs.c
Expand Up @@ -50,6 +50,7 @@
#include "src/common/libutil/blobref.h"

#include "proto.h"
#include "proto_functions.h"
#include "json_dirent.h"


Expand Down
1 change: 1 addition & 0 deletions src/common/libkvs/kvs_watch.c
Expand Up @@ -50,6 +50,7 @@
#include "src/common/libutil/blobref.h"

#include "proto.h"
#include "proto_functions.h"
#include "json_dirent.h"


Expand Down
1 change: 1 addition & 0 deletions src/common/libkvs/proto.c
Expand Up @@ -40,6 +40,7 @@
#include "src/common/libutil/xzmalloc.h"

#include "proto.h"
#include "proto_functions.h"

/* kvs.get
*/
Expand Down
49 changes: 0 additions & 49 deletions src/common/libkvs/proto.h
@@ -1,6 +1,3 @@
/* N.B. Decode functions return pointers to storage owned by the json object.
*/

// flags
enum {
KVS_PROTO_READDIR = 1, /* get, watch */
Expand All @@ -10,52 +7,6 @@ enum {
KVS_PROTO_TREEOBJ = 16, /* get */
};

/* kvs.get
*/
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 *rootdir, json_object *val);
int kp_rget_dec (json_object *o, json_object **rootdir, json_object **val);


/* kvs.watch
*/
json_object *kp_twatch_enc (const char *key, json_object *val, int flags);
int kp_twatch_dec (json_object *o, const char **key, json_object **val,
int *flags);

json_object *kp_rwatch_enc (json_object *val);
int kp_rwatch_dec (json_object *o, json_object **val);

/* kvs.unwatch
*/
json_object *kp_tunwatch_enc (const char *key);
int kp_tunwatch_dec (json_object *o, const char **key);
/* unwatch response is just errnum */

/* kvs.fence
* kvs.relayfence
*/
json_object *kp_tfence_enc (const char *name, int nprocs, int flags,
json_object *ops);
int kp_tfence_dec (json_object *o, const char **name, int *nprocs,
int *flags, json_object **ops);

/* kvs.setroot (event)
*/
json_object *kp_tsetroot_enc (int rootseq, const char *rootdir,
json_object *root, json_object *names);
int kp_tsetroot_dec (json_object *o, int *rootseq, const char **rootdir,
json_object **root, json_object **names);

/* kvs.error (event)
*/
json_object *kp_terror_enc (json_object *names, int errnum);
int kp_terror_dec (json_object *o, json_object **names, int *errnum);

/*
* vi:tabstop=4 shiftwidth=4 expandtab
*/

0 comments on commit 17aba0e

Please sign in to comment.