From 68db79479668c01a13adf4d0fe039206518e3e4b Mon Sep 17 00:00:00 2001 From: Jaeyun Jung Date: Fri, 2 Feb 2024 13:59:35 +0900 Subject: [PATCH] [C-Api/Service] internal function for ml-service handle Code clean, prepare new API for ml-service extension. Add internal function for ml-service handle. Signed-off-by: Jaeyun Jung --- c/include/ml-api-service.h | 50 ++++++---- c/include/nnstreamer-tizen-internal.h | 2 +- c/src/ml-api-service-agent-client.c | 57 +++++------ c/src/ml-api-service-common.c | 71 +++++++++++--- c/src/ml-api-service-private.h | 24 ++++- c/src/ml-api-service-query-client.c | 67 +++++++------ c/src/ml-api-service-remote.c | 115 ++++++++++++----------- tests/capi/unittest_capi_service_agent_client.cc | 27 +++--- 8 files changed, 251 insertions(+), 162 deletions(-) diff --git a/c/include/ml-api-service.h b/c/include/ml-api-service.h index d002940..21b8f69 100644 --- a/c/include/ml-api-service.h +++ b/c/include/ml-api-service.h @@ -40,6 +40,28 @@ extern "C" { */ /** + * @brief A handle for ml-service instance. + * @since_tizen 7.0 + */ +typedef void *ml_service_h; + +/** + * @brief Destroys the given service handle. + * @details If given service handle is created by ml_service_launch_pipeline(), this requests machine learning agent daemon to destroy the pipeline. + * @since_tizen 7.0 + * @param[in] handle The service handle. + * @return @c 0 on Success. Otherwise a negative error value. + * @retval #ML_ERROR_NONE Successful. + * @retval #ML_ERROR_NOT_SUPPORTED Not supported. + * @retval #ML_ERROR_INVALID_PARAMETER Fail. The parameter is invalid. + * @retval #ML_ERROR_STREAMS_PIPE Failed to access the pipeline state. + */ +int ml_service_destroy (ml_service_h handle); + +/**************************************************** + ** API for AI pipeline ** + ****************************************************/ +/** * @brief Sets the pipeline description with a given name. * @since_tizen 7.0 * @remarks If the name already exists, the pipeline description is overwritten. Overwriting an existing description is restricted to APP/service that set it. However, users should keep their @a name unexposed to prevent unexpected overwriting. @@ -116,12 +138,6 @@ int ml_service_get_pipeline (const char *name, char **pipeline_desc); int ml_service_delete_pipeline (const char *name); /** - * @brief A handle for ml-service instance. - * @since_tizen 7.0 - */ -typedef void *ml_service_h; - -/** * @brief Launches the pipeline of given service and gets the service handle. * @details This requests machine learning agent daemon to launch a new pipeline of given service. The pipeline of service @a name should be set. * @since_tizen 7.0 @@ -165,19 +181,6 @@ int ml_service_start_pipeline (ml_service_h handle); int ml_service_stop_pipeline (ml_service_h handle); /** - * @brief Destroys the given service handle. - * @details If given service handle is created by ml_service_launch_pipeline(), this requests machine learning agent daemon to destroy the pipeline. - * @since_tizen 7.0 - * @param[in] handle The service handle. - * @return @c 0 on Success. Otherwise a negative error value. - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_NOT_SUPPORTED Not supported. - * @retval #ML_ERROR_INVALID_PARAMETER Fail. The parameter is invalid. - * @retval #ML_ERROR_STREAMS_PIPE Failed to access the pipeline state. - */ -int ml_service_destroy (ml_service_h handle); - -/** * @brief Gets the state of given handle's pipeline. * @since_tizen 7.0 * @param[in] handle The service handle. @@ -190,6 +193,9 @@ int ml_service_destroy (ml_service_h handle); */ int ml_service_get_pipeline_state (ml_service_h handle, ml_pipeline_state_e *state); +/**************************************************** + ** API for among-device AI service ** + ****************************************************/ /** * @brief Creates query service handle with given ml-option handle. * @since_tizen 7.0 @@ -224,6 +230,9 @@ int ml_service_query_create (ml_option_h option, ml_service_h *handle); */ int ml_service_query_request (ml_service_h handle, const ml_tensors_data_h input, ml_tensors_data_h *output); +/**************************************************** + ** API for managing AI models ** + ****************************************************/ /** * @brief Registers new information of a neural network model. * @since_tizen 8.0 @@ -371,6 +380,9 @@ int ml_service_model_get_all (const char *name, ml_information_list_h *info_list */ int ml_service_model_delete (const char *name, const unsigned int version); +/**************************************************** + ** API for managing AI data files ** + ****************************************************/ /** * @brief Adds new information of machine learning resources those contain images, audio samples, binary files, and so on. * @since_tizen 8.0 diff --git a/c/include/nnstreamer-tizen-internal.h b/c/include/nnstreamer-tizen-internal.h index f4f9d9b..4e8639b 100644 --- a/c/include/nnstreamer-tizen-internal.h +++ b/c/include/nnstreamer-tizen-internal.h @@ -48,7 +48,7 @@ typedef enum { ML_SERVICE_EVENT_MODEL_REGISTERED = 0, ML_SERVICE_EVENT_PIPELINE_REGISTERED, - NNS_EDGE_EVENT_TYPE_UNKNOWN + ML_SERVICE_EVENT_UNKNOWN } ml_service_event_e; /** diff --git a/c/src/ml-api-service-agent-client.c b/c/src/ml-api-service-agent-client.c index f14156f..1f2ac6e 100644 --- a/c/src/ml-api-service-agent-client.c +++ b/c/src/ml-api-service-agent-client.c @@ -395,31 +395,28 @@ ml_service_launch_pipeline (const char *name, ml_service_h * handle) } *handle = NULL; - mls = g_try_new0 (ml_service_s, 1); + mls = _ml_service_create_internal (ML_SERVICE_TYPE_SERVER_PIPELINE); if (mls == NULL) { _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, "Failed to allocate memory for the service handle. Out of memory?"); } - server = g_try_new0 (_ml_service_server_s, 1); + mls->priv = server = g_try_new0 (_ml_service_server_s, 1); if (server == NULL) { - g_free (mls); + _ml_service_destroy_internal (mls); _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, "Failed to allocate memory for the service handle's private data. Out of memory?"); } ret = ml_agent_pipeline_launch (name, &(server->id), &err); if (ret < 0) { - g_free (server); - g_free (mls); - _ml_error_report ("Failed to invoke the method launch_pipeline (%s).", + _ml_service_destroy_internal (mls); + _ml_error_report_return (ret, + "Failed to invoke the method launch_pipeline (%s).", (err ? err->message : "Unknown error")); - return ret; } server->service_name = g_strdup (name); - mls->type = ML_SERVICE_TYPE_SERVER_PIPELINE; - mls->priv = server; *handle = mls; return ML_ERROR_NONE; @@ -432,18 +429,17 @@ int ml_service_start_pipeline (ml_service_h handle) { int ret = ML_ERROR_NONE; - ml_service_s *mls; + ml_service_s *mls = (ml_service_s *) handle; _ml_service_server_s *server; g_autoptr (GError) err = NULL; check_feature_state (ML_FEATURE_SERVICE); - if (!handle) { + if (!_ml_service_handle_is_valid (mls)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h."); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); } - mls = (ml_service_s *) handle; server = (_ml_service_server_s *) mls->priv; ret = ml_agent_pipeline_start (server->id, &err); if (ret < 0) { @@ -461,18 +457,17 @@ int ml_service_stop_pipeline (ml_service_h handle) { int ret = ML_ERROR_NONE; - ml_service_s *mls; + ml_service_s *mls = (ml_service_s *) handle; _ml_service_server_s *server; g_autoptr (GError) err = NULL; check_feature_state (ML_FEATURE_SERVICE); - if (!handle) { + if (!_ml_service_handle_is_valid (mls)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h."); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); } - mls = (ml_service_s *) handle; server = (_ml_service_server_s *) mls->priv; ret = ml_agent_pipeline_stop (server->id, &err); if (ret < 0) { @@ -491,7 +486,7 @@ ml_service_get_pipeline_state (ml_service_h handle, ml_pipeline_state_e * state) { int ret = ML_ERROR_NONE; gint _state = ML_PIPELINE_STATE_UNKNOWN; - ml_service_s *mls; + ml_service_s *mls = (ml_service_s *) handle; _ml_service_server_s *server; g_autoptr (GError) err = NULL; @@ -503,11 +498,11 @@ ml_service_get_pipeline_state (ml_service_h handle, ml_pipeline_state_e * state) } *state = ML_PIPELINE_STATE_UNKNOWN; - if (!handle) { + if (!_ml_service_handle_is_valid (mls)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h."); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); } - mls = (ml_service_s *) handle; + server = (_ml_service_server_s *) mls->priv; ret = ml_agent_pipeline_get_state (server->id, &_state, &err); if (ret < 0) { @@ -523,17 +518,23 @@ ml_service_get_pipeline_state (ml_service_h handle, ml_pipeline_state_e * state) * @brief Internal function to release ml-service pipeline data. */ int -ml_service_pipeline_release_internal (void *priv) +ml_service_pipeline_release_internal (ml_service_s * mls) { - _ml_service_server_s *server = (_ml_service_server_s *) priv; + _ml_service_server_s *server = (_ml_service_server_s *) mls->priv; g_autoptr (GError) err = NULL; int ret; - ret = ml_agent_pipeline_destroy (server->id, &err); - if (ret < 0) { - _ml_error_report_return (ret, - "Failed to invoke the method destroy_pipeline (%s).", - err ? err->message : "Unknown error"); + /* Supposed internal function call to release handle. */ + if (!server) + return ML_ERROR_NONE; + + if (server->id > 0) { + ret = ml_agent_pipeline_destroy (server->id, &err); + if (ret < 0) { + _ml_error_report_return (ret, + "Failed to invoke the method destroy_pipeline (%s).", + err ? err->message : "Unknown error"); + } } g_free (server->service_name); diff --git a/c/src/ml-api-service-common.c b/c/src/ml-api-service-common.c index 9e81c71..da85c95 100644 --- a/c/src/ml-api-service-common.c +++ b/c/src/ml-api-service-common.c @@ -13,37 +13,86 @@ #include "ml-api-service.h" #include "ml-api-service-private.h" +#define ML_SERVICE_MAGIC 0xfeeedeed +#define ML_SERVICE_MAGIC_DEAD 0xdeaddead + /** - * @brief Destroy the service handle. + * @brief Internal function to validate ml-service handle. + */ +gboolean +_ml_service_handle_is_valid (ml_service_s * mls) +{ + if (!mls) + return FALSE; + + if (mls->magic != ML_SERVICE_MAGIC) + return FALSE; + + return TRUE; +} + +/** + * @brief Internal function to create new ml-service handle. + */ +ml_service_s * +_ml_service_create_internal (ml_service_type_e ml_service_type) +{ + ml_service_s *mls; + + mls = g_try_new0 (ml_service_s, 1); + if (mls) { + mls->magic = ML_SERVICE_MAGIC; + mls->type = ml_service_type; + } + + return mls; +} + +/** + * @brief Internal function to release ml-service handle. */ int -ml_service_destroy (ml_service_h handle) +_ml_service_destroy_internal (ml_service_s * mls) { int ret = ML_ERROR_NONE; - ml_service_s *mls = (ml_service_s *) handle; - - check_feature_state (ML_FEATURE_SERVICE); - if (!handle) + if (!_ml_service_handle_is_valid (mls)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h."); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); + } switch (mls->type) { case ML_SERVICE_TYPE_SERVER_PIPELINE: - ret = ml_service_pipeline_release_internal (mls->priv); + ret = ml_service_pipeline_release_internal (mls); break; case ML_SERVICE_TYPE_CLIENT_QUERY: - ret = ml_service_query_release_internal (mls->priv); + ret = ml_service_query_release_internal (mls); break; case ML_SERVICE_TYPE_REMOTE: - ret = ml_service_remote_release_internal (mls->priv); + ret = ml_service_remote_release_internal (mls); break; default: _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, "Invalid type of ml_service_h."); } - if (ret == ML_ERROR_NONE) + if (ret == ML_ERROR_NONE) { + mls->magic = ML_SERVICE_MAGIC_DEAD; g_free (mls); + } else { + _ml_error_report ("Failed to release ml-service handle, internal error?"); + } + return ret; } + +/** + * @brief Destroy the service handle. + */ +int +ml_service_destroy (ml_service_h handle) +{ + check_feature_state (ML_FEATURE_SERVICE); + + return _ml_service_destroy_internal ((ml_service_s *) handle); +} diff --git a/c/src/ml-api-service-private.h b/c/src/ml-api-service-private.h index efa63e3..73d2e00 100644 --- a/c/src/ml-api-service-private.h +++ b/c/src/ml-api-service-private.h @@ -35,10 +35,11 @@ typedef enum } ml_service_type_e; /** - * @brief Structure for ml_remote_service_h + * @brief Structure for ml_service_h */ typedef struct { + uint32_t magic; ml_service_type_e type; void *priv; @@ -54,20 +55,35 @@ typedef struct } _ml_service_server_s; /** + * @brief Internal function to validate ml-service handle. + */ +gboolean _ml_service_handle_is_valid (ml_service_s * mls); + +/** + * @brief Internal function to create new ml-service handle. + */ +ml_service_s * _ml_service_create_internal (ml_service_type_e ml_service_type); + +/** + * @brief Internal function to release ml-service handle. + */ +int _ml_service_destroy_internal (ml_service_s * mls); + +/** * @brief Internal function to release ml-service pipeline data. */ -int ml_service_pipeline_release_internal (void *priv); +int ml_service_pipeline_release_internal (ml_service_s * mls); /** * @brief Internal function to release ml-service query data. */ -int ml_service_query_release_internal (void *priv); +int ml_service_query_release_internal (ml_service_s * mls); #if defined(ENABLE_REMOTE_SERVICE) /** * @brief Internal function to release ml-service remote data. */ -int ml_service_remote_release_internal (void *priv); +int ml_service_remote_release_internal (ml_service_s * mls); #else #define ml_service_remote_release_internal(...) ML_ERROR_NOT_SUPPORTED #endif diff --git a/c/src/ml-api-service-query-client.c b/c/src/ml-api-service-query-client.c index ddf970f..fe74054 100644 --- a/c/src/ml-api-service-query-client.c +++ b/c/src/ml-api-service-query-client.c @@ -59,28 +59,28 @@ _sink_callback_for_query_client (const ml_tensors_data_h data, * @brief Internal function to release ml-service query data. */ int -ml_service_query_release_internal (void *priv) +ml_service_query_release_internal (ml_service_s * mls) { - _ml_service_query_s *query = (_ml_service_query_s *) priv; + _ml_service_query_s *query = (_ml_service_query_s *) mls->priv; ml_tensors_data_h data_h; + /* Supposed internal function call to release handle. */ if (!query) - return ML_ERROR_INVALID_PARAMETER; + return ML_ERROR_NONE; - if (ml_pipeline_src_release_handle (query->src_h)) - _ml_error_report ("Failed to release src handle"); - - if (ml_pipeline_sink_unregister (query->sink_h)) - _ml_error_report ("Failed to unregister sink handle"); + if (query->pipe_h) { + if (ml_pipeline_destroy (query->pipe_h)) + _ml_error_report ("Failed to destroy pipeline"); + } - if (ml_pipeline_destroy (query->pipe_h)) - _ml_error_report ("Failed to destroy pipeline"); + if (query->out_data_queue) { + while ((data_h = g_async_queue_try_pop (query->out_data_queue))) { + ml_tensors_data_destroy (data_h); + } - while ((data_h = g_async_queue_try_pop (query->out_data_queue))) { - ml_tensors_data_destroy (data_h); + g_async_queue_unref (query->out_data_queue); } - g_async_queue_unref (query->out_data_queue); g_free (query); return ML_ERROR_NONE; @@ -94,11 +94,11 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) { int status = ML_ERROR_NONE; - gchar *description = NULL; + g_autofree gchar *description = NULL; void *value; GString *tensor_query_client_prop; - gchar *prop = NULL; + g_autofree gchar *prop = NULL; ml_service_s *mls; @@ -106,7 +106,7 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) ml_pipeline_h pipe_h; ml_pipeline_src_h src_h; ml_pipeline_sink_h sink_h; - gchar *caps = NULL; + g_autofree gchar *caps = NULL; guint timeout = 1000U; /* default 1s timeout */ check_feature_state (ML_FEATURE_SERVICE); @@ -122,6 +122,19 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid ml_service_h."); } + mls = _ml_service_create_internal (ML_SERVICE_TYPE_CLIENT_QUERY); + if (mls == NULL) { + _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, + "Failed to allocate memory for the service handle. Out of memory?"); + } + + mls->priv = query_s = g_try_new0 (_ml_service_query_s, 1); + if (query_s == NULL) { + _ml_service_destroy_internal (mls); + _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, + "Failed to allocate memory for the service handle's private data. Out of memory?"); + } + tensor_query_client_prop = g_string_new (NULL); if (ML_ERROR_NONE == ml_option_get (option, "host", &value)) @@ -154,6 +167,7 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) if (ML_ERROR_NONE != ml_option_get (option, "caps", &value)) { g_string_free (tensor_query_client_prop, TRUE); + _ml_service_destroy_internal (mls); _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, "The option 'caps' must be set before call ml_service_query_create."); } @@ -165,34 +179,31 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) ("appsrc name=srcx caps=%s ! tensor_query_client %s name=qcx ! tensor_sink name=sinkx async=false sync=false", caps, prop); - g_free (caps); - g_free (prop); - status = ml_pipeline_construct (description, NULL, NULL, &pipe_h); - g_free (description); if (ML_ERROR_NONE != status) { + _ml_service_destroy_internal (mls); _ml_error_report_return (status, "Failed to construct pipeline"); } status = ml_pipeline_start (pipe_h); if (ML_ERROR_NONE != status) { - _ml_error_report ("Failed to start pipeline"); ml_pipeline_destroy (pipe_h); - return status; + _ml_service_destroy_internal (mls); + _ml_error_report_return (status, "Failed to start pipeline"); } status = ml_pipeline_src_get_handle (pipe_h, "srcx", &src_h); if (ML_ERROR_NONE != status) { ml_pipeline_destroy (pipe_h); + _ml_service_destroy_internal (mls); _ml_error_report_return (status, "Failed to get src handle"); } - query_s = g_new0 (_ml_service_query_s, 1); status = ml_pipeline_sink_register (pipe_h, "sinkx", _sink_callback_for_query_client, query_s, &sink_h); if (ML_ERROR_NONE != status) { ml_pipeline_destroy (pipe_h); - g_free (query_s); + _ml_service_destroy_internal (mls); _ml_error_report_return (status, "Failed to register sink handle"); } @@ -202,10 +213,6 @@ ml_service_query_create (ml_option_h option, ml_service_h * handle) query_s->sink_h = sink_h; query_s->out_data_queue = g_async_queue_new (); - mls = g_new0 (ml_service_s, 1); - mls->type = ML_SERVICE_TYPE_CLIENT_QUERY; - mls->priv = query_s; - *handle = mls; return ML_ERROR_NONE; @@ -225,9 +232,9 @@ ml_service_query_request (ml_service_h handle, const ml_tensors_data_h input, check_feature_state (ML_FEATURE_SERVICE); check_feature_state (ML_FEATURE_INFERENCE); - if (!handle) + if (!_ml_service_handle_is_valid (mls)) _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h"); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); if (!input) _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, "The parameter, 'input' (ml_tensors_data_h), is NULL. It should be a valid ml_tensors_data_h."); diff --git a/c/src/ml-api-service-remote.c b/c/src/ml-api-service-remote.c index c5c40ec..b91407b 100644 --- a/c/src/ml-api-service-remote.c +++ b/c/src/ml-api-service-remote.c @@ -121,32 +121,35 @@ _mlrs_get_conn_type (const gchar * value) * @brief Get edge info from ml_option. */ static void -_mlrs_get_edge_info (ml_option_h option, edge_info_s * edge_info) +_mlrs_get_edge_info (ml_option_h option, edge_info_s ** edge_info) { + edge_info_s *_info; void *value; - if (ML_ERROR_NONE == ml_option_get (option, "host", &value)) { - g_free (edge_info->host); - edge_info->host = g_strdup (value); - } + *edge_info = _info = g_new0 (edge_info_s, 1); + + if (ML_ERROR_NONE == ml_option_get (option, "host", &value)) + _info->host = g_strdup (value); + else + _info->host = g_strdup ("localhost"); if (ML_ERROR_NONE == ml_option_get (option, "port", &value)) - edge_info->port = *((guint *) value); - if (ML_ERROR_NONE == ml_option_get (option, "dest-host", &value)) { - g_free (edge_info->dest_host); - edge_info->dest_host = g_strdup (value); - } + _info->port = *((guint *) value); + if (ML_ERROR_NONE == ml_option_get (option, "dest-host", &value)) + _info->dest_host = g_strdup (value); + else + _info->dest_host = g_strdup ("localhost"); if (ML_ERROR_NONE == ml_option_get (option, "dest-port", &value)) - edge_info->dest_port = *((guint *) value); + _info->dest_port = *((guint *) value); if (ML_ERROR_NONE == ml_option_get (option, "connect-type", &value)) - edge_info->conn_type = _mlrs_get_conn_type (value); + _info->conn_type = _mlrs_get_conn_type (value); + else + _info->conn_type = NNS_EDGE_CONNECT_TYPE_UNKNOWN; if (ML_ERROR_NONE == ml_option_get (option, "topic", &value)) - edge_info->topic = g_strdup (value); + _info->topic = g_strdup (value); if (ML_ERROR_NONE == ml_option_get (option, "node-type", &value)) - edge_info->node_type = _mlrs_get_node_type (value); - if (ML_ERROR_NONE == ml_option_get (option, "id", &value)) { - g_free (edge_info->id); - edge_info->id = g_strdup (value); - } + _info->node_type = _mlrs_get_node_type (value); + if (ML_ERROR_NONE == ml_option_get (option, "id", &value)) + _info->id = g_strdup (value); } /** @@ -179,6 +182,7 @@ _mlrs_release_edge_info (edge_info_s * edge_info) g_free (edge_info->host); g_free (edge_info->topic); g_free (edge_info->id); + g_free (edge_info); } /** @@ -359,7 +363,7 @@ _mlrs_process_remote_service (nns_edge_data_h data_h, void *user_data) ml_remote_service_type_e service_type; int ret = NNS_EDGE_ERROR_NONE; _ml_remote_service_s *remote_s = (_ml_remote_service_s *) user_data; - ml_service_event_e event_type = NNS_EDGE_EVENT_TYPE_UNKNOWN; + ml_service_event_e event_type = ML_SERVICE_EVENT_UNKNOWN; ret = nns_edge_data_get (data_h, 0, &data, &data_len); if (NNS_EDGE_ERROR_NONE != ret) { @@ -455,7 +459,7 @@ _mlrs_process_remote_service (nns_edge_data_h data_h, void *user_data) break; } - if (remote_s && event_type != NNS_EDGE_EVENT_TYPE_UNKNOWN) { + if (remote_s && event_type != ML_SERVICE_EVENT_UNKNOWN) { if (remote_s->event_cb) { remote_s->event_cb (event_type, remote_s->user_data); } @@ -549,17 +553,21 @@ _mlrs_create_edge_handle (_ml_remote_service_s * remote_s, * @brief Internal function to release ml-service remote data. */ int -ml_service_remote_release_internal (void *priv) +ml_service_remote_release_internal (ml_service_s * mls) { - _ml_remote_service_s *mlrs = (_ml_remote_service_s *) priv; + _ml_remote_service_s *mlrs = (_ml_remote_service_s *) mls->priv; + /* Supposed internal function call to release handle. */ if (!mlrs) - return ML_ERROR_INVALID_PARAMETER; + return ML_ERROR_NONE; - nns_edge_release_handle (mlrs->edge_h); + if (mlrs->edge_h) { + nns_edge_release_handle (mlrs->edge_h); + + /* Wait some time until release the edge handle. */ + g_usleep (1000000); + } - /* Wait some time until release the edge handle. */ - g_usleep (1000000); g_free (mlrs->path); g_free (mlrs); @@ -574,8 +582,8 @@ ml_service_remote_create (ml_option_h option, ml_service_event_cb cb, void *user_data, ml_service_h * handle) { ml_service_s *mls; - g_autofree _ml_remote_service_s *remote_s = NULL; - g_autofree edge_info_s *edge_info = NULL; + _ml_remote_service_s *remote_s = NULL; + edge_info_s *edge_info = NULL; int ret = ML_ERROR_NONE; gchar *_path = NULL; @@ -592,21 +600,6 @@ ml_service_remote_create (ml_option_h option, ml_service_event_cb cb, "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid ml_service_h."); } - edge_info = g_new0 (edge_info_s, 1); - edge_info->topic = NULL; - edge_info->host = g_strdup ("localhost"); - edge_info->port = 0; - edge_info->dest_host = g_strdup ("localhost"); - edge_info->dest_port = 0; - edge_info->conn_type = NNS_EDGE_CONNECT_TYPE_UNKNOWN; - edge_info->id = NULL; - - _mlrs_get_edge_info (option, edge_info); - - remote_s = g_new0 (_ml_remote_service_s, 1); - remote_s->node_type = edge_info->node_type; - remote_s->event_cb = cb; - remote_s->user_data = user_data; if (ML_ERROR_NONE == ml_option_get (option, "path", (void **) (&_path))) { if (!g_file_test (_path, G_FILE_TEST_IS_DIR)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, @@ -617,23 +610,37 @@ ml_service_remote_create (ml_option_h option, ml_service_event_cb cb, _ml_error_report_return (ML_ERROR_PERMISSION_DENIED, "Write permission denied, path: %s", _path); } - remote_s->path = g_strdup (_path); } - ret = _mlrs_create_edge_handle (remote_s, edge_info); - if (ML_ERROR_NONE != ret) { - return ret; + mls = _ml_service_create_internal (ML_SERVICE_TYPE_REMOTE); + if (mls == NULL) { + _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, + "Failed to allocate memory for the service handle. Out of memory?"); } - mls = g_new0 (ml_service_s, 1); - mls->type = ML_SERVICE_TYPE_REMOTE; - mls->priv = g_steal_pointer (&remote_s); + mls->priv = remote_s = g_try_new0 (_ml_remote_service_s, 1); + if (remote_s == NULL) { + _ml_service_destroy_internal (mls); + _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY, + "Failed to allocate memory for the service handle's private data. Out of memory?"); + } + + _mlrs_get_edge_info (option, &edge_info); + + remote_s->node_type = edge_info->node_type; + remote_s->event_cb = cb; + remote_s->user_data = user_data; + remote_s->path = g_strdup (_path); - *handle = mls; + ret = _mlrs_create_edge_handle (remote_s, edge_info); + if (ret != ML_ERROR_NONE) + _ml_service_destroy_internal (mls); + else + *handle = mls; _mlrs_release_edge_info (edge_info); - return ML_ERROR_NONE; + return ret; } /** @@ -656,9 +663,9 @@ ml_service_remote_register (ml_service_h handle, ml_option_h option, void *data, check_feature_state (ML_FEATURE_SERVICE); check_feature_state (ML_FEATURE_INFERENCE); - if (!handle) { + if (!_ml_service_handle_is_valid (mls)) { _ml_error_report_return (ML_ERROR_INVALID_PARAMETER, - "The parameter, 'handle' is NULL. It should be a valid ml_service_h."); + "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance."); } if (!option) { diff --git a/tests/capi/unittest_capi_service_agent_client.cc b/tests/capi/unittest_capi_service_agent_client.cc index 02c1896..bcd2970 100644 --- a/tests/capi/unittest_capi_service_agent_client.cc +++ b/tests/capi/unittest_capi_service_agent_client.cc @@ -500,19 +500,17 @@ TEST_F (MLServiceAgentTest, destroy_00_n) TEST_F (MLServiceAgentTest, destroy_01_n) { int status; - ml_service_h h; + ml_service_s *mls = _ml_service_create_internal (ML_SERVICE_TYPE_SERVER_PIPELINE); + ASSERT_TRUE (mls != NULL); - ml_service_s *mls = g_new0 (ml_service_s, 1); - _ml_service_server_s *server = g_new0 (_ml_service_server_s, 1); - mls->priv = server; + /* invalid type */ mls->type = ML_SERVICE_TYPE_MAX; - - h = (ml_service_h) mls; - status = ml_service_destroy (h); + status = ml_service_destroy ((ml_service_h) mls); EXPECT_EQ (ML_ERROR_INVALID_PARAMETER, status); - g_free (server); - g_free (mls); + mls->type = ML_SERVICE_TYPE_SERVER_PIPELINE; + status = ml_service_destroy ((ml_service_h) mls); + EXPECT_EQ (ML_ERROR_NONE, status); } /** @@ -532,7 +530,7 @@ TEST_F (MLServiceAgentTest, explicit_invalid_handle_00_n) ml_service_s *mls = (ml_service_s *) h; _ml_service_server_s *server = (_ml_service_server_s *) mls->priv; gint64 _id = server->id; - server->id = -987654321; /* explicitly set id as invalid number */ + server->id = 1; /* explicitly set id as invalid number */ status = ml_service_start_pipeline (h); EXPECT_EQ (ML_ERROR_INVALID_PARAMETER, status); @@ -1505,11 +1503,12 @@ TEST (MLServiceAgentTestDbusUnconnected, pipeline_n) status = ml_service_launch_pipeline ("test", &service); EXPECT_EQ (ML_ERROR_IO_ERROR, status); - ml_service_s *mls = g_new0 (ml_service_s, 1); + ml_service_s *mls = _ml_service_create_internal (ML_SERVICE_TYPE_SERVER_PIPELINE); + ASSERT_TRUE (mls != NULL); _ml_service_server_s *server = g_new0 (_ml_service_server_s, 1); mls->priv = server; - server->id = -987654321; /* explicitly set id as invalid number */ + server->id = 1; /* explicitly set id as invalid number */ service = (ml_service_h) mls; status = ml_service_start_pipeline (service); @@ -1522,12 +1521,10 @@ TEST (MLServiceAgentTestDbusUnconnected, pipeline_n) status = ml_service_get_pipeline_state (service, &state); EXPECT_EQ (ML_ERROR_IO_ERROR, status); - mls->type = ML_SERVICE_TYPE_SERVER_PIPELINE; status = ml_service_destroy (service); EXPECT_EQ (ML_ERROR_IO_ERROR, status); - g_free (server); - g_free (mls); + _ml_service_destroy_internal (mls); } /** -- 2.7.4