util: resource: Add JSON format support 37/273037/3 accepted/tizen/unified/20220401.033556 submit/tizen/20220401.020712
authorDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 29 Mar 2022 02:41:54 +0000 (11:41 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 31 Mar 2022 03:02:27 +0000 (12:02 +0900)
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 <dwoo08.lee@samsung.com>
include/util/request.h
include/util/resource.h
lib/tmonitor/tmonitor.c
lib/tmonitor/tmonitor.h
src/monitor/request-handler.c
src/util/resource.c

index beefa42..fcee614 100644 (file)
@@ -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,
index 18ce421..71d756f 100644 (file)
@@ -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);
index 0d2aacc..bfd9653 100644 (file)
@@ -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;
index f3c9688..cee45ea 100644 (file)
@@ -220,6 +220,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
  * @param[in] Resource 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);
index 3cb97ca..3bbea40 100644 (file)
@@ -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:
+        *  - <RESOURCE_ID>
+        * Format of REQUEST_GET_VALUE_JSON args:
+        *  - <RESOURCE_ID>:<ATTR_ID>
+        */
+       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;
index 5149726..aefe3cc 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <glib.h>
 #include <stdio.h>
+#include <json.h>
 
 #include <util/common.h>
 #include <util/resource.h>
@@ -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;