keep urls in http module and fix endless blocking thread in cmd mgr module 88/181588/2
authorJeonghoon Park <jh1979.park@samsung.com>
Fri, 15 Jun 2018 02:19:43 +0000 (11:19 +0900)
committerJeonghoon Park <jh1979.park@samsung.com>
Fri, 15 Jun 2018 02:27:51 +0000 (11:27 +0900)
Change-Id: I35e2a411b96c8582b56f5d602e20c327f59f45d5

daemon/include/ttd-http.h
daemon/src/ttd-cmd-mgr.c
daemon/src/ttd-http.c

index f7d9ece..bf1b98c 100644 (file)
@@ -19,9 +19,8 @@
 
 int ttd_http_init(void);
 int ttd_http_fini(void);
-int ttd_http_get_cloud_cmd(const char *url, char **cmd_json, long *res_code);
-int ttd_http_post_cmd_result(
-               const char *url, const char *result_json, long *res_code);
-int ttd_http_post_data(const char *url, const char *data, long *res_code);
+int ttd_http_command_get(char **cmd_json, long *res_code);
+int ttd_http_report_post(const char *result_json, long *res_code);
+int ttd_http_appdata_post(const char *url, const char *data, long *res_code);
 
 #endif /* __TT_DAEMON_HTTP_H__ */
index caf0434..e9ec48d 100644 (file)
 #include "ttd-build-json.h"
 #include "common-util.h"
 
-#ifndef SERVER_URL
-/* TODO : remove it after test */
-#define TEST_SERVER_URL "http://test.showiot.xyz/api/cmd?&target=test-page-device&owner=test-page&state=created"
-#define SERVER_URL TEST_SERVER_URL
-#endif
-
 #define CMD_MGR_GET_INTERVAL_SEC (3600 * 3)
 #define RESULT_WAIT_IN_SEC (10)
 #define RESULT_WAIT_TIME (RESULT_WAIT_IN_SEC * 1000000)
 #define RESULT_WAIT_TRY_MAX (6)
 
+// #define CMD_FETCH_TEST
+
 typedef struct _ttd_result_data_s {
        char *cmd_id;
        ttd_cmd_result_e result;
@@ -53,26 +49,35 @@ struct __cmd_mgr_h {
        GMutex get_mutex;
        GCond get_cond;
        GThread *launch_thread;
-       int launch_thread_running;
 };
 
+/* Just a pointer value to make unblocking async queue and exiting thread,
+ * it could be any address as long, as it isn't a valid queue item
+ */
+static const gpointer quit_marker = (gpointer) &ttd_cmd_mgr_init;
+
 /* Use singleton */
 static struct __cmd_mgr_h *g_handle = NULL;
 
-static const char *__ttd_get_cloud_url(void)
+static void __cmd_id_item_free(gpointer data)
 {
-       const char *url = NULL;
+       if (!data)
+               return;
 
-       /* TODO : get cloud url */
-       url = SERVER_URL;
+       if (data == quit_marker)
+               return;
 
-       return url;
+       g_free(data);
 }
 
 static void __result_item_free(gpointer data)
 {
        ttd_result_data_s *item = data;
-       if (!item)
+
+       if (!data)
+               return;
+
+       if (data == quit_marker)
                return;
 
        if (item->cmd_id)
@@ -126,13 +131,14 @@ static int _get_cloud_cmd(struct __cmd_mgr_h *handle, long *res_code)
 
        retv_if(!handle, -1);
 
-       ret = ttd_http_get_cloud_cmd(__ttd_get_cloud_url(), &cmd, &r_code);
+       ret = ttd_http_command_get(&cmd, &r_code);
        if (ret) {
                _E("failed to get cmd [%ld]", r_code);
                if (res_code)
                        *res_code = r_code;
                return -1;
        }
+
        if (res_code)
                *res_code = r_code;
 
@@ -179,7 +185,7 @@ static gpointer _get_thread(gpointer data)
        struct __cmd_mgr_h *handle = data;
 
        g_mutex_lock(&handle->get_mutex);
-       while (g_atomic_int_get(&(handle->get_thread_running))) {
+       while (TRUE) {
                int ret  = 0;
                guint64 until = 0;
                unsigned int retry = 0;
@@ -190,10 +196,15 @@ static gpointer _get_thread(gpointer data)
                g_cond_wait_until(&handle->get_cond, &handle->get_mutex, until);
                _D("thread unblocked");
 
-               if (g_handle->get_by_request)
+               if (!handle->get_thread_running)
+                       break;
+
+               if (handle->get_by_request)
                        retry = 5;
+               else
+                       retry = 1;
 
-               do {
+               while(retry) {
                        long res_code = 0;
 
                        ret = _get_cloud_cmd(handle, &res_code);
@@ -206,13 +217,14 @@ static gpointer _get_thread(gpointer data)
                                break;
 
                        retry--;
-                       g_usleep(G_USEC_PER_SEC); // sleep in 1 second before retry
-               } while(retry);
+                       if (retry)
+                               g_usleep(G_USEC_PER_SEC); // sleep in 1 second before retry
+               };
 
-               g_handle->get_by_request = 0;
+               handle->get_by_request = 0;
        }
        g_mutex_unlock(&handle->get_mutex);
-
+       _D("thread terminated");
        return NULL;
 }
 
@@ -220,7 +232,7 @@ static gpointer _launch_thread(gpointer data)
 {
        struct __cmd_mgr_h *handle = data;
 
-       while (g_atomic_int_get(&(handle->launch_thread_running))) {
+       while (TRUE) {
                char *cmd_id = NULL;
                ttd_cmd_data *cmd_data = NULL;
                char *report = NULL;
@@ -240,6 +252,9 @@ static gpointer _launch_thread(gpointer data)
                }
                _D("unblock launch thread");
 
+               if (cmd_id == quit_marker)
+                       goto THREAD_EXIT;
+
                // get cmd data from cmd_hash
                g_mutex_lock(&handle->mutex);
                cmd_data = g_hash_table_lookup(handle->cmd_hash, cmd_id);
@@ -253,9 +268,7 @@ static gpointer _launch_thread(gpointer data)
                cmd_type = ttd_cmd_get_type(cmd_data);
                report = ttd_build_json_create_report(cmd_id, cmd_type,
                        TTD_CMD_STATE_RUNNING, 0, "state update", NULL);
-               _D("report - %s", report);
-               ret = ttd_http_post_cmd_result(
-                               __ttd_get_cloud_url(), report, &r_code);
+               ret = ttd_http_report_post(report, &r_code);
                if (r_code != 200) {
                        _E("failed to post report [%ld]", r_code);
                        g_free(report);
@@ -271,8 +284,7 @@ static gpointer _launch_thread(gpointer data)
                        _E("cmd[%s] no proper launch function", cmd_id);
                        report = ttd_build_json_create_report(cmd_id, cmd_type,
                                TTD_CMD_STATE_FAILED, 0, "no proper launch function", NULL);
-                       _D("report - %s", report);
-                       ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+                       ttd_http_report_post(report, NULL);
                        g_free(report);
                        report = NULL;
                        goto DONE_N_WAIT;
@@ -283,8 +295,7 @@ static gpointer _launch_thread(gpointer data)
                        _E("cmd[%s] launch failed", cmd_id);
                        report = ttd_build_json_create_report(cmd_id, cmd_type,
                                TTD_CMD_STATE_FAILED, 0, "command launch failed", NULL);
-                       _D("report - %s", report);
-                       ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+                       ttd_http_report_post(report, NULL);
                        g_free(report);
                        report = NULL;
                        goto DONE_N_WAIT;
@@ -306,8 +317,7 @@ static gpointer _launch_thread(gpointer data)
                                /* timeout to wait result, report fail */
                                report = ttd_build_json_create_report(cmd_id, cmd_type,
                                        TTD_CMD_STATE_FAILED, 0, "timeout to wait result ", NULL);
-                               _D("report - %s", report);
-                               ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+                               ttd_http_report_post(report, NULL);
                                g_free(report);
                                report = NULL;
 
@@ -315,27 +325,23 @@ static gpointer _launch_thread(gpointer data)
                                break;
                        }
 
+                       if (result_item == quit_marker)
+                               goto THREAD_EXIT;
+
                        switch (result_item->result) {
                        case TTD_CMD_RESULT_RUNNING:
                                /* report running and wait more result */
                                report = ttd_build_json_create_report(cmd_id, cmd_type,
                                        TTD_CMD_STATE_RUNNING, 0,
                                        "report in progress", result_item->data);
-                               _D("report - %s", report);
-                               ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
-                               g_free(report);
-                               report = NULL;
+                               ttd_http_report_post(report, NULL);
                                break;
                        case TTD_CMD_RESULT_SUCCESS:
                                /* report done */
                                report = ttd_build_json_create_report(cmd_id, cmd_type,
                                        TTD_CMD_STATE_DONE, 0,
                                        "done", result_item->data);
-                               _D("report - %s", report);
-                               ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
-                               g_free(report);
-                               report = NULL;
-
+                               ttd_http_report_post(report, NULL);
                                result_wait = 0;
                                break;
                        case TTD_CMD_RESULT_FAIL:
@@ -343,16 +349,15 @@ static gpointer _launch_thread(gpointer data)
                                report = ttd_build_json_create_report(cmd_id, cmd_type,
                                        TTD_CMD_STATE_FAILED, 0,
                                        "failed to process command", result_item->data);
-                               _D("report - %s", report);
-                               ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
-                               g_free(report);
-                               report = NULL;
+                               ttd_http_report_post(report, NULL);
                                result_wait = 0;
                                break;
                        /* unhandled states */
                        default:
                                break;
                        }
+                       g_free(report);
+                       report = NULL;
                        __result_item_free(result_item);
                }
 
@@ -363,8 +368,13 @@ DONE_N_WAIT:
                        g_mutex_unlock(&handle->mutex);
                        g_free(cmd_id);
                }
-       }
+               continue;
 
+THREAD_EXIT:
+               _D("get quit_marker");
+               break;
+       }
+       _D("thread terminated");
        return NULL;
 }
 
@@ -373,20 +383,26 @@ static void __free_cmd_mgr_handle(void)
        if (!g_handle)
                return;
 
-       g_mutex_clear(&g_handle->mutex);
-
-       if (g_handle->launch_thread) {
-               g_atomic_int_set(&(g_handle->launch_thread_running), 0);
-               g_thread_join(g_handle->launch_thread);
-       }
-
        if (g_handle->get_thread) {
-               g_atomic_int_set(&(g_handle->get_thread_running), 0);
+               g_mutex_lock(&g_handle->get_mutex);
+               g_handle->get_thread_running = 0;
+               g_cond_broadcast(&g_handle->get_cond);
+               g_mutex_unlock(&g_handle->get_mutex);
+
                g_thread_join(g_handle->get_thread);
        }
        g_mutex_clear(&g_handle->get_mutex);
        g_cond_clear(&g_handle->get_cond);
 
+       if (g_handle->launch_thread) {
+               g_async_queue_push(g_handle->cmd_id_queue, quit_marker);
+               g_async_queue_push(g_handle->result_queue, quit_marker);
+
+               g_thread_join(g_handle->launch_thread);
+       }
+
+       g_mutex_clear(&g_handle->mutex);
+
        if (g_handle->result_queue)
                g_async_queue_unref(g_handle->result_queue);
 
@@ -402,12 +418,14 @@ static void __free_cmd_mgr_handle(void)
        g_handle = NULL;
 }
 
+#ifdef CMD_FETCH_TEST
 static gboolean __get_cmd_first_time(gpointer data)
 {
        ttd_cmd_mgr_get_cmd();
 
        return G_SOURCE_REMOVE;
 }
+#endif /* CMD_FETCH_TEST */
 
 int ttd_cmd_mgr_init(void)
 {
@@ -418,7 +436,7 @@ int ttd_cmd_mgr_init(void)
        g_handle = g_try_malloc0(sizeof(struct __cmd_mgr_h));
        retvm_if(!g_handle, -1, "failed to malloc");
 
-       g_handle->cmd_id_queue = g_async_queue_new_full((GDestroyNotify)g_free);
+       g_handle->cmd_id_queue = g_async_queue_new_full(__cmd_id_item_free);
        goto_if(!g_handle->cmd_id_queue, ERROR_N_EXIT);
 
        g_handle->cmd_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -430,9 +448,9 @@ int ttd_cmd_mgr_init(void)
 
        g_mutex_init(&g_handle->mutex);
 
-       g_atomic_int_set(&(g_handle->get_thread_running), 1);
        g_mutex_init(&g_handle->get_mutex);
        g_cond_init(&g_handle->get_cond);
+       g_handle->get_thread_running = 1;
 
        g_handle->get_thread =
                g_thread_try_new(NULL, (GThreadFunc)_get_thread, g_handle, &error);
@@ -442,7 +460,6 @@ int ttd_cmd_mgr_init(void)
                goto ERROR_N_EXIT;
        }
 
-       g_atomic_int_set(&(g_handle->launch_thread_running), 1);
        g_handle->launch_thread =
                g_thread_try_new(NULL, (GThreadFunc)_launch_thread, g_handle, &error);
        if (!g_handle->launch_thread) {
@@ -451,13 +468,15 @@ int ttd_cmd_mgr_init(void)
                goto ERROR_N_EXIT;
        }
 
-       // need it ??
+#ifdef CMD_FETCH_TEST
        g_idle_add(__get_cmd_first_time, NULL);
+#endif /* CMD_FETCH_TEST */
 
        return 0;
 
 ERROR_N_EXIT:
-       g_error_free(error);
+       if (error)
+               g_error_free(error);
        __free_cmd_mgr_handle();
        return -1;
 }
index edabe65..f81b68f 100644 (file)
 #include <openssl/crypto.h>
 #include <glib.h>
 #include "ttd-log.h"
+#include "ttd-url.h"
 
 #define CERT_FILE_PATH "/opt/share/cert-svc/ca-certificate.crt"
 
 static GMutex *mutex_a = NULL;
 static int http_initialized = 0;
+static char *urls[TTD_URL_TYPE_NUM] = { NULL, };
 
 static void __locking_function(int mode, int n, const char *file, int line)
 {
@@ -91,13 +93,28 @@ int ttd_http_init(void)
 
 int ttd_http_fini(void)
 {
+       int i= 0;
        __ssl_thread_mutex_cleanup();
        curl_global_cleanup();
+
+       for (i = 0; i < TTD_URL_TYPE_NUM; i++) {
+               g_free(urls[i]);
+               urls[i] = NULL;
+       }
+
        http_initialized = 0;
 
        return 0;
 }
 
+static const char *__get_url_by_type(ttd_url_type_e type)
+{
+       if (!urls[type])
+               urls[type] = ttd_url_get_by_type(type);
+
+       return urls[type];
+}
+
 static size_t _get_cmd_write(void *ptr, size_t size, size_t nmemb, void *data)
 {
        size_t res_size = 0;
@@ -122,17 +139,20 @@ static size_t _get_cmd_write(void *ptr, size_t size, size_t nmemb, void *data)
        return res_size;
 }
 
-int ttd_http_get_cloud_cmd(const char *url, char **cmd_json, long *res_code)
+int ttd_http_command_get(char **cmd_json, long *res_code)
 {
        int ret = 0;
        CURL *curl = NULL;
        CURLcode res = CURLE_OK;
        long r_code = 0;
+       const char *url = NULL;
 
        retvm_if(!http_initialized, -1, "http is not initialized yet");
-       retvm_if(!url, -1, "url is null");
        retvm_if(!cmd_json, -1, "cmd_json is null");
 
+       url = __get_url_by_type(TTD_URL_CMD);
+       retvm_if(!url, -1, "failed to get url for command GET");
+
        curl = curl_easy_init();
 
        retvm_if(!curl, NULL, "failed to curl_easy_init()");
@@ -201,10 +221,15 @@ static int __ttd_http_post(const char *url,
        return ret;
 }
 
-int ttd_http_post_cmd_result(
-       const char *url, const char *result_json, long *res_code)
+int ttd_http_report_post(const char *result_json, long *res_code)
 {
        struct curl_slist *headers = NULL;
+       const char *url = NULL;
+
+       url = __get_url_by_type(TTD_URL_REPORT);
+       retvm_if(!url, -1, "failed to get url for command POST");
+
+       _D("report - %s", result_json);
 
        headers = curl_slist_append(headers, "Accept: application/json");
        headers = curl_slist_append(headers, "Content-Type: application/json");
@@ -213,7 +238,7 @@ int ttd_http_post_cmd_result(
        return __ttd_http_post(url, result_json, headers, res_code);
 }
 
-int ttd_http_post_data(const char *url, const char *data, long *res_code)
+int ttd_http_appdata_post(const char *url, const char *data, long *res_code)
 {
        struct curl_slist *headers = NULL;