Skip to content

Commit

Permalink
Merge pull request #1269 from chu11/issue1264
Browse files Browse the repository at this point in the history
kvs: return const from cache_entry_get_json()
  • Loading branch information
grondo authored Nov 3, 2017
2 parents 07780af + bc0a6e2 commit 85353aa
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 67 deletions.
41 changes: 40 additions & 1 deletion src/common/libkvs/test/treeobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ json_t *create_large_dir (void)
json_decref (dir);
return NULL;
}
json_decref (ent);
}
return dir;
}
Expand Down Expand Up @@ -356,6 +357,34 @@ void test_dir (void)
json_decref (dir);
}

void test_dir_peek (void)
{
json_t *dir;
json_t *val = NULL;
const json_t *result;

ok (treeobj_peek_entry (NULL, NULL) == NULL,
"treeobj_peek_entry fails on bad input");

/* create test value */
val = treeobj_create_val ("foo", 4);
if (!val)
BAIL_OUT ("can't continue without test values");

ok ((dir = treeobj_create_dir ()) != NULL,
"treeobj_create_dir works");

ok (treeobj_insert_entry (dir, "foo", val) == 0,
"treeobj_insert_entry works");
ok ((result = treeobj_peek_entry (dir, "foo")) != NULL,
"treeobj_peek_entry works");
ok (result == val,
"treeobj_peek_entry returns correct pointer");

json_decref (val);
json_decref (dir);
}

void test_copy (void)
{
json_t *val, *symlink, *dirref, *valref, *dir;
Expand Down Expand Up @@ -597,6 +626,7 @@ void test_deep_copy (void)
void test_symlink (void)
{
json_t *o, *data;
const char *str;

ok (treeobj_create_symlink (NULL) == NULL
&& errno == EINVAL,
Expand All @@ -611,6 +641,12 @@ void test_symlink (void)
"treeobj_get_data returned string");
ok (!strcmp (json_string_value (data), "a.b.c"),
"and string has right content");
ok (treeobj_get_symlink (NULL) == NULL,
"treeobj_get_symlink fails on bad input");
ok ((str = treeobj_get_symlink (o)) != NULL,
"treeobj_get_symlink works");
ok (!strcmp (str, "a.b.c"),
"treeobj_get_symlink returns correct string");
json_decref (o);
}

Expand Down Expand Up @@ -640,8 +676,10 @@ void test_corner_cases (void)
ok (treeobj_get_count (val) < 0 && errno == EINVAL,
"treeobj_get_count detects invalid type");

ok (treeobj_decode (treeobj_encode (val)) == NULL && errno == EPROTO,
char *s = treeobj_encode (val);
ok (treeobj_decode (s) == NULL && errno == EPROTO,
"treeobj_decode returns EPROTO on bad treeobj");
free (s);

json_decref (val);

Expand Down Expand Up @@ -712,6 +750,7 @@ int main(int argc, char** argv)
test_val ();
test_dirref ();
test_dir ();
test_dir_peek ();
test_copy ();
test_deep_copy ();
test_symlink ();
Expand Down
109 changes: 87 additions & 22 deletions src/common/libkvs/treeobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,38 @@ static int treeobj_unpack (json_t *obj, const char **typep, json_t **datap)
return 0;
}

int treeobj_validate (json_t *obj)
static int treeobj_peek (const json_t *obj, const char **typep,
const json_t **datap)
{
json_t *o, *data;
json_t *data;
int version;
const char *type;

/* N.B. it should be safe to cast away const on 'obj' as long as 'data'
* parameter is not modified. We make 'data' const to ensure that.
*/
if (!obj || json_unpack ((json_t *)obj, "{s:i s:s s:o !}",
"ver", &version,
"type", &type,
"data", &data) < 0
|| version != treeobj_version) {
errno = EINVAL;
return -1;
}
if (typep)
*typep = type;
if (datap)
*datap = data;
return 0;
}

int treeobj_validate (const json_t *obj)
{
const json_t *o;
const json_t *data;
const char *type;

if (treeobj_unpack (obj, &type, &data) < 0)
if (treeobj_peek (obj, &type, &data) < 0)
goto inval;
if (!strcmp (type, "valref") || !strcmp (type, "dirref")) {
int i, len;
Expand All @@ -80,7 +106,10 @@ int treeobj_validate (json_t *obj)
const char *key;
if (!json_is_object (data))
goto inval;
json_object_foreach (data, key, o) {
/* N.B. it should be safe to cast away const on 'data' as long as
* 'o' is not modified. We make 'o' const to ensure that.
*/
json_object_foreach ((json_t *)data, key, o) {
if (treeobj_validate (o) < 0)
goto inval;
}
Expand All @@ -102,39 +131,39 @@ int treeobj_validate (json_t *obj)
return -1;
}

const char *treeobj_get_type (json_t *obj)
const char *treeobj_get_type (const json_t *obj)
{
const char *type;
if (treeobj_unpack (obj, &type, NULL) < 0)
if (!obj || treeobj_peek (obj, &type, NULL) < 0)
return NULL;
return type;
}

bool treeobj_is_symlink (json_t *obj)
bool treeobj_is_symlink (const json_t *obj)
{
const char *type = treeobj_get_type (obj);
return type && !strcmp (type, "symlink");
}

bool treeobj_is_val (json_t *obj)
bool treeobj_is_val (const json_t *obj)
{
const char *type = treeobj_get_type (obj);
return type && !strcmp (type, "val");
}

bool treeobj_is_valref (json_t *obj)
bool treeobj_is_valref (const json_t *obj)
{
const char *type = treeobj_get_type (obj);
return type && !strcmp (type, "valref");
}

bool treeobj_is_dir (json_t *obj)
bool treeobj_is_dir (const json_t *obj)
{
const char *type = treeobj_get_type (obj);
return type && !strcmp (type, "dir");
}

bool treeobj_is_dirref (json_t *obj)
bool treeobj_is_dirref (const json_t *obj)
{
const char *type = treeobj_get_type (obj);
return type && !strcmp (type, "dirref");
Expand All @@ -148,14 +177,32 @@ json_t *treeobj_get_data (json_t *obj)
return data;
}

int treeobj_decode_val (json_t *obj, void **dp, int *lp)
const char *treeobj_get_symlink (const json_t *obj)
{
const char *type;
const json_t *data;
const char *str;

if (treeobj_peek (obj, &type, &data) < 0
|| strcmp (type, "symlink") != 0) {
errno = EINVAL;
return NULL;
}
if (!(str = json_string_value (data))) {
errno = EINVAL;
return NULL;
}
return str;
}

int treeobj_decode_val (const json_t *obj, void **dp, int *lp)
{
const char *type, *xdatastr;
json_t *xdata;
const json_t *xdata;
int buflen, len, xlen;
char *data;

if (treeobj_unpack (obj, &type, &xdata) < 0
if (treeobj_peek (obj, &type, &xdata) < 0
|| strcmp (type, "val") != 0) {
errno = EINVAL;
return -1;
Expand Down Expand Up @@ -187,13 +234,13 @@ int treeobj_decode_val (json_t *obj, void **dp, int *lp)
return 0;
}

int treeobj_get_count (json_t *obj)
int treeobj_get_count (const json_t *obj)
{
json_t *data;
const json_t *data;
const char *type;
int count = -1;

if (treeobj_unpack (obj, &type, &data) < 0)
if (treeobj_peek (obj, &type, &data) < 0)
goto done;
if (!strcmp (type, "valref") || !strcmp (type, "dirref")) {
count = json_array_size (data);
Expand Down Expand Up @@ -263,6 +310,23 @@ int treeobj_insert_entry (json_t *obj, const char *name, json_t *obj2)
return 0;
}

const json_t *treeobj_peek_entry (const json_t *obj, const char *name)
{
const char *type;
const json_t *data, *obj2;

if (treeobj_peek (obj, &type, &data) < 0
|| strcmp (type, "dir") != 0) {
errno = EINVAL;
return NULL;
}
if (!(obj2 = json_object_get (data, name))) {
errno = ENOENT;
return NULL;
}
return obj2;
}

json_t *treeobj_copy (json_t *obj)
{
json_t *data;
Expand Down Expand Up @@ -302,7 +366,7 @@ json_t *treeobj_copy (json_t *obj)
return cpy;
}

json_t *treeobj_deep_copy (json_t *obj)
json_t *treeobj_deep_copy (const json_t *obj)
{
return json_deep_copy (obj);
}
Expand Down Expand Up @@ -334,12 +398,13 @@ int treeobj_append_blobref (json_t *obj, const char *blobref)
return rc;
}

const char *treeobj_get_blobref (json_t *obj, int index)
const char *treeobj_get_blobref (const json_t *obj, int index)
{
json_t *data, *o;
const json_t *data;
json_t *o;
const char *type, *blobref = NULL;

if (treeobj_unpack (obj, &type, &data) < 0
if (treeobj_peek (obj, &type, &data) < 0
|| (strcmp (type, "dirref") != 0
&& strcmp (type, "valref") != 0)) {
errno = EINVAL;
Expand Down Expand Up @@ -499,7 +564,7 @@ json_t *treeobj_decodeb (const char *buf, size_t buflen)
return NULL;
}

char *treeobj_encode (json_t *obj)
char *treeobj_encode (const json_t *obj)
{
return json_dumps (obj, JSON_COMPACT|JSON_SORT_KEYS);
}
Expand Down
34 changes: 22 additions & 12 deletions src/common/libkvs/treeobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ json_t *treeobj_create_dirref (const char *blobref);
/* Validate treeobj, recursively.
* Return 0 if valid, -1 with errno = EINVAL if invalid.
*/
int treeobj_validate (json_t *obj);
int treeobj_validate (const json_t *obj);

/* get type (RFC 11 defined strings or NULL on error with errno set).
*/
const char *treeobj_get_type (json_t *obj);
const char *treeobj_get_type (const json_t *obj);

/* Test for a particular type
*/
bool treeobj_is_symlink (json_t *obj);
bool treeobj_is_val (json_t *obj);
bool treeobj_is_valref (json_t *obj);
bool treeobj_is_dir (json_t *obj);
bool treeobj_is_dirref (json_t *obj);
bool treeobj_is_symlink (const json_t *obj);
bool treeobj_is_val (const json_t *obj);
bool treeobj_is_valref (const json_t *obj);
bool treeobj_is_dir (const json_t *obj);
bool treeobj_is_dirref (const json_t *obj);

/* get type-specific value.
* For dirref/valref, this is an array of blobrefs.
Expand All @@ -45,20 +45,24 @@ bool treeobj_is_dirref (json_t *obj);
*/
json_t *treeobj_get_data (json_t *obj);

/* get convenience functions, operate on type specific objects
*/
const char *treeobj_get_symlink (const json_t *obj);

/* get decoded val data.
* If len == 0, data will be NULL.
* If len > 0, data will be followed by an extra NULL byte in memory.
* Caller must free returned data.
*/
int treeobj_decode_val (json_t *obj, void **data, int *len);
int treeobj_decode_val (const json_t *obj, void **data, int *len);

/* get type-specific count.
* For dirref/valref, this is the number of blobrefs.
* For directory, this is number of entries
* For symlink or val, this is 1.
* Return count on success, -1 on error with errno = EINVAL.
*/
int treeobj_get_count (json_t *obj);
int treeobj_get_count (const json_t *obj);

/* get/add/remove directory entry
* Get returns JSON object (owned by 'obj', do not destory), NULL on error.
Expand All @@ -69,6 +73,12 @@ json_t *treeobj_get_entry (json_t *obj, const char *name);
int treeobj_insert_entry (json_t *obj, const char *name, json_t *obj2);
int treeobj_delete_entry (json_t *obj, const char *name);

/* peek directory entry
* identical to treeobj_get_entry(), but is a const equivalent. Good
* to use when modifications will not occur.
*/
const json_t *treeobj_peek_entry (const json_t *obj, const char *name);

/* Shallow copy a treeobj
* Note that this is not a shallow copy on the json object, but is a
* shallow copy on the data within a tree object. For example, for a
Expand All @@ -77,7 +87,7 @@ int treeobj_delete_entry (json_t *obj, const char *name);
json_t *treeobj_copy (json_t *obj);

/* Deep copy a treeobj */
json_t *treeobj_deep_copy (json_t *obj);
json_t *treeobj_deep_copy (const json_t *obj);

/* add blobref to dirref,valref object.
* Return 0 on success, -1 on failure with errno set.
Expand All @@ -87,7 +97,7 @@ int treeobj_append_blobref (json_t *obj, const char *blobref);
/* get blobref entry at 'index'.
* Return blobref on success, NULL on failure with errno set.
*/
const char *treeobj_get_blobref (json_t *obj, int index);
const char *treeobj_get_blobref (const json_t *obj, int index);

/* Create valref that refers to 'data', a blob of 'len' bytes using
* 'hashtype' hash algorithm (e.g. "sha1"). If 'maxblob' > 0, split the
Expand All @@ -102,7 +112,7 @@ json_t *treeobj_create_valref_buf (const char *hashtype, int maxblob,
*/
json_t *treeobj_decode (const char *buf);
json_t *treeobj_decodeb (const char *buf, size_t buflen);
char *treeobj_encode (json_t *obj);
char *treeobj_encode (const json_t *obj);

#endif /* !_FLUX_KVS_TREEOBJ_H */

Expand Down
2 changes: 1 addition & 1 deletion src/modules/kvs/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ int cache_entry_set_raw (struct cache_entry *hp, void *data, int len)
return -1;
}

json_t *cache_entry_get_treeobj (struct cache_entry *hp)
const json_t *cache_entry_get_treeobj (struct cache_entry *hp)
{
if (!hp || !hp->valid || !hp->data)
return NULL;
Expand Down
Loading

0 comments on commit 85353aa

Please sign in to comment.