diff options
author | Amar Tumballi <amarts@redhat.com> | 2017-12-19 16:10:11 +0530 |
---|---|---|
committer | Amar Tumballi <amarts@redhat.com> | 2017-12-27 05:20:30 +0000 |
commit | b868d6077c14e3653fdaddcb856ab2bf6ceb9c00 (patch) | |
tree | 201f61db8690929aa967808816b49d1d4280c385 | |
parent | 9a47978877a5415dbbac94b93b4b30d055349681 (diff) |
dict: support better on-wire transfer
This patch brings data type awareness to dictionary,
and also makes sure valid data is properly sent to the
other side of the wire using XDR.
Next step is to allow people to add more data types
(for example, Bool, UUID, iatt etc), and then make
it part of every fop signature in wire.
Fixes #203
Change-Id: Ie0eee2db847bea2bf7dad80dec89ce3e7c5917c1
Signed-off-by: Amar Tumballi <amarts@redhat.com>
-rw-r--r-- | libglusterfs/src/dict.c | 286 | ||||
-rw-r--r-- | libglusterfs/src/dict.h | 1 | ||||
-rw-r--r-- | rpc/xdr/src/glusterfs-fops.x | 10 | ||||
-rw-r--r-- | rpc/xdr/src/glusterfs3.h | 4 | ||||
-rw-r--r-- | rpc/xdr/src/rpc-common-xdr.x | 23 |
5 files changed, 257 insertions, 67 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index d0be267d2ee..1ce176e381c 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -28,11 +28,30 @@ #include "statedump.h" #include "libglusterfs-messages.h" +#include "glusterfs-fops.h" +#include "rpc-common-xdr.h" + struct dict_cmp { dict_t *dict; gf_boolean_t (*value_ignore) (char *k); }; +#define VALIDATE_DATA_AND_LOG(data, type, ret_val) do { \ + if (!data || !data->data) { \ + gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, \ + LG_MSG_INVALID_ARG, "data is NULL"); \ + return ret_val; \ + } \ + \ + if (data->data_type != type) { \ + gf_msg_callingfn ("dict", GF_LOG_INFO, EINVAL, \ + LG_MSG_INVALID_ARG, \ + "%s type asked, has %s type", \ + data_type_name[type], \ + data_type_name[data->data_type]); \ + } \ + } while (0) + data_t * get_new_data () { @@ -253,6 +272,7 @@ data_copy (data_t *old) if (!newdata->data) goto err_out; } + newdata->data_type = old->data_type; } LOCK_INIT (&newdata->lock); @@ -704,6 +724,7 @@ int_to_data (int64_t value) return NULL; } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_INT; return data; } @@ -723,6 +744,7 @@ data_from_int64 (int64_t value) return NULL; } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_INT; return data; } @@ -743,6 +765,7 @@ data_from_int32 (int32_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_INT; return data; } @@ -763,6 +786,7 @@ data_from_int16 (int16_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_INT; return data; } @@ -783,6 +807,7 @@ data_from_int8 (int8_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_INT; return data; } @@ -803,6 +828,7 @@ data_from_uint64 (uint64_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_UINT; return data; } @@ -824,6 +850,7 @@ data_from_double (double value) return NULL; } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_DOUBLE; return data; } @@ -845,6 +872,7 @@ data_from_uint32 (uint32_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_UINT; return data; } @@ -865,6 +893,7 @@ data_from_uint16 (uint16_t value) } data->len = strlen (data->data) + 1; + data->data_type = GF_DATA_TYPE_UINT; return data; } @@ -882,6 +911,7 @@ data_from_ptr_common (void *value, gf_boolean_t is_static) data->data = value; data->is_static = is_static; + data->data_type = GF_DATA_TYPE_PTR; return data; } @@ -899,6 +929,7 @@ str_to_data (char *value) return NULL; } data->len = strlen (value) + 1; + data->data_type = GF_DATA_TYPE_STR; data->data = value; data->is_static = 1; @@ -921,6 +952,7 @@ data_from_dynstr (char *value) return NULL; data->len = strlen (value) + 1; data->data = value; + data->data_type = GF_DATA_TYPE_STR; return data; } @@ -935,6 +967,7 @@ data_from_dynptr (void *value, int32_t len) data->len = len; data->data = value; + data->data_type = GF_DATA_TYPE_PTR; return data; } @@ -956,18 +989,24 @@ bin_to_data (void *value, int32_t len) data->is_static = 1; data->len = len; data->data = value; + data->data_type = GF_DATA_TYPE_PTR; return data; } +static char *data_type_name[GF_DATA_TYPE_MAX] = { + [GF_DATA_TYPE_UNKNOWN] = "unknown", + [GF_DATA_TYPE_INT] = "integer", + [GF_DATA_TYPE_UINT] = "unsigned integer", + [GF_DATA_TYPE_DOUBLE] = "float", + [GF_DATA_TYPE_STR] = "string", + [GF_DATA_TYPE_PTR] = "pointer", +}; + int64_t data_to_int64 (data_t *data) { - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return -1; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -1); char *str = alloca (data->len + 1); if (!str) @@ -981,11 +1020,7 @@ data_to_int64 (data_t *data) int32_t data_to_int32 (data_t *data) { - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return -1; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -1); char *str = alloca (data->len + 1); if (!str) @@ -1000,14 +1035,9 @@ data_to_int32 (data_t *data) int16_t data_to_int16 (data_t *data) { - int16_t value = 0; - - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return -1; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -1); + int16_t value = 0; char *str = alloca (data->len + 1); if (!str) return -1; @@ -1033,14 +1063,9 @@ data_to_int16 (data_t *data) int8_t data_to_int8 (data_t *data) { - int8_t value = 0; - - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return -1; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -1); + int8_t value = 0; char *str = alloca (data->len + 1); if (!str) return -1; @@ -1066,8 +1091,8 @@ data_to_int8 (data_t *data) uint64_t data_to_uint64 (data_t *data) { - if (!data) - return -1; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -1); + char *str = alloca (data->len + 1); if (!str) return -1; @@ -1081,8 +1106,7 @@ data_to_uint64 (data_t *data) uint32_t data_to_uint32 (data_t *data) { - if (!data) - return -1; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -1); char *str = alloca (data->len + 1); if (!str) @@ -1097,11 +1121,9 @@ data_to_uint32 (data_t *data) uint16_t data_to_uint16 (data_t *data) { - uint16_t value = 0; - - if (!data) - return -1; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -1); + uint16_t value = 0; char *str = alloca (data->len + 1); if (!str) return -1; @@ -1127,14 +1149,9 @@ data_to_uint16 (data_t *data) uint8_t data_to_uint8 (data_t *data) { - uint32_t value = 0; - - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return -1; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -1); + uint32_t value = 0; char *str = alloca (data->len + 1); if (!str) return -1; @@ -1159,33 +1176,21 @@ data_to_uint8 (data_t *data) char * data_to_str (data_t *data) { - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return NULL; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_STR, NULL); return data->data; } void * data_to_ptr (data_t *data) { - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return NULL; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, NULL); return data->data; } void * data_to_bin (data_t *data) { - if (!data) { - gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, - LG_MSG_INVALID_ARG, "data is NULL"); - return NULL; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, NULL); return data->data; } @@ -1701,6 +1706,8 @@ dict_get_int8 (dict_t *this, char *key, int8_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -EINVAL); + ret = data_to_int8_ptr (data, val); err: @@ -1746,6 +1753,8 @@ dict_get_int16 (dict_t *this, char *key, int16_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -EINVAL); + ret = data_to_int16_ptr (data, val); err: @@ -1791,6 +1800,8 @@ dict_get_int32 (dict_t *this, char *key, int32_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -EINVAL); + ret = data_to_int32_ptr (data, val); err: @@ -1836,6 +1847,8 @@ dict_get_int64 (dict_t *this, char *key, int64_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -EINVAL); + ret = data_to_int64_ptr (data, val); err: @@ -1881,6 +1894,8 @@ dict_get_uint16 (dict_t *this, char *key, uint16_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -EINVAL); + ret = data_to_uint16_ptr (data, val); err: @@ -1926,6 +1941,8 @@ dict_get_uint32 (dict_t *this, char *key, uint32_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -EINVAL); + ret = data_to_uint32_ptr (data, val); err: @@ -1972,6 +1989,8 @@ dict_get_uint64 (dict_t *this, char *key, uint64_t *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, -EINVAL); + ret = data_to_uint64_ptr (data, val); err: @@ -2017,6 +2036,8 @@ dict_get_double (dict_t *this, char *key, double *val) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_DOUBLE, -EINVAL); + ret = data_to_double_ptr (data, val); err: @@ -2101,6 +2122,8 @@ dict_get_ptr (dict_t *this, char *key, void **ptr) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, -EINVAL); + ret = data_to_ptr_common (data, ptr); if (ret != 0) { goto err; @@ -2129,6 +2152,8 @@ dict_get_ptr_and_len (dict_t *this, char *key, void **ptr, int *len) goto err; } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, -EINVAL); + *len = data->len; ret = data_to_ptr_common (data, ptr); @@ -2173,15 +2198,13 @@ dict_get_str (dict_t *this, char *key, char **str) if (!this || !key || !str) { goto err; } - ret = dict_get_with_ref (this, key, &data); if (ret < 0) { goto err; } - if (!data || !data->data) { - goto err; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_STR, -EINVAL); + *str = data->data; err: @@ -2290,9 +2313,8 @@ dict_get_bin (dict_t *this, char *key, void **bin) goto err; } - if (!data || !data->data) { - goto err; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, ret); + *bin = data->data; err: @@ -2408,12 +2430,7 @@ dict_get_str_boolean (dict_t *this, char *key, int default_val) goto err; } - GF_ASSERT (data); - - if (!data->data) { - ret = -1; - goto err; - } + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, -EINVAL); ret = gf_string2boolean (data->data, &boo); if (ret == -1) @@ -2823,6 +2840,7 @@ dict_unserialize (char *orig_buf, int32_t size, dict_t **fill) } value->len = vallen; value->data = memdup (buf, vallen); + value->data_type = GF_DATA_TYPE_STR; value->is_static = 0; buf += vallen; @@ -3136,3 +3154,137 @@ unlock: UNLOCK (&dict->lock); return 0; } + +/* dict_to_xdr () */ +int +dict_to_xdr (dict_t *this, gfx_dict *dict) +{ + int ret = -1; + int i = 0; + int index = 0; + data_pair_t *dpair = NULL; + gfx_dict_pair *xpair = NULL; + + if (!this || !dict) + goto out; + + dict->pairs.pairs_val = GF_CALLOC (1, (this->count * + sizeof (gfx_dict_pair)), + gf_common_mt_char); + if (!dict->pairs.pairs_val) + goto out; + + dpair = this->members_list; + for (i = 0; i < this->count; i++) { + xpair = &dict->pairs.pairs_val[index]; + + xpair->value.type = dpair->value->data_type; + xpair->key.key_val = dpair->key; + xpair->key.key_len = strlen (dpair->key) + 1; + + switch (dpair->value->data_type) { + /* Add more type here */ + case GF_DATA_TYPE_INT: + index++; + data_to_int64_ptr (dpair->value, &xpair->value.gfx_value_u.value_int); + break; + case GF_DATA_TYPE_UINT: + index++; + data_to_uint64_ptr (dpair->value, &xpair->value.gfx_value_u.value_uint); + break; + case GF_DATA_TYPE_DOUBLE: + index++; + data_to_double_ptr (dpair->value, + &xpair->value.gfx_value_u.value_dbl); + break; + case GF_DATA_TYPE_STR: + index++; + xpair->value.gfx_value_u.val_string.val_string_val = dpair->value->data; + xpair->value.gfx_value_u.val_string.val_string_len = dpair->value->len; + break; + default: + /* Unknown type and ptr type is not sent on wire */ + gf_log ("", GF_LOG_INFO, "%s is not sent on wire", dpair->key); + break; + } + + dpair = dpair->next; + } + + dict->pairs.pairs_len = index; + dict->count = index; + ret = 0; +out: + return ret; +} + +int +xdr_to_dict (gfx_dict *dict, dict_t **to) +{ + int ret = -1; + int index = 0; + char *key = NULL; + char *value = NULL; + gfx_dict_pair *xpair = NULL; + dict_t *this = NULL; + + if (!to || !dict) + goto out; + + this = dict_new(); + if (!this) + goto out; + + for (index = 0; index < dict->pairs.pairs_len; index++) { + ret = -1; + xpair = &dict->pairs.pairs_val[index]; + + key = xpair->key.key_val; + switch (xpair->value.type) { + /* Add more type here */ + case GF_DATA_TYPE_INT: + ret = dict_set_int64 (this, key, + xpair->value.gfx_value_u.value_int); + break; + case GF_DATA_TYPE_UINT: + ret = dict_set_uint64 (this, key, + xpair->value.gfx_value_u.value_uint); + break; + case GF_DATA_TYPE_DOUBLE: + ret = dict_set_double (this, key, + xpair->value.gfx_value_u.value_dbl); + break; + case GF_DATA_TYPE_STR: + value = gf_strdup (xpair->value.gfx_value_u.val_string.val_string_val); + if (!value) { + errno = ENOMEM; + goto out; + } + free (xpair->value.gfx_value_u.val_string.val_string_val); + ret = dict_set_dynstr (this, key, value); + break; + default: + ret = 0; + /* Unknown type and ptr type is not sent on wire */ + break; + } + if (ret) { + gf_msg_debug ("dict", ENOMEM, + "failed to set the key (%s) into dict", + key); + } + free (xpair->key.key_val); + } + + free (dict->pairs.pairs_val); + ret = 0; + + /* If everything is fine, assign the dictionary to target */ + *to = this; + this = NULL; +out: + if (this) + dict_unref (this); + + return ret; +} diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 48c6f242723..fab609cd31b 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -69,6 +69,7 @@ struct _data { char *data; gf_atomic_t refcount; gf_lock_t lock; + gf_dict_data_type_t data_type; }; struct _data_pair { diff --git a/rpc/xdr/src/glusterfs-fops.x b/rpc/xdr/src/glusterfs-fops.x index 5b5c5904678..44e5d9191a2 100644 --- a/rpc/xdr/src/glusterfs-fops.x +++ b/rpc/xdr/src/glusterfs-fops.x @@ -231,3 +231,13 @@ enum gf_upcall_flags_t { GF_UPCALL_LEASE_RECALL, GF_UPCALL_FLAGS_MAXVALUE }; + +enum gf_dict_data_type_t { + GF_DATA_TYPE_UNKNOWN, + GF_DATA_TYPE_INT, + GF_DATA_TYPE_UINT, + GF_DATA_TYPE_DOUBLE, + GF_DATA_TYPE_STR, + GF_DATA_TYPE_PTR, + GF_DATA_TYPE_MAX +}; diff --git a/rpc/xdr/src/glusterfs3.h b/rpc/xdr/src/glusterfs3.h index 0aa1ae80bf3..2da5594a347 100644 --- a/rpc/xdr/src/glusterfs3.h +++ b/rpc/xdr/src/glusterfs3.h @@ -418,4 +418,8 @@ gf_proto_cache_invalidation_to_upcall (xlator_t *this, out: return ret; } + +extern int dict_to_xdr (dict_t *this, gfx_dict *xdict); +extern int xdr_to_dict (gfx_dict *xdict, dict_t **to); + #endif /* !_GLUSTERFS3_H */ diff --git a/rpc/xdr/src/rpc-common-xdr.x b/rpc/xdr/src/rpc-common-xdr.x index 7ccfbb11a51..1af7c8041ed 100644 --- a/rpc/xdr/src/rpc-common-xdr.x +++ b/rpc/xdr/src/rpc-common-xdr.x @@ -17,6 +17,7 @@ * not captured in any section specific file */ %#include "xdr-common.h" +%#include "glusterfs-fops.h" struct auth_glusterfs_parms_v2 { int pid; @@ -64,3 +65,25 @@ struct gf_common_rsp { int op_errno; opaque xdata<>; /* Extra data */ } ; + + +union gfx_value switch (gf_dict_data_type_t type) { + case GF_DATA_TYPE_INT: + hyper value_int; + case GF_DATA_TYPE_UINT: + unsigned hyper value_uint; + case GF_DATA_TYPE_DOUBLE: + double value_dbl; + case GF_DATA_TYPE_STR: + opaque val_string<>; +}; + +struct gfx_dict_pair { + opaque key<>; + gfx_value value; +}; + +struct gfx_dict { + unsigned int count; + gfx_dict_pair pairs<>; +}; |