From: Dongwoo Lee Date: Tue, 29 Mar 2022 02:41:54 +0000 (+0900) Subject: util: resource: Add JSON format support X-Git-Tag: submit/tizen/20220401.020712^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92e445c6da8b6e97e24a18f1a2e817048e17c9fc;p=platform%2Fcore%2Fsystem%2Fpass.git util: resource: Add JSON format support To extend use of monitor resource, now all attributes in resource can be retrieved as JSON type format at once with new api below: - tmonitor_get_value_json: get a attribute of resource as json format - tmonitor_get_resource_json: get all attributes of resource as json format Change-Id: I14b1f5e2474d101ff7149a3377b2ebc1890223c8 Signed-off-by: Dongwoo Lee --- diff --git a/include/util/request.h b/include/util/request.h index beefa42..fcee614 100644 --- a/include/util/request.h +++ b/include/util/request.h @@ -19,7 +19,7 @@ #define __REQUEST_H__ #define GENERIC_BUFF_MAX (1024) -#define ARRAY_BUFF_MAX (64 * 1024) +#define HUGE_BUFF_MAX (64 * 1024) /* * request format * REQUEST_TYPE:REQUEST_CONTENT(if required) @@ -35,6 +35,8 @@ enum { REQUEST_SET_RESOURCE_ATTR, REQUEST_UNSET_RESOURCE_ATTR, REQUEST_IS_RESOURCE_ATTR_SUPPORTED, + REQUEST_GET_RESOURCE_JSON, + REQUEST_GET_VALUE_JSON, REQUEST_GET_VALUE_INT, REQUEST_GET_VALUE_INT64, REQUEST_GET_VALUE_UINT, diff --git a/include/util/resource.h b/include/util/resource.h index 18ce421..71d756f 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -179,6 +179,9 @@ resource_attr_supported_always(const struct resource *resource, return true; } +int get_resource_attrs_json(struct resource *resource, char **json_string); + +int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string); int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data); int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data); int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data); diff --git a/lib/tmonitor/tmonitor.c b/lib/tmonitor/tmonitor.c index 0d2aacc..bfd9653 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/tmonitor/tmonitor.c @@ -435,6 +435,81 @@ int tmonitor_update_resource(int id, int resource_id) return ret; } + +static int tmonitor_get_json(int id, char *json_string, int request_type, ...) +{ + int buffer_len, response_req, ret, resource_id; + u_int64_t attr_id; + char *buffer; + va_list args; + + buffer = malloc(HUGE_BUFF_MAX + 1); + if (!buffer) + return -ENOMEM; + + va_start(args, request_type); + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + resource_id = va_arg(args, int); + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d", + request_type, resource_id); + break; + case REQUEST_GET_VALUE_JSON: + resource_id = va_arg(args, int); + attr_id = va_arg(args, u_int64_t); + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d$%"PRIu64, + request_type, resource_id, attr_id); + break; + default: + va_end(args); + free(buffer); + return -EINVAL; + } + va_end(args); + + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + free(buffer); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, HUGE_BUFF_MAX, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + free(buffer); + return -EIO; + } + buffer[buffer_len] = '\0'; + + if (sscanf(buffer, "%d$%[^$]$%d", &response_req, json_string, &ret) < 3) { + free(buffer); + return -EINVAL; + } + + if (response_req != request_type) { + _E("[libpass] wrong response"); + free(buffer); + return -EINVAL; + } + + free(buffer); + + return ret; +} + +EXPORT +int tmonitor_get_resource_json(int id, int resource_id, char *json_string) +{ + return tmonitor_get_json(id, json_string, REQUEST_GET_RESOURCE_JSON, resource_id); +} + +EXPORT +int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr_id, char *json_string) +{ + return tmonitor_get_json(id, json_string, REQUEST_GET_VALUE_JSON, resource_id, attr_id); +} + EXPORT int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t *value) { @@ -648,17 +723,17 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** int response_req; int ret, i; - buffer = malloc(ARRAY_BUFF_MAX + 1); + buffer = malloc(HUGE_BUFF_MAX + 1); if (!buffer) return -ENOMEM; - array_str = malloc(ARRAY_BUFF_MAX); + array_str = malloc(HUGE_BUFF_MAX); if (!array_str) { free(buffer); return -ENOMEM; } - buffer_len = snprintf(buffer, ARRAY_BUFF_MAX, "%d$%d$%"PRIu64, + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_ARRAY, res_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -667,7 +742,7 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** } /* wait for response */ - buffer_len = recv(id, buffer, ARRAY_BUFF_MAX, 0); + buffer_len = recv(id, buffer, HUGE_BUFF_MAX, 0); if (buffer_len <= 0) { _E("[libpass] socket disconnected"); ret = -EIO; diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index f3c9688..cee45ea 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -219,6 +219,15 @@ int tmonitor_update(int id); */ int tmonitor_update_resource(int id, int resource_id); +/** + * @brief Get all value in interesting attributes of resource by the JSON string format + * @param[in] Tizen monitor id + * @param[in] Resource id + * @param[out] JSON type string for resource + * @return @c positive integer as resource count on success, otherwise a negative error value + */ +int tmonitor_get_resource_json(int id, int resource_id, char *json_string); + /** * @brief Get [int/int64/uint/uint64/double/string] value of resource attribute * @param[in] Tizen monitor id @@ -227,6 +236,8 @@ int tmonitor_update_resource(int id, int resource_id); * @param[out] Value retrieved from resource attribute * @return @ 0 on success, otherwise a negative error value */ + +int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr, char *json_string); int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value); int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value); int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value); diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 3cb97ca..3bbea40 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -247,6 +247,49 @@ static int handle_request_set_resource_ctrl(struct request_client *client, char return set_resource_control(res, ctrl_id, (void *)(intptr_t)value); } +static int +handle_request_get_json(struct request_client *client, char *args, + int request_type, char **json_string) +{ + struct resource *res; + u_int64_t attr_id; + int resource_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_GET_RESOURCE_JSON args: + * - + * Format of REQUEST_GET_VALUE_JSON args: + * - : + */ + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + resource_id = atoi(args); + break; + case REQUEST_GET_VALUE_JSON: + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) + return -EINVAL; + break; + default: + return -EINVAL; + } + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + return get_resource_attrs_json(res, json_string); + case REQUEST_GET_VALUE_JSON: + return get_resource_attr_json(res, attr_id, json_string); + default: + return -EINVAL; + } +} + static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value) { struct resource *res; @@ -438,10 +481,15 @@ static int handle_request(struct request_client *client, char *request) request_type = split_request_type_and_args(request, &args); - if (request_type == REQUEST_GET_VALUE_ARRAY) - buffer_len = ARRAY_BUFF_MAX + 1; - else + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + case REQUEST_GET_VALUE_JSON: + case REQUEST_GET_VALUE_ARRAY: + buffer_len = HUGE_BUFF_MAX + 1; + break; + default: buffer_len = GENERIC_BUFF_MAX + 1; + } response_entry = response = malloc(buffer_len); if (!response_entry) @@ -497,6 +545,20 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _E("failed to check whether attr is supported or not"); break; + case REQUEST_GET_RESOURCE_JSON: + case REQUEST_GET_VALUE_JSON: + { + char *json_string; + + ret = handle_request_get_json(client, args, request_type, &json_string); + if (ret < 0) + _E("failed to get resource JSON string"); + + ADD_RESPONSE(response, buffer_len, "%s$", json_string); + + free(json_string); + } + break; case REQUEST_GET_VALUE_INT: { int32_t value; diff --git a/src/util/resource.c b/src/util/resource.c index 5149726..aefe3cc 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -341,6 +342,198 @@ static bool check_attr_validate(struct resource *resource, u_int64_t attr_id, in return true; } +static json_object *_get_resource_attr_json(const struct resource_attribute *attr, + const struct resource_attribute_value *attr_value) +{ + json_object *jobj_attr, *jobj_attr_name, *jobj_attr_type, *jobj_attr_value, *jobj_temp; + struct array_value *array; + int i; + + switch (attr->type) { + case DATA_TYPE_INT: + jobj_attr_value = json_object_new_int(*((int32_t *)attr_value->data)); + break; + case DATA_TYPE_UINT: + jobj_attr_value = json_object_new_int(*((u_int32_t *)attr_value->data)); + break; + case DATA_TYPE_INT64: + jobj_attr_value = json_object_new_int64(*((int64_t *)attr_value->data)); + break; + case DATA_TYPE_UINT64: + jobj_attr_value = json_object_new_uint64(*((u_int64_t *)attr_value->data)); + break; + case DATA_TYPE_DOUBLE: + jobj_attr_value = json_object_new_double(*((double *)attr_value->data)); + break; + case DATA_TYPE_STRING: + jobj_attr_value = json_object_new_string((char *)attr_value->data); + break; + case DATA_TYPE_ARRAY: + array = attr_value->data; + + jobj_attr_value = json_object_new_array(); + + switch (array->type) { + case DATA_TYPE_INT: + for (i = 0; i < array->length; i++) { + int32_t *item = array->data; + + jobj_temp = json_object_new_int(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_UINT: + for (i = 0; i < array->length; i++) { + u_int32_t *item = array->data; + + jobj_temp = json_object_new_int(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_INT64: + for (i = 0; i < array->length; i++) { + int64_t *item = array->data; + + jobj_temp = json_object_new_int64(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_UINT64: + for (i = 0; i < array->length; i++) { + u_int64_t *item = array->data; + + jobj_temp = json_object_new_uint64(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_DOUBLE: + for (i = 0; i < array->length; i++) { + double *item = array->data; + + jobj_temp = json_object_new_double(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_STRING: + for (i = 0; i < array->length; i++) { + char **item = array->data; + + jobj_temp = json_object_new_string(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + default: + _E("wrong attribute data type in array\n"); + json_object_put(jobj_attr_value); + jobj_attr_value = json_object_new_null(); + } + break; + default: + _E("wrong attribute data type\n"); + jobj_attr_value = json_object_new_null(); + } + jobj_attr = json_object_new_object(); + + jobj_attr_name = json_object_new_string(attr->name); + /* + * Since actually JSON format has no data type limitation itself, in many + * cases except converting JSON into json-c, type is not required. So, + * for the case of converting JSON generated here to json-c object again + * json_type is stored in each attributes. + */ + jobj_attr_type = json_object_new_int(json_object_get_type(jobj_attr_value)); + + json_object_object_add(jobj_attr, "name", jobj_attr_name); + json_object_object_add(jobj_attr, "json_type", jobj_attr_type); + json_object_object_add(jobj_attr, "value", jobj_attr_value); + + return jobj_attr; +} + +static void _put_resource_attr_json(json_object *jobj_attr) +{ + json_object *jobj_attr_value; + + json_object_object_del(jobj_attr, "name"); + json_object_object_del(jobj_attr, "json_type"); + + if (json_object_object_get_ex(jobj_attr, "value", &jobj_attr_value) && + json_object_is_type(jobj_attr_value, json_type_array)) + json_object_array_del_idx(jobj_attr_value, 0, + json_object_array_length(jobj_attr_value)); + + json_object_object_del(jobj_attr, "value"); +} + +int get_resource_attrs_json(struct resource *resource, char **json_string) +{ + json_object *jobj_root, *jobj_res_name, *jobj_res_type, *jobj_res_attrs, *jobj_attr; + const struct resource_attribute *attr; + const struct resource_attribute_value *attr_value; + int i; + + if (!resource || !resource->type) + return -EINVAL; + + jobj_root = json_object_new_object(); + + jobj_res_name = json_object_new_string(resource->name); + jobj_res_type = json_object_new_int(resource->type); + jobj_res_attrs = json_object_new_array(); + + for (i = 0; i < resource->num_attrs; i++) { + if (!(resource->attrs[i].id & resource->attr_interest)) + continue; + + attr = &resource->attrs[i]; + attr_value = &resource->attrs_value[i]; + + jobj_attr = _get_resource_attr_json(attr, attr_value); + + json_object_array_add(jobj_res_attrs, jobj_attr); + } + + json_object_object_add(jobj_root, "res_name", jobj_res_name); + json_object_object_add(jobj_root, "res_type", jobj_res_type); + json_object_object_add(jobj_root, "res_attrs", jobj_res_attrs); + + *json_string = strdup(json_object_to_json_string(jobj_root)); + + for (i = 0; i < json_object_array_length(jobj_res_attrs); i++) { + jobj_attr = json_object_array_get_idx(jobj_res_attrs, i); + _put_resource_attr_json(jobj_attr); + } + json_object_array_del_idx(jobj_res_attrs, 0, json_object_array_length(jobj_res_attrs)); + + json_object_object_del(jobj_root, "res_attrs"); + json_object_object_del(jobj_root, "res_type"); + json_object_object_del(jobj_root, "res_name"); + json_object_put(jobj_root); + + return 0; +} + +int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string) +{ + const struct resource_attribute *attr; + const struct resource_attribute_value *attr_value; + json_object *jobj_attr; + + attr = get_resource_attr(resource, attr_id); + attr_value = get_resource_attr_value(resource, attr_id); + + if (!attr || !attr_value) + return -EINVAL; + + jobj_attr = _get_resource_attr_json(attr, attr_value); + + *json_string = strdup(json_object_to_json_string(jobj_attr)); + + _put_resource_attr_json(jobj_attr); + + return 0; +} + int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data) { struct resource_attribute_value *attr_value = NULL;