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#d53de7897d9eb6cef6879b50513588e5476c3924 Lines: 0.0 % 416 0
Test Date: 2026-05-07 08:24:32 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              : 
     242            0 :   for (i = 0; i < info.num_tensors; i++) {
     243            0 :     _info = gst_tensors_info_get_nth_info (&info, i);
     244              : 
     245            0 :     if (array)
     246            0 :       object = json_array_get_object_element (array, i);
     247              :     else
     248            0 :       object = json_node_get_object (info_node);
     249              : 
     250            0 :     if (json_object_has_member (object, "type")) {
     251            0 :       _str = json_object_get_string_member (object, "type");
     252              : 
     253            0 :       if (STR_IS_VALID (_str))
     254            0 :         _info->type = gst_tensor_get_type (_str);
     255              :     }
     256              : 
     257            0 :     if (json_object_has_member (object, "dimension")) {
     258            0 :       _str = json_object_get_string_member (object, "dimension");
     259              : 
     260            0 :       if (STR_IS_VALID (_str))
     261            0 :         gst_tensor_parse_dimension (_str, _info->dimension);
     262              :     }
     263              : 
     264            0 :     if (json_object_has_member (object, "name")) {
     265            0 :       _str = json_object_get_string_member (object, "name");
     266              : 
     267            0 :       if (STR_IS_VALID (_str))
     268            0 :         _info->name = g_strdup (_str);
     269              :     }
     270              :   }
     271              : 
     272            0 :   if (gst_tensors_info_validate (&info))
     273            0 :     status = _ml_tensors_info_create_from_gst (info_h, &info);
     274              :   else
     275            0 :     status = ML_ERROR_INVALID_PARAMETER;
     276              : 
     277            0 :   gst_tensors_info_free (&info);
     278            0 :   return status;
     279              : }
     280              : 
     281              : /**
     282              :  * @brief Internal function to get ml-service type.
     283              :  */
     284              : static ml_service_type_e
     285            0 : _ml_service_get_type (JsonObject * object)
     286              : {
     287            0 :   ml_service_type_e type = ML_SERVICE_TYPE_UNKNOWN;
     288              : 
     289              :   /** @todo add more services such as training offloading, offloading service */
     290            0 :   if (json_object_has_member (object, "single") ||
     291            0 :       json_object_has_member (object, "pipeline")) {
     292            0 :     type = ML_SERVICE_TYPE_EXTENSION;
     293            0 :   } else if (json_object_has_member (object, "offloading")) {
     294            0 :     type = ML_SERVICE_TYPE_OFFLOADING;
     295              :   }
     296              : 
     297            0 :   return type;
     298              : }
     299              : 
     300              : /**
     301              :  * @brief Creates a handle for machine learning service with configuration.
     302              :  */
     303              : int
     304            0 : ml_service_new (const char *config, ml_service_h * handle)
     305              : {
     306              :   ml_service_s *mls;
     307            0 :   ml_service_type_e service_type = ML_SERVICE_TYPE_UNKNOWN;
     308            0 :   g_autofree gchar *json_string = NULL;
     309            0 :   g_autofree gchar *contents = NULL;
     310            0 :   g_autoptr (JsonParser) parser = NULL;
     311            0 :   g_autoptr (GError) err = NULL;
     312              :   JsonNode *root;
     313              :   JsonObject *object;
     314              :   int status;
     315              : 
     316            0 :   check_feature_state (ML_FEATURE_SERVICE);
     317              : 
     318            0 :   if (!handle) {
     319            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     320              :         "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid pointer to create new instance.");
     321              :   }
     322              : 
     323              :   /* Init null. */
     324            0 :   *handle = NULL;
     325              : 
     326            0 :   if (!STR_IS_VALID (config) ||
     327            0 :       !g_file_test (config, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
     328            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     329              :         "The parameter, config, is invalid. It should be a valid path.");
     330              :   }
     331              : 
     332            0 :   if (!g_file_get_contents (config, &contents, NULL, NULL)) {
     333            0 :     _ml_error_report_return (ML_ERROR_IO_ERROR,
     334              :         "Failed to read configuration file '%s'.", config);
     335              :   }
     336              : 
     337            0 :   json_string = _ml_convert_predefined_entity (contents);
     338              : 
     339            0 :   parser = json_parser_new ();
     340            0 :   if (!parser) {
     341            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     342              :         "Failed to parse configuration file, cannot allocate memory for JsonParser. Out of memory?");
     343              :   }
     344              : 
     345            0 :   if (!json_parser_load_from_data (parser, json_string, -1, &err)) {
     346            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     347              :         "Failed to parse configuration file. Parse error: %s",
     348              :         err ? err->message : "Unknown error");
     349              :   }
     350              : 
     351            0 :   root = json_parser_get_root (parser);
     352            0 :   if (!root) {
     353            0 :     _ml_error_report_return (ML_ERROR_IO_ERROR,
     354              :         "Failed to parse configuration file, cannot get the top node from json string.");
     355              :   }
     356              : 
     357            0 :   object = json_node_get_object (root);
     358              : 
     359            0 :   service_type = _ml_service_get_type (object);
     360            0 :   if (ML_SERVICE_TYPE_UNKNOWN == service_type) {
     361            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     362              :         "Failed to parse configuration file, cannot get the valid type from configuration.");
     363              :   }
     364              : 
     365              :   /* Parse each service type. */
     366            0 :   mls = _ml_service_create_internal (service_type);
     367            0 :   if (mls == NULL) {
     368            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     369              :         "Failed to allocate memory for the ml-service handle. Out of memory?");
     370              :   }
     371              : 
     372            0 :   switch (service_type) {
     373            0 :     case ML_SERVICE_TYPE_EXTENSION:
     374            0 :       status = _ml_service_extension_create (mls, object);
     375            0 :       break;
     376            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     377            0 :       status = _ml_service_offloading_create (mls, object);
     378            0 :       break;
     379            0 :     default:
     380              :       /* Invalid handle type. */
     381            0 :       status = ML_ERROR_NOT_SUPPORTED;
     382            0 :       break;
     383              :   }
     384              : 
     385            0 :   if (status != ML_ERROR_NONE)
     386            0 :     goto error;
     387              : 
     388              :   /* Parse information. */
     389            0 :   if (json_object_has_member (object, "information")) {
     390            0 :     JsonObject *info = json_object_get_object_member (object, "information");
     391            0 :     g_autoptr (GList) members = json_object_get_members (info);
     392              :     GList *iter;
     393              : 
     394            0 :     for (iter = members; iter; iter = g_list_next (iter)) {
     395            0 :       const gchar *name = iter->data;
     396            0 :       const gchar *value = _ml_service_get_json_string_member (info, name);
     397              : 
     398            0 :       status = _ml_service_set_information_internal (mls, name, value);
     399            0 :       if (status != ML_ERROR_NONE)
     400            0 :         goto error;
     401              :     }
     402              :   }
     403              : 
     404            0 : error:
     405            0 :   if (status == ML_ERROR_NONE) {
     406            0 :     *handle = mls;
     407              :   } else {
     408            0 :     _ml_error_report ("Failed to open the ml-service configuration.");
     409            0 :     _ml_service_destroy_internal (mls);
     410              :   }
     411              : 
     412            0 :   return status;
     413              : }
     414              : 
     415              : /**
     416              :  * @brief Sets the callbacks which will be invoked when a new event occurs from ml-service.
     417              :  */
     418              : int
     419            0 : ml_service_set_event_cb (ml_service_h handle, ml_service_event_cb cb,
     420              :     void *user_data)
     421              : {
     422            0 :   ml_service_s *mls = (ml_service_s *) handle;
     423              : 
     424            0 :   check_feature_state (ML_FEATURE_SERVICE);
     425              : 
     426            0 :   if (!_ml_service_handle_is_valid (mls)) {
     427            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     428              :         "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().");
     429              :   }
     430              : 
     431            0 :   g_mutex_lock (&mls->lock);
     432              : 
     433            0 :   mls->cb_info.cb = cb;
     434            0 :   mls->cb_info.pdata = user_data;
     435              : 
     436            0 :   g_mutex_unlock (&mls->lock);
     437              : 
     438            0 :   return ML_ERROR_NONE;
     439              : }
     440              : 
     441              : /**
     442              :  * @brief Starts the process of ml-service.
     443              :  */
     444              : int
     445            0 : ml_service_start (ml_service_h handle)
     446              : {
     447            0 :   ml_service_s *mls = (ml_service_s *) handle;
     448            0 :   int status = ML_ERROR_NONE;
     449              : 
     450            0 :   check_feature_state (ML_FEATURE_SERVICE);
     451              : 
     452            0 :   if (!_ml_service_handle_is_valid (mls)) {
     453            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     454              :         "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().");
     455              :   }
     456              : 
     457            0 :   switch (mls->type) {
     458            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
     459              :     {
     460            0 :       _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
     461              : 
     462            0 :       status = ml_agent_pipeline_start (server->id);
     463            0 :       if (status < 0)
     464            0 :         _ml_error_report ("Failed to invoke the method start_pipeline.");
     465              : 
     466            0 :       break;
     467              :     }
     468            0 :     case ML_SERVICE_TYPE_EXTENSION:
     469            0 :       status = _ml_service_extension_start (mls);
     470            0 :       break;
     471            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     472            0 :       status = _ml_service_offloading_start (mls);
     473            0 :       break;
     474            0 :     default:
     475              :       /* Invalid handle type. */
     476            0 :       status = ML_ERROR_NOT_SUPPORTED;
     477            0 :       break;
     478              :   }
     479              : 
     480            0 :   return status;
     481              : }
     482              : 
     483              : /**
     484              :  * @brief Stops the process of ml-service.
     485              :  */
     486              : int
     487            0 : ml_service_stop (ml_service_h handle)
     488              : {
     489            0 :   ml_service_s *mls = (ml_service_s *) handle;
     490            0 :   int status = ML_ERROR_NONE;
     491              : 
     492            0 :   check_feature_state (ML_FEATURE_SERVICE);
     493              : 
     494            0 :   if (!_ml_service_handle_is_valid (mls)) {
     495            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     496              :         "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().");
     497              :   }
     498              : 
     499            0 :   switch (mls->type) {
     500            0 :     case ML_SERVICE_TYPE_SERVER_PIPELINE:
     501              :     {
     502            0 :       _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
     503              : 
     504            0 :       status = ml_agent_pipeline_stop (server->id);
     505            0 :       if (status < 0)
     506            0 :         _ml_error_report ("Failed to invoke the method stop_pipeline.");
     507              : 
     508            0 :       break;
     509              :     }
     510            0 :     case ML_SERVICE_TYPE_EXTENSION:
     511            0 :       status = _ml_service_extension_stop (mls);
     512            0 :       break;
     513            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     514            0 :       status = _ml_service_offloading_stop (mls);
     515            0 :       break;
     516            0 :     default:
     517              :       /* Invalid handle type. */
     518            0 :       status = ML_ERROR_NOT_SUPPORTED;
     519            0 :       break;
     520              :   }
     521              : 
     522            0 :   return status;
     523              : }
     524              : 
     525              : /**
     526              :  * @brief Gets the information of required input data.
     527              :  */
     528              : int
     529            0 : ml_service_get_input_information (ml_service_h handle, const char *name,
     530              :     ml_tensors_info_h * info)
     531              : {
     532            0 :   ml_service_s *mls = (ml_service_s *) handle;
     533              :   int status;
     534              : 
     535            0 :   check_feature_state (ML_FEATURE_SERVICE);
     536              : 
     537            0 :   if (!_ml_service_handle_is_valid (mls)) {
     538            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     539              :         "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().");
     540              :   }
     541              : 
     542            0 :   if (!info) {
     543            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     544              :         "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
     545              :   }
     546              : 
     547              :   /* Init null. */
     548            0 :   *info = NULL;
     549              : 
     550            0 :   switch (mls->type) {
     551            0 :     case ML_SERVICE_TYPE_EXTENSION:
     552            0 :       status = _ml_service_extension_get_input_information (mls, name, info);
     553            0 :       break;
     554            0 :     default:
     555              :       /* Invalid handle type. */
     556            0 :       status = ML_ERROR_NOT_SUPPORTED;
     557            0 :       break;
     558              :   }
     559              : 
     560            0 :   if (status != ML_ERROR_NONE) {
     561            0 :     if (*info) {
     562            0 :       ml_tensors_info_destroy (*info);
     563            0 :       *info = NULL;
     564              :     }
     565              :   }
     566              : 
     567            0 :   return status;
     568              : }
     569              : 
     570              : /**
     571              :  * @brief Gets the information of output data.
     572              :  */
     573              : int
     574            0 : ml_service_get_output_information (ml_service_h handle, const char *name,
     575              :     ml_tensors_info_h * info)
     576              : {
     577            0 :   ml_service_s *mls = (ml_service_s *) handle;
     578              :   int status;
     579              : 
     580            0 :   check_feature_state (ML_FEATURE_SERVICE);
     581              : 
     582            0 :   if (!_ml_service_handle_is_valid (mls)) {
     583            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     584              :         "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().");
     585              :   }
     586              : 
     587            0 :   if (!info) {
     588            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     589              :         "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
     590              :   }
     591              : 
     592              :   /* Init null. */
     593            0 :   *info = NULL;
     594              : 
     595            0 :   switch (mls->type) {
     596            0 :     case ML_SERVICE_TYPE_EXTENSION:
     597            0 :       status = _ml_service_extension_get_output_information (mls, name, info);
     598            0 :       break;
     599            0 :     default:
     600              :       /* Invalid handle type. */
     601            0 :       status = ML_ERROR_NOT_SUPPORTED;
     602            0 :       break;
     603              :   }
     604              : 
     605            0 :   if (status != ML_ERROR_NONE) {
     606            0 :     if (*info) {
     607            0 :       ml_tensors_info_destroy (*info);
     608            0 :       *info = NULL;
     609              :     }
     610              :   }
     611              : 
     612            0 :   return status;
     613              : }
     614              : 
     615              : /**
     616              :  * @brief Sets the information for ml-service.
     617              :  */
     618              : int
     619            0 : ml_service_set_information (ml_service_h handle, const char *name,
     620              :     const char *value)
     621              : {
     622            0 :   ml_service_s *mls = (ml_service_s *) handle;
     623              :   int status;
     624              : 
     625            0 :   check_feature_state (ML_FEATURE_SERVICE);
     626              : 
     627            0 :   if (!_ml_service_handle_is_valid (mls)) {
     628            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     629              :         "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().");
     630              :   }
     631              : 
     632            0 :   if (!STR_IS_VALID (name)) {
     633            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     634              :         "The parameter, name '%s', is invalid.", name);
     635              :   }
     636              : 
     637            0 :   if (!STR_IS_VALID (value)) {
     638            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     639              :         "The parameter, value '%s', is invalid.", value);
     640              :   }
     641              : 
     642            0 :   g_mutex_lock (&mls->lock);
     643            0 :   status = _ml_service_set_information_internal (mls, name, value);
     644            0 :   g_mutex_unlock (&mls->lock);
     645              : 
     646            0 :   if (status != ML_ERROR_NONE) {
     647            0 :     _ml_error_report_return (status,
     648              :         "Failed to set the information '%s'.", name);
     649              :   }
     650              : 
     651            0 :   return ML_ERROR_NONE;
     652              : }
     653              : 
     654              : /**
     655              :  * @brief Gets the information from ml-service.
     656              :  */
     657              : int
     658            0 : ml_service_get_information (ml_service_h handle, const char *name, char **value)
     659              : {
     660            0 :   ml_service_s *mls = (ml_service_s *) handle;
     661            0 :   gchar *val = NULL;
     662              :   int status;
     663              : 
     664            0 :   check_feature_state (ML_FEATURE_SERVICE);
     665              : 
     666            0 :   if (!_ml_service_handle_is_valid (mls)) {
     667            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     668              :         "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().");
     669              :   }
     670              : 
     671            0 :   if (!STR_IS_VALID (name)) {
     672            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     673              :         "The parameter, name '%s', is invalid.", name);
     674              :   }
     675              : 
     676            0 :   if (!value) {
     677            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     678              :         "The parameter, value, is NULL. It should be a valid pointer.");
     679              :   }
     680              : 
     681            0 :   g_mutex_lock (&mls->lock);
     682            0 :   status = ml_option_get (mls->information, name, (void **) (&val));
     683            0 :   g_mutex_unlock (&mls->lock);
     684              : 
     685            0 :   if (status != ML_ERROR_NONE) {
     686            0 :     _ml_error_report_return (status,
     687              :         "The ml-service handle does not include the information '%s'.", name);
     688              :   }
     689              : 
     690            0 :   *value = g_strdup (val);
     691            0 :   return ML_ERROR_NONE;
     692              : }
     693              : 
     694              : /**
     695              :  * @brief Adds an input data to process the model in ml-service extension handle.
     696              :  */
     697              : int
     698            0 : ml_service_request (ml_service_h handle, const char *name,
     699              :     const ml_tensors_data_h data)
     700              : {
     701            0 :   ml_service_s *mls = (ml_service_s *) handle;
     702              :   int status;
     703              : 
     704            0 :   check_feature_state (ML_FEATURE_SERVICE);
     705              : 
     706            0 :   if (!_ml_service_handle_is_valid (mls)) {
     707            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     708              :         "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().");
     709              :   }
     710              : 
     711            0 :   if (!data) {
     712            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     713              :         "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().");
     714              :   }
     715              : 
     716            0 :   switch (mls->type) {
     717            0 :     case ML_SERVICE_TYPE_EXTENSION:
     718            0 :       status = _ml_service_extension_request (mls, name, data);
     719            0 :       break;
     720            0 :     case ML_SERVICE_TYPE_OFFLOADING:
     721            0 :       status = _ml_service_offloading_request (mls, name, data);
     722            0 :       break;
     723            0 :     default:
     724              :       /* Invalid handle type. */
     725            0 :       status = ML_ERROR_NOT_SUPPORTED;
     726            0 :       break;
     727              :   }
     728              : 
     729            0 :   return status;
     730              : }
     731              : 
     732              : /**
     733              :  * @brief Destroys the handle for machine learning service.
     734              :  */
     735              : int
     736            0 : ml_service_destroy (ml_service_h handle)
     737              : {
     738            0 :   ml_service_s *mls = (ml_service_s *) handle;
     739              : 
     740            0 :   check_feature_state (ML_FEATURE_SERVICE);
     741              : 
     742            0 :   if (!_ml_service_handle_is_valid (mls)) {
     743            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     744              :         "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().");
     745              :   }
     746              : 
     747            0 :   return _ml_service_destroy_internal (mls);
     748              : }
     749              : 
     750              : /**
     751              :  * @brief Creates query client service handle with given ml-option handle.
     752              :  */
     753              : int
     754            0 : ml_service_query_create (ml_option_h option, ml_service_h * handle)
     755              : {
     756              :   ml_service_s *mls;
     757              :   int status;
     758              : 
     759            0 :   check_feature_state (ML_FEATURE_SERVICE);
     760            0 :   check_feature_state (ML_FEATURE_INFERENCE);
     761              : 
     762            0 :   if (!option) {
     763            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     764              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
     765              :   }
     766              : 
     767            0 :   if (!handle) {
     768            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     769              :         "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid ml_service_h.");
     770              :   }
     771              : 
     772            0 :   mls = _ml_service_create_internal (ML_SERVICE_TYPE_CLIENT_QUERY);
     773            0 :   if (mls == NULL) {
     774            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     775              :         "Failed to allocate memory for the service handle. Out of memory?");
     776              :   }
     777              : 
     778            0 :   status = _ml_service_query_create (mls, option);
     779              : 
     780            0 :   if (status == ML_ERROR_NONE) {
     781            0 :     *handle = mls;
     782              :   } else {
     783            0 :     _ml_error_report ("Failed to create ml-service for query.");
     784            0 :     _ml_service_destroy_internal (mls);
     785              :   }
     786              : 
     787            0 :   return status;
     788              : }
     789              : 
     790              : /**
     791              :  * @brief Requests query client service an output with given input data.
     792              :  */
     793              : int
     794            0 : ml_service_query_request (ml_service_h handle, const ml_tensors_data_h input,
     795              :     ml_tensors_data_h * output)
     796              : {
     797            0 :   ml_service_s *mls = (ml_service_s *) handle;
     798              : 
     799            0 :   check_feature_state (ML_FEATURE_SERVICE);
     800            0 :   check_feature_state (ML_FEATURE_INFERENCE);
     801              : 
     802            0 :   if (!_ml_service_handle_is_valid (mls)) {
     803            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     804              :         "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance.");
     805              :   }
     806              : 
     807            0 :   if (!input) {
     808            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     809              :         "The parameter, 'input' (ml_tensors_data_h), is NULL. It should be a valid ml_tensors_data_h.");
     810              :   }
     811              : 
     812            0 :   if (!output) {
     813            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     814              :         "The parameter, 'output' (ml_tensors_data_h *), is NULL. It should be a valid pointer to an instance of ml_tensors_data_h.");
     815              :   }
     816              : 
     817            0 :   return _ml_service_query_request (mls, input, output);
     818              : }
     819              : 
     820              : /**
     821              :  * @brief Internal function to get json string member.
     822              :  */
     823              : const gchar *
     824            0 : _ml_service_get_json_string_member (JsonObject * object,
     825              :     const gchar * member_name)
     826              : {
     827            0 :   const gchar *ret = NULL;
     828              : 
     829            0 :   if (!object) {
     830            0 :     _ml_error_report_return (ret,
     831              :         "The parameter, object (JsonObject *), is NULL. It should be a valid JsonObject instance.");
     832              :   }
     833              : 
     834            0 :   if (!member_name) {
     835            0 :     _ml_error_report_return (ret,
     836              :         "The parameter, member_name (const gchar *), is NULL.");
     837              :   }
     838              : 
     839            0 :   if (json_object_has_member (object, member_name)) {
     840            0 :     ret = json_object_get_string_member (object, member_name);
     841              :   }
     842              : 
     843            0 :   return ret;
     844              : }
     845              : 
     846              : /**
     847              :  * @brief Generating an ML service event and passing received data and event to
     848              :  * a registered callback function.
     849              :  */
     850              : int
     851            0 : _ml_service_invoke_event_new_data (ml_service_s * mls, const char *name,
     852              :     const ml_tensors_data_h data)
     853              : {
     854            0 :   ml_service_event_cb_info_s cb_info = { 0 };
     855            0 :   ml_information_h ml_info = NULL;
     856            0 :   int status = ML_ERROR_NONE;
     857              : 
     858            0 :   if (!mls || !data) {
     859            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     860              :         "Failed to create ml-service event data, invalid parameter.");
     861              :   }
     862              : 
     863            0 :   _ml_service_get_event_cb_info (mls, &cb_info);
     864              : 
     865            0 :   if (cb_info.cb) {
     866              :     /* Create information handle for ml-service event. */
     867            0 :     status = _ml_information_create (&ml_info);
     868            0 :     if (status != ML_ERROR_NONE)
     869            0 :       goto done;
     870              : 
     871            0 :     if (name) {
     872            0 :       status = _ml_information_set (ml_info, "name", (void *) name, NULL);
     873            0 :       if (status != ML_ERROR_NONE)
     874            0 :         goto done;
     875              :     }
     876              : 
     877            0 :     status = _ml_information_set (ml_info, "data", (void *) data, NULL);
     878            0 :     if (status != ML_ERROR_NONE)
     879            0 :       goto done;
     880              : 
     881            0 :     cb_info.cb (ML_SERVICE_EVENT_NEW_DATA, ml_info, cb_info.pdata);
     882              :   }
     883              : 
     884            0 : done:
     885            0 :   if (ml_info)
     886            0 :     ml_information_destroy (ml_info);
     887              : 
     888            0 :   if (status != ML_ERROR_NONE) {
     889            0 :     _ml_error_report ("Failed to invoke 'new data' event.");
     890              :   }
     891              : 
     892            0 :   return status;
     893              : }
     894              : 
     895              : /**
     896              :  * @brief Callback for sink node in pipeline description.
     897              :  * Processes incoming data from pipeline sink element and forwards it to
     898              :  * _ml_service_invoke_event_new_data().
     899              :  */
     900              : void
     901            0 : _ml_service_pipeline_sink_cb (const ml_tensors_data_h data,
     902              :     const ml_tensors_info_h info, void *user_data)
     903              : {
     904            0 :   ml_service_s *mls = NULL;
     905            0 :   ml_service_node_info_s *node_info = NULL;
     906              : 
     907            0 :   node_info = (ml_service_node_info_s *) user_data;
     908            0 :   g_return_if_fail (node_info != NULL);
     909            0 :   mls = (ml_service_s *) node_info->mls;
     910            0 :   g_return_if_fail (mls != NULL);
     911              : 
     912            0 :   _ml_service_invoke_event_new_data (mls, node_info->name, data);
     913              : }
        

Generated by: LCOV version 2.0-1