LCOV - code coverage report
Current view: top level - capi-machine-learning-inference-1.8.8/c/src - ml-api-service.c (source / functions) Coverage Total Hit
Test: ML API 1.8.8-0 platform/core/api/machine-learning#e7fedae8956bcd2b3c627ecaa01984707296bbdb Lines: 0.0 % 418 0
Test Date: 2026-04-30 21:49:05 Functions: 0.0 % 23 0

            Line data    Source code
       1              : /* SPDX-License-Identifier: Apache-2.0 */
       2              : /**
       3              :  * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
       4              :  *
       5              :  * @file ml-api-service.c
       6              :  * @date 31 Aug 2022
       7              :  * @brief Some implementation of NNStreamer/Service C-API
       8              :  * @see https://github.com/nnstreamer/nnstreamer
       9              :  * @author Yongjoo Ahn <yongjoo1.ahn@samsung.com>
      10              :  * @bug No known bugs except for NYI items
      11              :  */
      12              : 
      13              : #include <nnstreamer_plugin_api_util.h>
      14              : 
      15              : #include "ml-api-service.h"
      16              : #include "ml-api-service-extension.h"
      17              : #include "ml-api-service-offloading.h"
      18              : #include "ml-api-service-query.h"
      19              : 
      20              : #define ML_SERVICE_MAGIC 0xfeeedeed
      21              : #define ML_SERVICE_MAGIC_DEAD 0xdeaddead
      22              : 
      23              : /**
      24              :  * @brief Internal function to validate ml-service handle.
      25              :  */
      26              : gboolean
      27            0 : _ml_service_handle_is_valid (ml_service_s * mls)
      28              : {
      29            0 :   if (!mls)
      30            0 :     return FALSE;
      31              : 
      32            0 :   if (mls->magic != ML_SERVICE_MAGIC)
      33            0 :     return FALSE;
      34              : 
      35            0 :   switch (mls->type) {
      36            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
      37              :     case ML_SERVICE_TYPE_CLIENT_QUERY:
      38              :     case ML_SERVICE_TYPE_OFFLOADING:
      39              :     case ML_SERVICE_TYPE_EXTENSION:
      40            0 :       if (mls->priv == NULL)
      41            0 :         return FALSE;
      42            0 :       break;
      43            0 :     default:
      44              :       /* Invalid handle type. */
      45            0 :       return FALSE;
      46              :   }
      47              : 
      48            0 :   return TRUE;
      49              : }
      50              : 
      51              : /**
      52              :  * @brief Internal function to set information.
      53              :  */
      54              : static int
      55            0 : _ml_service_set_information_internal (ml_service_s * mls, const char *name,
      56              :     const char *value)
      57              : {
      58            0 :   int status = ML_ERROR_NONE;
      59              : 
      60              :   /* Prevent empty string case. */
      61            0 :   if (!STR_IS_VALID (name) || !STR_IS_VALID (value))
      62            0 :     return ML_ERROR_INVALID_PARAMETER;
      63              : 
      64            0 :   status = ml_option_set (mls->information, name, g_strdup (value), g_free);
      65            0 :   if (status != ML_ERROR_NONE)
      66            0 :     return status;
      67              : 
      68            0 :   switch (mls->type) {
      69            0 :     case ML_SERVICE_TYPE_EXTENSION:
      70            0 :       status = _ml_service_extension_set_information (mls, name, value);
      71            0 :       break;
      72            0 :     case ML_SERVICE_TYPE_OFFLOADING:
      73            0 :       status = _ml_service_offloading_set_information (mls, name, value);
      74            0 :       break;
      75            0 :     default:
      76            0 :       break;
      77              :   }
      78              : 
      79            0 :   return status;
      80              : }
      81              : 
      82              : /**
      83              :  * @brief Internal function to create new ml-service handle.
      84              :  */
      85              : ml_service_s *
      86            0 : _ml_service_create_internal (ml_service_type_e ml_service_type)
      87              : {
      88              :   ml_service_s *mls;
      89              :   int status;
      90              : 
      91            0 :   mls = g_try_new0 (ml_service_s, 1);
      92            0 :   if (mls) {
      93            0 :     status = ml_option_create (&mls->information);
      94            0 :     if (status != ML_ERROR_NONE) {
      95            0 :       g_free (mls);
      96            0 :       _ml_error_report_return (NULL,
      97              :           "Failed to create ml-option handle in ml-service.");
      98              :     }
      99              : 
     100            0 :     mls->magic = ML_SERVICE_MAGIC;
     101            0 :     mls->type = ml_service_type;
     102            0 :     g_mutex_init (&mls->lock);
     103            0 :     g_cond_init (&mls->cond);
     104              :   }
     105              : 
     106            0 :   return mls;
     107              : }
     108              : 
     109              : /**
     110              :  * @brief Internal function to release ml-service handle.
     111              :  */
     112              : int
     113            0 : _ml_service_destroy_internal (ml_service_s * mls)
     114              : {
     115              :   ml_service_event_cb_info_s old_cb;
     116            0 :   int status = ML_ERROR_NONE;
     117              : 
     118            0 :   if (!mls) {
     119              :     /* Internal error? */
     120            0 :     return ML_ERROR_INVALID_PARAMETER;
     121              :   }
     122              : 
     123              :   /* Clear callback before closing internal handles. */
     124            0 :   g_mutex_lock (&mls->lock);
     125            0 :   old_cb = mls->cb_info;
     126            0 :   memset (&mls->cb_info, 0, sizeof (ml_service_event_cb_info_s));
     127            0 :   g_mutex_unlock (&mls->lock);
     128              : 
     129            0 :   switch (mls->type) {
     130            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
     131            0 :       status = _ml_service_pipeline_release_internal (mls);
     132            0 :       break;
     133            0 :     case ML_SERVICE_TYPE_CLIENT_QUERY:
     134            0 :       status = _ml_service_query_release_internal (mls);
     135            0 :       break;
     136            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     137            0 :       status = _ml_service_offloading_release_internal (mls);
     138            0 :       break;
     139            0 :     case ML_SERVICE_TYPE_EXTENSION:
     140            0 :       status = _ml_service_extension_destroy (mls);
     141            0 :       break;
     142            0 :     default:
     143            0 :       _ml_error_report ("Invalid type of ml_service_h.");
     144            0 :       status = ML_ERROR_INVALID_PARAMETER;
     145            0 :       break;
     146              :   }
     147              : 
     148            0 :   if (status == ML_ERROR_NONE) {
     149            0 :     mls->magic = ML_SERVICE_MAGIC_DEAD;
     150            0 :     ml_option_destroy (mls->information);
     151              : 
     152            0 :     g_cond_clear (&mls->cond);
     153            0 :     g_mutex_clear (&mls->lock);
     154            0 :     g_free (mls);
     155              :   } else {
     156            0 :     _ml_error_report ("Failed to release ml-service handle, internal error?");
     157              : 
     158            0 :     g_mutex_lock (&mls->lock);
     159            0 :     mls->cb_info = old_cb;
     160            0 :     g_mutex_unlock (&mls->lock);
     161              :   }
     162              : 
     163            0 :   return status;
     164              : }
     165              : 
     166              : /**
     167              :  * @brief Internal function to get ml-service event callback.
     168              :  */
     169              : void
     170            0 : _ml_service_get_event_cb_info (ml_service_s * mls,
     171              :     ml_service_event_cb_info_s * cb_info)
     172              : {
     173            0 :   if (!mls || !cb_info)
     174            0 :     return;
     175              : 
     176            0 :   g_mutex_lock (&mls->lock);
     177            0 :   *cb_info = mls->cb_info;
     178            0 :   g_mutex_unlock (&mls->lock);
     179              : }
     180              : 
     181              : /**
     182              :  * @brief Internal function to parse string value from json.
     183              :  */
     184              : int
     185            0 : _ml_service_conf_parse_string (JsonNode * str_node, const gchar * delimiter,
     186              :     gchar ** str)
     187              : {
     188              :   guint i, n;
     189              : 
     190            0 :   if (!str_node || !delimiter || !str)
     191            0 :     return ML_ERROR_INVALID_PARAMETER;
     192              : 
     193            0 :   *str = NULL;
     194              : 
     195            0 :   if (JSON_NODE_HOLDS_ARRAY (str_node)) {
     196            0 :     JsonArray *array = json_node_get_array (str_node);
     197            0 :     GString *val = g_string_new (NULL);
     198              : 
     199            0 :     n = (array) ? json_array_get_length (array) : 0U;
     200            0 :     for (i = 0; i < n; i++) {
     201            0 :       const gchar *p = json_array_get_string_element (array, i);
     202              : 
     203              :       g_string_append (val, p);
     204            0 :       if (i < n - 1)
     205              :         g_string_append (val, delimiter);
     206              :     }
     207              : 
     208            0 :     *str = g_string_free (val, FALSE);
     209              :   } else {
     210            0 :     *str = g_strdup (json_node_get_string (str_node));
     211              :   }
     212              : 
     213            0 :   return (*str != NULL) ? ML_ERROR_NONE : ML_ERROR_INVALID_PARAMETER;
     214              : }
     215              : 
     216              : /**
     217              :  * @brief Internal function to parse tensors-info from json.
     218              :  */
     219              : int
     220            0 : _ml_service_conf_parse_tensors_info (JsonNode * info_node,
     221              :     ml_tensors_info_h * info_h)
     222              : {
     223            0 :   JsonArray *array = NULL;
     224              :   JsonObject *object;
     225              :   GstTensorsInfo info;
     226              :   GstTensorInfo *_info;
     227              :   const gchar *_str;
     228              :   guint i;
     229              :   int status;
     230              : 
     231            0 :   if (!info_node || !info_h)
     232            0 :     return ML_ERROR_INVALID_PARAMETER;
     233              : 
     234            0 :   gst_tensors_info_init (&info);
     235              : 
     236            0 :   info.num_tensors = 1;
     237            0 :   if (JSON_NODE_HOLDS_ARRAY (info_node)) {
     238            0 :     array = json_node_get_array (info_node);
     239            0 :     info.num_tensors = json_array_get_length (array);
     240              : 
     241            0 :     if (info.num_tensors > NNS_TENSOR_SIZE_LIMIT) {
     242            0 :       _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     243              :           "The array length of json for tensor information (%u) exceeds the max limit.",
     244              :           info.num_tensors);
     245              :     }
     246              :   }
     247              : 
     248            0 :   for (i = 0; i < info.num_tensors; i++) {
     249            0 :     _info = gst_tensors_info_get_nth_info (&info, i);
     250              : 
     251            0 :     if (array)
     252            0 :       object = json_array_get_object_element (array, i);
     253              :     else
     254            0 :       object = json_node_get_object (info_node);
     255              : 
     256            0 :     if (json_object_has_member (object, "type")) {
     257            0 :       _str = json_object_get_string_member (object, "type");
     258              : 
     259            0 :       if (STR_IS_VALID (_str))
     260            0 :         _info->type = gst_tensor_get_type (_str);
     261              :     }
     262              : 
     263            0 :     if (json_object_has_member (object, "dimension")) {
     264            0 :       _str = json_object_get_string_member (object, "dimension");
     265              : 
     266            0 :       if (STR_IS_VALID (_str))
     267            0 :         gst_tensor_parse_dimension (_str, _info->dimension);
     268              :     }
     269              : 
     270            0 :     if (json_object_has_member (object, "name")) {
     271            0 :       _str = json_object_get_string_member (object, "name");
     272              : 
     273            0 :       if (STR_IS_VALID (_str))
     274            0 :         _info->name = g_strdup (_str);
     275              :     }
     276              :   }
     277              : 
     278            0 :   if (gst_tensors_info_validate (&info))
     279            0 :     status = _ml_tensors_info_create_from_gst (info_h, &info);
     280              :   else
     281            0 :     status = ML_ERROR_INVALID_PARAMETER;
     282              : 
     283            0 :   gst_tensors_info_free (&info);
     284            0 :   return status;
     285              : }
     286              : 
     287              : /**
     288              :  * @brief Internal function to get ml-service type.
     289              :  */
     290              : static ml_service_type_e
     291            0 : _ml_service_get_type (JsonObject * object)
     292              : {
     293            0 :   ml_service_type_e type = ML_SERVICE_TYPE_UNKNOWN;
     294              : 
     295              :   /** @todo add more services such as training offloading, offloading service */
     296            0 :   if (json_object_has_member (object, "single") ||
     297            0 :       json_object_has_member (object, "pipeline")) {
     298            0 :     type = ML_SERVICE_TYPE_EXTENSION;
     299            0 :   } else if (json_object_has_member (object, "offloading")) {
     300            0 :     type = ML_SERVICE_TYPE_OFFLOADING;
     301              :   }
     302              : 
     303            0 :   return type;
     304              : }
     305              : 
     306              : /**
     307              :  * @brief Creates a handle for machine learning service with configuration.
     308              :  */
     309              : int
     310            0 : ml_service_new (const char *config, ml_service_h * handle)
     311              : {
     312              :   ml_service_s *mls;
     313            0 :   ml_service_type_e service_type = ML_SERVICE_TYPE_UNKNOWN;
     314            0 :   g_autofree gchar *json_string = NULL;
     315            0 :   g_autofree gchar *contents = NULL;
     316            0 :   g_autoptr (JsonParser) parser = NULL;
     317            0 :   g_autoptr (GError) err = NULL;
     318              :   JsonNode *root;
     319              :   JsonObject *object;
     320              :   int status;
     321              : 
     322            0 :   check_feature_state (ML_FEATURE_SERVICE);
     323              : 
     324            0 :   if (!handle) {
     325            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     326              :         "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid pointer to create new instance.");
     327              :   }
     328              : 
     329              :   /* Init null. */
     330            0 :   *handle = NULL;
     331              : 
     332            0 :   if (!STR_IS_VALID (config) ||
     333            0 :       !g_file_test (config, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
     334            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     335              :         "The parameter, config, is invalid. It should be a valid path.");
     336              :   }
     337              : 
     338            0 :   if (!g_file_get_contents (config, &contents, NULL, NULL)) {
     339            0 :     _ml_error_report_return (ML_ERROR_IO_ERROR,
     340              :         "Failed to read configuration file '%s'.", config);
     341              :   }
     342              : 
     343            0 :   json_string = _ml_convert_predefined_entity (contents);
     344              : 
     345            0 :   parser = json_parser_new ();
     346            0 :   if (!parser) {
     347            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     348              :         "Failed to parse configuration file, cannot allocate memory for JsonParser. Out of memory?");
     349              :   }
     350              : 
     351            0 :   if (!json_parser_load_from_data (parser, json_string, -1, &err)) {
     352            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     353              :         "Failed to parse configuration file. Parse error: %s",
     354              :         err ? err->message : "Unknown error");
     355              :   }
     356              : 
     357            0 :   root = json_parser_get_root (parser);
     358            0 :   if (!root) {
     359            0 :     _ml_error_report_return (ML_ERROR_IO_ERROR,
     360              :         "Failed to parse configuration file, cannot get the top node from json string.");
     361              :   }
     362              : 
     363            0 :   object = json_node_get_object (root);
     364              : 
     365            0 :   service_type = _ml_service_get_type (object);
     366            0 :   if (ML_SERVICE_TYPE_UNKNOWN == service_type) {
     367            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     368              :         "Failed to parse configuration file, cannot get the valid type from configuration.");
     369              :   }
     370              : 
     371              :   /* Parse each service type. */
     372            0 :   mls = _ml_service_create_internal (service_type);
     373            0 :   if (mls == NULL) {
     374            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     375              :         "Failed to allocate memory for the ml-service handle. Out of memory?");
     376              :   }
     377              : 
     378            0 :   switch (service_type) {
     379            0 :     case ML_SERVICE_TYPE_EXTENSION:
     380            0 :       status = _ml_service_extension_create (mls, object);
     381            0 :       break;
     382            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     383            0 :       status = _ml_service_offloading_create (mls, object);
     384            0 :       break;
     385            0 :     default:
     386              :       /* Invalid handle type. */
     387            0 :       status = ML_ERROR_NOT_SUPPORTED;
     388            0 :       break;
     389              :   }
     390              : 
     391            0 :   if (status != ML_ERROR_NONE)
     392            0 :     goto error;
     393              : 
     394              :   /* Parse information. */
     395            0 :   if (json_object_has_member (object, "information")) {
     396            0 :     JsonObject *info = json_object_get_object_member (object, "information");
     397            0 :     g_autoptr (GList) members = json_object_get_members (info);
     398              :     GList *iter;
     399              : 
     400            0 :     for (iter = members; iter; iter = g_list_next (iter)) {
     401            0 :       const gchar *name = iter->data;
     402            0 :       const gchar *value = _ml_service_get_json_string_member (info, name);
     403              : 
     404            0 :       status = _ml_service_set_information_internal (mls, name, value);
     405            0 :       if (status != ML_ERROR_NONE)
     406            0 :         goto error;
     407              :     }
     408              :   }
     409              : 
     410            0 : error:
     411            0 :   if (status == ML_ERROR_NONE) {
     412            0 :     *handle = mls;
     413              :   } else {
     414            0 :     _ml_error_report ("Failed to open the ml-service configuration.");
     415            0 :     _ml_service_destroy_internal (mls);
     416              :   }
     417              : 
     418            0 :   return status;
     419              : }
     420              : 
     421              : /**
     422              :  * @brief Sets the callbacks which will be invoked when a new event occurs from ml-service.
     423              :  */
     424              : int
     425            0 : ml_service_set_event_cb (ml_service_h handle, ml_service_event_cb cb,
     426              :     void *user_data)
     427              : {
     428            0 :   ml_service_s *mls = (ml_service_s *) handle;
     429              : 
     430            0 :   check_feature_state (ML_FEATURE_SERVICE);
     431              : 
     432            0 :   if (!_ml_service_handle_is_valid (mls)) {
     433            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     434              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     435              :   }
     436              : 
     437            0 :   g_mutex_lock (&mls->lock);
     438              : 
     439            0 :   mls->cb_info.cb = cb;
     440            0 :   mls->cb_info.pdata = user_data;
     441              : 
     442            0 :   g_mutex_unlock (&mls->lock);
     443              : 
     444            0 :   return ML_ERROR_NONE;
     445              : }
     446              : 
     447              : /**
     448              :  * @brief Starts the process of ml-service.
     449              :  */
     450              : int
     451            0 : ml_service_start (ml_service_h handle)
     452              : {
     453            0 :   ml_service_s *mls = (ml_service_s *) handle;
     454            0 :   int status = ML_ERROR_NONE;
     455              : 
     456            0 :   check_feature_state (ML_FEATURE_SERVICE);
     457              : 
     458            0 :   if (!_ml_service_handle_is_valid (mls)) {
     459            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     460              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     461              :   }
     462              : 
     463            0 :   switch (mls->type) {
     464            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
     465              :     {
     466            0 :       _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
     467              : 
     468            0 :       status = ml_agent_pipeline_start (server->id);
     469            0 :       if (status < 0)
     470            0 :         _ml_error_report ("Failed to invoke the method start_pipeline.");
     471              : 
     472            0 :       break;
     473              :     }
     474            0 :     case ML_SERVICE_TYPE_EXTENSION:
     475            0 :       status = _ml_service_extension_start (mls);
     476            0 :       break;
     477            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     478            0 :       status = _ml_service_offloading_start (mls);
     479            0 :       break;
     480            0 :     default:
     481              :       /* Invalid handle type. */
     482            0 :       status = ML_ERROR_NOT_SUPPORTED;
     483            0 :       break;
     484              :   }
     485              : 
     486            0 :   return status;
     487              : }
     488              : 
     489              : /**
     490              :  * @brief Stops the process of ml-service.
     491              :  */
     492              : int
     493            0 : ml_service_stop (ml_service_h handle)
     494              : {
     495            0 :   ml_service_s *mls = (ml_service_s *) handle;
     496            0 :   int status = ML_ERROR_NONE;
     497              : 
     498            0 :   check_feature_state (ML_FEATURE_SERVICE);
     499              : 
     500            0 :   if (!_ml_service_handle_is_valid (mls)) {
     501            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     502              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     503              :   }
     504              : 
     505            0 :   switch (mls->type) {
     506            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
     507              :     {
     508            0 :       _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
     509              : 
     510            0 :       status = ml_agent_pipeline_stop (server->id);
     511            0 :       if (status < 0)
     512            0 :         _ml_error_report ("Failed to invoke the method stop_pipeline.");
     513              : 
     514            0 :       break;
     515              :     }
     516            0 :     case ML_SERVICE_TYPE_EXTENSION:
     517            0 :       status = _ml_service_extension_stop (mls);
     518            0 :       break;
     519            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     520            0 :       status = _ml_service_offloading_stop (mls);
     521            0 :       break;
     522            0 :     default:
     523              :       /* Invalid handle type. */
     524            0 :       status = ML_ERROR_NOT_SUPPORTED;
     525            0 :       break;
     526              :   }
     527              : 
     528            0 :   return status;
     529              : }
     530              : 
     531              : /**
     532              :  * @brief Gets the information of required input data.
     533              :  */
     534              : int
     535            0 : ml_service_get_input_information (ml_service_h handle, const char *name,
     536              :     ml_tensors_info_h * info)
     537              : {
     538            0 :   ml_service_s *mls = (ml_service_s *) handle;
     539              :   int status;
     540              : 
     541            0 :   check_feature_state (ML_FEATURE_SERVICE);
     542              : 
     543            0 :   if (!_ml_service_handle_is_valid (mls)) {
     544            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     545              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     546              :   }
     547              : 
     548            0 :   if (!info) {
     549            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     550              :         "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
     551              :   }
     552              : 
     553              :   /* Init null. */
     554            0 :   *info = NULL;
     555              : 
     556            0 :   switch (mls->type) {
     557            0 :     case ML_SERVICE_TYPE_EXTENSION:
     558            0 :       status = _ml_service_extension_get_input_information (mls, name, info);
     559            0 :       break;
     560            0 :     default:
     561              :       /* Invalid handle type. */
     562            0 :       status = ML_ERROR_NOT_SUPPORTED;
     563            0 :       break;
     564              :   }
     565              : 
     566            0 :   if (status != ML_ERROR_NONE) {
     567            0 :     if (*info) {
     568            0 :       ml_tensors_info_destroy (*info);
     569            0 :       *info = NULL;
     570              :     }
     571              :   }
     572              : 
     573            0 :   return status;
     574              : }
     575              : 
     576              : /**
     577              :  * @brief Gets the information of output data.
     578              :  */
     579              : int
     580            0 : ml_service_get_output_information (ml_service_h handle, const char *name,
     581              :     ml_tensors_info_h * info)
     582              : {
     583            0 :   ml_service_s *mls = (ml_service_s *) handle;
     584              :   int status;
     585              : 
     586            0 :   check_feature_state (ML_FEATURE_SERVICE);
     587              : 
     588            0 :   if (!_ml_service_handle_is_valid (mls)) {
     589            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     590              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     591              :   }
     592              : 
     593            0 :   if (!info) {
     594            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     595              :         "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
     596              :   }
     597              : 
     598              :   /* Init null. */
     599            0 :   *info = NULL;
     600              : 
     601            0 :   switch (mls->type) {
     602            0 :     case ML_SERVICE_TYPE_EXTENSION:
     603            0 :       status = _ml_service_extension_get_output_information (mls, name, info);
     604            0 :       break;
     605            0 :     default:
     606              :       /* Invalid handle type. */
     607            0 :       status = ML_ERROR_NOT_SUPPORTED;
     608            0 :       break;
     609              :   }
     610              : 
     611            0 :   if (status != ML_ERROR_NONE) {
     612            0 :     if (*info) {
     613            0 :       ml_tensors_info_destroy (*info);
     614            0 :       *info = NULL;
     615              :     }
     616              :   }
     617              : 
     618            0 :   return status;
     619              : }
     620              : 
     621              : /**
     622              :  * @brief Sets the information for ml-service.
     623              :  */
     624              : int
     625            0 : ml_service_set_information (ml_service_h handle, const char *name,
     626              :     const char *value)
     627              : {
     628            0 :   ml_service_s *mls = (ml_service_s *) handle;
     629              :   int status;
     630              : 
     631            0 :   check_feature_state (ML_FEATURE_SERVICE);
     632              : 
     633            0 :   if (!_ml_service_handle_is_valid (mls)) {
     634            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     635              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     636              :   }
     637              : 
     638            0 :   if (!STR_IS_VALID (name)) {
     639            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     640              :         "The parameter, name '%s', is invalid.", name);
     641              :   }
     642              : 
     643            0 :   if (!STR_IS_VALID (value)) {
     644            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     645              :         "The parameter, value '%s', is invalid.", value);
     646              :   }
     647              : 
     648            0 :   g_mutex_lock (&mls->lock);
     649            0 :   status = _ml_service_set_information_internal (mls, name, value);
     650            0 :   g_mutex_unlock (&mls->lock);
     651              : 
     652            0 :   if (status != ML_ERROR_NONE) {
     653            0 :     _ml_error_report_return (status,
     654              :         "Failed to set the information '%s'.", name);
     655              :   }
     656              : 
     657            0 :   return ML_ERROR_NONE;
     658              : }
     659              : 
     660              : /**
     661              :  * @brief Gets the information from ml-service.
     662              :  */
     663              : int
     664            0 : ml_service_get_information (ml_service_h handle, const char *name, char **value)
     665              : {
     666            0 :   ml_service_s *mls = (ml_service_s *) handle;
     667            0 :   gchar *val = NULL;
     668              :   int status;
     669              : 
     670            0 :   check_feature_state (ML_FEATURE_SERVICE);
     671              : 
     672            0 :   if (!_ml_service_handle_is_valid (mls)) {
     673            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     674              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     675              :   }
     676              : 
     677            0 :   if (!STR_IS_VALID (name)) {
     678            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     679              :         "The parameter, name '%s', is invalid.", name);
     680              :   }
     681              : 
     682            0 :   if (!value) {
     683            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     684              :         "The parameter, value, is NULL. It should be a valid pointer.");
     685              :   }
     686              : 
     687            0 :   g_mutex_lock (&mls->lock);
     688            0 :   status = ml_option_get (mls->information, name, (void **) (&val));
     689            0 :   g_mutex_unlock (&mls->lock);
     690              : 
     691            0 :   if (status != ML_ERROR_NONE) {
     692            0 :     _ml_error_report_return (status,
     693              :         "The ml-service handle does not include the information '%s'.", name);
     694              :   }
     695              : 
     696            0 :   *value = g_strdup (val);
     697            0 :   return ML_ERROR_NONE;
     698              : }
     699              : 
     700              : /**
     701              :  * @brief Adds an input data to process the model in ml-service extension handle.
     702              :  */
     703              : int
     704            0 : ml_service_request (ml_service_h handle, const char *name,
     705              :     const ml_tensors_data_h data)
     706              : {
     707            0 :   ml_service_s *mls = (ml_service_s *) handle;
     708              :   int status;
     709              : 
     710            0 :   check_feature_state (ML_FEATURE_SERVICE);
     711              : 
     712            0 :   if (!_ml_service_handle_is_valid (mls)) {
     713            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     714              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     715              :   }
     716              : 
     717            0 :   if (!data) {
     718            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     719              :         "The parameter, data (ml_tensors_data_h), is NULL. It should be a valid ml_tensor_data_h instance, which is usually created by ml_tensors_data_create().");
     720              :   }
     721              : 
     722            0 :   switch (mls->type) {
     723            0 :     case ML_SERVICE_TYPE_EXTENSION:
     724            0 :       status = _ml_service_extension_request (mls, name, data);
     725            0 :       break;
     726            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     727            0 :       status = _ml_service_offloading_request (mls, name, data);
     728            0 :       break;
     729            0 :     default:
     730              :       /* Invalid handle type. */
     731            0 :       status = ML_ERROR_NOT_SUPPORTED;
     732            0 :       break;
     733              :   }
     734              : 
     735            0 :   return status;
     736              : }
     737              : 
     738              : /**
     739              :  * @brief Destroys the handle for machine learning service.
     740              :  */
     741              : int
     742            0 : ml_service_destroy (ml_service_h handle)
     743              : {
     744            0 :   ml_service_s *mls = (ml_service_s *) handle;
     745              : 
     746            0 :   check_feature_state (ML_FEATURE_SERVICE);
     747              : 
     748            0 :   if (!_ml_service_handle_is_valid (mls)) {
     749            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     750              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance, which is usually created by ml_service_new().");
     751              :   }
     752              : 
     753            0 :   return _ml_service_destroy_internal (mls);
     754              : }
     755              : 
     756              : /**
     757              :  * @brief Creates query client service handle with given ml-option handle.
     758              :  */
     759              : int
     760            0 : ml_service_query_create (ml_option_h option, ml_service_h * handle)
     761              : {
     762              :   ml_service_s *mls;
     763              :   int status;
     764              : 
     765            0 :   check_feature_state (ML_FEATURE_SERVICE);
     766            0 :   check_feature_state (ML_FEATURE_INFERENCE);
     767              : 
     768            0 :   if (!option) {
     769            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     770              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
     771              :   }
     772              : 
     773            0 :   if (!handle) {
     774            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     775              :         "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid ml_service_h.");
     776              :   }
     777              : 
     778            0 :   mls = _ml_service_create_internal (ML_SERVICE_TYPE_CLIENT_QUERY);
     779            0 :   if (mls == NULL) {
     780            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     781              :         "Failed to allocate memory for the service handle. Out of memory?");
     782              :   }
     783              : 
     784            0 :   status = _ml_service_query_create (mls, option);
     785              : 
     786            0 :   if (status == ML_ERROR_NONE) {
     787            0 :     *handle = mls;
     788              :   } else {
     789            0 :     _ml_error_report ("Failed to create ml-service for query.");
     790            0 :     _ml_service_destroy_internal (mls);
     791              :   }
     792              : 
     793            0 :   return status;
     794              : }
     795              : 
     796              : /**
     797              :  * @brief Requests query client service an output with given input data.
     798              :  */
     799              : int
     800            0 : ml_service_query_request (ml_service_h handle, const ml_tensors_data_h input,
     801              :     ml_tensors_data_h * output)
     802              : {
     803            0 :   ml_service_s *mls = (ml_service_s *) handle;
     804              : 
     805            0 :   check_feature_state (ML_FEATURE_SERVICE);
     806            0 :   check_feature_state (ML_FEATURE_INFERENCE);
     807              : 
     808            0 :   if (!_ml_service_handle_is_valid (mls)) {
     809            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     810              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance.");
     811              :   }
     812              : 
     813            0 :   if (!input) {
     814            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     815              :         "The parameter, 'input' (ml_tensors_data_h), is NULL. It should be a valid ml_tensors_data_h.");
     816              :   }
     817              : 
     818            0 :   if (!output) {
     819            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     820              :         "The parameter, 'output' (ml_tensors_data_h *), is NULL. It should be a valid pointer to an instance of ml_tensors_data_h.");
     821              :   }
     822              : 
     823            0 :   return _ml_service_query_request (mls, input, output);
     824              : }
     825              : 
     826              : /**
     827              :  * @brief Internal function to get json string member.
     828              :  */
     829              : const gchar *
     830            0 : _ml_service_get_json_string_member (JsonObject * object,
     831              :     const gchar * member_name)
     832              : {
     833            0 :   const gchar *ret = NULL;
     834              : 
     835            0 :   if (!object) {
     836            0 :     _ml_error_report_return (ret,
     837              :         "The parameter, object (JsonObject *), is NULL. It should be a valid JsonObject instance.");
     838              :   }
     839              : 
     840            0 :   if (!member_name) {
     841            0 :     _ml_error_report_return (ret,
     842              :         "The parameter, member_name (const gchar *), is NULL.");
     843              :   }
     844              : 
     845            0 :   if (json_object_has_member (object, member_name)) {
     846            0 :     ret = json_object_get_string_member (object, member_name);
     847              :   }
     848              : 
     849            0 :   return ret;
     850              : }
     851              : 
     852              : /**
     853              :  * @brief Generating an ML service event and passing received data and event to
     854              :  * a registered callback function.
     855              :  */
     856              : int
     857            0 : _ml_service_invoke_event_new_data (ml_service_s * mls, const char *name,
     858              :     const ml_tensors_data_h data)
     859              : {
     860            0 :   ml_service_event_cb_info_s cb_info = { 0 };
     861            0 :   ml_information_h ml_info = NULL;
     862            0 :   int status = ML_ERROR_NONE;
     863              : 
     864            0 :   if (!mls || !data) {
     865            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     866              :         "Failed to create ml-service event data, invalid parameter.");
     867              :   }
     868              : 
     869            0 :   _ml_service_get_event_cb_info (mls, &cb_info);
     870              : 
     871            0 :   if (cb_info.cb) {
     872              :     /* Create information handle for ml-service event. */
     873            0 :     status = _ml_information_create (&ml_info);
     874            0 :     if (status != ML_ERROR_NONE)
     875            0 :       goto done;
     876              : 
     877            0 :     if (name) {
     878            0 :       status = _ml_information_set (ml_info, "name", (void *) name, NULL);
     879            0 :       if (status != ML_ERROR_NONE)
     880            0 :         goto done;
     881              :     }
     882              : 
     883            0 :     status = _ml_information_set (ml_info, "data", (void *) data, NULL);
     884            0 :     if (status != ML_ERROR_NONE)
     885            0 :       goto done;
     886              : 
     887            0 :     cb_info.cb (ML_SERVICE_EVENT_NEW_DATA, ml_info, cb_info.pdata);
     888              :   }
     889              : 
     890            0 : done:
     891            0 :   if (ml_info)
     892            0 :     ml_information_destroy (ml_info);
     893              : 
     894            0 :   if (status != ML_ERROR_NONE) {
     895            0 :     _ml_error_report ("Failed to invoke 'new data' event.");
     896              :   }
     897              : 
     898            0 :   return status;
     899              : }
     900              : 
     901              : /**
     902              :  * @brief Callback for sink node in pipeline description.
     903              :  * Processes incoming data from pipeline sink element and forwards it to
     904              :  * _ml_service_invoke_event_new_data().
     905              :  */
     906              : void
     907            0 : _ml_service_pipeline_sink_cb (const ml_tensors_data_h data,
     908              :     const ml_tensors_info_h info, void *user_data)
     909              : {
     910            0 :   ml_service_s *mls = NULL;
     911            0 :   ml_service_node_info_s *node_info = NULL;
     912              : 
     913            0 :   node_info = (ml_service_node_info_s *) user_data;
     914            0 :   g_return_if_fail (node_info != NULL);
     915            0 :   mls = (ml_service_s *) node_info->mls;
     916            0 :   g_return_if_fail (mls != NULL);
     917              : 
     918            0 :   _ml_service_invoke_event_new_data (mls, node_info->name, data);
     919              : }
        

Generated by: LCOV version 2.4-0