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 service-db.cc
6 : * @date 29 Jul 2022
7 : * @brief Database implementation of ML Agent
8 : * @see https://github.com/nnstreamer/deviceMLOps.MLAgent
9 : * @author Sangjung Woo <sangjung.woo@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : */
12 :
13 : #include "service-db.hh"
14 : #include "service-db-util.h"
15 : #include "log.h"
16 :
17 : #define sqlite3_clear_errmsg(m) \
18 : do { \
19 : if (m) { \
20 : sqlite3_free (m); \
21 : (m) = nullptr; \
22 : } \
23 : } while (0)
24 :
25 : /**
26 : * @brief The version of pipeline table schema. It should be a positive integer.
27 : */
28 : #define TBL_VER_PIPELINE_DESCRIPTION (1)
29 :
30 : /**
31 : * @brief The version of model table schema. It should be a positive integer.
32 : */
33 : #define TBL_VER_MODEL_INFO (1)
34 :
35 : /**
36 : * @brief The version of resource table schema. It should be a positive integer.
37 : */
38 : #define TBL_VER_RESOURCE_INFO (1)
39 :
40 : typedef enum {
41 : TBL_DB_INFO = 0,
42 : TBL_PIPELINE_DESCRIPTION = 1,
43 : TBL_MODEL_INFO = 2,
44 : TBL_RESOURCE_INFO = 3,
45 :
46 : TBL_MAX
47 : } mlsvc_table_e;
48 :
49 : const char *g_mlsvc_table_schema_v1[] = {
50 : /* TBL_DB_INFO */ "tblMLDBInfo (name TEXT PRIMARY KEY NOT NULL, version INTEGER DEFAULT 1)",
51 : /* TBL_PIPELINE_DESCRIPTION */ "tblPipeline (key TEXT PRIMARY KEY NOT NULL, description TEXT, CHECK (length(description) > 0))",
52 : /* TBL_MODEL_INFO */ "tblModel (key TEXT NOT NULL, version INTEGER DEFAULT 1, active TEXT DEFAULT 'F', path TEXT, description TEXT, app_info TEXT, PRIMARY KEY (key, version), CHECK (length(path) > 0), CHECK (active IN ('T', 'F')))",
53 : /* TBL_RESOURCE_INFO */ "tblResource (key TEXT NOT NULL, path TEXT, description TEXT, app_info TEXT, PRIMARY KEY (key, path), CHECK (length(path) > 0))",
54 : /* Sentinel */ NULL
55 : };
56 :
57 : const char **g_mlsvc_table_schema = g_mlsvc_table_schema_v1;
58 :
59 : /**
60 : * @brief Construct a new MLServiceDB object.
61 : * @param path database path
62 : */
63 60 : MLServiceDB::MLServiceDB (std::string path)
64 60 : : _path (path), _initialized (false), _db (nullptr)
65 : {
66 60 : }
67 :
68 : /**
69 : * @brief Destroy the MLServiceDB object.
70 : */
71 92 : MLServiceDB::~MLServiceDB ()
72 : {
73 60 : disconnectDB ();
74 60 : _initialized = false;
75 124 : }
76 :
77 : /**
78 : * @brief Create table and handle database version.
79 : */
80 : void
81 49 : MLServiceDB::initDB ()
82 : {
83 : int i, tbl_ver;
84 :
85 49 : if (_initialized)
86 0 : return;
87 :
88 : /**
89 : * @todo data migration
90 : * handle database version and update each table
91 : * 1. get all records from table
92 : * 2. drop old table
93 : * 3. create new table and insert records
94 : */
95 49 : if (!set_transaction (true))
96 0 : return;
97 :
98 : /* Create tables. */
99 245 : for (i = 0; i < TBL_MAX; i++) {
100 588 : if (!create_table (g_mlsvc_table_schema[i]))
101 0 : return;
102 : }
103 :
104 : /* Check pipeline table. */
105 98 : if ((tbl_ver = get_table_version ("tblPipeline", TBL_VER_PIPELINE_DESCRIPTION)) < 0)
106 0 : return;
107 :
108 : if (tbl_ver != TBL_VER_PIPELINE_DESCRIPTION) {
109 : /** @todo update pipeline table if table schema is changed */
110 : }
111 :
112 98 : if (!set_table_version ("tblPipeline", TBL_VER_PIPELINE_DESCRIPTION))
113 0 : return;
114 :
115 : /* Check model table. */
116 98 : if ((tbl_ver = get_table_version ("tblModel", TBL_VER_MODEL_INFO)) < 0)
117 0 : return;
118 :
119 : if (tbl_ver != TBL_VER_MODEL_INFO) {
120 : /** @todo update model table if table schema is changed */
121 : }
122 :
123 98 : if (!set_table_version ("tblModel", TBL_VER_MODEL_INFO))
124 0 : return;
125 :
126 : /* Check resource table. */
127 98 : if ((tbl_ver = get_table_version ("tblResource", TBL_VER_RESOURCE_INFO)) < 0)
128 0 : return;
129 :
130 : if (tbl_ver != TBL_VER_RESOURCE_INFO) {
131 : /** @todo update resource table if table schema is changed */
132 : }
133 :
134 98 : if (!set_table_version ("tblResource", TBL_VER_RESOURCE_INFO))
135 0 : return;
136 :
137 49 : if (!set_transaction (false))
138 0 : return;
139 :
140 49 : _initialized = true;
141 : }
142 :
143 : /**
144 : * @brief Connect to ML Service DB and initialize the private variables.
145 : */
146 : void
147 49 : MLServiceDB::connectDB ()
148 : {
149 : int rc;
150 :
151 49 : if (_db != nullptr)
152 0 : return;
153 :
154 49 : g_autofree gchar *db_path = g_strdup_printf ("%s/.ml-service.db", _path.c_str ());
155 49 : rc = sqlite3_open (db_path, &_db);
156 49 : if (rc != SQLITE_OK) {
157 0 : ml_loge ("Failed to open database: %s (ret: %d, path: %s)",
158 : sqlite3_errmsg (_db), rc, _path.c_str ());
159 0 : goto error;
160 : }
161 :
162 49 : initDB ();
163 :
164 49 : error:
165 49 : if (!_initialized) {
166 0 : disconnectDB ();
167 0 : throw std::runtime_error ("Failed to connect DB.");
168 : }
169 49 : }
170 :
171 : /**
172 : * @brief Disconnect the DB.
173 : */
174 : void
175 109 : MLServiceDB::disconnectDB ()
176 : {
177 109 : if (_db) {
178 49 : sqlite3_close (_db);
179 49 : _db = nullptr;
180 : }
181 109 : }
182 :
183 : /**
184 : * @brief Get table version.
185 : */
186 : int
187 147 : MLServiceDB::get_table_version (const std::string tbl_name, const int default_ver)
188 : {
189 : int rc, tbl_ver;
190 : sqlite3_stmt *res;
191 147 : std::string sql = "SELECT version FROM tblMLDBInfo WHERE name = '" + tbl_name + "';";
192 :
193 147 : rc = sqlite3_prepare_v2 (_db, sql.c_str (), -1, &res, nullptr);
194 147 : if (rc != SQLITE_OK) {
195 0 : ml_logw ("Failed to get the version of table %s: %s (%d)",
196 : tbl_name.c_str (), sqlite3_errmsg (_db), rc);
197 0 : return -1;
198 : }
199 :
200 147 : tbl_ver = (sqlite3_step (res) == SQLITE_ROW) ? sqlite3_column_int (res, 0) : default_ver;
201 147 : sqlite3_finalize (res);
202 :
203 147 : return tbl_ver;
204 147 : }
205 :
206 : /**
207 : * @brief Set table version.
208 : */
209 : bool
210 147 : MLServiceDB::set_table_version (const std::string tbl_name, const int tbl_ver)
211 : {
212 : sqlite3_stmt *res;
213 147 : std::string sql = "INSERT OR REPLACE INTO tblMLDBInfo VALUES (?1, ?2);";
214 :
215 147 : bool is_done = (sqlite3_prepare_v2 (_db, sql.c_str (), -1, &res, nullptr) == SQLITE_OK
216 147 : && sqlite3_bind_text (res, 1, tbl_name.c_str (), -1, nullptr) == SQLITE_OK
217 147 : && sqlite3_bind_int (res, 2, tbl_ver) == SQLITE_OK
218 294 : && sqlite3_step (res) == SQLITE_DONE);
219 :
220 147 : sqlite3_finalize (res);
221 :
222 147 : if (!is_done)
223 0 : ml_logw ("Failed to update version of table %s.", tbl_name.c_str ());
224 147 : return is_done;
225 147 : }
226 :
227 : /**
228 : * @brief Create DB table.
229 : */
230 : bool
231 196 : MLServiceDB::create_table (const std::string tbl_name)
232 : {
233 : int rc;
234 196 : char *errmsg = nullptr;
235 196 : std::string sql = "CREATE TABLE IF NOT EXISTS " + tbl_name;
236 :
237 196 : rc = sqlite3_exec (_db, sql.c_str (), nullptr, nullptr, &errmsg);
238 196 : if (rc != SQLITE_OK) {
239 0 : ml_logw ("Failed to create table %s: %s (%d)", tbl_name.c_str (), errmsg, rc);
240 0 : sqlite3_clear_errmsg (errmsg);
241 0 : return false;
242 : }
243 :
244 196 : return true;
245 196 : }
246 :
247 : /**
248 : * @brief Begin/end transaction.
249 : */
250 : bool
251 165 : MLServiceDB::set_transaction (bool begin)
252 : {
253 : int rc;
254 165 : char *errmsg = nullptr;
255 :
256 165 : rc = sqlite3_exec (_db, begin ? "BEGIN TRANSACTION;" : "END TRANSACTION;",
257 : nullptr, nullptr, &errmsg);
258 165 : if (rc != SQLITE_OK)
259 3 : ml_logw ("Failed to %s transaction: %s (%d)", begin ? "begin" : "end", errmsg, rc);
260 :
261 165 : sqlite3_clear_errmsg (errmsg);
262 165 : return (rc == SQLITE_OK);
263 : }
264 :
265 : /**
266 : * @brief Set the pipeline description with the given name.
267 : * @note If the name already exists, the pipeline description is overwritten.
268 : * @param[in] name Unique name to set the associated pipeline description.
269 : * @param[in] description The pipeline description to be stored.
270 : */
271 : void
272 9 : MLServiceDB::set_pipeline (const std::string name, const std::string description)
273 : {
274 : sqlite3_stmt *res;
275 :
276 9 : if (name.empty () || description.empty ())
277 4 : throw std::invalid_argument ("Invalid name or value parameters!");
278 :
279 5 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
280 5 : key_with_prefix += name;
281 :
282 5 : if (!set_transaction (true))
283 1 : throw std::runtime_error ("Failed to begin transaction.");
284 :
285 4 : if (sqlite3_prepare_v2 (_db,
286 : "INSERT OR REPLACE INTO tblPipeline VALUES (?1, ?2)", -1, &res, nullptr)
287 : != SQLITE_OK
288 4 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
289 4 : || sqlite3_bind_text (res, 2, description.c_str (), -1, nullptr) != SQLITE_OK
290 8 : || sqlite3_step (res) != SQLITE_DONE) {
291 0 : sqlite3_finalize (res);
292 0 : throw std::runtime_error ("Failed to insert pipeline description of " + name);
293 : }
294 :
295 4 : sqlite3_finalize (res);
296 :
297 4 : if (!set_transaction (false))
298 0 : throw std::runtime_error ("Failed to end transaction.");
299 5 : }
300 :
301 : /**
302 : * @brief Get the pipeline description with the given name.
303 : * @param[in] name The unique name to retrieve.
304 : * @param[out] description The pipeline corresponding with the given name.
305 : */
306 : void
307 10 : MLServiceDB::get_pipeline (const std::string name, gchar **description)
308 : {
309 10 : char *value = nullptr;
310 : sqlite3_stmt *res;
311 :
312 10 : if (name.empty () || !description)
313 4 : throw std::invalid_argument ("Invalid name or description parameter!");
314 :
315 6 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
316 6 : key_with_prefix += name;
317 :
318 6 : if (sqlite3_prepare_v2 (_db,
319 : "SELECT description FROM tblPipeline WHERE key = ?1", -1, &res, nullptr)
320 : == SQLITE_OK
321 5 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
322 11 : && sqlite3_step (res) == SQLITE_ROW)
323 3 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
324 :
325 6 : sqlite3_finalize (res);
326 :
327 6 : if (value) {
328 3 : *description = value;
329 : } else {
330 3 : throw std::invalid_argument ("Failed to get pipeline description of " + name);
331 : }
332 6 : }
333 :
334 : /**
335 : * @brief Delete the pipeline description with a given name.
336 : * @param[in] name The unique name to delete.
337 : */
338 : void
339 8 : MLServiceDB::delete_pipeline (const std::string name)
340 : {
341 : sqlite3_stmt *res;
342 :
343 8 : if (name.empty ())
344 2 : throw std::invalid_argument ("Invalid name parameters!");
345 :
346 6 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
347 6 : key_with_prefix += name;
348 :
349 6 : if (sqlite3_prepare_v2 (_db, "DELETE FROM tblPipeline WHERE key = ?1", -1, &res, nullptr) != SQLITE_OK
350 5 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
351 11 : || sqlite3_step (res) != SQLITE_DONE) {
352 1 : sqlite3_finalize (res);
353 1 : throw std::runtime_error ("Failed to delete pipeline description of " + name);
354 : }
355 :
356 5 : sqlite3_finalize (res);
357 :
358 5 : if (sqlite3_changes (_db) == 0) {
359 1 : throw std::invalid_argument ("There is no pipeline description of " + name);
360 : }
361 6 : }
362 :
363 : /**
364 : * @brief Check the model is registered.
365 : */
366 : bool
367 40 : MLServiceDB::is_model_registered (const std::string key, const guint version)
368 : {
369 : sqlite3_stmt *res;
370 : gchar *sql;
371 : bool registered;
372 :
373 40 : if (version > 0U)
374 17 : sql = g_strdup_printf (
375 : "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = %u)", version);
376 : else
377 23 : sql = g_strdup ("SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1)");
378 :
379 : registered
380 78 : = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
381 38 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
382 38 : || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1);
383 40 : sqlite3_finalize (res);
384 40 : g_free (sql);
385 :
386 40 : return registered;
387 : }
388 :
389 : /**
390 : * @brief Check the model is activated.
391 : */
392 : bool
393 1 : MLServiceDB::is_model_activated (const std::string key, const guint version)
394 : {
395 : sqlite3_stmt *res;
396 : gchar *sql;
397 : bool activated;
398 :
399 1 : sql = g_strdup ("SELECT active FROM tblModel WHERE key = ?1 AND version = ?2");
400 :
401 2 : activated = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
402 1 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
403 1 : || sqlite3_bind_int (res, 2, version) != SQLITE_OK
404 1 : || sqlite3_step (res) != SQLITE_ROW
405 1 : || !g_str_equal (sqlite3_column_text (res, 0), "T"));
406 1 : sqlite3_finalize (res);
407 1 : g_free (sql);
408 :
409 1 : return activated;
410 : }
411 :
412 : /**
413 : * @brief Check the resource is registered.
414 : */
415 : bool
416 16 : MLServiceDB::is_resource_registered (const std::string key)
417 : {
418 : sqlite3_stmt *res;
419 : gchar *sql;
420 : bool registered;
421 :
422 16 : sql = g_strdup_printf ("SELECT EXISTS(SELECT 1 FROM tblResource WHERE key = ?1)");
423 :
424 : registered
425 30 : = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
426 14 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
427 14 : || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1);
428 16 : sqlite3_finalize (res);
429 16 : g_free (sql);
430 :
431 16 : return registered;
432 : }
433 :
434 : /**
435 : * @brief Set the model with the given name.
436 : * @param[in] name Unique name for model.
437 : * @param[in] model The model to be stored.
438 : * @param[in] is_active The model is active or not.
439 : * @param[in] description The model description.
440 : * @param[in] app_info The application information.
441 : * @param[out] version The version of the model.
442 : */
443 : void
444 20 : MLServiceDB::set_model (const std::string name, const std::string model, const bool is_active,
445 : const std::string description, const std::string app_info, guint *version)
446 : {
447 20 : guint _version = 0U;
448 : sqlite3_stmt *res;
449 :
450 20 : if (name.empty () || model.empty () || !version)
451 6 : throw std::invalid_argument ("Invalid name, model, or version parameter!");
452 :
453 14 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
454 14 : key_with_prefix += name;
455 :
456 14 : if (!set_transaction (true))
457 1 : throw std::runtime_error ("Failed to begin transaction.");
458 :
459 : /* set other models as NOT active */
460 13 : if (is_active) {
461 6 : if (sqlite3_prepare_v2 (_db,
462 : "UPDATE tblModel SET active = 'F' WHERE key = ?1", -1, &res, nullptr)
463 : != SQLITE_OK
464 6 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
465 12 : || sqlite3_step (res) != SQLITE_DONE) {
466 0 : sqlite3_finalize (res);
467 0 : throw std::runtime_error ("Failed to set other models as NOT active.");
468 : }
469 6 : sqlite3_finalize (res);
470 : }
471 :
472 : /* insert new row */
473 13 : if (sqlite3_prepare_v2 (_db, "INSERT OR REPLACE INTO tblModel VALUES (?1, IFNULL ((SELECT version from tblModel WHERE key = ?2 ORDER BY version DESC LIMIT 1) + 1, 1), ?3, ?4, ?5, ?6)",
474 : -1, &res, nullptr)
475 : != SQLITE_OK
476 13 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
477 13 : || sqlite3_bind_text (res, 2, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
478 13 : || sqlite3_bind_text (res, 3, is_active ? "T" : "F", -1, nullptr) != SQLITE_OK
479 13 : || sqlite3_bind_text (res, 4, model.c_str (), -1, nullptr) != SQLITE_OK
480 13 : || sqlite3_bind_text (res, 5, description.c_str (), -1, nullptr) != SQLITE_OK
481 13 : || sqlite3_bind_text (res, 6, app_info.c_str (), -1, nullptr) != SQLITE_OK
482 26 : || sqlite3_step (res) != SQLITE_DONE) {
483 0 : sqlite3_finalize (res);
484 0 : throw std::runtime_error ("Failed to register the model " + name);
485 : }
486 :
487 13 : sqlite3_finalize (res);
488 :
489 13 : long long int last_id = sqlite3_last_insert_rowid (_db);
490 13 : if (last_id == 0) {
491 0 : ml_loge ("Failed to get last inserted row id: %s", sqlite3_errmsg (_db));
492 0 : throw std::runtime_error ("Failed to get last inserted row id.");
493 : }
494 :
495 : /* get model's version */
496 13 : if (sqlite3_prepare_v2 (_db, "SELECT version FROM tblModel WHERE rowid = ? ORDER BY version DESC LIMIT 1;",
497 : -1, &res, nullptr)
498 : == SQLITE_OK
499 13 : && sqlite3_bind_int (res, 1, last_id) == SQLITE_OK && sqlite3_step (res) == SQLITE_ROW) {
500 13 : _version = sqlite3_column_int (res, 0);
501 : }
502 :
503 13 : sqlite3_finalize (res);
504 :
505 13 : if (!set_transaction (false))
506 0 : throw std::runtime_error ("Failed to end transaction.");
507 :
508 13 : if (_version == 0) {
509 0 : ml_loge ("Failed to get model version with name %s: %s", name.c_str (),
510 : sqlite3_errmsg (_db));
511 0 : throw std::invalid_argument ("Failed to get model version of " + name);
512 : }
513 :
514 13 : *version = _version;
515 14 : }
516 :
517 : /**
518 : * @brief Update the model description with the given name.
519 : * @param[in] name Unique name for model.
520 : * @param[in] version The version of the model.
521 : * @param[in] description The model description.
522 : */
523 : void
524 11 : MLServiceDB::update_model_description (
525 : const std::string name, const guint version, const std::string description)
526 : {
527 : sqlite3_stmt *res;
528 :
529 11 : if (name.empty () || description.empty ())
530 4 : throw std::invalid_argument ("Invalid name or description parameter!");
531 :
532 7 : if (version == 0U)
533 3 : throw std::invalid_argument ("Invalid version number!");
534 :
535 4 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
536 4 : key_with_prefix += name;
537 :
538 : /* check the existence of given model */
539 4 : if (!is_model_registered (key_with_prefix, version)) {
540 2 : throw std::invalid_argument ("Failed to check the existence of " + name
541 4 : + " version " + std::to_string (version));
542 : }
543 :
544 2 : if (!set_transaction (true))
545 0 : throw std::runtime_error ("Failed to begin transaction.");
546 :
547 : /* update model description */
548 2 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET description = ?1 WHERE key = ?2 AND version = ?3",
549 : -1, &res, nullptr)
550 : != SQLITE_OK
551 2 : || sqlite3_bind_text (res, 1, description.c_str (), -1, nullptr) != SQLITE_OK
552 2 : || sqlite3_bind_text (res, 2, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
553 4 : || sqlite3_bind_int (res, 3, version) != SQLITE_OK || sqlite3_step (res) != SQLITE_DONE) {
554 0 : sqlite3_finalize (res);
555 0 : throw std::runtime_error ("Failed to update model description.");
556 : }
557 :
558 2 : sqlite3_finalize (res);
559 :
560 2 : if (!set_transaction (false))
561 0 : throw std::runtime_error ("Failed to end transaction.");
562 4 : }
563 :
564 : /**
565 : * @brief Activate the model with the given name.
566 : * @param[in] name Unique name for model.
567 : * @param[in] version The version of the model.
568 : */
569 : void
570 9 : MLServiceDB::activate_model (const std::string name, const guint version)
571 : {
572 : sqlite3_stmt *res;
573 :
574 9 : if (name.empty ())
575 2 : throw std::invalid_argument ("Invalid name parameter!");
576 :
577 7 : if (version == 0U)
578 3 : throw std::invalid_argument ("Invalid version number!");
579 :
580 4 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
581 4 : key_with_prefix += name;
582 :
583 : /* check the existence */
584 4 : if (!is_model_registered (key_with_prefix, version)) {
585 2 : throw std::invalid_argument ("There is no model with name " + name
586 4 : + " and version " + std::to_string (version));
587 : }
588 :
589 2 : if (!set_transaction (true))
590 0 : throw std::runtime_error ("Failed to begin transaction.");
591 :
592 : /* set other row active as F */
593 2 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET active = 'F' WHERE key = ?1", -1, &res, nullptr) != SQLITE_OK
594 2 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
595 4 : || sqlite3_step (res) != SQLITE_DONE) {
596 0 : sqlite3_finalize (res);
597 0 : throw std::runtime_error ("Failed to deactivate other models of " + name);
598 : }
599 :
600 2 : sqlite3_finalize (res);
601 :
602 : /* set the given row active as T */
603 2 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET active = 'T' WHERE key = ?1 AND version = ?2",
604 : -1, &res, nullptr)
605 : != SQLITE_OK
606 2 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
607 4 : || sqlite3_bind_int (res, 2, version) != SQLITE_OK || sqlite3_step (res) != SQLITE_DONE) {
608 0 : sqlite3_finalize (res);
609 0 : throw std::runtime_error ("Failed to activate model with name " + name
610 0 : + " and version " + std::to_string (version));
611 : }
612 :
613 2 : sqlite3_finalize (res);
614 :
615 2 : if (!set_transaction (false))
616 0 : throw std::runtime_error ("Failed to end transaction.");
617 4 : }
618 :
619 : /**
620 : * @brief Get the model with the given name.
621 : * @param[in] name The unique name to retrieve.
622 : * @param[in] version The version of the model. If it is 0, all models will return, if it is -1, return the active model.
623 : * @param[out] model The model corresponding with the given name.
624 : */
625 : void
626 24 : MLServiceDB::get_model (const std::string name, const gint version, gchar **model)
627 : {
628 24 : const char model_info_json[]
629 : = "json_object('version', CAST(version AS TEXT), 'active', active, 'path', path, 'description', description, 'app_info', app_info)";
630 : char *sql;
631 24 : char *value = nullptr;
632 : sqlite3_stmt *res;
633 :
634 24 : if (name.empty () || !model)
635 8 : throw std::invalid_argument ("Invalid name or model parameters!");
636 :
637 16 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
638 16 : key_with_prefix += name;
639 :
640 : /* check the existence of given model */
641 16 : guint ver = (version > 0) ? version : 0U;
642 16 : if (!is_model_registered (key_with_prefix, ver)) {
643 6 : throw std::invalid_argument ("Failed to check the existence of " + name);
644 : }
645 :
646 10 : if (version == 0)
647 4 : sql = g_strdup_printf (
648 : "SELECT json_group_array(%s) FROM tblModel WHERE key = ?1", model_info_json);
649 6 : else if (version == -1)
650 4 : sql = g_strdup_printf ("SELECT %s FROM tblModel WHERE key = ?1 and active = 'T' ORDER BY version DESC LIMIT 1",
651 : model_info_json);
652 2 : else if (version > 0)
653 2 : sql = g_strdup_printf ("SELECT %s FROM tblModel WHERE key = ?1 and version = %d",
654 : model_info_json, version);
655 : else
656 0 : throw std::invalid_argument ("Invalid version parameter!");
657 :
658 10 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) == SQLITE_OK
659 10 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
660 20 : && sqlite3_step (res) == SQLITE_ROW)
661 9 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
662 :
663 10 : sqlite3_finalize (res);
664 10 : g_free (sql);
665 :
666 10 : if (value) {
667 9 : *model = value;
668 : } else {
669 1 : throw std::invalid_argument ("Failed to get model with name " + name
670 2 : + " and version " + std::to_string (version));
671 : }
672 16 : }
673 :
674 : /**
675 : * @brief Delete the model.
676 : * @param[in] name The unique name to delete.
677 : * @param[in] version The version of the model to delete.
678 : * @param[in] force The model to delete by force (default is false).
679 : */
680 : void
681 18 : MLServiceDB::delete_model (const std::string name, const guint version, const gboolean force)
682 : {
683 : char *sql;
684 : sqlite3_stmt *res;
685 :
686 18 : if (name.empty ())
687 2 : throw std::invalid_argument ("Invalid name parameters!");
688 :
689 16 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
690 16 : key_with_prefix += name;
691 :
692 : /* existence check */
693 16 : if (!is_model_registered (key_with_prefix, version)) {
694 4 : throw std::invalid_argument ("There is no model with name " + name
695 8 : + " and version " + std::to_string (version));
696 : }
697 :
698 12 : if (version > 0U) {
699 3 : if (force)
700 2 : ml_logw ("The model with name %s and version %u may be activated, delete it from ml-service.",
701 : name.c_str (), version);
702 1 : else if (is_model_activated (key_with_prefix, version))
703 1 : throw std::invalid_argument ("The model with name " + name
704 2 : + " and version " + std::to_string (version)
705 3 : + " is activated, cannot delete it.");
706 :
707 2 : sql = g_strdup_printf ("DELETE FROM tblModel WHERE key = ?1 and version = %u", version);
708 : } else {
709 9 : sql = g_strdup ("DELETE FROM tblModel WHERE key = ?1");
710 : }
711 :
712 11 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
713 11 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
714 22 : || sqlite3_step (res) != SQLITE_DONE) {
715 0 : sqlite3_finalize (res);
716 0 : g_free (sql);
717 0 : throw std::runtime_error ("Failed to delete model with name " + name
718 0 : + " and version " + std::to_string (version));
719 : }
720 :
721 11 : sqlite3_finalize (res);
722 11 : g_free (sql);
723 :
724 11 : if (sqlite3_changes (_db) == 0) {
725 0 : throw std::invalid_argument ("There is no model with the given name " + name
726 0 : + " and version " + std::to_string (version));
727 : }
728 16 : }
729 :
730 : /**
731 : * @brief Set the resource with given name.
732 : * @param[in] name Unique name of ml-resource.
733 : * @param[in] path The path to be stored.
734 : * @param[in] description The description for ml-resource.
735 : * @param[in] app_info The application information.
736 : */
737 : void
738 16 : MLServiceDB::set_resource (const std::string name, const std::string path,
739 : const std::string description, const std::string app_info)
740 : {
741 : sqlite3_stmt *res;
742 :
743 16 : if (name.empty () || path.empty ())
744 4 : throw std::invalid_argument ("Invalid name or path parameter!");
745 :
746 12 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
747 12 : key_with_prefix += name;
748 :
749 12 : if (!set_transaction (true))
750 1 : throw std::runtime_error ("Failed to begin transaction.");
751 :
752 11 : if (sqlite3_prepare_v2 (_db,
753 : "INSERT OR REPLACE INTO tblResource VALUES (?1, ?2, ?3, ?4)", -1, &res, nullptr)
754 : != SQLITE_OK
755 11 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
756 11 : || sqlite3_bind_text (res, 2, path.c_str (), -1, nullptr) != SQLITE_OK
757 11 : || sqlite3_bind_text (res, 3, description.c_str (), -1, nullptr) != SQLITE_OK
758 11 : || sqlite3_bind_text (res, 4, app_info.c_str (), -1, nullptr) != SQLITE_OK
759 22 : || sqlite3_step (res) != SQLITE_DONE) {
760 0 : sqlite3_finalize (res);
761 0 : throw std::runtime_error ("Failed to add the resource " + name);
762 : }
763 :
764 11 : sqlite3_finalize (res);
765 :
766 11 : if (!set_transaction (false))
767 0 : throw std::runtime_error ("Failed to end transaction.");
768 :
769 11 : long long int last_id = sqlite3_last_insert_rowid (_db);
770 11 : if (last_id == 0) {
771 0 : ml_loge ("Failed to get last inserted row id: %s", sqlite3_errmsg (_db));
772 0 : throw std::runtime_error ("Failed to get last inserted row id.");
773 : }
774 12 : }
775 :
776 : /**
777 : * @brief Get the resource with given name.
778 : * @param[in] name The unique name to retrieve.
779 : * @param[out] resource The resource corresponding with the given name.
780 : */
781 : void
782 11 : MLServiceDB::get_resource (const std::string name, gchar **resource)
783 : {
784 11 : const char res_info_json[]
785 : = "json_object('path', path, 'description', description, 'app_info', app_info)";
786 : char *sql;
787 11 : char *value = nullptr;
788 : sqlite3_stmt *res;
789 :
790 11 : if (name.empty () || !resource)
791 4 : throw std::invalid_argument ("Invalid name or resource parameters!");
792 :
793 7 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
794 7 : key_with_prefix += name;
795 :
796 : /* existence check */
797 7 : if (!is_resource_registered (key_with_prefix))
798 3 : throw std::invalid_argument ("There is no resource with name " + name);
799 :
800 : /* Get json string with insertion order. */
801 4 : sql = g_strdup_printf ("SELECT json_group_array(%s) FROM (SELECT * FROM tblResource WHERE key = ?1 ORDER BY ROWID ASC)",
802 : res_info_json);
803 :
804 4 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) == SQLITE_OK
805 4 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
806 8 : && sqlite3_step (res) == SQLITE_ROW)
807 4 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
808 :
809 4 : sqlite3_finalize (res);
810 4 : g_free (sql);
811 :
812 4 : if (!value)
813 0 : throw std::invalid_argument ("Failed to get resource with name " + name);
814 :
815 4 : *resource = value;
816 7 : }
817 :
818 : /**
819 : * @brief Delete the resource.
820 : * @param[in] name The unique name to delete.
821 : */
822 : void
823 11 : MLServiceDB::delete_resource (const std::string name)
824 : {
825 : char *sql;
826 : sqlite3_stmt *res;
827 :
828 11 : if (name.empty ())
829 2 : throw std::invalid_argument ("Invalid name parameters!");
830 :
831 9 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
832 9 : key_with_prefix += name;
833 :
834 : /* existence check */
835 9 : if (!is_resource_registered (key_with_prefix))
836 3 : throw std::invalid_argument ("There is no resource with name " + name);
837 :
838 6 : sql = g_strdup ("DELETE FROM tblResource WHERE key = ?1");
839 :
840 6 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
841 6 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
842 12 : || sqlite3_step (res) != SQLITE_DONE) {
843 0 : sqlite3_finalize (res);
844 0 : g_free (sql);
845 0 : throw std::runtime_error ("Failed to delete resource with name " + name);
846 : }
847 :
848 6 : sqlite3_finalize (res);
849 6 : g_free (sql);
850 :
851 6 : if (sqlite3_changes (_db) == 0)
852 0 : throw std::invalid_argument ("There is no resource with name " + name);
853 9 : }
854 :
855 : static MLServiceDB *g_svcdb_instance = nullptr;
856 :
857 : /**
858 : * @brief Get the service-db instance.
859 : */
860 : static MLServiceDB *
861 104 : svcdb_get (void)
862 : {
863 104 : g_assert (g_svcdb_instance);
864 104 : return g_svcdb_instance;
865 : }
866 :
867 : G_BEGIN_DECLS
868 : /**
869 : * @brief Initialize the service-db.
870 : */
871 : gint
872 32 : svcdb_initialize (const gchar *path)
873 : {
874 32 : gint ret = 0;
875 :
876 32 : if (g_svcdb_instance) {
877 0 : ml_logw ("ML service DB is already opened, close old DB.");
878 0 : svcdb_finalize ();
879 : }
880 :
881 : try {
882 64 : g_svcdb_instance = new MLServiceDB (path);
883 32 : g_svcdb_instance->connectDB ();
884 0 : } catch (const std::exception &e) {
885 0 : ml_loge ("Failed to initialize database: %s", e.what ());
886 0 : svcdb_finalize ();
887 0 : ret = -EIO;
888 0 : }
889 :
890 32 : return ret;
891 : }
892 :
893 : /**
894 : * @brief Close the service-db.
895 : */
896 : void
897 32 : svcdb_finalize (void)
898 : {
899 32 : if (g_svcdb_instance) {
900 32 : g_svcdb_instance->disconnectDB ();
901 32 : delete g_svcdb_instance;
902 : }
903 :
904 32 : g_svcdb_instance = nullptr;
905 32 : }
906 :
907 : /**
908 : * @brief Set the pipeline description with given name.
909 : * @note If the name already exists, the pipeline description is overwritten.
910 : * @param[in] name Unique name to set the associated pipeline description.
911 : * @param[in] description The pipeline description to be stored.
912 : * @return @c 0 on success. Otherwise a negative error value.
913 : */
914 : gint
915 8 : svcdb_pipeline_set (const gchar *name, const gchar *description)
916 : {
917 8 : gint ret = 0;
918 8 : MLServiceDB *db = svcdb_get ();
919 :
920 : try {
921 38 : db->set_pipeline (name, description);
922 4 : } catch (const std::invalid_argument &e) {
923 2 : ml_loge ("%s", e.what ());
924 2 : ret = -EINVAL;
925 4 : } catch (const std::exception &e) {
926 2 : ml_loge ("%s", e.what ());
927 2 : ret = -EIO;
928 2 : }
929 :
930 8 : return ret;
931 : }
932 :
933 : /**
934 : * @brief Get the pipeline description with given name.
935 : * @param[in] name The unique name to retrieve.
936 : * @param[out] description The pipeline corresponding with given name.
937 : * @return @c 0 on success. Otherwise a negative error value.
938 : */
939 : gint
940 8 : svcdb_pipeline_get (const gchar *name, gchar **description)
941 : {
942 8 : gint ret = 0;
943 8 : MLServiceDB *db = svcdb_get ();
944 :
945 : try {
946 24 : db->get_pipeline (name, description);
947 5 : } catch (const std::invalid_argument &e) {
948 4 : ml_loge ("%s", e.what ());
949 4 : ret = -EINVAL;
950 5 : } catch (const std::exception &e) {
951 1 : ml_loge ("%s", e.what ());
952 1 : ret = -EIO;
953 1 : }
954 :
955 8 : return ret;
956 : }
957 :
958 : /**
959 : * @brief Delete the pipeline description with a given name.
960 : * @param[in] name The unique name to delete.
961 : * @return @c 0 on success. Otherwise a negative error value.
962 : */
963 : gint
964 7 : svcdb_pipeline_delete (const gchar *name)
965 : {
966 7 : gint ret = 0;
967 7 : MLServiceDB *db = svcdb_get ();
968 :
969 : try {
970 21 : db->delete_pipeline (name);
971 3 : } catch (const std::invalid_argument &e) {
972 2 : ml_loge ("%s", e.what ());
973 2 : ret = -EINVAL;
974 3 : } catch (const std::exception &e) {
975 1 : ml_loge ("%s", e.what ());
976 1 : ret = -EIO;
977 1 : }
978 :
979 7 : return ret;
980 : }
981 :
982 : /**
983 : * @brief Add the model with given name.
984 : * @param[in] name Unique name for model.
985 : * @param[in] model The model to be stored.
986 : * @param[in] is_active The model is active or not.
987 : * @param[in] description The model description.
988 : * @param[in] app_info The application information.
989 : * @param[out] version The version of the model.
990 : * @return @c 0 on success. Otherwise a negative error value.
991 : */
992 : gint
993 14 : svcdb_model_add (const gchar *name, const gchar *path, const bool is_active,
994 : const gchar *description, const gchar *app_info, guint *version)
995 : {
996 14 : gint ret = 0;
997 14 : MLServiceDB *db = svcdb_get ();
998 :
999 : try {
1000 116 : db->set_model (name, path, is_active, description, app_info, version);
1001 5 : } catch (const std::invalid_argument &e) {
1002 3 : ml_loge ("%s", e.what ());
1003 3 : ret = -EINVAL;
1004 5 : } catch (const std::exception &e) {
1005 2 : ml_loge ("%s", e.what ());
1006 2 : ret = -EIO;
1007 2 : }
1008 :
1009 14 : return ret;
1010 : }
1011 :
1012 : /**
1013 : * @brief Update the model description with given name and version.
1014 : * @param[in] name Unique name for model.
1015 : * @param[in] version The version of the model.
1016 : * @param[in] description The model description.
1017 : * @return @c 0 on success. Otherwise a negative error value.
1018 : */
1019 : gint
1020 8 : svcdb_model_update_description (const gchar *name, const guint version,
1021 : const gchar *description)
1022 : {
1023 8 : gint ret = 0;
1024 8 : MLServiceDB *db = svcdb_get ();
1025 :
1026 : try {
1027 38 : db->update_model_description (name, version, description);
1028 7 : } catch (const std::invalid_argument &e) {
1029 5 : ml_loge ("%s", e.what ());
1030 5 : ret = -EINVAL;
1031 7 : } catch (const std::exception &e) {
1032 2 : ml_loge ("%s", e.what ());
1033 2 : ret = -EIO;
1034 2 : }
1035 :
1036 8 : return ret;
1037 : }
1038 :
1039 : /**
1040 : * @brief Activate the model with given name.
1041 : * @param[in] name Unique name for model.
1042 : * @param[in] version The version of the model.
1043 : * @return @c 0 on success. Otherwise a negative error value.
1044 : */
1045 : gint
1046 6 : svcdb_model_activate (const gchar *name, const guint version)
1047 : {
1048 6 : gint ret = 0;
1049 6 : MLServiceDB *db = svcdb_get ();
1050 :
1051 : try {
1052 18 : db->activate_model (name, version);
1053 5 : } catch (const std::invalid_argument &e) {
1054 4 : ml_loge ("%s", e.what ());
1055 4 : ret = -EINVAL;
1056 5 : } catch (const std::exception &e) {
1057 1 : ml_loge ("%s", e.what ());
1058 1 : ret = -EIO;
1059 1 : }
1060 :
1061 6 : return ret;
1062 : }
1063 :
1064 : /**
1065 : * @brief Get the model information with given name and version.
1066 : * @param[in] name The unique name to retrieve.
1067 : * @param[in] version The version of the model. If it is 0, all models will return, if it is -1, return the active model.
1068 : * @param[out] model_info The model information.
1069 : * @return @c 0 on success. Otherwise a negative error value.
1070 : */
1071 : gint
1072 6 : svcdb_model_get (const gchar *name, const guint version, gchar **model_info)
1073 : {
1074 6 : gint ret = 0;
1075 6 : MLServiceDB *db = svcdb_get ();
1076 :
1077 : try {
1078 18 : db->get_model (name, version, model_info);
1079 5 : } catch (const std::invalid_argument &e) {
1080 4 : ml_loge ("%s", e.what ());
1081 4 : ret = -EINVAL;
1082 5 : } catch (const std::exception &e) {
1083 1 : ml_loge ("%s", e.what ());
1084 1 : ret = -EIO;
1085 1 : }
1086 :
1087 6 : return ret;
1088 : }
1089 :
1090 : /**
1091 : * @brief Get the activated model information with given name.
1092 : * @param[in] name The unique name to retrieve.
1093 : * @param[out] model_info The model information.
1094 : * @return @c 0 on success. Otherwise a negative error value.
1095 : */
1096 : gint
1097 6 : svcdb_model_get_activated (const gchar *name, gchar **model_info)
1098 : {
1099 6 : gint ret = 0;
1100 6 : MLServiceDB *db = svcdb_get ();
1101 :
1102 : try {
1103 18 : db->get_model (name, -1, model_info);
1104 5 : } catch (const std::invalid_argument &e) {
1105 4 : ml_loge ("%s", e.what ());
1106 4 : ret = -EINVAL;
1107 5 : } catch (const std::exception &e) {
1108 1 : ml_loge ("%s", e.what ());
1109 1 : ret = -EIO;
1110 1 : }
1111 :
1112 6 : return ret;
1113 : }
1114 :
1115 : /**
1116 : * @brief Get the model information with given name.
1117 : * @param[in] name The unique name to retrieve.
1118 : * @param[out] model_info The model information.
1119 : * @return @c 0 on success. Otherwise a negative error value.
1120 : */
1121 : gint
1122 7 : svcdb_model_get_all (const gchar *name, gchar **model_info)
1123 : {
1124 7 : gint ret = 0;
1125 7 : MLServiceDB *db = svcdb_get ();
1126 :
1127 : try {
1128 21 : db->get_model (name, 0, model_info);
1129 4 : } catch (const std::invalid_argument &e) {
1130 3 : ml_loge ("%s", e.what ());
1131 3 : ret = -EINVAL;
1132 4 : } catch (const std::exception &e) {
1133 1 : ml_loge ("%s", e.what ());
1134 1 : ret = -EIO;
1135 1 : }
1136 :
1137 7 : return ret;
1138 : }
1139 :
1140 : /**
1141 : * @brief Delete the model.
1142 : * @param[in] name The unique name to delete.
1143 : * @param[in] version The version of the model to delete.
1144 : * @param[in] force If the force is set to @c TRUE, the target model will be forced to delete.
1145 : * @return @c 0 on success. Otherwise a negative error value.
1146 : */
1147 : gint
1148 12 : svcdb_model_delete (const gchar *name, const guint version, const gboolean force)
1149 : {
1150 12 : gint ret = 0;
1151 12 : MLServiceDB *db = svcdb_get ();
1152 :
1153 : try {
1154 36 : db->delete_model (name, version, force);
1155 4 : } catch (const std::invalid_argument &e) {
1156 3 : ml_loge ("%s", e.what ());
1157 3 : ret = -EINVAL;
1158 4 : } catch (const std::exception &e) {
1159 1 : ml_loge ("%s", e.what ());
1160 1 : ret = -EIO;
1161 1 : }
1162 :
1163 12 : return ret;
1164 : }
1165 :
1166 : /**
1167 : * @brief Set the resource with given name.
1168 : * @param[in] name Unique name of ml-resource.
1169 : * @param[in] path The path to be stored.
1170 : * @param[in] description The description for ml-resource.
1171 : * @param[in] app_info The application information.
1172 : * @return @c 0 on success. Otherwise a negative error value.
1173 : */
1174 : gint
1175 10 : svcdb_resource_add (const gchar *name, const gchar *path,
1176 : const gchar *description, const gchar *app_info)
1177 : {
1178 10 : gint ret = 0;
1179 10 : MLServiceDB *db = svcdb_get ();
1180 :
1181 : try {
1182 80 : db->set_resource (name, path, description, app_info);
1183 4 : } catch (const std::invalid_argument &e) {
1184 2 : ml_loge ("%s", e.what ());
1185 2 : ret = -EINVAL;
1186 4 : } catch (const std::exception &e) {
1187 2 : ml_loge ("%s", e.what ());
1188 2 : ret = -EIO;
1189 2 : }
1190 :
1191 10 : return ret;
1192 : }
1193 :
1194 : /**
1195 : * @brief Get the resource with given name.
1196 : * @param[in] name The unique name to retrieve.
1197 : * @param[out] resource The resource information.
1198 : * @return @c 0 on success. Otherwise a negative error value.
1199 : */
1200 : gint
1201 6 : svcdb_resource_get (const gchar *name, gchar **res_info)
1202 : {
1203 6 : gint ret = 0;
1204 6 : MLServiceDB *db = svcdb_get ();
1205 :
1206 : try {
1207 18 : db->get_resource (name, res_info);
1208 4 : } catch (const std::invalid_argument &e) {
1209 3 : ml_loge ("%s", e.what ());
1210 3 : ret = -EINVAL;
1211 4 : } catch (const std::exception &e) {
1212 1 : ml_loge ("%s", e.what ());
1213 1 : ret = -EIO;
1214 1 : }
1215 :
1216 6 : return ret;
1217 : }
1218 :
1219 : /**
1220 : * @brief Delete the resource.
1221 : * @param[in] name The unique name to delete.
1222 : * @return @c 0 on success. Otherwise a negative error value.
1223 : */
1224 : gint
1225 6 : svcdb_resource_delete (const gchar *name)
1226 : {
1227 6 : gint ret = 0;
1228 6 : MLServiceDB *db = svcdb_get ();
1229 :
1230 : try {
1231 18 : db->delete_resource (name);
1232 3 : } catch (const std::invalid_argument &e) {
1233 2 : ml_loge ("%s", e.what ());
1234 2 : ret = -EINVAL;
1235 3 : } catch (const std::exception &e) {
1236 1 : ml_loge ("%s", e.what ());
1237 1 : ret = -EIO;
1238 1 : }
1239 :
1240 6 : return ret;
1241 : }
1242 : G_END_DECLS
|