lib: tmonitor: Implement tmonitor APIs 15/271615/14
authorDongwoo Lee <dwoo08.lee@samsung.com>
Mon, 7 Mar 2022 07:49:04 +0000 (16:49 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 8 Mar 2022 06:57:28 +0000 (15:57 +0900)
Tmonitor provides resource monitoring feature by using socket
connection. This is the first version of that implements a
subset of a tmonitor API set.

Change-Id: I9174ba3849f0eae069ace34e9a1b26be0064a436
Signed-off-by: Sung-hun Kim <sfoon.kim@samsung.com>
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
lib/tmonitor/tmonitor.c
lib/tmonitor/tmonitor.h

index 5b0071d..a5bde45 100644 (file)
 
 #define _GNU_SOURCE
 #include <errno.h>
+#include <util/log.h>
+#include <util/request.h>
+#include <util/resource.h>
+#include <tmonitor/tmonitor.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define REQUEST_SERVER_IP "127.0.0.1"
+#define REQUEST_SERVER_PORT 10001
 
 extern char *program_invocation_name;
 
@@ -27,27 +44,235 @@ extern char *program_invocation_name;
 #define EXPORT __attribute__ ((visibility("default")))
 #endif
 
+struct tmonitor_client {
+       int id;
+       int period;
+       int (*func)(void *data, void *user_data);
+       void *user_data;
+};
+
+#define MAX_BUF_SIZE 1024
+
+static GList *g_tmonitor_client_head;
+static GMutex g_mutex;
+
+void add_client_to_list(struct tmonitor_client *client)
+{
+       if (!client)
+               return;
+
+       g_mutex_lock(&g_mutex);
+       g_tmonitor_client_head =
+                       g_list_append(g_tmonitor_client_head, (gpointer)client);
+       g_mutex_unlock(&g_mutex);
+}
+
+void remove_client_from_list(struct tmonitor_client *client)
+{
+       if (!client)
+               return;
+
+       g_mutex_lock(&g_mutex);
+       g_tmonitor_client_head =
+                       g_list_remove(g_tmonitor_client_head, (gpointer)client);
+       g_mutex_unlock(&g_mutex);
+}
+
+static struct tmonitor_client *find_client_by_id(int id)
+{
+       struct tmonitor_client *client;
+       GList *node;
+
+       for (node = g_tmonitor_client_head;
+                       node != NULL;
+                       node = node->next) {
+               client = node->data;
+               if (client->id == id)
+                       return client;
+       }
+
+       return NULL;
+}
+
 EXPORT
 int tmonitor_init(int period, int (*func)(void *data, void* user_data), void *user_data)
 {
-       /* TODO */
-       return 0;
+       struct tmonitor_client *client;
+       struct sockaddr_in server_addr;
+       int ret = -EIO;
+
+       client = malloc(sizeof(struct tmonitor_client));
+       if (!client) {
+               _E("[libpass] failed to allocate memory");
+               return -ENOMEM;
+       }
+
+       /* the minimum period is 100ms */
+       if (period > 0 || period < 100)
+               period = 100;
+
+       client->period = period;
+       client->func = func;
+       client->user_data = user_data;
+
+       /* open socket to server */
+       client->id = socket(AF_INET, SOCK_STREAM, 0);
+       if (client->id < 0) {
+               _E("[libpass] socket creation error");
+               goto err_out_free;
+       }
+
+       server_addr.sin_family = AF_INET;
+       server_addr.sin_port = htons(REQUEST_SERVER_PORT);
+
+       if (inet_pton(AF_INET, REQUEST_SERVER_IP, &server_addr.sin_addr) <= 0) {
+               _E("[libpass] invalid address");
+               goto err_out_close;
+       }
+
+       if (connect(client->id, (struct sockaddr *)&server_addr,
+                                       sizeof(server_addr)) < 0) {
+               _E("[libpass] connection failed");
+               goto err_out_close;
+       }
+
+       add_client_to_list(client);
+
+       return client->id;
+
+err_out_close:
+       close(client->id);
+err_out_free:
+       free(client);
+
+       return ret;
 }
 
 EXPORT
-void tmonitor_exit(int id)
+int tmonitor_connect(void)
 {
-       /* TODO */
+       return tmonitor_init(0, NULL, NULL);
 }
 
 EXPORT
-int tmonitor_set_attrs(int id, int resource_type, u_int64_t attr_mask)
+int tmonitor_exit(int id)
 {
-       /* TODO */
+       struct tmonitor_client *client;
+
+       client = find_client_by_id(id);
+       if (!client) {
+               _E("[libpass] cannot find client-%d", id);
+               return -EINVAL;
+       }
+
+       close(client->id);
+       remove_client_from_list(client);
+       free(client);
+
        return 0;
 }
 
 EXPORT
+int tmonitor_create_resource(int id, int resource_type)
+{
+       char buffer[MAX_BUF_SIZE + 1];
+       int buffer_len;
+       int response_req;
+       int ret;
+
+       buffer_len = sprintf(buffer, "%d:%d", REQUEST_CREATE_RESOURCE, resource_type);
+       if (send(id, buffer, buffer_len, 0) < 0) {
+               _E("[libpass] error occurred while sending buffer for create resource");
+               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", &response_req, &ret) < 2)
+               return -EINVAL;
+
+       if (response_req != REQUEST_CREATE_RESOURCE) {
+               _E("wrong response");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+EXPORT
+int tmonitor_set_attr_interest(int id, int resource_id, u_int64_t attr_mask)
+{
+       char buffer[MAX_BUF_SIZE + 1];
+       int buffer_len;
+       int response_req;
+       int ret;
+
+       buffer_len = sprintf(buffer, "%d:%d:%"PRIu64,
+                       REQUEST_SET_ATTR_INTEREST, resource_id, attr_mask);
+       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", &response_req, &ret) < 2)
+               return -EINVAL;
+
+       if (response_req != REQUEST_SET_ATTR_INTEREST) {
+               _E("[libpass] wrong response");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+EXPORT
+int tmonitor_set_resource_control(int id, int resource_id, u_int64_t ctrl_id, int value)
+{
+       char buffer[MAX_BUF_SIZE + 1];
+       int buffer_len;
+       int response_req;
+       int ret;
+
+       buffer_len = sprintf(buffer, "%d:%d:%"PRIu64":%d",
+                       REQUEST_SET_RESOURCE_CONTROL, resource_id, ctrl_id, value);
+       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", &response_req, &ret) < 2)
+               return -EINVAL;
+
+       if (response_req != REQUEST_SET_RESOURCE_CONTROL) {
+               _E("[libpass] wrong response");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+EXPORT
 int tmonitor_get_available_attrs(int id, int resource_type,
                                int *available_attrs[], int *num_attrs)
 {
@@ -58,33 +283,90 @@ int tmonitor_get_available_attrs(int id, int resource_type,
 EXPORT
 int tmonitor_start(int id)
 {
-       /* TODO */
        return 0;
 }
 
 EXPORT
-void tmonitor_stop(int id)
+int tmonitor_stop(int id)
 {
-       /* TODO */
+       return 0;
 }
 
 EXPORT
 int tmonitor_update(int id)
 {
-       /* TODO */
        return 0;
 }
 
 EXPORT
-int tmonitor_get_value_int(int id, int resource_type, u_int64_t attr)
+int tmonitor_update_resource(int id, int resource_id)
 {
-       /* TODO */
-       return 0;
+       char buffer[MAX_BUF_SIZE + 1];
+       int buffer_len;
+       int response_req;
+       int ret;
+
+       buffer_len = sprintf(buffer, "%d:%d", REQUEST_UPDATE_RESOURCE, resource_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", &response_req, &ret) < 2)
+               return -EINVAL;
+
+       if (response_req != REQUEST_UPDATE_RESOURCE) {
+               _E("[libpass] wrong response");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+EXPORT
+int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int *value)
+{
+       char buffer[MAX_BUF_SIZE + 1];
+       int buffer_len;
+       int response_req;
+       int ret;
+
+       buffer_len = sprintf(buffer, "%d:%d:%"PRIu64,
+                       REQUEST_GET_VALUE_INT, resource_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", &response_req, value, &ret) < 3)
+               return -EINVAL;
+
+       if (response_req != REQUEST_GET_VALUE_INT) {
+               _E("[libpass] wrong response");
+               return -EINVAL;
+       }
+
+       return ret;
 }
 
 EXPORT
 int tmonitor_get_resource_num(int id, int resource_type)
 {
-       /* TODO */
        return 0;
 }
index 3c4a667..d661db2 100644 (file)
@@ -118,30 +118,50 @@ extern "C" {
 int tmonitor_init(int period, int (*func)(void *data, void* user_data), void *user_data);
 
 /**
+ * @brief Initialize the tizen monitor quickly
+ * @return @c positive integer on success, otherwise a negative error value
+ */
+int tmonitor_connect(void);
+
+/**
  * @brief Exit the tizem monitor
  * @param[in] Unique id of tizen monitor which be returnted by tmonitor_init
+ * @return @c 0 on success, otherwise a negative error value
+ */
+int tmonitor_exit(int id);
+
+/**
+ * @brief Alias of tmonitor_exit to provide pair with tmonitor_connect
+ * @param[in] Unique id of tizen monitor which be returnted by tmonitor_connect
+ * @return @c 0 on success, otherwise a negative error value
+ */
+#define tmonitor_disconnect tmonitor_exit
+
+/**
+ * @brief Create resource for given resource_type
+ * @param[in] Unique id of tizen monitor which be returnted by tmonitor_init/connect
+ * @param[in] Resource type
+ * @return @c positive integer as resource handler id on success, otherwise a negative error value
  */
-void tmonitor_exit(int id);
+int tmonitor_create_resource(int id, int resource_type);
 
 /**
  * @brief Set the interested attributes for monitoring
  * @param[in] Unique id of tizen monitor
- * @param[in] Resource type
+ * @param[in] Unique id of resource
  * @param[in] Attribute mask including the various attributes
  * @return @c 0 on success, otherwise a negative error value
  */
-int tmonitor_set_attrs(int id, int resource_type, u_int64_t attr_mask);
+int tmonitor_set_attr_interest(int id, int resource_id, u_int64_t attr_mask);
 
 /**
- * @brief Get the available attribute list according to resource type
+ * @brief Set the interested attributes for monitoring
  * @param[in] Unique id of tizen monitor
- * @param[in] Resource type
- * @param[out] List of available attribute list
- * @param[out] Number of available attributes
+ * @param[in] Unique id of resource
+ * @param[in] Attribute mask including the various attributes
  * @return @c 0 on success, otherwise a negative error value
  */
-int tmonitor_get_available_attrs(int id, int resource_type,
-                               int *available_attrs[], int *num_attrs);
+int tmonitor_set_resource_control(int id, int resource_id, u_int64_t ctrl_id, int value);
 
 /**
  * @brief Start tizen monitor with asynchronous method
@@ -153,8 +173,9 @@ int tmonitor_start(int id);
 /**
  * @brief Stop tizen monitor
  * @param[in] Unique id of tizen monitor
+ * @return @c 0 on success, otherwise a negative error value
  */
-void tmonitor_stop(int id);
+int tmonitor_stop(int id);
 
 /**
  * @brief Update value of the interested attributes by tmonitor_set_attrs()
@@ -164,13 +185,22 @@ void tmonitor_stop(int id);
 int tmonitor_update(int id);
 
 /**
+ * @brief Update value of the interested attributes by tmonitor_set_attrs()
+ * @param[in] Unique id of tizen monitor
+ * @param[in] Unique id of resource
+ * @return @c 0 on success, otherwise a negative error value
+ */
+int tmonitor_update_resource(int id, int resource_id);
+
+/**
  * @brief Get integer value of resource attribute
  * @param[in] Unique id of tizen monitor
- * @param[in] Resource type
+ * @param[in] Unique id of resource
  * @param[in] Resoruce attribute id
- * @return @c positive integer value, otherwise a negative error value
+ * @param[out] Value retrieved from resource attribute
+ * @return @ 0 on success, otherwise a negative error value
  */
-int tmonitor_get_value_int(int id, int resource_type, u_int64_t attr);
+int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr, int *value);
 
 /**
  * @brief Get the supported resource number