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 :
19 : #define ML_SERVICE_MAGIC 0xfeeedeed
20 : #define ML_SERVICE_MAGIC_DEAD 0xdeaddead
21 :
22 : /**
23 : * @brief Internal function to validate ml-service handle.
24 : */
25 : gboolean
26 0 : _ml_service_handle_is_valid (ml_service_s * mls)
27 : {
28 0 : if (!mls)
29 0 : return FALSE;
30 :
31 0 : if (mls->magic != ML_SERVICE_MAGIC)
32 0 : return FALSE;
33 :
34 0 : switch (mls->type) {
35 0 : case ML_SERVICE_TYPE_SERVER_PIPELINE:
36 : case ML_SERVICE_TYPE_CLIENT_QUERY:
37 : case ML_SERVICE_TYPE_OFFLOADING:
38 : case ML_SERVICE_TYPE_EXTENSION:
39 0 : if (mls->priv == NULL)
40 0 : return FALSE;
41 0 : break;
42 0 : default:
43 : /* Invalid handle type. */
44 0 : return FALSE;
45 : }
46 :
47 0 : return TRUE;
48 : }
49 :
50 : /**
51 : * @brief Internal function to set information.
52 : */
53 : static int
54 0 : _ml_service_set_information_internal (ml_service_s * mls, const char *name,
55 : const char *value)
56 : {
57 0 : int status = ML_ERROR_NONE;
58 :
59 : /* Prevent empty string case. */
60 0 : if (!STR_IS_VALID (name) || !STR_IS_VALID (value))
61 0 : return ML_ERROR_INVALID_PARAMETER;
62 :
63 0 : status = ml_option_set (mls->information, name, g_strdup (value), g_free);
64 0 : if (status != ML_ERROR_NONE)
65 0 : return status;
66 :
67 0 : switch (mls->type) {
68 0 : case ML_SERVICE_TYPE_EXTENSION:
69 0 : status = ml_service_extension_set_information (mls, name, value);
70 0 : break;
71 0 : case ML_SERVICE_TYPE_OFFLOADING:
72 0 : status = ml_service_offloading_set_information (mls, name, value);
73 0 : break;
74 0 : default:
75 0 : break;
76 : }
77 :
78 0 : return status;
79 : }
80 :
81 : /**
82 : * @brief Internal function to create new ml-service handle.
83 : */
84 : ml_service_s *
85 0 : _ml_service_create_internal (ml_service_type_e ml_service_type)
86 : {
87 : ml_service_s *mls;
88 : int status;
89 :
90 0 : mls = g_try_new0 (ml_service_s, 1);
91 0 : if (mls) {
92 0 : status = ml_option_create (&mls->information);
93 0 : if (status != ML_ERROR_NONE) {
94 0 : g_free (mls);
95 0 : _ml_error_report_return (NULL,
96 : "Failed to create ml-option handle in ml-service.");
97 : }
98 :
99 0 : mls->magic = ML_SERVICE_MAGIC;
100 0 : mls->type = ml_service_type;
101 0 : g_mutex_init (&mls->lock);
102 0 : g_cond_init (&mls->cond);
103 : }
104 :
105 0 : return mls;
106 : }
107 :
108 : /**
109 : * @brief Internal function to release ml-service handle.
110 : */
111 : int
112 0 : _ml_service_destroy_internal (ml_service_s * mls)
113 : {
114 : ml_service_event_cb_info_s old_cb;
115 0 : int status = ML_ERROR_NONE;
116 :
117 0 : if (!mls) {
118 : /* Internal error? */
119 0 : return ML_ERROR_INVALID_PARAMETER;
120 : }
121 :
122 : /* Clear callback before closing internal handles. */
123 0 : g_mutex_lock (&mls->lock);
124 0 : old_cb = mls->cb_info;
125 0 : memset (&mls->cb_info, 0, sizeof (ml_service_event_cb_info_s));
126 0 : g_mutex_unlock (&mls->lock);
127 :
128 0 : switch (mls->type) {
129 0 : case ML_SERVICE_TYPE_SERVER_PIPELINE:
130 0 : status = ml_service_pipeline_release_internal (mls);
131 0 : break;
132 0 : case ML_SERVICE_TYPE_CLIENT_QUERY:
133 0 : status = ml_service_query_release_internal (mls);
134 0 : break;
135 0 : case ML_SERVICE_TYPE_OFFLOADING:
136 0 : status = ml_service_offloading_release_internal (mls);
137 0 : break;
138 0 : case ML_SERVICE_TYPE_EXTENSION:
139 0 : status = ml_service_extension_destroy (mls);
140 0 : break;
141 0 : default:
142 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
143 : "Invalid type of ml_service_h.");
144 : }
145 :
146 0 : if (status == ML_ERROR_NONE) {
147 0 : mls->magic = ML_SERVICE_MAGIC_DEAD;
148 0 : ml_option_destroy (mls->information);
149 :
150 0 : g_cond_clear (&mls->cond);
151 0 : g_mutex_clear (&mls->lock);
152 0 : g_free (mls);
153 : } else {
154 0 : _ml_error_report ("Failed to release ml-service handle, internal error?");
155 :
156 0 : g_mutex_lock (&mls->lock);
157 0 : mls->cb_info = old_cb;
158 0 : g_mutex_unlock (&mls->lock);
159 : }
160 :
161 0 : return status;
162 : }
163 :
164 : /**
165 : * @brief Internal function to get ml-service event callback.
166 : */
167 : void
168 0 : _ml_service_get_event_cb_info (ml_service_s * mls,
169 : ml_service_event_cb_info_s * cb_info)
170 : {
171 0 : if (!mls || !cb_info)
172 0 : return;
173 :
174 0 : g_mutex_lock (&mls->lock);
175 0 : *cb_info = mls->cb_info;
176 0 : g_mutex_unlock (&mls->lock);
177 : }
178 :
179 : /**
180 : * @brief Internal function to parse string value from json.
181 : */
182 : int
183 0 : _ml_service_conf_parse_string (JsonNode * str_node, const gchar * delimiter,
184 : gchar ** str)
185 : {
186 : guint i, n;
187 :
188 0 : if (!str_node || !delimiter || !str)
189 0 : return ML_ERROR_INVALID_PARAMETER;
190 :
191 0 : *str = NULL;
192 :
193 0 : if (JSON_NODE_HOLDS_ARRAY (str_node)) {
194 0 : JsonArray *array = json_node_get_array (str_node);
195 0 : GString *val = g_string_new (NULL);
196 :
197 0 : n = (array) ? json_array_get_length (array) : 0U;
198 0 : for (i = 0; i < n; i++) {
199 0 : const gchar *p = json_array_get_string_element (array, i);
200 :
201 : g_string_append (val, p);
202 0 : if (i < n - 1)
203 : g_string_append (val, delimiter);
204 : }
205 :
206 0 : *str = g_string_free (val, FALSE);
207 : } else {
208 0 : *str = g_strdup (json_node_get_string (str_node));
209 : }
210 :
211 0 : return (*str != NULL) ? ML_ERROR_NONE : ML_ERROR_INVALID_PARAMETER;
212 : }
213 :
214 : /**
215 : * @brief Internal function to parse tensors-info from json.
216 : */
217 : int
218 0 : _ml_service_conf_parse_tensors_info (JsonNode * info_node,
219 : ml_tensors_info_h * info_h)
220 : {
221 0 : JsonArray *array = NULL;
222 : JsonObject *object;
223 : GstTensorsInfo info;
224 : GstTensorInfo *_info;
225 : const gchar *_str;
226 : guint i;
227 : int status;
228 :
229 0 : if (!info_node || !info_h)
230 0 : return ML_ERROR_INVALID_PARAMETER;
231 :
232 0 : gst_tensors_info_init (&info);
233 :
234 0 : info.num_tensors = 1;
235 0 : if (JSON_NODE_HOLDS_ARRAY (info_node)) {
236 0 : array = json_node_get_array (info_node);
237 0 : info.num_tensors = json_array_get_length (array);
238 : }
239 :
240 0 : for (i = 0; i < info.num_tensors; i++) {
241 0 : _info = gst_tensors_info_get_nth_info (&info, i);
242 :
243 0 : if (array)
244 0 : object = json_array_get_object_element (array, i);
245 : else
246 0 : object = json_node_get_object (info_node);
247 :
248 0 : if (json_object_has_member (object, "type")) {
249 0 : _str = json_object_get_string_member (object, "type");
250 :
251 0 : if (STR_IS_VALID (_str))
252 0 : _info->type = gst_tensor_get_type (_str);
253 : }
254 :
255 0 : if (json_object_has_member (object, "dimension")) {
256 0 : _str = json_object_get_string_member (object, "dimension");
257 :
258 0 : if (STR_IS_VALID (_str))
259 0 : gst_tensor_parse_dimension (_str, _info->dimension);
260 : }
261 :
262 0 : if (json_object_has_member (object, "name")) {
263 0 : _str = json_object_get_string_member (object, "name");
264 :
265 0 : if (STR_IS_VALID (_str))
266 0 : _info->name = g_strdup (_str);
267 : }
268 : }
269 :
270 0 : if (gst_tensors_info_validate (&info))
271 0 : status = _ml_tensors_info_create_from_gst (info_h, &info);
272 : else
273 0 : status = ML_ERROR_INVALID_PARAMETER;
274 :
275 0 : gst_tensors_info_free (&info);
276 0 : return status;
277 : }
278 :
279 : /**
280 : * @brief Internal function to get ml-service type.
281 : */
282 : static ml_service_type_e
283 0 : _ml_service_get_type (JsonObject * object)
284 : {
285 0 : ml_service_type_e type = ML_SERVICE_TYPE_UNKNOWN;
286 :
287 : /** @todo add more services such as training offloading, offloading service */
288 0 : if (json_object_has_member (object, "single") ||
289 0 : json_object_has_member (object, "pipeline")) {
290 0 : type = ML_SERVICE_TYPE_EXTENSION;
291 0 : } else if (json_object_has_member (object, "offloading")) {
292 0 : type = ML_SERVICE_TYPE_OFFLOADING;
293 : }
294 :
295 0 : return type;
296 : }
297 :
298 : /**
299 : * @brief Creates a handle for machine learning service with configuration.
300 : */
301 : int
302 0 : ml_service_new (const char *config, ml_service_h * handle)
303 : {
304 : ml_service_s *mls;
305 0 : ml_service_type_e service_type = ML_SERVICE_TYPE_UNKNOWN;
306 0 : g_autofree gchar *json_string = NULL;
307 0 : g_autoptr (JsonParser) parser = NULL;
308 0 : g_autoptr (GError) err = NULL;
309 : JsonNode *root;
310 : JsonObject *object;
311 : int status;
312 :
313 0 : check_feature_state (ML_FEATURE_SERVICE);
314 :
315 0 : if (!handle) {
316 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
317 : "The parameter, 'handle' (ml_service_h), is NULL. It should be a valid pointer to create new instance.");
318 : }
319 :
320 : /* Init null. */
321 0 : *handle = NULL;
322 :
323 0 : if (!STR_IS_VALID (config) ||
324 0 : !g_file_test (config, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
325 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
326 : "The parameter, config, is invalid. It should be a valid path.");
327 : }
328 :
329 0 : if (!g_file_get_contents (config, &json_string, NULL, NULL)) {
330 0 : _ml_error_report_return (ML_ERROR_IO_ERROR,
331 : "Failed to read configuration file '%s'.", config);
332 : }
333 :
334 0 : parser = json_parser_new ();
335 0 : if (!parser) {
336 0 : _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
337 : "Failed to parse configuration file, cannot allocate memory for JsonParser. Out of memory?");
338 : }
339 :
340 0 : if (!json_parser_load_from_data (parser, json_string, -1, &err)) {
341 0 : _ml_error_report_return (ML_ERROR_IO_ERROR,
342 : "Failed to parse configuration file, cannot load json string (%s).",
343 : err ? err->message : "Unknown error");
344 : }
345 :
346 0 : root = json_parser_get_root (parser);
347 0 : if (!root) {
348 0 : _ml_error_report_return (ML_ERROR_IO_ERROR,
349 : "Failed to parse configuration file, cannot get the top node from json string.");
350 : }
351 :
352 0 : object = json_node_get_object (root);
353 :
354 0 : service_type = _ml_service_get_type (object);
355 0 : if (ML_SERVICE_TYPE_UNKNOWN == service_type) {
356 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
357 : "Failed to parse configuration file, cannot get the valid type from configuration.");
358 : }
359 :
360 : /* Parse each service type. */
361 0 : mls = _ml_service_create_internal (service_type);
362 0 : if (mls == NULL) {
363 0 : _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
364 : "Failed to allocate memory for the ml-service handle. Out of memory?");
365 : }
366 :
367 0 : switch (service_type) {
368 0 : case ML_SERVICE_TYPE_EXTENSION:
369 0 : status = ml_service_extension_create (mls, object);
370 0 : break;
371 0 : case ML_SERVICE_TYPE_OFFLOADING:
372 0 : status = ml_service_offloading_create (mls, object);
373 0 : break;
374 0 : default:
375 : /* Invalid handle type. */
376 0 : status = ML_ERROR_NOT_SUPPORTED;
377 0 : break;
378 : }
379 :
380 0 : if (status != ML_ERROR_NONE)
381 0 : goto error;
382 :
383 : /* Parse information. */
384 0 : if (json_object_has_member (object, "information")) {
385 0 : JsonObject *info = json_object_get_object_member (object, "information");
386 0 : g_autoptr (GList) members = json_object_get_members (info);
387 : GList *iter;
388 :
389 0 : for (iter = members; iter; iter = g_list_next (iter)) {
390 0 : const gchar *name = iter->data;
391 0 : const gchar *value = json_object_get_string_member (info, name);
392 :
393 0 : status = _ml_service_set_information_internal (mls, name, value);
394 0 : if (status != ML_ERROR_NONE)
395 0 : goto error;
396 : }
397 : }
398 :
399 0 : error:
400 0 : if (status == ML_ERROR_NONE) {
401 0 : *handle = mls;
402 : } else {
403 0 : _ml_error_report ("Failed to open the ml-service configuration.");
404 0 : _ml_service_destroy_internal (mls);
405 : }
406 :
407 0 : return status;
408 : }
409 :
410 : /**
411 : * @brief Sets the callbacks which will be invoked when a new event occurs from ml-service.
412 : */
413 : int
414 0 : ml_service_set_event_cb (ml_service_h handle, ml_service_event_cb cb,
415 : void *user_data)
416 : {
417 0 : ml_service_s *mls = (ml_service_s *) handle;
418 :
419 0 : check_feature_state (ML_FEATURE_SERVICE);
420 :
421 0 : if (!_ml_service_handle_is_valid (mls)) {
422 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
423 : "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().");
424 : }
425 :
426 0 : g_mutex_lock (&mls->lock);
427 :
428 0 : mls->cb_info.cb = cb;
429 0 : mls->cb_info.pdata = user_data;
430 :
431 0 : g_mutex_unlock (&mls->lock);
432 :
433 0 : return ML_ERROR_NONE;
434 : }
435 :
436 : /**
437 : * @brief Starts the process of ml-service.
438 : */
439 : int
440 0 : ml_service_start (ml_service_h handle)
441 : {
442 0 : ml_service_s *mls = (ml_service_s *) handle;
443 0 : int status = ML_ERROR_NONE;
444 :
445 0 : check_feature_state (ML_FEATURE_SERVICE);
446 :
447 0 : if (!_ml_service_handle_is_valid (mls)) {
448 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
449 : "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().");
450 : }
451 :
452 0 : switch (mls->type) {
453 0 : case ML_SERVICE_TYPE_SERVER_PIPELINE:
454 : {
455 0 : _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
456 :
457 0 : status = ml_agent_pipeline_start (server->id);
458 0 : if (status < 0)
459 0 : _ml_error_report ("Failed to invoke the method start_pipeline.");
460 :
461 0 : break;
462 : }
463 0 : case ML_SERVICE_TYPE_EXTENSION:
464 0 : status = ml_service_extension_start (mls);
465 0 : break;
466 0 : case ML_SERVICE_TYPE_OFFLOADING:
467 0 : status = ml_service_offloading_start (mls);
468 0 : break;
469 0 : default:
470 : /* Invalid handle type. */
471 0 : status = ML_ERROR_NOT_SUPPORTED;
472 0 : break;
473 : }
474 :
475 0 : return status;
476 : }
477 :
478 : /**
479 : * @brief Stops the process of ml-service.
480 : */
481 : int
482 0 : ml_service_stop (ml_service_h handle)
483 : {
484 0 : ml_service_s *mls = (ml_service_s *) handle;
485 0 : int status = ML_ERROR_NONE;
486 :
487 0 : check_feature_state (ML_FEATURE_SERVICE);
488 :
489 0 : if (!_ml_service_handle_is_valid (mls)) {
490 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
491 : "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().");
492 : }
493 :
494 0 : switch (mls->type) {
495 0 : case ML_SERVICE_TYPE_SERVER_PIPELINE:
496 : {
497 0 : _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
498 :
499 0 : status = ml_agent_pipeline_stop (server->id);
500 0 : if (status < 0)
501 0 : _ml_error_report ("Failed to invoke the method stop_pipeline.");
502 :
503 0 : break;
504 : }
505 0 : case ML_SERVICE_TYPE_EXTENSION:
506 0 : status = ml_service_extension_stop (mls);
507 0 : break;
508 0 : case ML_SERVICE_TYPE_OFFLOADING:
509 0 : status = ml_service_offloading_stop (mls);
510 0 : break;
511 0 : default:
512 : /* Invalid handle type. */
513 0 : status = ML_ERROR_NOT_SUPPORTED;
514 0 : break;
515 : }
516 :
517 0 : return status;
518 : }
519 :
520 : /**
521 : * @brief Gets the information of required input data.
522 : */
523 : int
524 0 : ml_service_get_input_information (ml_service_h handle, const char *name,
525 : ml_tensors_info_h * info)
526 : {
527 0 : ml_service_s *mls = (ml_service_s *) handle;
528 : int status;
529 :
530 0 : check_feature_state (ML_FEATURE_SERVICE);
531 :
532 0 : if (!_ml_service_handle_is_valid (mls)) {
533 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
534 : "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().");
535 : }
536 :
537 0 : if (!info) {
538 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
539 : "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
540 : }
541 :
542 : /* Init null. */
543 0 : *info = NULL;
544 :
545 0 : switch (mls->type) {
546 0 : case ML_SERVICE_TYPE_EXTENSION:
547 0 : status = ml_service_extension_get_input_information (mls, name, info);
548 0 : break;
549 0 : default:
550 : /* Invalid handle type. */
551 0 : status = ML_ERROR_NOT_SUPPORTED;
552 0 : break;
553 : }
554 :
555 0 : if (status != ML_ERROR_NONE) {
556 0 : if (*info) {
557 0 : ml_tensors_info_destroy (*info);
558 0 : *info = NULL;
559 : }
560 : }
561 :
562 0 : return status;
563 : }
564 :
565 : /**
566 : * @brief Gets the information of output data.
567 : */
568 : int
569 0 : ml_service_get_output_information (ml_service_h handle, const char *name,
570 : ml_tensors_info_h * info)
571 : {
572 0 : ml_service_s *mls = (ml_service_s *) handle;
573 : int status;
574 :
575 0 : check_feature_state (ML_FEATURE_SERVICE);
576 :
577 0 : if (!_ml_service_handle_is_valid (mls)) {
578 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
579 : "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().");
580 : }
581 :
582 0 : if (!info) {
583 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
584 : "The parameter, info (ml_tensors_info_h), is NULL. It should be a valid pointer to create new instance.");
585 : }
586 :
587 : /* Init null. */
588 0 : *info = NULL;
589 :
590 0 : switch (mls->type) {
591 0 : case ML_SERVICE_TYPE_EXTENSION:
592 0 : status = ml_service_extension_get_output_information (mls, name, info);
593 0 : break;
594 0 : default:
595 : /* Invalid handle type. */
596 0 : status = ML_ERROR_NOT_SUPPORTED;
597 0 : break;
598 : }
599 :
600 0 : if (status != ML_ERROR_NONE) {
601 0 : if (*info) {
602 0 : ml_tensors_info_destroy (*info);
603 0 : *info = NULL;
604 : }
605 : }
606 :
607 0 : return status;
608 : }
609 :
610 : /**
611 : * @brief Sets the information for ml-service.
612 : */
613 : int
614 0 : ml_service_set_information (ml_service_h handle, const char *name,
615 : const char *value)
616 : {
617 0 : ml_service_s *mls = (ml_service_s *) handle;
618 : int status;
619 :
620 0 : check_feature_state (ML_FEATURE_SERVICE);
621 :
622 0 : if (!_ml_service_handle_is_valid (mls)) {
623 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
624 : "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().");
625 : }
626 :
627 0 : if (!STR_IS_VALID (name)) {
628 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
629 : "The parameter, name '%s', is invalid.", name);
630 : }
631 :
632 0 : if (!STR_IS_VALID (value)) {
633 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
634 : "The parameter, value '%s', is invalid.", value);
635 : }
636 :
637 0 : g_mutex_lock (&mls->lock);
638 0 : status = _ml_service_set_information_internal (mls, name, value);
639 0 : g_mutex_unlock (&mls->lock);
640 :
641 0 : if (status != ML_ERROR_NONE) {
642 0 : _ml_error_report_return (status,
643 : "Failed to set the information '%s'.", name);
644 : }
645 :
646 0 : return ML_ERROR_NONE;
647 : }
648 :
649 : /**
650 : * @brief Gets the information from ml-service.
651 : */
652 : int
653 0 : ml_service_get_information (ml_service_h handle, const char *name, char **value)
654 : {
655 0 : ml_service_s *mls = (ml_service_s *) handle;
656 0 : gchar *val = NULL;
657 : int status;
658 :
659 0 : check_feature_state (ML_FEATURE_SERVICE);
660 :
661 0 : if (!_ml_service_handle_is_valid (mls)) {
662 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
663 : "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().");
664 : }
665 :
666 0 : if (!STR_IS_VALID (name)) {
667 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
668 : "The parameter, name '%s', is invalid.", name);
669 : }
670 :
671 0 : if (!value) {
672 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
673 : "The parameter, value, is NULL. It should be a valid pointer.");
674 : }
675 :
676 0 : g_mutex_lock (&mls->lock);
677 0 : status = ml_option_get (mls->information, name, (void **) (&val));
678 0 : g_mutex_unlock (&mls->lock);
679 :
680 0 : if (status != ML_ERROR_NONE) {
681 0 : _ml_error_report_return (status,
682 : "The ml-service handle does not include the information '%s'.", name);
683 : }
684 :
685 0 : *value = g_strdup (val);
686 0 : return ML_ERROR_NONE;
687 : }
688 :
689 : /**
690 : * @brief Adds an input data to process the model in ml-service extension handle.
691 : */
692 : int
693 0 : ml_service_request (ml_service_h handle, const char *name,
694 : const ml_tensors_data_h data)
695 : {
696 0 : ml_service_s *mls = (ml_service_s *) handle;
697 : int status;
698 :
699 0 : check_feature_state (ML_FEATURE_SERVICE);
700 :
701 0 : if (!_ml_service_handle_is_valid (mls)) {
702 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
703 : "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().");
704 : }
705 :
706 0 : if (!data) {
707 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
708 : "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().");
709 : }
710 :
711 0 : switch (mls->type) {
712 0 : case ML_SERVICE_TYPE_EXTENSION:
713 0 : status = ml_service_extension_request (mls, name, data);
714 0 : break;
715 0 : case ML_SERVICE_TYPE_OFFLOADING:
716 0 : status = ml_service_offloading_request (mls, name, data);
717 0 : break;
718 0 : default:
719 : /* Invalid handle type. */
720 0 : status = ML_ERROR_NOT_SUPPORTED;
721 0 : break;
722 : }
723 :
724 0 : return status;
725 : }
726 :
727 : /**
728 : * @brief Destroys the handle for machine learning service.
729 : */
730 : int
731 0 : ml_service_destroy (ml_service_h handle)
732 : {
733 0 : ml_service_s *mls = (ml_service_s *) handle;
734 :
735 0 : check_feature_state (ML_FEATURE_SERVICE);
736 :
737 0 : if (!_ml_service_handle_is_valid (mls)) {
738 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
739 : "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().");
740 : }
741 :
742 0 : return _ml_service_destroy_internal (mls);
743 : }
|