[Service] deleting activated model
authorJaeyun Jung <jy1210.jung@samsung.com>
Wed, 3 May 2023 11:49:06 +0000 (20:49 +0900)
committerjaeyun-jung <39614140+jaeyun-jung@users.noreply.github.com>
Tue, 23 May 2023 10:23:44 +0000 (19:23 +0900)
Add util functions in service-db,
1. prevent deleting activated model,
2. add util function to check model registration.

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
daemon/includes/service-db.hh
daemon/service-db.cc
tests/capi/unittest_capi_service_agent_client.cc
tests/daemon/unittest_service_db.cc

index 9b01d0f..87ef597 100644 (file)
@@ -49,6 +49,8 @@ class MLServiceDB
 
   void initDB ();
   bool set_transaction (bool begin);
+  bool is_model_registered (const std::string key, const guint version);
+  bool is_model_activated (const std::string key, const guint version);
 
   std::string _path;
   bool _initialized;
index 53a1bab..c98f0bf 100644 (file)
@@ -344,6 +344,55 @@ MLServiceDB::delete_pipeline (const std::string name)
 }
 
 /**
+ * @brief Check the model is registered.
+ */
+bool
+MLServiceDB::is_model_registered (const std::string key, const guint version)
+{
+  sqlite3_stmt *res;
+  gchar *sql;
+  bool registered;
+
+  if (version > 0U)
+    sql = g_strdup_printf (
+        "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = %u)", version);
+  else
+    sql = g_strdup ("SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1)");
+
+  registered
+      = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
+          || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
+          || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1);
+  sqlite3_finalize (res);
+  g_free (sql);
+
+  return registered;
+}
+
+/**
+ * @brief Check the model is activated.
+ */
+bool
+MLServiceDB::is_model_activated (const std::string key, const guint version)
+{
+  sqlite3_stmt *res;
+  gchar *sql;
+  bool activated;
+
+  sql = g_strdup ("SELECT active FROM tblModel WHERE key = ?1 AND version = ?2");
+
+  activated = !(sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
+                || sqlite3_bind_text (res, 1, key.c_str (), -1, nullptr) != SQLITE_OK
+                || sqlite3_bind_int (res, 2, version) != SQLITE_OK
+                || sqlite3_step (res) != SQLITE_ROW
+                || !g_str_equal (sqlite3_column_text (res, 0), "T"));
+  sqlite3_finalize (res);
+  g_free (sql);
+
+  return activated;
+}
+
+/**
  * @brief Set the model with the given name.
  * @param[in] name Unique name for model.
  * @param[in] model The model to be stored.
@@ -447,19 +496,11 @@ MLServiceDB::update_model_description (
   key_with_prefix += name;
 
   /* check the existence of given model */
-  if (sqlite3_prepare_v2 (_db, "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = ?2)",
-          -1, &res, nullptr)
-          != SQLITE_OK
-      || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
-      || sqlite3_bind_int (res, 2, version) != SQLITE_OK
-      || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1) {
-    sqlite3_finalize (res);
+  if (!is_model_registered (key_with_prefix, version)) {
     throw std::invalid_argument ("Failed to check the existence of " + name
                                  + " version " + std::to_string (version));
   }
 
-  sqlite3_finalize (res);
-
   /* update model description */
   if (sqlite3_prepare_v2 (_db, "UPDATE tblModel SET description = ?1 WHERE key = ?2 AND version = ?3",
           -1, &res, nullptr)
@@ -494,19 +535,11 @@ MLServiceDB::activate_model (const std::string name, const guint version)
   key_with_prefix += name;
 
   /* check the existence */
-  if (sqlite3_prepare_v2 (_db, "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = ?2)",
-          -1, &res, nullptr)
-          != SQLITE_OK
-      || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
-      || sqlite3_bind_int (res, 2, version) != SQLITE_OK
-      || sqlite3_step (res) != SQLITE_ROW || sqlite3_column_int (res, 0) != 1) {
-    sqlite3_finalize (res);
+  if (!is_model_registered (key_with_prefix, version)) {
     throw std::invalid_argument ("There is no model with name " + name
                                  + " and version " + std::to_string (version));
   }
 
-  sqlite3_finalize (res);
-
   if (!set_transaction (true))
     throw std::runtime_error ("Failed to begin transaction.");
 
@@ -601,31 +634,21 @@ MLServiceDB::delete_model (const std::string name, const guint version)
   key_with_prefix += name;
 
   /* existence check */
-  if (0U != version) {
-    if (sqlite3_prepare_v2 (_db, "SELECT EXISTS(SELECT 1 FROM tblModel WHERE key = ?1 AND version = ?2);",
-            -1, &res, nullptr)
-            != SQLITE_OK
-        || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
-        || sqlite3_bind_int (res, 2, version) != SQLITE_OK
-        || sqlite3_step (res) != SQLITE_ROW) {
-      sqlite3_finalize (res);
-      throw std::runtime_error ("Failed to check the existence of model with name "
-                                + name + " and version " + std::to_string (version));
-    }
-
-    if (sqlite3_column_int (res, 0) != 1) {
-      sqlite3_finalize (res);
-      throw std::invalid_argument ("There is no model with name " + name
-                                   + " and version " + std::to_string (version));
-    }
-
-    sqlite3_finalize (res);
+  if (!is_model_registered (key_with_prefix, version)) {
+    throw std::invalid_argument ("There is no model with name " + name
+                                 + " and version " + std::to_string (version));
   }
 
-  if (0U == version)
-    sql = g_strdup ("DELETE FROM tblModel WHERE key = ?1");
-  else
+  if (version > 0U) {
+    if (is_model_activated (key_with_prefix, version))
+      throw std::invalid_argument ("The model with name " + name
+                                   + " and version " + std::to_string (version)
+                                   + " is activated, cannot delete it.");
+
     sql = g_strdup_printf ("DELETE FROM tblModel WHERE key = ?1 and version = %u", version);
+  } else {
+    sql = g_strdup ("DELETE FROM tblModel WHERE key = ?1");
+  }
 
   if (sqlite3_prepare_v2 (_db, sql, -1, &res, nullptr) != SQLITE_OK
       || sqlite3_bind_text (res, 1, key_with_prefix.c_str (), -1, nullptr) != SQLITE_OK
index 1b55a86..f7696fd 100644 (file)
@@ -1155,14 +1155,11 @@ TEST_F (MLServiceAgentTest, model_scenario)
 
   g_free (info_list);
 
-  /* delete the active model */
+  /* failed to delete the active model */
   status = ml_service_model_delete (key, 1U);
-  EXPECT_EQ (ML_ERROR_NONE, status);
-
-  /* no active model */
-  status = ml_service_model_get_activated (key, &activated_model_info);
   EXPECT_EQ (ML_ERROR_INVALID_PARAMETER, status);
 
+  /* activate model with invalid version number */
   status = ml_service_model_activate (key, 91243U);
   EXPECT_EQ (ML_ERROR_INVALID_PARAMETER, status);
 
@@ -1179,12 +1176,13 @@ TEST_F (MLServiceAgentTest, model_scenario)
   status = ml_option_destroy (activated_model_info);
   EXPECT_EQ (ML_ERROR_NONE, status);
 
+  /* failed to delete the active model */
   status = ml_service_model_delete (key, 2U);
-  EXPECT_EQ (ML_ERROR_NONE, status);
-
-  status = ml_service_model_delete (key, 1U);
   EXPECT_EQ (ML_ERROR_INVALID_PARAMETER, status);
 
+  status = ml_service_model_delete (key, 0U);
+  EXPECT_EQ (ML_ERROR_NONE, status);
+
   g_free (test_model1);
   g_free (test_model2);
 }
index 44772bc..2fa5097 100644 (file)
@@ -232,6 +232,58 @@ TEST (serviceDB, delete_model_n)
 }
 
 /**
+ * @brief Negative test for delete_model. Model is not registered.
+ */
+TEST (serviceDB, delete_model_unregistered_n)
+{
+  MLServiceDB &db = MLServiceDB::getInstance ();
+  int gotException = 0;
+  guint version;
+
+  db.connectDB ();
+
+  /* Test condition, remove all model with name 'test'. */
+  db.set_model ("test", "test_model", true, "", "", &version);
+  db.delete_model ("test", 0U);
+
+  try {
+    db.delete_model ("test", version);
+  } catch (const std::exception &e) {
+    g_critical ("Got Exception: %s", e.what ());
+    gotException = 1;
+  }
+  EXPECT_EQ (gotException, 1);
+
+  db.disconnectDB ();
+}
+
+/**
+ * @brief Negative test for delete_model. Model is activated.
+ */
+TEST (serviceDB, delete_model_activated_n)
+{
+  MLServiceDB &db = MLServiceDB::getInstance ();
+  int gotException = 0;
+  guint version;
+
+  db.connectDB ();
+
+  /* Test condition, add new model as activated. */
+  db.set_model ("test", "test_model", true, "", "", &version);
+
+  try {
+    db.delete_model ("test", version);
+  } catch (const std::exception &e) {
+    g_critical ("Got Exception: %s", e.what ());
+    gotException = 1;
+  }
+  EXPECT_EQ (gotException, 1);
+
+  db.delete_model ("test", 0U);
+  db.disconnectDB ();
+}
+
+/**
  * @brief Negative test for set_pipline. DB is not initialized.
  */
 TEST (serviceDBNotInitalized, set_pipeline_n)