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-agent-client.c
6 : * @date 20 Jul 2022
7 : * @brief agent (dbus) 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 <glib/gstdio.h>
14 : #include <json-glib/json-glib.h>
15 :
16 : #include "ml-api-internal.h"
17 : #include "ml-api-service-private.h"
18 : #include "ml-api-service.h"
19 :
20 : #define WARN_MSG_DPTR_SET_OVER "The memory blocks pointed by pipeline_desc will be set over with a new one.\n" \
21 : "It is highly suggested that `%s` before it is set."
22 :
23 : #if defined(__TIZEN__)
24 : #include <app_common.h>
25 : #include <app_common_internal.h>
26 :
27 : /**
28 : * @brief Parse app_info and update path (for model from rpk). Only for Tizen Applications.
29 : */
30 : static int
31 0 : _parse_app_info_and_update_path (ml_information_h ml_info)
32 : {
33 0 : int ret = ML_ERROR_NONE;
34 :
35 0 : gchar *app_info = NULL;
36 0 : g_autoptr (JsonParser) parser = NULL;
37 0 : g_autoptr (GError) err = NULL;
38 :
39 : JsonObject *jobj;
40 :
41 : /* parsing app_info and fill path (for rpk) */
42 0 : ret = ml_information_get (ml_info, "app_info", (void **) &app_info);
43 0 : if (ret != ML_ERROR_NONE) {
44 : /* ml-info may not contain app_info, ignore this case. */
45 0 : _ml_error_report_return (ML_ERROR_NONE,
46 : "Failed to get app_info from the model info.");
47 : }
48 :
49 0 : _ml_logi ("Parsing app_info: %s", app_info);
50 :
51 : /* parsing the app_info json string. If the model is from rpk, path should be updated. */
52 0 : parser = json_parser_new ();
53 0 : if (!json_parser_load_from_data (parser, app_info, -1, &err)) {
54 0 : _ml_logi ("Failed to parse app_info (%s). Skip it.",
55 : err ? err->message : "Unknown error");
56 0 : return ML_ERROR_NONE;
57 : }
58 :
59 0 : jobj = json_node_get_object (json_parser_get_root (parser));
60 0 : if (!jobj) {
61 0 : _ml_error_report_return (ML_ERROR_NONE,
62 : "Failed to get json object from the app_info. Skip it.");
63 : }
64 :
65 0 : if (g_strcmp0 (json_object_get_string_member (jobj, "is_rpk"), "T") == 0) {
66 : gchar *ori_path, *new_path;
67 0 : g_autofree gchar *global_resource_path;
68 0 : const gchar *res_type = json_object_get_string_member (jobj, "res_type");
69 :
70 0 : ret = ml_information_get (ml_info, "path", (void **) &ori_path);
71 0 : if (ret != ML_ERROR_NONE) {
72 0 : _ml_error_report_return (ret, "Failed to get path from the model info.");
73 : }
74 :
75 0 : ret = app_get_res_control_global_resource_path (res_type,
76 : &global_resource_path);
77 0 : if (ret != APP_ERROR_NONE) {
78 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
79 : "Failed to get global resource path.");
80 : }
81 :
82 0 : new_path = g_strdup_printf ("%s/%s", global_resource_path, ori_path);
83 0 : ret = _ml_information_set (ml_info, "path", new_path, g_free);
84 0 : if (ret != ML_ERROR_NONE) {
85 0 : _ml_error_report_return (ret, "Failed to set path to the model info.");
86 : }
87 : } else {
88 0 : _ml_logi ("The model is not from rpk. Skip it.");
89 : }
90 :
91 0 : return ML_ERROR_NONE;
92 : }
93 :
94 : /**
95 : * @brief Get Tizen application info. It should be a json string.
96 : */
97 : static gchar *
98 0 : _get_app_info (void)
99 : {
100 0 : g_autofree gchar *app_id = NULL;
101 0 : g_autoptr (JsonBuilder) builder = NULL;
102 0 : g_autoptr (JsonGenerator) gen = NULL;
103 : int ret;
104 :
105 0 : ret = app_get_id (&app_id);
106 0 : if (ret == APP_ERROR_INVALID_CONTEXT) {
107 : /* Not a Tizen APP context, e.g. gbs build test */
108 0 : _ml_logi ("Not an APP context, skip creating app_info.");
109 0 : return NULL;
110 : }
111 :
112 : /**
113 : * @todo Check whether the given path is in the app's resource directory.
114 : * Below is sample code for this (unfortunately, TCT get error with it):
115 : * g_autofree gchar *app_resource_path = NULL;
116 : * g_autofree gchar *app_shared_resource_path = NULL;
117 : * app_resource_path = app_get_resource_path ();
118 : * app_shared_resource_path = app_get_shared_resource_path ();
119 : * if (!app_resource_path || !app_shared_resource_path) {
120 : * _ml_error_report_return (ML_ERROR_PERMISSION_DENIED,
121 : * "Failed to get the app resource path of the caller.");
122 : * }
123 : * if (!g_str_has_prefix (path, app_resource_path) &&
124 : * !g_str_has_prefix (path, app_shared_resource_path)) {
125 : * _ml_error_report_return (ML_ERROR_PERMISSION_DENIED,
126 : * "The model file '%s' is not in the app's resource directory.", path);
127 : * }
128 : */
129 0 : builder = json_builder_new ();
130 0 : json_builder_begin_object (builder);
131 :
132 0 : json_builder_set_member_name (builder, "is_rpk");
133 0 : json_builder_add_string_value (builder, "F");
134 :
135 0 : json_builder_set_member_name (builder, "app_id");
136 0 : json_builder_add_string_value (builder, app_id);
137 :
138 0 : json_builder_end_object (builder);
139 :
140 0 : gen = json_generator_new ();
141 0 : json_generator_set_root (gen, json_builder_get_root (builder));
142 0 : json_generator_set_pretty (gen, TRUE);
143 :
144 0 : return json_generator_to_data (gen, NULL);
145 : }
146 : #else
147 : #define _parse_app_info_and_update_path(...) ((int) ML_ERROR_NONE)
148 : #define _get_app_info(...) (NULL)
149 : #endif
150 :
151 : /**
152 : * @brief Build ml_information_h from json cstring.
153 : */
154 : static gint
155 0 : _build_ml_info_from_json_cstr (const gchar * jcstring, void **handle)
156 : {
157 0 : g_autoptr (GError) err = NULL;
158 0 : g_autoptr (JsonParser) parser = NULL;
159 0 : g_autoptr (GList) members = NULL;
160 0 : ml_information_list_h _info_list = NULL;
161 0 : ml_information_h _info = NULL;
162 0 : JsonNode *rnode = NULL;
163 0 : JsonArray *array = NULL;
164 0 : JsonObject *jobj = NULL;
165 : GList *l;
166 0 : gint ret = ML_ERROR_NONE;
167 : guint i, n;
168 :
169 0 : if (!handle) {
170 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
171 : "The argument for ml-information should not be NULL.");
172 : }
173 :
174 0 : if (NULL != *handle) {
175 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "info");
176 0 : *handle = NULL;
177 : }
178 :
179 0 : parser = json_parser_new ();
180 0 : if (!parser) {
181 0 : _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
182 : "Failed to allocate memory for JsonParser. Out of memory?");
183 : }
184 :
185 0 : if (!json_parser_load_from_data (parser, jcstring, -1, &err)) {
186 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
187 : "Failed to parse the json string (%s).",
188 : err ? err->message : "Unknown error");
189 : }
190 :
191 0 : rnode = json_parser_get_root (parser);
192 0 : if (!rnode) {
193 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
194 : "Failed to get the root node of json string.");
195 : }
196 :
197 0 : if (JSON_NODE_HOLDS_ARRAY (rnode)) {
198 0 : array = json_node_get_array (rnode);
199 0 : n = (array) ? json_array_get_length (array) : 0U;
200 : } else {
201 0 : n = 1U;
202 : }
203 :
204 0 : if (n == 0U) {
205 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
206 : "Failed to retrieve the length of the json array.");
207 : }
208 :
209 0 : if (array)
210 0 : ret = _ml_information_list_create (n, &_info_list);
211 : else
212 0 : ret = _ml_information_create (&_info);
213 0 : if (ML_ERROR_NONE != ret) {
214 0 : _ml_error_report ("Failed to parse app_info, cannot create info handle.");
215 0 : goto done;
216 : }
217 :
218 0 : for (i = 0; i < n; i++) {
219 0 : if (array) {
220 0 : jobj = json_array_get_object_element (array, i);
221 0 : ml_information_list_get (_info_list, i, &_info);
222 : } else {
223 0 : jobj = json_node_get_object (rnode);
224 : }
225 :
226 0 : members = json_object_get_members (jobj);
227 0 : for (l = members; l != NULL; l = l->next) {
228 0 : const gchar *key = l->data;
229 0 : const gchar *val = json_object_get_string_member (jobj, key);
230 :
231 : /* Prevent empty string case. */
232 0 : if (STR_IS_VALID (key) && STR_IS_VALID (val)) {
233 0 : ret = _ml_information_set (_info, key, g_strdup (val), g_free);
234 0 : if (ret != ML_ERROR_NONE) {
235 0 : _ml_error_report ("Failed to append app info to the info handle.");
236 0 : goto done;
237 : }
238 : }
239 : }
240 :
241 0 : ret = _parse_app_info_and_update_path (_info);
242 0 : if (ret != ML_ERROR_NONE) {
243 0 : _ml_error_report ("Failed to parse app_info and update path.");
244 0 : goto done;
245 : }
246 : }
247 :
248 0 : done:
249 0 : if (ret == ML_ERROR_NONE) {
250 0 : *handle = (array) ? _info_list : _info;
251 : } else {
252 0 : if (_info_list)
253 0 : ml_information_list_destroy (_info_list);
254 0 : if (_info)
255 0 : ml_information_destroy (_info);
256 : }
257 :
258 0 : return ret;
259 : }
260 :
261 : /**
262 : * @brief Internal function to check the path of model or resource.
263 : */
264 : static int
265 0 : _ml_service_check_path (const char *path)
266 : {
267 : int ret;
268 0 : g_autofree gchar *dir_name = NULL;
269 : GStatBuf statbuf;
270 :
271 0 : if (!path) {
272 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
273 : "The parameter, 'path' is NULL. It should be a valid string.");
274 : }
275 :
276 0 : if (g_file_test (path, G_FILE_TEST_IS_DIR))
277 0 : dir_name = g_strdup (path);
278 : else
279 0 : dir_name = g_path_get_dirname (path);
280 :
281 0 : ret = g_stat (dir_name, &statbuf);
282 0 : if (ret != 0) {
283 0 : _ml_error_report_return (ML_ERROR_PERMISSION_DENIED,
284 : "Failed to get the information of given path '%s'.", path);
285 : }
286 :
287 0 : if (!g_path_is_absolute (path)
288 0 : || !g_file_test (path, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
289 0 : || g_file_test (path, G_FILE_TEST_IS_SYMLINK)) {
290 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
291 : "Given path '%s' is not a regular.", path);
292 : }
293 :
294 0 : return ML_ERROR_NONE;
295 : }
296 :
297 : /**
298 : * @brief Set the pipeline description with a given name.
299 : */
300 : int
301 0 : ml_service_pipeline_set (const char *name, const char *pipeline_desc)
302 : {
303 0 : int ret = ML_ERROR_NONE;
304 :
305 0 : check_feature_state (ML_FEATURE_SERVICE);
306 :
307 0 : if (!name) {
308 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
309 : "The parameter, 'name' is NULL. It should be a valid string.");
310 : }
311 :
312 0 : if (!pipeline_desc) {
313 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
314 : "The parameter, 'pipeline_desc' is NULL. It should be a valid string.");
315 : }
316 :
317 0 : ret = ml_agent_pipeline_set_description (name, pipeline_desc);
318 0 : if (ret < 0) {
319 0 : _ml_error_report ("Failed to invoke the method set_pipeline.");
320 : }
321 :
322 0 : return ret;
323 : }
324 :
325 : /**
326 : * @brief Get the pipeline description with a given name.
327 : */
328 : int
329 0 : ml_service_pipeline_get (const char *name, char **pipeline_desc)
330 : {
331 0 : int ret = ML_ERROR_NONE;
332 :
333 0 : check_feature_state (ML_FEATURE_SERVICE);
334 :
335 0 : if (!name) {
336 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
337 : "The parameter, 'name' is NULL, It should be a valid string.");
338 : }
339 :
340 0 : if (pipeline_desc == NULL) {
341 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
342 : "The argument for 'pipeline_desc' should not be NULL.");
343 : }
344 :
345 0 : if (*pipeline_desc != NULL) {
346 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "char *pipeline_desc = NULL");
347 0 : *pipeline_desc = NULL;
348 : }
349 :
350 0 : ret = ml_agent_pipeline_get_description (name, pipeline_desc);
351 0 : if (ret < 0) {
352 0 : _ml_error_report ("Failed to invoke the method get_pipeline.");
353 : }
354 :
355 0 : return ret;
356 : }
357 :
358 : /**
359 : * @brief Delete the pipeline description with a given name.
360 : */
361 : int
362 0 : ml_service_pipeline_delete (const char *name)
363 : {
364 0 : int ret = ML_ERROR_NONE;
365 :
366 0 : check_feature_state (ML_FEATURE_SERVICE);
367 :
368 0 : if (!name) {
369 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
370 : "The parameter, 'name' is NULL, It should be a valid string.");
371 : }
372 :
373 0 : ret = ml_agent_pipeline_delete (name);
374 0 : if (ret < 0) {
375 0 : _ml_error_report ("Failed to invoke the method delete_pipeline.");
376 : }
377 :
378 0 : return ret;
379 : }
380 :
381 : /**
382 : * @brief Launch the pipeline of given service.
383 : */
384 : int
385 0 : ml_service_pipeline_launch (const char *name, ml_service_h * handle)
386 : {
387 0 : int ret = ML_ERROR_NONE;
388 : ml_service_s *mls;
389 : _ml_service_server_s *server;
390 :
391 0 : check_feature_state (ML_FEATURE_SERVICE);
392 :
393 0 : if (handle == NULL) {
394 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
395 : "The argument for 'handle' should not be NULL.");
396 : }
397 :
398 0 : if (*handle != NULL) {
399 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "ml_service_h *handle = NULL");
400 : }
401 0 : *handle = NULL;
402 :
403 0 : mls = _ml_service_create_internal (ML_SERVICE_TYPE_SERVER_PIPELINE);
404 0 : if (mls == NULL) {
405 0 : _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
406 : "Failed to allocate memory for the service handle. Out of memory?");
407 : }
408 :
409 0 : mls->priv = server = g_try_new0 (_ml_service_server_s, 1);
410 0 : if (server == NULL) {
411 0 : _ml_service_destroy_internal (mls);
412 0 : _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
413 : "Failed to allocate memory for the service handle's private data. Out of memory?");
414 : }
415 :
416 0 : ret = ml_agent_pipeline_launch (name, &(server->id));
417 0 : if (ret < 0) {
418 0 : _ml_service_destroy_internal (mls);
419 0 : _ml_error_report_return (ret,
420 : "Failed to invoke the method launch_pipeline.");
421 : }
422 :
423 0 : server->service_name = g_strdup (name);
424 0 : *handle = mls;
425 :
426 0 : return ML_ERROR_NONE;
427 : }
428 :
429 : /**
430 : * @brief Return state of given ml_service_h
431 : */
432 : int
433 0 : ml_service_pipeline_get_state (ml_service_h handle, ml_pipeline_state_e * state)
434 : {
435 0 : int ret = ML_ERROR_NONE;
436 0 : gint _state = ML_PIPELINE_STATE_UNKNOWN;
437 0 : ml_service_s *mls = (ml_service_s *) handle;
438 : _ml_service_server_s *server;
439 :
440 0 : check_feature_state (ML_FEATURE_SERVICE);
441 :
442 0 : if (NULL == state) {
443 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
444 : "The parameter 'state' should not be NULL.");
445 : }
446 0 : *state = ML_PIPELINE_STATE_UNKNOWN;
447 :
448 0 : if (!_ml_service_handle_is_valid (mls)) {
449 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
450 : "The parameter, 'handle' (ml_service_h), is invalid. It should be a valid ml_service_h instance.");
451 : }
452 :
453 0 : server = (_ml_service_server_s *) mls->priv;
454 0 : ret = ml_agent_pipeline_get_state (server->id, &_state);
455 0 : if (ret < 0) {
456 0 : _ml_error_report ("Failed to invoke the method get_state.");
457 : }
458 :
459 0 : *state = (ml_pipeline_state_e) _state;
460 0 : return ret;
461 : }
462 :
463 : /**
464 : * @brief Internal function to release ml-service pipeline data.
465 : */
466 : int
467 0 : ml_service_pipeline_release_internal (ml_service_s * mls)
468 : {
469 0 : _ml_service_server_s *server = (_ml_service_server_s *) mls->priv;
470 : int ret;
471 :
472 : /* Supposed internal function call to release handle. */
473 0 : if (!server)
474 0 : return ML_ERROR_NONE;
475 :
476 0 : if (server->id > 0) {
477 0 : ret = ml_agent_pipeline_destroy (server->id);
478 0 : if (ret < 0) {
479 0 : _ml_error_report_return (ret,
480 : "Failed to invoke the method destroy_pipeline.");
481 : }
482 : }
483 :
484 0 : g_free (server->service_name);
485 0 : g_free (server);
486 0 : mls->priv = NULL;
487 :
488 0 : return ML_ERROR_NONE;
489 : }
490 :
491 : /**
492 : * @brief Registers new information of a neural network model.
493 : */
494 : int
495 0 : ml_service_model_register (const char *name, const char *path,
496 : const bool activate, const char *description, unsigned int *version)
497 : {
498 0 : int ret = ML_ERROR_NONE;
499 0 : g_autofree gchar *app_info = NULL;
500 :
501 0 : check_feature_state (ML_FEATURE_SERVICE);
502 :
503 0 : if (!name) {
504 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
505 : "The parameter, 'name' is NULL. It should be a valid string.");
506 : }
507 :
508 0 : if (NULL == version) {
509 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
510 : "The parameter 'version' should not be NULL.");
511 : }
512 0 : *version = 0U;
513 :
514 0 : ret = _ml_service_check_path (path);
515 0 : if (ret != ML_ERROR_NONE)
516 0 : return ret;
517 :
518 0 : app_info = _get_app_info ();
519 :
520 0 : ret = ml_agent_model_register (name, path, activate,
521 0 : description ? description : "", app_info ? app_info : "", version);
522 0 : if (ret < 0) {
523 0 : _ml_error_report ("Failed to invoke the method model_register.");
524 : }
525 :
526 0 : return ret;
527 : }
528 :
529 : /**
530 : * @brief Updates the description of neural network model with given @a name and @a version.
531 : */
532 : int
533 0 : ml_service_model_update_description (const char *name,
534 : const unsigned int version, const char *description)
535 : {
536 0 : int ret = ML_ERROR_NONE;
537 :
538 0 : check_feature_state (ML_FEATURE_SERVICE);
539 :
540 0 : if (!name) {
541 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
542 : "The parameter, 'name' is NULL. It should be a valid string.");
543 : }
544 :
545 0 : if (version == 0U) {
546 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
547 : "The parameter, 'version' is 0. It should be a valid unsigned int.");
548 : }
549 :
550 0 : if (!description) {
551 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
552 : "The parameter, 'description' is NULL. It should be a valid string.");
553 : }
554 :
555 0 : ret = ml_agent_model_update_description (name, version, description);
556 0 : if (ret < 0) {
557 0 : _ml_error_report ("Failed to invoke the method model_update_description.");
558 : }
559 :
560 0 : return ret;
561 : }
562 :
563 : /**
564 : * @brief Activates a neural network model with given @a name and @a version.
565 : */
566 : int
567 0 : ml_service_model_activate (const char *name, const unsigned int version)
568 : {
569 0 : int ret = ML_ERROR_NONE;
570 :
571 0 : check_feature_state (ML_FEATURE_SERVICE);
572 :
573 0 : if (!name) {
574 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
575 : "The parameter, 'name' is NULL. It should be a valid string.");
576 : }
577 :
578 0 : if (version == 0U) {
579 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
580 : "The parameter, 'version' is 0. It should be a valid unsigned int.");
581 : }
582 :
583 0 : ret = ml_agent_model_activate (name, version);
584 0 : if (ret < 0) {
585 0 : _ml_error_report ("Failed to invoke the method model_activate.");
586 : }
587 :
588 0 : return ret;
589 : }
590 :
591 : /**
592 : * @brief Gets the information of neural network model with given @a name and @a version.
593 : */
594 : int
595 0 : ml_service_model_get (const char *name, const unsigned int version,
596 : ml_information_h * info)
597 : {
598 0 : int ret = ML_ERROR_NONE;
599 0 : ml_information_h _info = NULL;
600 0 : g_autofree gchar *description = NULL;
601 :
602 0 : check_feature_state (ML_FEATURE_SERVICE);
603 :
604 0 : if (!name) {
605 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
606 : "The parameter, 'name' is NULL. It should be a valid string.");
607 : }
608 :
609 0 : if (info == NULL) {
610 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
611 : "The argument for 'info' should not be NULL.");
612 : }
613 :
614 0 : if (*info != NULL) {
615 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "ml_information_h info = NULL");
616 : }
617 0 : *info = NULL;
618 :
619 0 : ret = ml_agent_model_get (name, version, &description);
620 0 : if (ML_ERROR_NONE != ret || !description) {
621 0 : _ml_error_report ("Failed to invoke the method model_get.");
622 0 : return ret;
623 : }
624 :
625 0 : ret = _build_ml_info_from_json_cstr (description, &_info);
626 0 : if (ML_ERROR_NONE != ret)
627 0 : _ml_error_report ("Failed to convert json string to ml-information.");
628 : else
629 0 : *info = _info;
630 :
631 0 : return ret;
632 : }
633 :
634 : /**
635 : * @brief Gets the information of activated neural network model with given @a name.
636 : */
637 : int
638 0 : ml_service_model_get_activated (const char *name, ml_information_h * info)
639 : {
640 0 : int ret = ML_ERROR_NONE;
641 :
642 0 : ml_information_h _info = NULL;
643 0 : g_autofree gchar *description = NULL;
644 :
645 0 : check_feature_state (ML_FEATURE_SERVICE);
646 :
647 0 : if (!name) {
648 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
649 : "The parameter, 'name' is NULL. It should be a valid string.");
650 : }
651 :
652 0 : if (info == NULL) {
653 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
654 : "The argument for 'info' should not be NULL.");
655 : }
656 :
657 0 : if (*info != NULL) {
658 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "ml_information_h info = NULL");
659 : }
660 0 : *info = NULL;
661 :
662 0 : ret = ml_agent_model_get_activated (name, &description);
663 0 : if (ML_ERROR_NONE != ret || !description) {
664 0 : _ml_error_report ("Failed to invoke the method model_get_activated.");
665 0 : return ret;
666 : }
667 :
668 0 : ret = _build_ml_info_from_json_cstr (description, &_info);
669 0 : if (ML_ERROR_NONE != ret)
670 0 : _ml_error_report ("Failed to convert json string to ml_information_h.");
671 : else
672 0 : *info = _info;
673 :
674 0 : return ret;
675 : }
676 :
677 : /**
678 : * @brief Gets the list of neural network model with given @a name.
679 : */
680 : int
681 0 : ml_service_model_get_all (const char *name, ml_information_list_h * info_list)
682 : {
683 0 : g_autofree gchar *description = NULL;
684 0 : ml_information_list_h _info_list = NULL;
685 0 : int ret = ML_ERROR_NONE;
686 :
687 0 : check_feature_state (ML_FEATURE_SERVICE);
688 :
689 0 : if (!name) {
690 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
691 : "The parameter, 'name' is NULL. It should be a valid string.");
692 : }
693 :
694 0 : if (NULL == info_list) {
695 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
696 : "The parameter 'info_list' should not be NULL.");
697 : }
698 0 : *info_list = NULL;
699 :
700 0 : ret = ml_agent_model_get_all (name, &description);
701 0 : if (ML_ERROR_NONE != ret || !description) {
702 0 : _ml_error_report_return (ret, "Failed to invoke the method model_get_all.");
703 : }
704 :
705 0 : ret = _build_ml_info_from_json_cstr (description, &_info_list);
706 0 : if (ML_ERROR_NONE != ret)
707 0 : _ml_error_report ("Failed to convert json string to ml-information list.");
708 : else
709 0 : *info_list = _info_list;
710 :
711 0 : return ret;
712 : }
713 :
714 : /**
715 : * @brief Deletes a model information with given @a name and @a version from machine learning service.
716 : */
717 : int
718 0 : ml_service_model_delete (const char *name, const unsigned int version)
719 : {
720 0 : int ret = ML_ERROR_NONE;
721 :
722 0 : check_feature_state (ML_FEATURE_SERVICE);
723 :
724 0 : if (!name) {
725 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
726 : "The parameter, 'name' is NULL. It should be a valid string.");
727 : }
728 :
729 0 : ret = ml_agent_model_delete (name, version, FALSE);
730 0 : if (ret < 0) {
731 0 : _ml_error_report ("Failed to invoke the method model_delete.");
732 : }
733 :
734 0 : return ret;
735 : }
736 :
737 : /**
738 : * @brief Adds new information of machine learning resources.
739 : */
740 : int
741 0 : ml_service_resource_add (const char *name, const char *path,
742 : const char *description)
743 : {
744 0 : int ret = ML_ERROR_NONE;
745 0 : g_autofree gchar *app_info = NULL;
746 :
747 0 : check_feature_state (ML_FEATURE_SERVICE);
748 :
749 0 : if (!name) {
750 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
751 : "The parameter, 'name' is NULL. It should be a valid string.");
752 : }
753 :
754 0 : ret = _ml_service_check_path (path);
755 0 : if (ret != ML_ERROR_NONE)
756 0 : return ret;
757 :
758 0 : app_info = _get_app_info ();
759 :
760 0 : ret = ml_agent_resource_add (name, path, description ? description : "",
761 0 : app_info ? app_info : "");
762 0 : if (ret < 0) {
763 0 : _ml_error_report ("Failed to invoke the method resource_add.");
764 : }
765 :
766 0 : return ret;
767 : }
768 :
769 : /**
770 : * @brief Deletes the information of the resources from machine learning service.
771 : */
772 : int
773 0 : ml_service_resource_delete (const char *name)
774 : {
775 0 : int ret = ML_ERROR_NONE;
776 :
777 0 : check_feature_state (ML_FEATURE_SERVICE);
778 :
779 0 : if (!name) {
780 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
781 : "The parameter, 'name' is NULL. It should be a valid string.");
782 : }
783 :
784 0 : ret = ml_agent_resource_delete (name);
785 0 : if (ret < 0) {
786 0 : _ml_error_report ("Failed to invoke the method resource_delete.");
787 : }
788 :
789 0 : return ret;
790 : }
791 :
792 : /**
793 : * @brief Gets the information of the resources from machine learning service.
794 : */
795 : int
796 0 : ml_service_resource_get (const char *name, ml_information_list_h * res)
797 : {
798 0 : int ret = ML_ERROR_NONE;
799 0 : ml_information_list_h _info_list = NULL;
800 0 : g_autofree gchar *res_info = NULL;
801 :
802 0 : check_feature_state (ML_FEATURE_SERVICE);
803 :
804 0 : if (!name) {
805 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
806 : "The parameter, 'name' is NULL. It should be a valid string.");
807 : }
808 :
809 0 : if (res == NULL) {
810 0 : _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
811 : "The argument for 'res' should not be NULL.");
812 : }
813 :
814 0 : if (*res != NULL) {
815 0 : _ml_logw (WARN_MSG_DPTR_SET_OVER, "ml_information_list_h res = NULL");
816 : }
817 0 : *res = NULL;
818 :
819 0 : ret = ml_agent_resource_get (name, &res_info);
820 0 : if (ML_ERROR_NONE != ret || !res_info) {
821 0 : _ml_error_report_return (ret, "Failed to invoke the method resource_get.");
822 : }
823 :
824 0 : ret = _build_ml_info_from_json_cstr (res_info, &_info_list);
825 0 : if (ML_ERROR_NONE != ret)
826 0 : _ml_error_report ("Failed to convert json string to ml-information list.");
827 : else
828 0 : *res = _info_list;
829 :
830 0 : return ret;
831 : }
|