From 16ed77dc86b4869d97db625f796fd3e9f67e2c89 Mon Sep 17 00:00:00 2001 From: Jaeyun Jung Date: Mon, 20 Jan 2025 16:46:29 +0900 Subject: [PATCH] [Android] include database Separate node info for pipeline, and include mlops database based on sqlite to build android library. Signed-off-by: Jaeyun Jung --- daemon/meson.build | 2 +- daemon/mlops-agent-android.c | 40 ++--- daemon/mlops-agent-interface.c | 5 +- daemon/mlops-agent-node.c | 281 +++++++++++++++++++++++++++++++++ daemon/mlops-agent-node.h | 61 +++++++ daemon/pipeline-dbus-impl.cc | 198 +---------------------- daemon/service-db-util.h | 1 + jni/mlops-agent.mk | 5 +- 8 files changed, 379 insertions(+), 214 deletions(-) create mode 100755 daemon/mlops-agent-node.c create mode 100755 daemon/mlops-agent-node.h diff --git a/daemon/meson.build b/daemon/meson.build index 71c0056..adb8eb7 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -1,6 +1,6 @@ # Machine Learning Agent ml_agent_incs = include_directories('.', 'include') -ml_agent_lib_srcs = files('modules.c', 'gdbus-util.c', 'mlops-agent-interface.c', +ml_agent_lib_srcs = files('modules.c', 'gdbus-util.c', 'mlops-agent-interface.c', 'mlops-agent-node.c', 'pipeline-dbus-impl.cc', 'model-dbus-impl.cc', 'resource-dbus-impl.cc', 'service-db.cc') ml_agent_deps = [ diff --git a/daemon/mlops-agent-android.c b/daemon/mlops-agent-android.c index 37b391c..48cf00c 100644 --- a/daemon/mlops-agent-android.c +++ b/daemon/mlops-agent-android.c @@ -15,6 +15,8 @@ #include "log.h" #include "mlops-agent-interface.h" #include "mlops-agent-internal.h" +#include "mlops-agent-node.h" +#include "service-db-util.h" /** * @brief An interface exported for setting the description of a pipeline. @@ -26,7 +28,7 @@ ml_agent_pipeline_set_description (const char *name, const char *pipeline_desc) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_pipeline_set (name, pipeline_desc); } /** @@ -39,7 +41,7 @@ ml_agent_pipeline_get_description (const char *name, char **pipeline_desc) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_pipeline_get (name, pipeline_desc); } /** @@ -52,7 +54,7 @@ ml_agent_pipeline_delete (const char *name) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_pipeline_delete (name); } /** @@ -65,7 +67,7 @@ ml_agent_pipeline_launch (const char *name, int64_t * id) g_return_val_if_reached (-EINVAL); } - return 0; + return mlops_node_create (name, MLOPS_NODE_TYPE_PIPELINE, id); } /** @@ -74,7 +76,7 @@ ml_agent_pipeline_launch (const char *name, int64_t * id) int ml_agent_pipeline_start (const int64_t id) { - return 0; + return mlops_node_start (id); } /** @@ -83,7 +85,7 @@ ml_agent_pipeline_start (const int64_t id) int ml_agent_pipeline_stop (const int64_t id) { - return 0; + return mlops_node_stop (id); } /** @@ -92,7 +94,7 @@ ml_agent_pipeline_stop (const int64_t id) int ml_agent_pipeline_destroy (const int64_t id) { - return 0; + return mlops_node_destroy (id); } /** @@ -101,7 +103,7 @@ ml_agent_pipeline_destroy (const int64_t id) int ml_agent_pipeline_get_state (const int64_t id, int *state) { - return 0; + return mlops_node_get_state (id, (GstState *) state); } /** @@ -115,7 +117,8 @@ ml_agent_model_register (const char *name, const char *path, if (!STR_IS_VALID (name) || !STR_IS_VALID (path) || !version) { g_return_val_if_reached (-EINVAL); } - return 0; + + return svcdb_model_add (name, path, activate, description, app_info, version); } /** @@ -128,7 +131,8 @@ ml_agent_model_update_description (const char *name, if (!STR_IS_VALID (name) || !STR_IS_VALID (description) || version == 0U) { g_return_val_if_reached (-EINVAL); } - return 0; + + return svcdb_model_update_description (name, version, description); } /** @@ -141,7 +145,7 @@ ml_agent_model_activate (const char *name, const uint32_t version) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_model_activate (name, version); } /** @@ -154,7 +158,7 @@ ml_agent_model_get (const char *name, const uint32_t version, char **model_info) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_model_get (name, version, model_info); } /** @@ -167,7 +171,7 @@ ml_agent_model_get_activated (const char *name, char **model_info) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_model_get_activated (name, model_info); } /** @@ -180,7 +184,7 @@ ml_agent_model_get_all (const char *name, char **model_info) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_model_get_all (name, model_info); } /** @@ -195,7 +199,7 @@ ml_agent_model_delete (const char *name, const uint32_t version, g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_model_delete (name, version, force); } /** @@ -209,7 +213,7 @@ ml_agent_resource_add (const char *name, const char *path, g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_resource_add (name, path, description, app_info); } /** @@ -222,7 +226,7 @@ ml_agent_resource_delete (const char *name) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_resource_delete (name); } /** @@ -235,5 +239,5 @@ ml_agent_resource_get (const char *name, char **res_info) g_return_val_if_reached (-EINVAL); } - return 0; + return svcdb_resource_get (name, res_info); } diff --git a/daemon/mlops-agent-interface.c b/daemon/mlops-agent-interface.c index d18a029..0193f4d 100644 --- a/daemon/mlops-agent-interface.c +++ b/daemon/mlops-agent-interface.c @@ -202,6 +202,7 @@ ml_agent_pipeline_set_description (const char *name, const char *pipeline_desc) { MachinelearningServicePipeline *mlsp; gboolean result; + gint ret; if (!STR_IS_VALID (name) || !STR_IS_VALID (pipeline_desc)) { g_return_val_if_reached (-EINVAL); @@ -213,10 +214,10 @@ ml_agent_pipeline_set_description (const char *name, const char *pipeline_desc) } result = machinelearning_service_pipeline_call_set_pipeline_sync (mlsp, - name, pipeline_desc, NULL, NULL, NULL); + name, pipeline_desc, &ret, NULL, NULL); g_object_unref (mlsp); - g_return_val_if_fail (result, -EIO); + g_return_val_if_fail (ret == 0 && result, ret); return 0; } diff --git a/daemon/mlops-agent-node.c b/daemon/mlops-agent-node.c new file mode 100755 index 0000000..af754a0 --- /dev/null +++ b/daemon/mlops-agent-node.c @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/** + * NNStreamer API / Machine Learning Agent Daemon + * Copyright (C) 2025 Samsung Electronics Co., Ltd. All Rights Reserved. + */ + +/** + * @file mlops-agent-node.c + * @date 20 january 2025 + * @brief Implementation of mlops node. + * @see https://github.com/nnstreamer/deviceMLOps.MLAgent + * @author Jaeyun Jung + * @bug No known bugs except for NYI items + * @details This implements the node information to run a pipeline. + */ + +#include "log.h" +#include "mlops-agent-node.h" +#include "service-db-util.h" + +static GHashTable *g_mlops_node_table = NULL; +G_LOCK_DEFINE_STATIC (mlops_node_table); + +/** + * @brief Structure for mlops node. + */ +typedef struct +{ + mlops_node_type_e type; + gint64 id; + GMutex lock; + GstElement *element; + gchar *service_name; + gchar *description; +} mlops_node_s; + +/** + * @brief Internal function to get node info. + */ +static mlops_node_s * +_mlops_node_get (const int64_t id) +{ + mlops_node_s *node = NULL; + + G_LOCK (mlops_node_table); + node = (mlops_node_s *) g_hash_table_lookup (g_mlops_node_table, + GINT_TO_POINTER (id)); + G_UNLOCK (mlops_node_table); + + if (!node) { + ml_loge ("There is no pipeline matched with ID %" G_GINT64_FORMAT, id); + } + + return node; +} + +/** + * @brief Internal function to change pipeline state. + */ +static int +_mlops_node_set_pipeline_state (mlops_node_s * node, GstState state) +{ + GstStateChangeReturn ret; + + g_return_val_if_fail (node != NULL, -EINVAL); + + g_mutex_lock (&node->lock); + ret = gst_element_set_state (node->element, state); + g_mutex_unlock (&node->lock); + + if (ret == GST_STATE_CHANGE_FAILURE) { + ml_loge ("Failed to set the state of the pipeline to %s with ID %" + G_GINT64_FORMAT, gst_element_state_get_name (state), node->id); + return ESTRPIPE; + } + + return 0; +} + +/** + * @brief Internal function to release mlops node. + */ +static void +_mlops_node_free (gpointer data) +{ + mlops_node_s *node = (mlops_node_s *) data; + + if (!node) { + ml_logw ("The data pointer is null, internal error?"); + return; + } + + g_mutex_lock (&node->lock); + + node->type = MLOPS_NODE_TYPE_NONE; + node->id = 0; + if (node->element) { + gst_object_unref (node->element); + node->element = NULL; + } + g_free (node->service_name); + node->service_name = NULL; + g_free (node->description); + node->description = NULL; + + g_mutex_unlock (&node->lock); + + g_mutex_clear (&node->lock); + g_free (node); +} + +/** + * @brief Internal function to initialize mlops node info. + */ +static inline void +_mlops_node_check_init (void) +{ + G_LOCK (mlops_node_table); + if (!g_mlops_node_table) { + g_mlops_node_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, _mlops_node_free); + } + g_assert (g_mlops_node_table != NULL); + G_UNLOCK (mlops_node_table); +} + +/** + * @brief Check service name and launch the pipeline. + */ +int +mlops_node_create (const gchar * name, const mlops_node_type_e type, + int64_t * id) +{ + mlops_node_s *node = NULL; + gint result = -EIO; + gchar *desc = NULL; + GstElement *pipeline = NULL; + GError *err = NULL; + GstStateChangeReturn ret; + + _mlops_node_check_init (); + + switch (type) { + case MLOPS_NODE_TYPE_PIPELINE: + { + result = svcdb_pipeline_get (name, &desc); + if (result != 0) { + ml_loge ("Failed to launch pipeline of '%s'.", name); + goto error; + } + break; + } + default: + return -EINVAL; + } + + pipeline = gst_parse_launch (desc, &err); + if (!pipeline || err) { + ml_loge ("Failed to launch pipeline '%s' (error msg: %s).", + desc, (err) ? err->message : "unknown reason"); + g_clear_error (&err); + + if (pipeline) + gst_object_unref (pipeline); + + result = -ESTRPIPE; + goto error; + } + + /* Set pipeline as paused state. */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (ret == GST_STATE_CHANGE_FAILURE) { + ml_loge + ("Failed to set the state of the pipeline to PAUSED. For the detail, please check the GStreamer log message."); + + gst_object_unref (pipeline); + result = -ESTRPIPE; + goto error; + } + + /* Add node info into hash table. */ + node = g_new0 (mlops_node_s, 1); + node->type = type; + node->id = g_get_monotonic_time (); + node->element = pipeline; + node->service_name = g_strdup (name); + node->description = g_strdup (desc); + g_mutex_init (&node->lock); + + G_LOCK (mlops_node_table); + g_hash_table_insert (g_mlops_node_table, GINT_TO_POINTER (node->id), node); + G_UNLOCK (mlops_node_table); + +error: + if (result == 0) { + *id = node->id; + } else { + if (node) + _mlops_node_free (node); + } + + g_free (desc); + return result; +} + +/** + * @brief Start the pipeline with given id. + */ +int +mlops_node_start (const int64_t id) +{ + mlops_node_s *node = NULL; + + _mlops_node_check_init (); + + node = _mlops_node_get (id); + return _mlops_node_set_pipeline_state (node, GST_STATE_PLAYING); +} + +/** + * @brief Stop the pipeline with given id. + */ +int +mlops_node_stop (const int64_t id) +{ + mlops_node_s *node = NULL; + + _mlops_node_check_init (); + + node = _mlops_node_get (id); + return _mlops_node_set_pipeline_state (node, GST_STATE_PAUSED); +} + +/** + * @brief Destroy the pipeline with given id. + */ +int +mlops_node_destroy (const int64_t id) +{ + mlops_node_s *node = NULL; + + _mlops_node_check_init (); + + node = _mlops_node_get (id); + if (node) { + _mlops_node_set_pipeline_state (node, GST_STATE_NULL); + + G_LOCK (mlops_node_table); + g_hash_table_remove (g_mlops_node_table, GINT_TO_POINTER (id)); + G_UNLOCK (mlops_node_table); + } + + return node ? 0 : -EINVAL; +} + +/** + * @brief Get the state of pipeline with given id. + */ +int +mlops_node_get_state (const int64_t id, GstState * state) +{ + mlops_node_s *node = NULL; + GstStateChangeReturn ret; + + _mlops_node_check_init (); + + node = _mlops_node_get (id); + g_return_val_if_fail (node != NULL, -EINVAL); + + g_mutex_lock (&node->lock); + ret = gst_element_get_state (node->element, state, NULL, GST_MSECOND); + g_mutex_unlock (&node->lock); + + if (ret == GST_STATE_CHANGE_FAILURE) { + ml_loge ("Failed to get the state of the pipeline with ID %" + G_GINT64_FORMAT, id); + return -ESTRPIPE; + } + + return 0; +} diff --git a/daemon/mlops-agent-node.h b/daemon/mlops-agent-node.h new file mode 100755 index 0000000..d587f9a --- /dev/null +++ b/daemon/mlops-agent-node.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/** + * NNStreamer API / Machine Learning Agent Daemon + * Copyright (C) 2025 Samsung Electronics Co., Ltd. All Rights Reserved. + */ + +/** + * @file mlops-agent-node.h + * @date 20 january 2025 + * @brief Implementation of mlops node. + * @see https://github.com/nnstreamer/deviceMLOps.MLAgent + * @author Jaeyun Jung + * @bug No known bugs except for NYI items + * @details This implements the node information to run a pipeline. + */ + +#ifndef _MLOPS_AGENT_NODE_H_ +#define _MLOPS_AGENT_NODE_H_ + +#include +#include + +G_BEGIN_DECLS + +/** + * @brief Enumeration for mlops node type. + */ +typedef enum +{ + MLOPS_NODE_TYPE_NONE = 0, + MLOPS_NODE_TYPE_PIPELINE, + MLOPS_NODE_TYPE_MAX +} mlops_node_type_e; + +/** + * @brief Check service name and launch the pipeline. + */ +int mlops_node_create (const gchar *name, const mlops_node_type_e type, int64_t *id); + +/** + * @brief Start the pipeline with given id. + */ +int mlops_node_start (const int64_t id); + +/** + * @brief Stop the pipeline with given id. + */ +int mlops_node_stop (const int64_t id); + +/** + * @brief Destroy the pipeline with given id. + */ +int mlops_node_destroy (const int64_t id); + +/* + * @brief Get the state of pipeline with given id. + */ +int mlops_node_get_state (const int64_t id, GstState *state); + +G_END_DECLS +#endif /* _MLOPS_AGENT_NODE_H_ */ diff --git a/daemon/pipeline-dbus-impl.cc b/daemon/pipeline-dbus-impl.cc index 07642ec..6cb2f6a 100644 --- a/daemon/pipeline-dbus-impl.cc +++ b/daemon/pipeline-dbus-impl.cc @@ -24,49 +24,12 @@ #include "dbus-interface.h" #include "gdbus-util.h" #include "log.h" +#include "mlops-agent-node.h" #include "modules.h" #include "pipeline-dbus.h" #include "service-db-util.h" static MachinelearningServicePipeline *g_gdbus_instance = NULL; -static GHashTable *pipeline_table = NULL; -G_LOCK_DEFINE_STATIC (pipeline_table_lock); - -/** - * @brief Structure for pipeline. - */ -typedef struct _pipeline { - GstElement *element; - gint64 id; - GMutex lock; - gchar *service_name; - gchar *description; -} pipeline_s; - -/** - * @brief Internal function to destroy pipeline instances. - */ -static void -_pipeline_free (gpointer data) -{ - pipeline_s *p; - - if (!data) { - ml_loge ("internal error, the data should not be NULL"); - return; - } - - p = (pipeline_s *) data; - - if (p->element) - gst_object_unref (p->element); - - g_free (p->service_name); - g_free (p->description); - g_mutex_clear (&p->lock); - - g_free (p); -} /** * @brief Get the skeleton object of the DBus interface. @@ -141,55 +104,8 @@ dbus_cb_core_launch_pipeline (MachinelearningServicePipeline *obj, { gint result = 0; gint64 id = -1; - GError *err = NULL; - GstStateChangeReturn sc_ret; - GstElement *pipeline = NULL; - pipeline_s *p; - g_autofree gchar *desc = NULL; - - result = svcdb_pipeline_get (service_name, &desc); - if (result != 0) { - ml_loge ("Failed to launch pipeline of '%s'.", service_name); - goto error; - } - - pipeline = gst_parse_launch (desc, &err); - if (!pipeline || err) { - ml_loge ("Failed to launch pipeline '%s' (error msg: %s).", - desc, (err) ? err->message : "unknown reason"); - g_clear_error (&err); - if (pipeline) - gst_object_unref (pipeline); - - result = -ESTRPIPE; - goto error; - } - - /** now set pipeline as paused state */ - sc_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); - if (sc_ret == GST_STATE_CHANGE_FAILURE) { - ml_loge ("Failed to set the state of the pipeline to PAUSED. For the detail, please check the GStreamer log message. The input pipeline was '%s'.", - desc); - - gst_object_unref (pipeline); - result = -ESTRPIPE; - goto error; - } - - /** now fill the struct and store into hash table */ - p = g_new0 (pipeline_s, 1); - p->element = pipeline; - p->description = g_strdup (desc); - p->service_name = g_strdup (service_name); - g_mutex_init (&p->lock); - - G_LOCK (pipeline_table_lock); - id = p->id = g_get_monotonic_time (); - g_hash_table_insert (pipeline_table, GINT_TO_POINTER (p->id), p); - G_UNLOCK (pipeline_table_lock); - -error: + result = mlops_node_create (service_name, MLOPS_NODE_TYPE_PIPELINE, &id); machinelearning_service_pipeline_complete_launch_pipeline (obj, invoc, result, id); return TRUE; @@ -203,29 +119,8 @@ dbus_cb_core_start_pipeline (MachinelearningServicePipeline *obj, GDBusMethodInvocation *invoc, gint64 id, gpointer user_data) { gint result = 0; - GstStateChangeReturn sc_ret; - pipeline_s *p = NULL; - - G_LOCK (pipeline_table_lock); - p = (pipeline_s *) g_hash_table_lookup (pipeline_table, GINT_TO_POINTER (id)); - - if (!p) { - ml_loge ("The callback start_pipeline is called, but there is no pipeline matched with ID."); - G_UNLOCK (pipeline_table_lock); - result = -EINVAL; - } else { - g_mutex_lock (&p->lock); - G_UNLOCK (pipeline_table_lock); - sc_ret = gst_element_set_state (p->element, GST_STATE_PLAYING); - g_mutex_unlock (&p->lock); - - if (sc_ret == GST_STATE_CHANGE_FAILURE) { - ml_loge ("Failed to set the state of the pipeline to PLAYING whose service name is %s.", - p->service_name); - result = -ESTRPIPE; - } - } + result = mlops_node_start (id); machinelearning_service_pipeline_complete_start_pipeline (obj, invoc, result); return TRUE; @@ -239,29 +134,8 @@ dbus_cb_core_stop_pipeline (MachinelearningServicePipeline *obj, GDBusMethodInvocation *invoc, gint64 id, gpointer user_data) { gint result = 0; - GstStateChangeReturn sc_ret; - pipeline_s *p = NULL; - - G_LOCK (pipeline_table_lock); - p = (pipeline_s *) g_hash_table_lookup (pipeline_table, GINT_TO_POINTER (id)); - - if (!p) { - ml_loge ("The callback stop_pipeline is called, but there is no pipeline matched with ID."); - G_UNLOCK (pipeline_table_lock); - result = -EINVAL; - } else { - g_mutex_lock (&p->lock); - G_UNLOCK (pipeline_table_lock); - sc_ret = gst_element_set_state (p->element, GST_STATE_PAUSED); - g_mutex_unlock (&p->lock); - - if (sc_ret == GST_STATE_CHANGE_FAILURE) { - ml_loge ("Failed to set the state of the pipeline to PAUSED whose service name is %s.", - p->service_name); - result = -ESTRPIPE; - } - } + result = mlops_node_stop (id); machinelearning_service_pipeline_complete_stop_pipeline (obj, invoc, result); return TRUE; @@ -275,34 +149,8 @@ dbus_cb_core_destroy_pipeline (MachinelearningServicePipeline *obj, GDBusMethodInvocation *invoc, gint64 id, gpointer user_data) { gint result = 0; - pipeline_s *p = NULL; - - G_LOCK (pipeline_table_lock); - p = (pipeline_s *) g_hash_table_lookup (pipeline_table, GINT_TO_POINTER (id)); - - if (!p) { - ml_loge ("The callback destroy_pipeline is called, but there is no pipeline matched with ID."); - result = -EINVAL; - } else { - /** - * @todo Fix hanging issue when trying to set GST_STATE_NULL state for pipelines - * containing tensor_query_*. As a workaround, just unref the pipeline instance. - * To fix this issue, tensor_query elements and nnstreamer-edge should well-behavior - * to the state change. And it should properly free socket resources. Revive following code after then. - * - * GstStateChangeReturn sc_ret; - * g_mutex_lock (&p->lock); - * sc_ret = gst_element_set_state (p->element, GST_STATE_NULL); - * g_mutex_unlock (&p->lock); - * if (sc_ret == GST_STATE_CHANGE_FAILURE) { - * ml_loge ("Failed to set the state of the pipeline to NULL whose service name is %s. Destroy it anyway.", p->service_name); - * result = -ESTRPIPE; - * } - */ - g_hash_table_remove (pipeline_table, GINT_TO_POINTER (id)); - } - G_UNLOCK (pipeline_table_lock); + result = mlops_node_destroy (id); machinelearning_service_pipeline_complete_destroy_pipeline (obj, invoc, result); return TRUE; @@ -316,32 +164,9 @@ dbus_cb_core_get_state (MachinelearningServicePipeline *obj, GDBusMethodInvocation *invoc, gint64 id, gpointer user_data) { gint result = 0; - GstStateChangeReturn sc_ret; GstState state = GST_STATE_NULL; - pipeline_s *p = NULL; - - G_LOCK (pipeline_table_lock); - p = (pipeline_s *) g_hash_table_lookup (pipeline_table, GINT_TO_POINTER (id)); - - if (!p) { - ml_loge ("The callback get_state is called, but there is no pipeline matched with ID."); - result = -EINVAL; - machinelearning_service_pipeline_complete_get_state (obj, invoc, result, (gint) state); - G_UNLOCK (pipeline_table_lock); - return TRUE; - } - - g_mutex_lock (&p->lock); - G_UNLOCK (pipeline_table_lock); - sc_ret = gst_element_get_state (p->element, &state, NULL, GST_MSECOND); - g_mutex_unlock (&p->lock); - - if (sc_ret == GST_STATE_CHANGE_FAILURE) { - ml_loge ("Failed to get the state of the pipeline whose service name is %s.", - p->service_name); - result = -ESTRPIPE; - } + result = mlops_node_get_state (id, &state); machinelearning_service_pipeline_complete_get_state (obj, invoc, result, (gint) state); return TRUE; @@ -444,11 +269,6 @@ static void init_pipeline_module (void *data) { gdbus_initialize (); - - G_LOCK (pipeline_table_lock); - g_assert (NULL == pipeline_table); /** Internal error */ - pipeline_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, _pipeline_free); - G_UNLOCK (pipeline_table_lock); } /** @@ -457,12 +277,6 @@ init_pipeline_module (void *data) static void exit_pipeline_module (void *data) { - G_LOCK (pipeline_table_lock); - g_assert (pipeline_table); /** Internal error */ - g_hash_table_destroy (pipeline_table); - pipeline_table = NULL; - G_UNLOCK (pipeline_table_lock); - gdbus_disconnect_signal (g_gdbus_instance, ARRAY_SIZE (handler_infos), handler_infos); gdbus_put_pipeline_instance (&g_gdbus_instance); } diff --git a/daemon/service-db-util.h b/daemon/service-db-util.h index 7565478..353dcaa 100644 --- a/daemon/service-db-util.h +++ b/daemon/service-db-util.h @@ -14,6 +14,7 @@ #define __SERVICE_DB_UTIL_H__ #include +#include G_BEGIN_DECLS diff --git a/jni/mlops-agent.mk b/jni/mlops-agent.mk index 706d573..f0b138c 100644 --- a/jni/mlops-agent.mk +++ b/jni/mlops-agent.mk @@ -6,4 +6,7 @@ endif MLOPS_AGENT_INCLUDE := $(MLOPS_AGENT_ROOT)/daemon/include # mlops agent sources -MLOPS_AGENT_SRCS := $(MLOPS_AGENT_ROOT)/daemon/mlops-agent-android.c +MLOPS_AGENT_SRCS := \ + $(MLOPS_AGENT_ROOT)/daemon/mlops-agent-android.c \ + $(MLOPS_AGENT_ROOT)/daemon/mlops-agent-node.c \ + $(MLOPS_AGENT_ROOT)/daemon/service-db.cc