lib: tmonitor: Add get APIs for array type attributes 23/272423/2
authorDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 15 Mar 2022 03:45:22 +0000 (12:45 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 17 Mar 2022 03:39:51 +0000 (12:39 +0900)
This adds internal API for getting array type attributes as below:

 - tmonitor_get_array_int
 - tmonitor_get_array_int64
 - tmonitor_get_array_uint
 - tmonitor_get_array_uint64
 - tmonitor_get_array_double
 - tmonitor_get_array_string

Since users get dynamically allocated array with length by just
passing pointer of pointer for each data type, it should be freed
after use.

Change-Id: I8f72ff5c6ceebcc4eda8998f2ad4fed47f71e3d5
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
include/util/request.h
lib/tmonitor/tmonitor.c
lib/tmonitor/tmonitor.h
src/monitor/request-handler.c

index a0bb183..f9316a6 100644 (file)
@@ -39,6 +39,7 @@ enum {
        REQUEST_GET_VALUE_UINT64,
        REQUEST_GET_VALUE_DOUBLE,
        REQUEST_GET_VALUE_STRING,
+       REQUEST_GET_VALUE_ARRAY,
        REQUEST_MAX,
 };
 
index fa6b22b..d53c655 100644 (file)
@@ -640,3 +640,182 @@ int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char *
 
        return ret;
 }
+
+static int
+tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void **array, int *length)
+{
+       char buffer[MAX_BUF_SIZE + 1];
+       char _array_str[MAX_BUF_SIZE];
+       char *array_item, *array_str = _array_str;
+       int array_len, array_type;
+       int buffer_len;
+       int response_req;
+       int ret, i;
+
+       buffer_len = sprintf(buffer, "%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");
+               return -EIO;
+       }
+
+       /* wait for response */
+       buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0);
+       if (buffer_len <= 0) {
+               _E("[libpass] socket disconnected");
+               return -EIO;
+       }
+
+       buffer[buffer_len] = '\0';
+       if (sscanf(buffer, "%d:%d|%d|%[^:]:%d", &response_req,
+                               &array_type, &array_len, array_str, &ret) < 5)
+               return -EINVAL;
+
+       if (response_req != REQUEST_GET_VALUE_ARRAY) {
+               _E("[libpass] wrong response");
+               return -EINVAL;
+       }
+
+       if (data_type != array_type) {
+               _E("[libpass] wrong data type");
+               return -EINVAL;
+       }
+
+       switch (array_type) {
+       case DATA_TYPE_INT:
+               {
+                       int32_t *new_array = malloc(array_len * sizeof(int32_t));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++)
+                               new_array[i] = strtol(array_item, NULL, 10);
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       case DATA_TYPE_INT64:
+               {
+                       int64_t *new_array = malloc(array_len * sizeof(int64_t));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++)
+                               new_array[i] = strtoll(array_item, NULL, 10);
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       case DATA_TYPE_UINT:
+               {
+                       u_int32_t *new_array = malloc(array_len * sizeof(u_int32_t));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++)
+                               new_array[i] = strtoul(array_item, NULL, 10);
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       case DATA_TYPE_UINT64:
+               {
+                       u_int64_t *new_array = malloc(array_len * sizeof(u_int64_t));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++)
+                               new_array[i] = strtoull(array_item, NULL, 10);
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       case DATA_TYPE_DOUBLE:
+               {
+                       double *new_array = malloc(array_len * sizeof(double));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++)
+                               new_array[i] = strtod(array_item, NULL);
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       case DATA_TYPE_STRING:
+               {
+                       char **new_array = calloc(array_len, sizeof(char *));
+
+                       if (!new_array)
+                               return -ENOMEM;
+
+                       for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) {
+                               char *new_item = g_strdup(array_item);
+
+                               if (!new_item) {
+                                       for (int j = i - 1; j >= 0; j--)
+                                               free(new_array[j]);
+                                       free(new_array);
+                                       return -ENOMEM;
+                               }
+
+                               new_array[i] = new_item;
+                       }
+
+                       *array = (void *)new_array;
+                       *length = array_len;
+                       break;
+               }
+       default:
+               _E("[libpass] not supported array data type");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+EXPORT
+int tmonitor_get_array_int(int id, int res_id, u_int64_t attr_id, int32_t **array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT, (void **)array, length);
+}
+
+EXPORT
+int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr_id, int64_t **array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT64, (void **)array, length);
+}
+
+EXPORT
+int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr_id, u_int32_t **array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT, (void **)array, length);
+}
+
+EXPORT
+int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr_id, u_int64_t **array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT64, (void **)array, length);
+}
+
+EXPORT
+int tmonitor_get_array_double(int id, int res_id, u_int64_t attr_id, double **array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_DOUBLE, (void **)array, length);
+}
+
+EXPORT
+int tmonitor_get_array_string(int id, int res_id, u_int64_t attr_id, char ***array, int *length)
+{
+       return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_STRING, (void **)array, length);
+}
index ae859c6..d64ad51 100644 (file)
@@ -226,6 +226,22 @@ int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t
 int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value);
 int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr, char *value);
 
+/**
+ * @brief Get [int/int64/uint/uint64/double/string] array of resource attribute
+ * @param[in] Tizen monitor id
+ * @param[in] Resource id
+ * @param[in] Resource attribute id
+ * @param[out] Array retrieved from resource attribute
+ * @param[out] Length of array
+ * @return @ 0 on success, otherwise a negative error value
+ */
+int tmonitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length);
+int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length);
+int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length);
+int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length);
+int tmonitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length);
+int tmonitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length);
+
 #ifdef __cplusplus
 }
 #endif
index 82d598a..edaabdb 100644 (file)
@@ -402,6 +402,30 @@ static int handle_request_get_value_string(struct request_client *client, char *
        return get_resource_attr_string(res, attr_id, value);
 }
 
+static int
+handle_request_get_value_array(struct request_client *client, char *args, struct array_value **arr)
+{
+       struct resource *res;
+       int resource_id;
+       u_int64_t attr_id;
+
+       if (!client || !args)
+               return -ENOENT;
+
+       /**
+        * Format of REQUEST_GET_VALUE_ARRAY args:
+        *  - <RESOURCE_ID:ATTR_ID>
+        */
+       if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2)
+               return -EINVAL;
+
+       res = get_resource_by_id(client, resource_id);
+       if (!res)
+               return -EINVAL;
+
+       return get_resource_attr_array(res, attr_id, arr);
+}
+
 static int split_request_type_and_args(char *buffer, char **args)
 {
        char *request_type_str;
@@ -413,13 +437,21 @@ static int split_request_type_and_args(char *buffer, char **args)
        return atoi(request_type_str);
 }
 
+#define ADD_RESPONSE(__buf__, __remain__, __format__, ...)     { \
+       int __len__ = snprintf(__buf__, __remain__, __format__, __VA_ARGS__); \
+       __buf__ += __len__;  \
+       __remain__ -= __len__; \
+       if (__remain__ < 0) \
+               _E("failed to add response"); \
+} \
+
 static void handle_request(struct request_client *client, char *buffer)
 {
        char _response[REQUEST_BUFFER_MAX];
        char *response = _response;
        char *args;
        int request_type;
-       int ret, len;
+       int ret;
        int buffer_len = REQUEST_BUFFER_MAX;
 
        request_type = split_request_type_and_args(buffer, &args);
@@ -428,9 +460,7 @@ static void handle_request(struct request_client *client, char *buffer)
         * Format of response
         *  - <REQUEST_TYPE[:REQUEST_RESULT_PAYLOAD]:REQUEST_RESULT_VALUE>
         */
-       len = snprintf(response, buffer_len, "%d:", request_type);
-       response += len;
-       buffer_len -= len;
+       ADD_RESPONSE(response, buffer_len, "%d:", request_type);
 
        switch (request_type) {
        case REQUEST_CREATE_RESOURCE:
@@ -484,9 +514,7 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%d:", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%d:", value);
                }
                break;
        case REQUEST_GET_VALUE_INT64:
@@ -497,9 +525,7 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%"PRId64":", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%"PRId64":", value);
                }
                break;
        case REQUEST_GET_VALUE_UINT:
@@ -510,9 +536,7 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%u:", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%u:", value);
                }
                break;
        case REQUEST_GET_VALUE_UINT64:
@@ -523,9 +547,7 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%"PRIu64":", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%"PRIu64":", value);
                }
                break;
        case REQUEST_GET_VALUE_DOUBLE:
@@ -536,9 +558,7 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%lf:", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%lf:", value);
                }
                break;
        case REQUEST_GET_VALUE_STRING:
@@ -549,9 +569,72 @@ static void handle_request(struct request_client *client, char *buffer)
                        if (ret < 0)
                                _D("failed to get value");
 
-                       len = snprintf(response, buffer_len, "%s:", value);
-                       response += len;
-                       buffer_len -= len;
+                       ADD_RESPONSE(response, buffer_len, "%s:", value);
+               }
+               break;
+       case REQUEST_GET_VALUE_ARRAY:
+               {
+                       struct array_value *array;
+                       int i;
+
+                       ret = handle_request_get_value_array(client, args, &array);
+                       if (ret < 0)
+                               _D("failed to get value");
+
+                       if (array->length == 0) {
+                               ADD_RESPONSE(response, buffer_len, "%d|%d|:",
+                                               array->type, array->length);
+                               break;
+                       }
+
+                       ADD_RESPONSE(response, buffer_len, "%d|%d|", array->type, array->length);
+
+                       switch (array->type) {
+                       case DATA_TYPE_INT:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%d,",
+                                                       ((int32_t *)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%d:",
+                                               ((int32_t *)array->data)[i]);
+                               break;
+                       case DATA_TYPE_INT64:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%"PRId64",",
+                                                       ((int64_t *)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%"PRId64":",
+                                               ((int64_t *)array->data)[i]);
+                               break;
+                       case DATA_TYPE_UINT:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%u,",
+                                                       ((u_int32_t *)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%u:",
+                                               ((u_int32_t *)array->data)[i]);
+                               break;
+                       case DATA_TYPE_UINT64:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%"PRIu64",",
+                                                       ((u_int64_t *)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%"PRIu64":",
+                                               ((u_int64_t *)array->data)[i]);
+                               break;
+                       case DATA_TYPE_DOUBLE:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%lf,",
+                                                       ((double *)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%lf:",
+                                               ((double *)array->data)[i]);
+                               break;
+                       case DATA_TYPE_STRING:
+                               for (i = 0; i < array->length - 1; i++)
+                                       ADD_RESPONSE(response, buffer_len, "%s,",
+                                                       ((char **)array->data)[i]);
+                               ADD_RESPONSE(response, buffer_len, "%s:",
+                                               ((char **)array->data)[i]);
+                               break;
+                       default:
+                               _E("Not supported data type");
+                       }
                }
                break;
        default:
@@ -559,7 +642,7 @@ static void handle_request(struct request_client *client, char *buffer)
                ret = -EINVAL;
                break;
        }
-       snprintf(response, buffer_len, "%d", ret);
+       ADD_RESPONSE(response, buffer_len, "%d", ret);
 
        if (send(client->socket_fd, _response, strlen(_response), 0) < 0)
                _E("Failed to send respones, error: %s", strerror(errno));