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 0 : MLServiceDB::MLServiceDB (std::string path)
64 0 : : _path (path), _initialized (false), _db (nullptr)
65 : {
66 0 : }
67 :
68 : /**
69 : * @brief Destroy the MLServiceDB object.
70 : */
71 0 : MLServiceDB::~MLServiceDB ()
72 : {
73 0 : disconnectDB ();
74 0 : _initialized = false;
75 0 : }
76 :
77 : /**
78 : * @brief Create table and handle database version.
79 : */
80 : void
81 0 : MLServiceDB::initDB ()
82 : {
83 : int i, tbl_ver;
84 :
85 0 : 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 0 : if (!set_transaction (true))
96 0 : return;
97 :
98 : /* Create tables. */
99 0 : for (i = 0; i < TBL_MAX; i++) {
100 0 : if (!create_table (g_mlsvc_table_schema[i]))
101 0 : return;
102 : }
103 :
104 : /* Check pipeline table. */
105 0 : 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 0 : if (!set_table_version ("tblPipeline", TBL_VER_PIPELINE_DESCRIPTION))
113 0 : return;
114 :
115 : /* Check model table. */
116 0 : 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 0 : if (!set_table_version ("tblModel", TBL_VER_MODEL_INFO))
124 0 : return;
125 :
126 : /* Check resource table. */
127 0 : 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 0 : if (!set_table_version ("tblResource", TBL_VER_RESOURCE_INFO))
135 0 : return;
136 :
137 0 : if (!set_transaction (false))
138 0 : return;
139 :
140 0 : _initialized = true;
141 : }
142 :
143 : /**
144 : * @brief Connect to ML Service DB and initialize the private variables.
145 : */
146 : void
147 0 : MLServiceDB::connectDB ()
148 : {
149 : int rc;
150 :
151 0 : if (_db != nullptr)
152 0 : return;
153 :
154 0 : g_autofree gchar *db_path = g_strdup_printf ("%s/.ml-service.db", _path.c_str ());
155 0 : rc = sqlite3_open (db_path, &_db);
156 0 : 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 0 : initDB ();
163 :
164 0 : error:
165 0 : if (!_initialized) {
166 0 : disconnectDB ();
167 0 : throw std::runtime_error ("Failed to connect DB.");
168 : }
169 0 : }
170 :
171 : /**
172 : * @brief Disconnect the DB.
173 : */
174 : void
175 0 : MLServiceDB::disconnectDB ()
176 : {
177 0 : if (_db) {
178 0 : sqlite3_close (_db);
179 0 : _db = nullptr;
180 : }
181 0 : }
182 :
183 : /**
184 : * @brief Get table version.
185 : */
186 : int
187 0 : MLServiceDB::get_table_version (const std::string tbl_name, const int default_ver)
188 : {
189 : int rc, tbl_ver;
190 : sqlite3_stmt *res;
191 0 : std::string sql = "SELECT version FROM tblMLDBInfo WHERE name = '" + tbl_name + "';";
192 :
193 0 : rc = sqlite3_prepare_v2 (_db, sql.c_str (), -1, &res, nullptr);
194 0 : 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 0 : tbl_ver = (sqlite3_step (res) == SQLITE_ROW) ? sqlite3_column_int (res, 0) : default_ver;
201 0 : sqlite3_finalize (res);
202 :
203 0 : return tbl_ver;
204 0 : }
205 :
206 : /**
207 : * @brief Set table version.
208 : */
209 : bool
210 0 : MLServiceDB::set_table_version (const std::string tbl_name, const int tbl_ver)
211 : {
212 : sqlite3_stmt *res;
213 0 : std::string sql = "INSERT OR REPLACE INTO tblMLDBInfo VALUES (?1, ?2);";
214 :
215 0 : bool is_done = (sqlite3_prepare_v2 (_db, sql.c_str (), -1, &res, nullptr) == SQLITE_OK
216 0 : && sqlite3_bind_text (res, 1, tbl_name.c_str (), -1, nullptr) == SQLITE_OK
217 0 : && sqlite3_bind_int (res, 2, tbl_ver) == SQLITE_OK
218 0 : && sqlite3_step (res) == SQLITE_DONE);
219 :
220 0 : sqlite3_finalize (res);
221 :
222 0 : if (!is_done)
223 0 : ml_logw ("Failed to update version of table %s.", tbl_name.c_str ());
224 0 : return is_done;
225 0 : }
226 :
227 : /**
228 : * @brief Create DB table.
229 : */
230 : bool
231 0 : MLServiceDB::create_table (const std::string tbl_name)
232 : {
233 : int rc;
234 0 : char *errmsg = nullptr;
235 0 : std::string sql = "CREATE TABLE IF NOT EXISTS " + tbl_name;
236 :
237 0 : rc = sqlite3_exec (_db, sql.c_str (), nullptr, nullptr, &errmsg);
238 0 : 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 0 : return true;
245 0 : }
246 :
247 : /**
248 : * @brief Begin/end transaction.
249 : */
250 : bool
251 0 : MLServiceDB::set_transaction (bool begin)
252 : {
253 : int rc;
254 0 : char *errmsg = nullptr;
255 :
256 0 : rc = sqlite3_exec (_db, begin ? "BEGIN TRANSACTION;" : "END TRANSACTION;",
257 : nullptr, nullptr, &errmsg);
258 0 : if (rc != SQLITE_OK)
259 0 : ml_logw ("Failed to %s transaction: %s (%d)", begin ? "begin" : "end", errmsg, rc);
260 :
261 0 : sqlite3_clear_errmsg (errmsg);
262 0 : 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 0 : MLServiceDB::set_pipeline (const std::string name, const std::string description)
273 : {
274 : sqlite3_stmt *res;
275 :
276 0 : if (name.empty () || description.empty ())
277 0 : throw std::invalid_argument ("Invalid name or value parameters!");
278 :
279 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
280 0 : key_with_prefix += name;
281 :
282 0 : if (!set_transaction (true))
283 0 : throw std::runtime_error ("Failed to begin transaction.");
284 :
285 0 : if (sqlite3_prepare_v2 (_db,
286 : "INSERT OR REPLACE INTO tblPipeline VALUES (?1, ?2)", -1, &res, nullptr)
287 : != SQLITE_OK
288 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
289 0 : || sqlite3_bind_text (res, 2, description.c_str (), -1, nullptr) != SQLITE_OK
290 0 : || 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 0 : sqlite3_finalize (res);
296 :
297 0 : if (!set_transaction (false))
298 0 : throw std::runtime_error ("Failed to end transaction.");
299 0 : }
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 0 : MLServiceDB::get_pipeline (const std::string name, gchar **description)
308 : {
309 0 : char *value = nullptr;
310 : sqlite3_stmt *res;
311 :
312 0 : if (name.empty () || !description)
313 0 : throw std::invalid_argument ("Invalid name or description parameter!");
314 :
315 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
316 0 : key_with_prefix += name;
317 :
318 0 : if (sqlite3_prepare_v2 (_db,
319 : "SELECT description FROM tblPipeline WHERE key = ?1", -1, &res, nullptr)
320 : == SQLITE_OK
321 0 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
322 0 : && sqlite3_step (res) == SQLITE_ROW)
323 0 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
324 :
325 0 : sqlite3_finalize (res);
326 :
327 0 : if (value) {
328 0 : *description = value;
329 : } else {
330 0 : throw std::invalid_argument ("Failed to get pipeline description of " + name);
331 : }
332 0 : }
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 0 : MLServiceDB::delete_pipeline (const std::string name)
340 : {
341 : sqlite3_stmt *res;
342 :
343 0 : if (name.empty ())
344 0 : throw std::invalid_argument ("Invalid name parameters!");
345 :
346 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_pipeline_");
347 0 : key_with_prefix += name;
348 :
349 0 : if (sqlite3_prepare_v2 (_db, "DELETE FROM tblPipeline WHERE key = ?1", -1, &res, nullptr) != SQLITE_OK
350 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
351 0 : || sqlite3_step (res) != SQLITE_DONE) {
352 0 : sqlite3_finalize (res);
353 0 : throw std::runtime_error ("Failed to delete pipeline description of " + name);
354 : }
355 :
356 0 : sqlite3_finalize (res);
357 :
358 0 : if (sqlite3_changes (_db) == 0) {
359 0 : throw std::invalid_argument ("There is no pipeline description of " + name);
360 : }
361 0 : }
362 :
363 : /**
364 : * @brief Check the model is registered.
365 : */
366 : bool
367 0 : MLServiceDB::is_model_registered (const std::string key, const guint version)
368 : {
369 : sqlite3_stmt *res;
370 : gchar *sql;
371 : bool registered;
372 :
373 0 : if (version > 0U)
374 0 : sql = g_strdup_printf (
375 : "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = %u)", version);
376 : else
377 0 : sql = g_strdup ("SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1)");
378 :
379 : registered
380 0 : = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
381 0 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
382 0 : || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1);
383 0 : sqlite3_finalize (res);
384 0 : g_free (sql);
385 :
386 0 : return registered;
387 : }
388 :
389 : /**
390 : * @brief Check the model is activated.
391 : */
392 : bool
393 0 : MLServiceDB::is_model_activated (const std::string key, const guint version)
394 : {
395 : sqlite3_stmt *res;
396 : gchar *sql;
397 : bool activated;
398 :
399 0 : sql = g_strdup ("SELECT active FROM tblModel WHERE key = ?1 AND version = ?2");
400 :
401 0 : activated = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
402 0 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
403 0 : || sqlite3_bind_int (res, 2, version) != SQLITE_OK
404 0 : || sqlite3_step (res) != SQLITE_ROW
405 0 : || !g_str_equal (sqlite3_column_text (res, 0), "T"));
406 0 : sqlite3_finalize (res);
407 0 : g_free (sql);
408 :
409 0 : return activated;
410 : }
411 :
412 : /**
413 : * @brief Check the resource is registered.
414 : */
415 : bool
416 0 : MLServiceDB::is_resource_registered (const std::string key)
417 : {
418 : sqlite3_stmt *res;
419 : gchar *sql;
420 : bool registered;
421 :
422 0 : sql = g_strdup_printf ("SELECT EXISTS(SELECT 1 FROM tblResource WHERE key = ?1)");
423 :
424 : registered
425 0 : = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
426 0 : || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
427 0 : || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1);
428 0 : sqlite3_finalize (res);
429 0 : g_free (sql);
430 :
431 0 : 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 0 : 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 0 : guint _version = 0U;
448 : sqlite3_stmt *res;
449 :
450 0 : if (name.empty () || model.empty () || !version)
451 0 : throw std::invalid_argument ("Invalid name, model, or version parameter!");
452 :
453 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
454 0 : key_with_prefix += name;
455 :
456 0 : if (!set_transaction (true))
457 0 : throw std::runtime_error ("Failed to begin transaction.");
458 :
459 : /* set other models as NOT active */
460 0 : if (is_active) {
461 0 : if (sqlite3_prepare_v2 (_db,
462 : "UPDATE tblModel SET active = 'F' WHERE key = ?1", -1, &res, nullptr)
463 : != SQLITE_OK
464 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
465 0 : || 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 0 : sqlite3_finalize (res);
470 : }
471 :
472 : /* insert new row */
473 0 : 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 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
477 0 : || sqlite3_bind_text (res, 2, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
478 0 : || sqlite3_bind_text (res, 3, is_active ? "T" : "F", -1, nullptr) != SQLITE_OK
479 0 : || sqlite3_bind_text (res, 4, model.c_str (), -1, nullptr) != SQLITE_OK
480 0 : || sqlite3_bind_text (res, 5, description.c_str (), -1, nullptr) != SQLITE_OK
481 0 : || sqlite3_bind_text (res, 6, app_info.c_str (), -1, nullptr) != SQLITE_OK
482 0 : || 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 0 : sqlite3_finalize (res);
488 :
489 0 : long long int last_id = sqlite3_last_insert_rowid (_db);
490 0 : 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 0 : 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 0 : && sqlite3_bind_int (res, 1, last_id) == SQLITE_OK && sqlite3_step (res) == SQLITE_ROW) {
500 0 : _version = sqlite3_column_int (res, 0);
501 : }
502 :
503 0 : sqlite3_finalize (res);
504 :
505 0 : if (!set_transaction (false))
506 0 : throw std::runtime_error ("Failed to end transaction.");
507 :
508 0 : 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 0 : *version = _version;
515 0 : }
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 0 : MLServiceDB::update_model_description (
525 : const std::string name, const guint version, const std::string description)
526 : {
527 : sqlite3_stmt *res;
528 :
529 0 : if (name.empty () || description.empty ())
530 0 : throw std::invalid_argument ("Invalid name or description parameter!");
531 :
532 0 : if (version == 0U)
533 0 : throw std::invalid_argument ("Invalid version number!");
534 :
535 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
536 0 : key_with_prefix += name;
537 :
538 : /* check the existence of given model */
539 0 : if (!is_model_registered (key_with_prefix, version)) {
540 0 : throw std::invalid_argument ("Failed to check the existence of " + name
541 0 : + " version " + std::to_string (version));
542 : }
543 :
544 0 : if (!set_transaction (true))
545 0 : throw std::runtime_error ("Failed to begin transaction.");
546 :
547 : /* update model description */
548 0 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET description = ?1 WHERE key = ?2 AND version = ?3",
549 : -1, &res, nullptr)
550 : != SQLITE_OK
551 0 : || sqlite3_bind_text (res, 1, description.c_str (), -1, nullptr) != SQLITE_OK
552 0 : || sqlite3_bind_text (res, 2, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
553 0 : || 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 0 : sqlite3_finalize (res);
559 :
560 0 : if (!set_transaction (false))
561 0 : throw std::runtime_error ("Failed to end transaction.");
562 0 : }
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 0 : MLServiceDB::activate_model (const std::string name, const guint version)
571 : {
572 : sqlite3_stmt *res;
573 :
574 0 : if (name.empty ())
575 0 : throw std::invalid_argument ("Invalid name parameter!");
576 :
577 0 : if (version == 0U)
578 0 : throw std::invalid_argument ("Invalid version number!");
579 :
580 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
581 0 : key_with_prefix += name;
582 :
583 : /* check the existence */
584 0 : if (!is_model_registered (key_with_prefix, version)) {
585 0 : throw std::invalid_argument ("There is no model with name " + name
586 0 : + " and version " + std::to_string (version));
587 : }
588 :
589 0 : if (!set_transaction (true))
590 0 : throw std::runtime_error ("Failed to begin transaction.");
591 :
592 : /* set other row active as F */
593 0 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET active = 'F' WHERE key = ?1", -1, &res, nullptr) != SQLITE_OK
594 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
595 0 : || 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 0 : sqlite3_finalize (res);
601 :
602 : /* set the given row active as T */
603 0 : if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET active = 'T' WHERE key = ?1 AND version = ?2",
604 : -1, &res, nullptr)
605 : != SQLITE_OK
606 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
607 0 : || 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 0 : sqlite3_finalize (res);
614 :
615 0 : if (!set_transaction (false))
616 0 : throw std::runtime_error ("Failed to end transaction.");
617 0 : }
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 0 : MLServiceDB::get_model (const std::string name, const gint version, gchar **model)
627 : {
628 0 : 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 0 : char *value = nullptr;
632 : sqlite3_stmt *res;
633 :
634 0 : if (name.empty () || !model)
635 0 : throw std::invalid_argument ("Invalid name or model parameters!");
636 :
637 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
638 0 : key_with_prefix += name;
639 :
640 : /* check the existence of given model */
641 0 : guint ver = (version > 0) ? version : 0U;
642 0 : if (!is_model_registered (key_with_prefix, ver)) {
643 0 : throw std::invalid_argument ("Failed to check the existence of " + name);
644 : }
645 :
646 0 : if (version == 0)
647 0 : sql = g_strdup_printf (
648 : "SELECT json_group_array(%s) FROM tblModel WHERE key = ?1", model_info_json);
649 0 : else if (version == -1)
650 0 : 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 0 : else if (version > 0)
653 0 : 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 0 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) == SQLITE_OK
659 0 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
660 0 : && sqlite3_step (res) == SQLITE_ROW)
661 0 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
662 :
663 0 : sqlite3_finalize (res);
664 0 : g_free (sql);
665 :
666 0 : if (value) {
667 0 : *model = value;
668 : } else {
669 0 : throw std::invalid_argument ("Failed to get model with name " + name
670 0 : + " and version " + std::to_string (version));
671 : }
672 0 : }
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 0 : MLServiceDB::delete_model (const std::string name, const guint version, const gboolean force)
682 : {
683 : char *sql;
684 : sqlite3_stmt *res;
685 :
686 0 : if (name.empty ())
687 0 : throw std::invalid_argument ("Invalid name parameters!");
688 :
689 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_model_");
690 0 : key_with_prefix += name;
691 :
692 : /* existence check */
693 0 : if (!is_model_registered (key_with_prefix, version)) {
694 0 : throw std::invalid_argument ("There is no model with name " + name
695 0 : + " and version " + std::to_string (version));
696 : }
697 :
698 0 : if (version > 0U) {
699 0 : if (force)
700 0 : ml_logw ("The model with name %s and version %u may be activated, delete it from ml-service.",
701 : name.c_str (), version);
702 0 : else if (is_model_activated (key_with_prefix, version))
703 0 : throw std::invalid_argument ("The model with name " + name
704 0 : + " and version " + std::to_string (version)
705 0 : + " is activated, cannot delete it.");
706 :
707 0 : sql = g_strdup_printf ("DELETE FROM tblModel WHERE key = ?1 and version = %u", version);
708 : } else {
709 0 : sql = g_strdup ("DELETE FROM tblModel WHERE key = ?1");
710 : }
711 :
712 0 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
713 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
714 0 : || 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 0 : sqlite3_finalize (res);
722 0 : g_free (sql);
723 :
724 0 : 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 0 : }
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 0 : 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 0 : if (name.empty () || path.empty ())
744 0 : throw std::invalid_argument ("Invalid name or path parameter!");
745 :
746 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
747 0 : key_with_prefix += name;
748 :
749 0 : if (!set_transaction (true))
750 0 : throw std::runtime_error ("Failed to begin transaction.");
751 :
752 0 : if (sqlite3_prepare_v2 (_db,
753 : "INSERT OR REPLACE INTO tblResource VALUES (?1, ?2, ?3, ?4)", -1, &res, nullptr)
754 : != SQLITE_OK
755 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
756 0 : || sqlite3_bind_text (res, 2, path.c_str (), -1, nullptr) != SQLITE_OK
757 0 : || sqlite3_bind_text (res, 3, description.c_str (), -1, nullptr) != SQLITE_OK
758 0 : || sqlite3_bind_text (res, 4, app_info.c_str (), -1, nullptr) != SQLITE_OK
759 0 : || 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 0 : sqlite3_finalize (res);
765 :
766 0 : if (!set_transaction (false))
767 0 : throw std::runtime_error ("Failed to end transaction.");
768 :
769 0 : long long int last_id = sqlite3_last_insert_rowid (_db);
770 0 : 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 0 : }
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 0 : MLServiceDB::get_resource (const std::string name, gchar **resource)
783 : {
784 0 : const char res_info_json[]
785 : = "json_object('path', path, 'description', description, 'app_info', app_info)";
786 : char *sql;
787 0 : char *value = nullptr;
788 : sqlite3_stmt *res;
789 :
790 0 : if (name.empty () || !resource)
791 0 : throw std::invalid_argument ("Invalid name or resource parameters!");
792 :
793 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
794 0 : key_with_prefix += name;
795 :
796 : /* existence check */
797 0 : if (!is_resource_registered (key_with_prefix))
798 0 : throw std::invalid_argument ("There is no resource with name " + name);
799 :
800 : /* Get json string with insertion order. */
801 0 : 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 0 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) == SQLITE_OK
805 0 : && sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) == SQLITE_OK
806 0 : && sqlite3_step (res) == SQLITE_ROW)
807 0 : value = g_strdup_printf ("%s", sqlite3_column_text (res, 0));
808 :
809 0 : sqlite3_finalize (res);
810 0 : g_free (sql);
811 :
812 0 : if (!value)
813 0 : throw std::invalid_argument ("Failed to get resource with name " + name);
814 :
815 0 : *resource = value;
816 0 : }
817 :
818 : /**
819 : * @brief Delete the resource.
820 : * @param[in] name The unique name to delete.
821 : */
822 : void
823 0 : MLServiceDB::delete_resource (const std::string name)
824 : {
825 : char *sql;
826 : sqlite3_stmt *res;
827 :
828 0 : if (name.empty ())
829 0 : throw std::invalid_argument ("Invalid name parameters!");
830 :
831 0 : std::string key_with_prefix = DB_KEY_PREFIX + std::string ("_resource_");
832 0 : key_with_prefix += name;
833 :
834 : /* existence check */
835 0 : if (!is_resource_registered (key_with_prefix))
836 0 : throw std::invalid_argument ("There is no resource with name " + name);
837 :
838 0 : sql = g_strdup ("DELETE FROM tblResource WHERE key = ?1");
839 :
840 0 : if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
841 0 : || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
842 0 : || 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 0 : sqlite3_finalize (res);
849 0 : g_free (sql);
850 :
851 0 : if (sqlite3_changes (_db) == 0)
852 0 : throw std::invalid_argument ("There is no resource with name " + name);
853 0 : }
854 :
855 : static MLServiceDB *g_svcdb_instance = nullptr;
856 :
857 : /**
858 : * @brief Get the service-db instance.
859 : */
860 : static MLServiceDB *
861 0 : svcdb_get (void)
862 : {
863 0 : g_assert (g_svcdb_instance);
864 0 : return g_svcdb_instance;
865 : }
866 :
867 : G_BEGIN_DECLS
868 : /**
869 : * @brief Initialize the service-db.
870 : */
871 : void
872 0 : svcdb_initialize (const gchar *path)
873 : {
874 0 : if (g_svcdb_instance) {
875 0 : ml_logw ("ML service DB is already opened, close old DB.");
876 0 : delete g_svcdb_instance;
877 : }
878 :
879 0 : g_svcdb_instance = new MLServiceDB (path);
880 0 : g_assert (g_svcdb_instance);
881 0 : g_svcdb_instance->connectDB ();
882 0 : }
883 :
884 : /**
885 : * @brief Close the service-db.
886 : */
887 : void
888 0 : svcdb_finalize (void)
889 : {
890 0 : if (g_svcdb_instance) {
891 0 : g_svcdb_instance->disconnectDB ();
892 0 : delete g_svcdb_instance;
893 : }
894 :
895 0 : g_svcdb_instance = nullptr;
896 0 : }
897 :
898 : /**
899 : * @brief Set the pipeline description with given name.
900 : * @note If the name already exists, the pipeline description is overwritten.
901 : * @param[in] name Unique name to set the associated pipeline description.
902 : * @param[in] description The pipeline description to be stored.
903 : * @return @c 0 on success. Otherwise a negative error value.
904 : */
905 : gint
906 0 : svcdb_pipeline_set (const gchar *name, const gchar *description)
907 : {
908 0 : gint ret = 0;
909 0 : MLServiceDB *db = svcdb_get ();
910 :
911 : try {
912 0 : db->set_pipeline (name, description);
913 0 : } catch (const std::invalid_argument &e) {
914 0 : ml_loge ("%s", e.what ());
915 0 : ret = -EINVAL;
916 0 : } catch (const std::exception &e) {
917 0 : ml_loge ("%s", e.what ());
918 0 : ret = -EIO;
919 0 : }
920 :
921 0 : return ret;
922 : }
923 :
924 : /**
925 : * @brief Get the pipeline description with given name.
926 : * @param[in] name The unique name to retrieve.
927 : * @param[out] description The pipeline corresponding with given name.
928 : * @return @c 0 on success. Otherwise a negative error value.
929 : */
930 : gint
931 0 : svcdb_pipeline_get (const gchar *name, gchar **description)
932 : {
933 0 : gint ret = 0;
934 0 : MLServiceDB *db = svcdb_get ();
935 :
936 : try {
937 0 : db->get_pipeline (name, description);
938 0 : } catch (const std::invalid_argument &e) {
939 0 : ml_loge ("%s", e.what ());
940 0 : ret = -EINVAL;
941 0 : } catch (const std::exception &e) {
942 0 : ml_loge ("%s", e.what ());
943 0 : ret = -EIO;
944 0 : }
945 :
946 0 : return ret;
947 : }
948 :
949 : /**
950 : * @brief Delete the pipeline description with a given name.
951 : * @param[in] name The unique name to delete.
952 : * @return @c 0 on success. Otherwise a negative error value.
953 : */
954 : gint
955 0 : svcdb_pipeline_delete (const gchar *name)
956 : {
957 0 : gint ret = 0;
958 0 : MLServiceDB *db = svcdb_get ();
959 :
960 : try {
961 0 : db->delete_pipeline (name);
962 0 : } catch (const std::invalid_argument &e) {
963 0 : ml_loge ("%s", e.what ());
964 0 : ret = -EINVAL;
965 0 : } catch (const std::exception &e) {
966 0 : ml_loge ("%s", e.what ());
967 0 : ret = -EIO;
968 0 : }
969 :
970 0 : return ret;
971 : }
972 :
973 : /**
974 : * @brief Add the model with given name.
975 : * @param[in] name Unique name for model.
976 : * @param[in] model The model to be stored.
977 : * @param[in] is_active The model is active or not.
978 : * @param[in] description The model description.
979 : * @param[in] app_info The application information.
980 : * @param[out] version The version of the model.
981 : * @return @c 0 on success. Otherwise a negative error value.
982 : */
983 : gint
984 0 : svcdb_model_add (const gchar *name, const gchar *path, const bool is_active,
985 : const gchar *description, const gchar *app_info, guint *version)
986 : {
987 0 : gint ret = 0;
988 0 : MLServiceDB *db = svcdb_get ();
989 :
990 : try {
991 0 : db->set_model (name, path, is_active, description, app_info, version);
992 0 : } catch (const std::invalid_argument &e) {
993 0 : ml_loge ("%s", e.what ());
994 0 : ret = -EINVAL;
995 0 : } catch (const std::exception &e) {
996 0 : ml_loge ("%s", e.what ());
997 0 : ret = -EIO;
998 0 : }
999 :
1000 0 : return ret;
1001 : }
1002 :
1003 : /**
1004 : * @brief Update the model description with given name and version.
1005 : * @param[in] name Unique name for model.
1006 : * @param[in] version The version of the model.
1007 : * @param[in] description The model description.
1008 : * @return @c 0 on success. Otherwise a negative error value.
1009 : */
1010 : gint
1011 0 : svcdb_model_update_description (const gchar *name, const guint version,
1012 : const gchar *description)
1013 : {
1014 0 : gint ret = 0;
1015 0 : MLServiceDB *db = svcdb_get ();
1016 :
1017 : try {
1018 0 : db->update_model_description (name, version, description);
1019 0 : } catch (const std::invalid_argument &e) {
1020 0 : ml_loge ("%s", e.what ());
1021 0 : ret = -EINVAL;
1022 0 : } catch (const std::exception &e) {
1023 0 : ml_loge ("%s", e.what ());
1024 0 : ret = -EIO;
1025 0 : }
1026 :
1027 0 : return ret;
1028 : }
1029 :
1030 : /**
1031 : * @brief Activate the model with given name.
1032 : * @param[in] name Unique name for model.
1033 : * @param[in] version The version of the model.
1034 : * @return @c 0 on success. Otherwise a negative error value.
1035 : */
1036 : gint
1037 0 : svcdb_model_activate (const gchar *name, const guint version)
1038 : {
1039 0 : gint ret = 0;
1040 0 : MLServiceDB *db = svcdb_get ();
1041 :
1042 : try {
1043 0 : db->activate_model (name, version);
1044 0 : } catch (const std::invalid_argument &e) {
1045 0 : ml_loge ("%s", e.what ());
1046 0 : ret = -EINVAL;
1047 0 : } catch (const std::exception &e) {
1048 0 : ml_loge ("%s", e.what ());
1049 0 : ret = -EIO;
1050 0 : }
1051 :
1052 0 : return ret;
1053 : }
1054 :
1055 : /**
1056 : * @brief Get the model information with given name and version.
1057 : * @param[in] name The unique name to retrieve.
1058 : * @param[in] version The version of the model. If it is 0, all models will return, if it is -1, return the active model.
1059 : * @param[out] model_info The model information.
1060 : * @return @c 0 on success. Otherwise a negative error value.
1061 : */
1062 : gint
1063 0 : svcdb_model_get (const gchar *name, const guint version, gchar **model_info)
1064 : {
1065 0 : gint ret = 0;
1066 0 : MLServiceDB *db = svcdb_get ();
1067 :
1068 : try {
1069 0 : db->get_model (name, version, model_info);
1070 0 : } catch (const std::invalid_argument &e) {
1071 0 : ml_loge ("%s", e.what ());
1072 0 : ret = -EINVAL;
1073 0 : } catch (const std::exception &e) {
1074 0 : ml_loge ("%s", e.what ());
1075 0 : ret = -EIO;
1076 0 : }
1077 :
1078 0 : return ret;
1079 : }
1080 :
1081 : /**
1082 : * @brief Get the activated model information with given name.
1083 : * @param[in] name The unique name to retrieve.
1084 : * @param[out] model_info The model information.
1085 : * @return @c 0 on success. Otherwise a negative error value.
1086 : */
1087 : gint
1088 0 : svcdb_model_get_activated (const gchar *name, gchar **model_info)
1089 : {
1090 0 : gint ret = 0;
1091 0 : MLServiceDB *db = svcdb_get ();
1092 :
1093 : try {
1094 0 : db->get_model (name, -1, model_info);
1095 0 : } catch (const std::invalid_argument &e) {
1096 0 : ml_loge ("%s", e.what ());
1097 0 : ret = -EINVAL;
1098 0 : } catch (const std::exception &e) {
1099 0 : ml_loge ("%s", e.what ());
1100 0 : ret = -EIO;
1101 0 : }
1102 :
1103 0 : return ret;
1104 : }
1105 :
1106 : /**
1107 : * @brief Get the model information with given name.
1108 : * @param[in] name The unique name to retrieve.
1109 : * @param[out] model_info The model information.
1110 : * @return @c 0 on success. Otherwise a negative error value.
1111 : */
1112 : gint
1113 0 : svcdb_model_get_all (const gchar *name, gchar **model_info)
1114 : {
1115 0 : gint ret = 0;
1116 0 : MLServiceDB *db = svcdb_get ();
1117 :
1118 : try {
1119 0 : db->get_model (name, 0, model_info);
1120 0 : } catch (const std::invalid_argument &e) {
1121 0 : ml_loge ("%s", e.what ());
1122 0 : ret = -EINVAL;
1123 0 : } catch (const std::exception &e) {
1124 0 : ml_loge ("%s", e.what ());
1125 0 : ret = -EIO;
1126 0 : }
1127 :
1128 0 : return ret;
1129 : }
1130 :
1131 : /**
1132 : * @brief Delete the model.
1133 : * @param[in] name The unique name to delete.
1134 : * @param[in] version The version of the model to delete.
1135 : * @param[in] force If the force is set to @c TRUE, the target model will be forced to delete.
1136 : * @return @c 0 on success. Otherwise a negative error value.
1137 : */
1138 : gint
1139 0 : svcdb_model_delete (const gchar *name, const guint version, const gboolean force)
1140 : {
1141 0 : gint ret = 0;
1142 0 : MLServiceDB *db = svcdb_get ();
1143 :
1144 : try {
1145 0 : db->delete_model (name, version, force);
1146 0 : } catch (const std::invalid_argument &e) {
1147 0 : ml_loge ("%s", e.what ());
1148 0 : ret = -EINVAL;
1149 0 : } catch (const std::exception &e) {
1150 0 : ml_loge ("%s", e.what ());
1151 0 : ret = -EIO;
1152 0 : }
1153 :
1154 0 : return ret;
1155 : }
1156 :
1157 : /**
1158 : * @brief Set the resource with given name.
1159 : * @param[in] name Unique name of ml-resource.
1160 : * @param[in] path The path to be stored.
1161 : * @param[in] description The description for ml-resource.
1162 : * @param[in] app_info The application information.
1163 : * @return @c 0 on success. Otherwise a negative error value.
1164 : */
1165 : gint
1166 0 : svcdb_resource_add (const gchar *name, const gchar *path,
1167 : const gchar *description, const gchar *app_info)
1168 : {
1169 0 : gint ret = 0;
1170 0 : MLServiceDB *db = svcdb_get ();
1171 :
1172 : try {
1173 0 : db->set_resource (name, path, description, app_info);
1174 0 : } catch (const std::invalid_argument &e) {
1175 0 : ml_loge ("%s", e.what ());
1176 0 : ret = -EINVAL;
1177 0 : } catch (const std::exception &e) {
1178 0 : ml_loge ("%s", e.what ());
1179 0 : ret = -EIO;
1180 0 : }
1181 :
1182 0 : return ret;
1183 : }
1184 :
1185 : /**
1186 : * @brief Get the resource with given name.
1187 : * @param[in] name The unique name to retrieve.
1188 : * @param[out] resource The resource information.
1189 : * @return @c 0 on success. Otherwise a negative error value.
1190 : */
1191 : gint
1192 0 : svcdb_resource_get (const gchar *name, gchar **res_info)
1193 : {
1194 0 : gint ret = 0;
1195 0 : MLServiceDB *db = svcdb_get ();
1196 :
1197 : try {
1198 0 : db->get_resource (name, res_info);
1199 0 : } catch (const std::invalid_argument &e) {
1200 0 : ml_loge ("%s", e.what ());
1201 0 : ret = -EINVAL;
1202 0 : } catch (const std::exception &e) {
1203 0 : ml_loge ("%s", e.what ());
1204 0 : ret = -EIO;
1205 0 : }
1206 :
1207 0 : return ret;
1208 : }
1209 :
1210 : /**
1211 : * @brief Delete the resource.
1212 : * @param[in] name The unique name to delete.
1213 : * @return @c 0 on success. Otherwise a negative error value.
1214 : */
1215 : gint
1216 0 : svcdb_resource_delete (const gchar *name)
1217 : {
1218 0 : gint ret = 0;
1219 0 : MLServiceDB *db = svcdb_get ();
1220 :
1221 : try {
1222 0 : db->delete_resource (name);
1223 0 : } catch (const std::invalid_argument &e) {
1224 0 : ml_loge ("%s", e.what ());
1225 0 : ret = -EINVAL;
1226 0 : } catch (const std::exception &e) {
1227 0 : ml_loge ("%s", e.what ());
1228 0 : ret = -EIO;
1229 0 : }
1230 :
1231 0 : return ret;
1232 : }
1233 : G_END_DECLS
|