Hi Zoran, 

static std::string ReverseDn(std::string& input) in imm_xmlw_dump.cc seems to 
do the same as reverseDn in this patch.

/Hans

-----Original Message-----
From: Zoran Milinkovic [mailto:[email protected]] 
Sent: den 1 november 2017 15:44
To: Vu Minh Nguyen <[email protected]>
Cc: [email protected]
Subject: [devel] [PATCH 1/1] imm: improve the cascade delete [#2667]

IMMND will reduce the number of object deleted messages to PBE with sending 
only one message containing the root object name instead of sending one message 
for each delete object.
---
 src/imm/common/immpbe_dump.cc | 541 ++++++++++++++++++++++++++++++++++--------
 src/imm/immnd/ImmModel.cc     |  18 +-
 src/imm/immnd/ImmModel.h      |   3 +-
 src/imm/immnd/immnd_evt.c     | 217 ++++++++---------
 4 files changed, 557 insertions(+), 222 deletions(-)

diff --git a/src/imm/common/immpbe_dump.cc b/src/imm/common/immpbe_dump.cc 
index 11af674..98aa267 100644
--- a/src/imm/common/immpbe_dump.cc
+++ b/src/imm/common/immpbe_dump.cc
@@ -67,8 +67,6 @@ void pbeClosePrepareTrans() {
 
 static std::string *sPbeFileName;
 
-#define SQL_STMT_SIZE 31
-
 enum {
   /* INSERT */
   SQL_INS_OBJECTS_INT_MULTI = 0,
@@ -104,7 +102,21 @@ enum {
   SQL_DEL_OBJ_TEXT_MULTI_VAL,
   SQL_DEL_CCB_COMMITS,
   /* UPDATE */
-  SQL_UPD_OBJECTS
+  SQL_UPD_OBJECTS,
+  /* INMEMORY DB */
+  SQL_MEM_SEL_DEL_OBJ_CLASSES,
+  SQL_MEM_INS_REVERSE_DN,
+  SQL_MEM_INS_DEL_OBJ,
+  SQL_MEM_DEL_OBJECTS,
+  SQL_MEM_DEL_OBJECT,
+  SQL_MEM_DEL_OBJ_INT_MULTI_ID,
+  SQL_MEM_DEL_OBJ_REAL_MULTI_ID,
+  SQL_MEM_DEL_OBJ_TEXT_MULTI_ID,
+  SQL_MEM_DEL_REVERSE_DN,
+  SQL_MEM_DEL_DELETE_OBJ,
+
+  /* enum size */
+  SQL_STMT_SIZE
 };
 
 static const char *preparedSql[] = {
@@ -142,7 +154,24 @@ static const char *preparedSql[] = {
     "DELETE FROM objects_text_multi WHERE obj_id = ? AND attr_name = ? AND 
text_val = ?",
     "DELETE FROM ccb_commits WHERE epoch <= ?",
     /* UPDATE */
-    "UPDATE objects SET last_ccb = ? WHERE obj_id = ?"};
+    "UPDATE objects SET last_ccb = ? WHERE obj_id = ?",
+    /* INMEMORY DB */
+    "SELECT class_name FROM mem.delete_obj GROUP BY class_name",
+    "INSERT INTO mem.reverse_dn VALUES (?, ?)",
+    "INSERT INTO mem.delete_obj SELECT r.obj_id, c.class_name "
+        "FROM mem.reverse_dn r INNER JOIN objects o ON o.obj_id = r.obj_id "
+        "INNER JOIN classes c on c.class_id = o.class_id "
+        "WHERE r.rev_dn = ? OR r.rev_dn LIKE ?",
+    "DELETE FROM objects WHERE obj_id IN (SELECT obj_id FROM mem.delete_obj)",
+    "DELETE FROM mem.reverse_dn WHERE obj_id = ?",
+
+    "DELETE FROM objects_int_multi WHERE obj_id IN (SELECT obj_id FROM 
mem.delete_obj)",
+    "DELETE FROM objects_real_multi WHERE obj_id IN (SELECT obj_id FROM 
mem.delete_obj)",
+    "DELETE FROM objects_text_multi WHERE obj_id IN (SELECT obj_id FROM 
+ mem.delete_obj)",
+
+    "DELETE FROM mem.reverse_dn WHERE obj_id IN (SELECT obj_id FROM 
mem.delete_obj)",
+    "DELETE FROM mem.delete_obj"
+};
 
 static sqlite3_stmt *preparedStmt[SQL_STMT_SIZE] = {NULL};
 
@@ -546,6 +575,152 @@ void pbeAtomicSwitchFile(const char *filePath, 
std::string localTmpFilename) {
   }
 }
 
+static std::string reverseDn(std::string &dn) {
+  std::string revdn;
+  std::string rdn;
+  char ch[2];
+  int escape = 0;
+
+  ch[1] = 0;
+  for(size_t i=0; i<dn.size(); ++i) {
+    ch[0] = dn.at(i);
+    if(escape) {
+      rdn.append(ch);
+      escape = 0;
+    } else if(ch[0] == ',') {
+      if(revdn.empty()) {
+        revdn = rdn;
+      } else {
+        revdn = rdn + "," + revdn;
+      }
+      rdn.clear();
+    } else {
+      rdn.append(ch);
+      escape = (ch[0] == '\\');
+    }
+  }
+
+  if(!rdn.empty()) {
+    if(revdn.empty()) {
+      revdn = rdn;
+    } else {
+      revdn = rdn + "," + revdn;
+    }
+  }
+
+  return revdn;
+}
+
+static bool reverseAndInsertDn(sqlite3 *dbHandle, std::string &dn, int 
+obj_id) {
+  std::string revdn;
+  sqlite3_stmt *stmt;
+  bool ret = false;
+  int rc;
+
+  revdn = reverseDn(dn);
+  stmt = preparedStmt[SQL_MEM_INS_REVERSE_DN];
+
+  if ((rc = sqlite3_bind_text(stmt, 1, revdn.c_str(), -1, NULL)) !=
+      SQLITE_OK) {
+    LOG_ER("Failed to bind rev_dn with error code: %d", rc);
+    goto bailout;
+  }
+  if ((rc = sqlite3_bind_int(stmt, 2, obj_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because with error code: %d",
+           preparedSql[SQL_MEM_INS_REVERSE_DN], rc);
+    goto bailout;
+  }
+
+  ret = true;
+
+bailout:
+  sqlite3_reset(stmt);
+
+  return ret;
+}
+
+static bool prepareReverseDNs(sqlite3 *dbHandle) {
+  sqlite3_stmt *stmt = NULL;
+  const char *sql = "SELECT dn, obj_id FROM objects";
+  int rc;
+  bool ret = false;
+  int obj_id;
+  std::string dn;
+  int count = 0;
+
+  TRACE_ENTER();
+
+  rc = sqlite3_prepare_v2(dbHandle, sql, -1, &stmt, NULL);  if (rc != 
+ SQLITE_OK) {
+    LOG_ER("Failed to prepare SQL statement for: %s", sql);
+    goto failed;
+  }
+
+  while((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
+    dn = (char *)sqlite3_column_text(stmt, 0);
+    obj_id = sqlite3_column_int(stmt, 1);
+
+    ret = reverseAndInsertDn(dbHandle, dn, obj_id);
+    if(!ret) {
+      LOG_ER("Failed to insert reverse DN");
+      goto failed;
+    }
+    ++count;
+  }
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed. Error code: %d", sql, rc);
+    goto failed;
+  }
+
+  TRACE("Added %d reverse DNs to reverse_dn table", count);
+
+  ret = true;
+
+failed:
+  if(stmt) {
+    sqlite3_finalize(stmt);
+  }
+
+  TRACE_LEAVE();
+
+  return ret;
+}
+
+static bool attach_memory_database(sqlite3 *dbHandle) {
+  char *zErr = NULL;
+  int ret = false;
+  int rc;
+  const char *sql[] = {
+      "ATTACH DATABASE ':memory:' AS mem",
+      "CREATE TABLE mem.reverse_dn (rev_dn text primary key, obj_id integer, "
+                                    "unique (obj_id))",
+      "CREATE TABLE mem.delete_obj (obj_id integer primary key, class_name 
text)",
+      "CREATE INDEX mem.del_obj_class_idx ON delete_obj (class_name)",
+      NULL
+  };
+
+  for (int ix = 0; sql[ix] != NULL; ++ix) {
+    rc = sqlite3_exec(dbHandle, sql[ix], NULL, NULL, &zErr);
+    if (rc != SQLITE_OK) {
+      LOG_ER("SQL statement %u/('%s') failed because:\n %s", ix, sql[ix],
+             zErr);
+      sqlite3_free(zErr);
+      goto failed;
+    }
+    TRACE("Successfully executed %s", sql[ix]);  }
+
+  ret = true;
+
+failed:
+  return ret;
+}
+
 void *pbeRepositoryInit(const char *filePath, bool create,
                         std::string &localTmpFilename) {
   int fd = (-1);
@@ -598,6 +773,7 @@ void *pbeRepositoryInit(const char *filePath, bool create,
       "CREATE INDEX ccb_commits_idx on ccb_commits (ccb_id, epoch)",
 
       "COMMIT TRANSACTION",
+
       NULL};
   TRACE_ENTER();
 
@@ -719,6 +895,11 @@ void *pbeRepositoryInit(const char *filePath, bool create,
     TRACE("Successfully executed %s", sql_tr[ix]);
   }
 
+  if(!attach_memory_database(dbHandle)) {
+    LOG_ER("Failed to attach memory database");
+    goto bailout;
+  }
+
   prepareSqlStatements(dbHandle);
 
   *sPbeFileName = std::string(filePath); @@ -822,8 +1003,15 @@ re_attach:
   *sPbeFileName =
       std::string(filePath); /* Avoid apend to presumed empty string */
 
+  if(!attach_memory_database(dbHandle)) {
+    LOG_ER("Failed to attach memory database");
+    goto bailout;
+  }
+
   prepareSqlStatements(dbHandle);
 
+  prepareReverseDNs(dbHandle);
+
   TRACE_LEAVE();
   return dbHandle;
 
@@ -2032,6 +2220,192 @@ bailout:
   exit(1);
 }
 
+static void oneObjectDeleteToPBE(std::string objectNameString, void 
+*db_handle) {
+  sqlite3 *dbHandle = (sqlite3 *)db_handle;
+  sqlite3_stmt *stmt;
+  std::string sql("delete from \"");
+
+  int rc = 0;
+  char *zErr = NULL;
+  std::string object_id_str;
+  int object_id;
+  int class_id;
+  std::string class_name;
+  bool badfile = false;
+  std::string revdn;
+  TRACE_ENTER();
+  assert(dbHandle);
+
+  /* First, look up obj_id and class_id  from objects where dn == 
+ objname. */  stmt = preparedStmt[SQL_SEL_OBJECTS_DN];  if ((rc = 
+ sqlite3_bind_text(stmt, 1, objectNameString.c_str(), -1, NULL)) !=
+      SQLITE_OK) {
+    LOG_ER("Failed to bind dn with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc == SQLITE_DONE) {
+    LOG_ER("Expected 1 row got 0 rows (line: %u)", __LINE__);
+    badfile = true;
+    goto bailout;
+  }
+  if (rc != SQLITE_ROW) {
+    LOG_ER("Could not access object '%s' for delete, error:%s",
+           objectNameString.c_str(), sqlite3_errmsg(dbHandle));
+    badfile = true;
+    goto bailout;
+  }
+
+  object_id = sqlite3_column_int(stmt, 0);  object_id_str.append((char 
+ *)sqlite3_column_text(stmt, 0));  class_id = sqlite3_column_int(stmt, 
+ 1);
+
+  if (sqlite3_step(stmt) == SQLITE_ROW) {
+    LOG_ER("Expected 1 row got more then 1 row (line: %u)", __LINE__);
+    badfile = true;
+    goto bailout;
+  }
+  sqlite3_reset(stmt);
+
+  TRACE_2("Successfully accessed object '%s'.", 
+ objectNameString.c_str());  TRACE_2("object_id:%d class_id:%d", 
+ object_id, class_id);
+
+  /*
+    Second, delete the root object tuple in objects for obj_id.
+  */
+  stmt = preparedStmt[SQL_DEL_OBJECTS];  if ((rc = 
+ sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_DEL_OBJECTS], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+  sqlite3_reset(stmt);
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));
+
+  /* Third get the class-name for the object */  stmt = 
+ preparedStmt[SQL_SEL_CLASSES_ID];  if ((rc = sqlite3_bind_int(stmt, 1, 
+ class_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind class_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc == SQLITE_DONE) {
+    LOG_ER("Expected 1 row got 0 rows (line: %u)", __LINE__);
+    badfile = true;
+    goto bailout;
+  }
+  if (rc != SQLITE_ROW) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_SEL_CLASSES_ID], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+
+  class_name.append((char *)sqlite3_column_text(stmt, 0));
+
+  if (sqlite3_step(stmt) == SQLITE_ROW) {
+    LOG_ER("Expected 1 row got more then 1 row (line: %u)", __LINE__);
+    badfile = true;
+    goto bailout;
+  }
+  sqlite3_reset(stmt);
+
+  TRACE_2("Successfully accessed classes class_id:%d class_name:'%s'", 
class_id,
+          class_name.c_str());
+
+  /* Fourth delete the base attribute tuple from table 'classname' for obj_id.
+   */
+  sql.append(class_name);
+  sql.append("\" where obj_id = ");
+  sql.append(object_id_str);
+
+  TRACE("GENERATED 4:%s", sql.c_str());  rc = sqlite3_exec(dbHandle, 
+ sql.c_str(), NULL, NULL, &zErr);  if (rc) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s", sql.c_str(), zErr);
+    sqlite3_free(zErr);
+    goto bailout;
+  }
+
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));
+
+  /*
+    Fifth delete from objects_int_multi, objects_real_multi, objects_text_multi
+    where obj_id ==OBJ_ID
+   */
+  stmt = preparedStmt[SQL_DEL_OBJ_INT_MULTI_ID];
+  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_DEL_OBJ_INT_MULTI_ID], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));  
+ sqlite3_reset(stmt);
+
+  stmt = preparedStmt[SQL_DEL_OBJ_REAL_MULTI_ID];
+  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_DEL_OBJ_REAL_MULTI_ID], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));  
+ sqlite3_reset(stmt);
+
+  stmt = preparedStmt[SQL_DEL_OBJ_TEXT_MULTI_ID];
+  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_DEL_OBJ_TEXT_MULTI_ID], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));  
+ sqlite3_reset(stmt);
+
+  /* Delete from reverse DN table */
+  stmt = preparedStmt[SQL_MEM_DEL_OBJECT];  if ((rc = 
+ sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
+    LOG_ER("Failed to bind obj_id with error code: %d", rc);
+    goto bailout;
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+           preparedSql[SQL_MEM_DEL_OBJECT], sqlite3_errmsg(dbHandle));
+    goto bailout;
+  }
+  TRACE("Deleted %u values", sqlite3_changes(dbHandle));  
+ sqlite3_reset(stmt);
+
+  TRACE_LEAVE();
+  return;
+
+bailout:
+  sqlite3_close((sqlite3 *)dbHandle);
+  if (badfile) {
+    discardPbeFile(*sPbeFileName);
+  }
+  LOG_ER("Exiting (line:%u)", __LINE__);
+  exit(1);
+}
+
 unsigned int purgeInstancesOfClassToPBE(SaImmHandleT immHandle,
                                         std::string className,
                                         void *db_handle) { @@ -2084,7 +2458,7 
@@ unsigned int purgeInstancesOfClassToPBE(SaImmHandleT immHandle,
 
     // assert(attrs[0] == NULL);
 
-    objectDeleteToPBE(std::string(osaf_extended_name_borrow(&objectName)),
+    
+ oneObjectDeleteToPBE(std::string(osaf_extended_name_borrow(&objectName
+ )),
                       db_handle);
     ++nrofDeletes;
   } while (true);
@@ -2181,156 +2555,114 @@ bailout:
 void objectDeleteToPBE(std::string objectNameString, void *db_handle) {
   sqlite3 *dbHandle = (sqlite3 *)db_handle;
   sqlite3_stmt *stmt;
-  std::string sql("delete from \"");
-
+  std::string revDn = reverseDn(objectNameString);  std::string 
+ likeRevDn = revDn + ",\%";
   int rc = 0;
+  bool badfile = false;
   char *zErr = NULL;
-  std::string object_id_str;
-  int object_id;
-  int class_id;
   std::string class_name;
-  bool badfile = false;
+
   TRACE_ENTER();
-  assert(dbHandle);
 
-  /* First, look up obj_id and class_id  from objects where dn == objname. */
-  stmt = preparedStmt[SQL_SEL_OBJECTS_DN];
-  if ((rc = sqlite3_bind_text(stmt, 1, objectNameString.c_str(), -1, NULL)) !=
+  /* Fill in mem.delete_obj with objects */  stmt = 
+ preparedStmt[SQL_MEM_INS_DEL_OBJ];
+  if ((rc = sqlite3_bind_text(stmt, 1, revDn.c_str(), -1, NULL)) !=
       SQLITE_OK) {
-    LOG_ER("Failed to bind dn with error code: %d", rc);
+    LOG_ER("Failed to bind reverse dn with error code: %d", rc);
     goto bailout;
   }
-  rc = sqlite3_step(stmt);
-  if (rc == SQLITE_DONE) {
-    LOG_ER("Expected 1 row got 0 rows (line: %u)", __LINE__);
-    badfile = true;
+  if ((rc = sqlite3_bind_text(stmt, 2, likeRevDn.c_str(), -1, NULL)) !=
+      SQLITE_OK) {
+    LOG_ER("Failed to bind like reverse dn with error code: %d", rc);
     goto bailout;
   }
-  if (rc != SQLITE_ROW) {
-    LOG_ER("Could not access object '%s' for delete, error:%s",
-           objectNameString.c_str(), sqlite3_errmsg(dbHandle));
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+        preparedSql[SQL_MEM_INS_DEL_OBJ], zErr);
     badfile = true;
     goto bailout;
   }
+  sqlite3_reset(stmt);
 
-  object_id = sqlite3_column_int(stmt, 0);
-  object_id_str.append((char *)sqlite3_column_text(stmt, 0));
-  class_id = sqlite3_column_int(stmt, 1);
-
-  if (sqlite3_step(stmt) == SQLITE_ROW) {
-    LOG_ER("Expected 1 row got more then 1 row (line: %u)", __LINE__);
+  /* cascade delete from objects table */  stmt = 
+ preparedStmt[SQL_MEM_DEL_OBJECTS];
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_DONE) {
+    LOG_ER("SQL statement ('%s') failed because:\n %s",
+        preparedSql[SQL_MEM_DEL_OBJECTS], zErr);
     badfile = true;
     goto bailout;
   }
   sqlite3_reset(stmt);
 
-  TRACE_2("Successfully accessed object '%s'.", objectNameString.c_str());
-  TRACE_2("object_id:%d class_id:%d", object_id, class_id);
+  /* Delete objects from each affected class */  stmt = 
+ preparedStmt[SQL_MEM_SEL_DEL_OBJ_CLASSES];
+  while((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
+    char *class_name = (char *)sqlite3_column_text(stmt, 0);
+    std::string sql = std::string("DELETE FROM ") + class_name +
+        " WHERE obj_id IN (SELECT obj_id "
+                          "FROM mem.delete_obj "
+                          "WHERE class_name = '" + class_name + "')";
+    rc = sqlite3_exec(dbHandle, sql.c_str(), NULL, NULL, &zErr);
+    if (rc) {
+      LOG_ER("SQL statement ('%s') failed because:\n %s", sql.c_str(), zErr);
+      sqlite3_free(zErr);
+      goto bailout;
+    }
+  }
+  sqlite3_reset(stmt);
 
   /*
-    Second, delete the root object tuple in objects for obj_id.
-  */
-  stmt = preparedStmt[SQL_DEL_OBJECTS];
-  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
-    LOG_ER("Failed to bind obj_id with error code: %d", rc);
-    goto bailout;
-  }
+    Delete from objects_int_multi, objects_real_multi, objects_text_multi
+   */
+  stmt = preparedStmt[SQL_MEM_DEL_OBJ_INT_MULTI_ID];
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     LOG_ER("SQL statement ('%s') failed because:\n %s",
-           preparedSql[SQL_DEL_OBJECTS], sqlite3_errmsg(dbHandle));
+           preparedSql[SQL_MEM_DEL_OBJ_INT_MULTI_ID], 
+ sqlite3_errmsg(dbHandle));
     goto bailout;
   }
-  sqlite3_reset(stmt);
   TRACE("Deleted %u values", sqlite3_changes(dbHandle));
+  sqlite3_reset(stmt);
 
-  /* Third get the class-name for the object */
-  stmt = preparedStmt[SQL_SEL_CLASSES_ID];
-  if ((rc = sqlite3_bind_int(stmt, 1, class_id)) != SQLITE_OK) {
-    LOG_ER("Failed to bind class_id with error code: %d", rc);
-    goto bailout;
-  }
+  stmt = preparedStmt[SQL_MEM_DEL_OBJ_REAL_MULTI_ID];
   rc = sqlite3_step(stmt);
-  if (rc == SQLITE_DONE) {
-    LOG_ER("Expected 1 row got 0 rows (line: %u)", __LINE__);
-    badfile = true;
-    goto bailout;
-  }
-  if (rc != SQLITE_ROW) {
+  if (rc != SQLITE_DONE) {
     LOG_ER("SQL statement ('%s') failed because:\n %s",
-           preparedSql[SQL_SEL_CLASSES_ID], sqlite3_errmsg(dbHandle));
-    goto bailout;
-  }
-
-  class_name.append((char *)sqlite3_column_text(stmt, 0));
-
-  if (sqlite3_step(stmt) == SQLITE_ROW) {
-    LOG_ER("Expected 1 row got more then 1 row (line: %u)", __LINE__);
-    badfile = true;
-    goto bailout;
-  }
-  sqlite3_reset(stmt);
-
-  TRACE_2("Successfully accessed classes class_id:%d class_name:'%s'", 
class_id,
-          class_name.c_str());
-
-  /* Fourth delete the base attribute tuple from table 'classname' for obj_id.
-   */
-  sql.append(class_name);
-  sql.append("\" where obj_id = ");
-  sql.append(object_id_str);
-
-  TRACE("GENERATED 4:%s", sql.c_str());
-  rc = sqlite3_exec(dbHandle, sql.c_str(), NULL, NULL, &zErr);
-  if (rc) {
-    LOG_ER("SQL statement ('%s') failed because:\n %s", sql.c_str(), zErr);
-    sqlite3_free(zErr);
+           preparedSql[SQL_MEM_DEL_OBJ_REAL_MULTI_ID], 
+ sqlite3_errmsg(dbHandle));
     goto bailout;
   }
-
   TRACE("Deleted %u values", sqlite3_changes(dbHandle));
+  sqlite3_reset(stmt);
 
-  /*
-    Fifth delete from objects_int_multi, objects_real_multi, objects_text_multi
-    where obj_id ==OBJ_ID
-   */
-  stmt = preparedStmt[SQL_DEL_OBJ_INT_MULTI_ID];
-  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
-    LOG_ER("Failed to bind obj_id with error code: %d", rc);
-    goto bailout;
-  }
+  stmt = preparedStmt[SQL_MEM_DEL_OBJ_TEXT_MULTI_ID];
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     LOG_ER("SQL statement ('%s') failed because:\n %s",
-           preparedSql[SQL_DEL_OBJ_INT_MULTI_ID], sqlite3_errmsg(dbHandle));
+           preparedSql[SQL_MEM_DEL_OBJ_TEXT_MULTI_ID], 
+ sqlite3_errmsg(dbHandle));
     goto bailout;
   }
   TRACE("Deleted %u values", sqlite3_changes(dbHandle));
   sqlite3_reset(stmt);
 
-  stmt = preparedStmt[SQL_DEL_OBJ_REAL_MULTI_ID];
-  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
-    LOG_ER("Failed to bind obj_id with error code: %d", rc);
-    goto bailout;
-  }
+  /* remove objects from reverse_dn table */  stmt = 
+ preparedStmt[SQL_MEM_DEL_REVERSE_DN];
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     LOG_ER("SQL statement ('%s') failed because:\n %s",
-           preparedSql[SQL_DEL_OBJ_REAL_MULTI_ID], sqlite3_errmsg(dbHandle));
+           preparedSql[SQL_MEM_DEL_REVERSE_DN], 
+ sqlite3_errmsg(dbHandle));
     goto bailout;
   }
   TRACE("Deleted %u values", sqlite3_changes(dbHandle));
   sqlite3_reset(stmt);
 
-  stmt = preparedStmt[SQL_DEL_OBJ_TEXT_MULTI_ID];
-  if ((rc = sqlite3_bind_int(stmt, 1, object_id)) != SQLITE_OK) {
-    LOG_ER("Failed to bind obj_id with error code: %d", rc);
-    goto bailout;
-  }
+  /* Clean delete_obj table */
+  stmt = preparedStmt[SQL_MEM_DEL_DELETE_OBJ];
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE) {
     LOG_ER("SQL statement ('%s') failed because:\n %s",
-           preparedSql[SQL_DEL_OBJ_TEXT_MULTI_ID], sqlite3_errmsg(dbHandle));
+           preparedSql[SQL_MEM_DEL_DELETE_OBJ], 
+ sqlite3_errmsg(dbHandle));
     goto bailout;
   }
   TRACE("Deleted %u values", sqlite3_changes(dbHandle)); @@ -2486,6 +2818,11 
@@ bool objectToPBE(std::string objectNameString, const SaImmAttrValuesT_2 
**attrs,
   sqlite3_reset(stmt);
   sqlite3_clear_bindings(stmt);
 
+  if(!reverseAndInsertDn(dbHandle, objectNameString, object_id)) {
+    LOG_ER("Failed to insert reverse DN");
+    goto bailout;
+  }
+
   TRACE_LEAVE();
   return true;
 bailout:
diff --git a/src/imm/immnd/ImmModel.cc b/src/imm/immnd/ImmModel.cc index 
16fd4d8..44069c3 100644
--- a/src/imm/immnd/ImmModel.cc
+++ b/src/imm/immnd/ImmModel.cc
@@ -2476,6 +2476,7 @@ void ImmModel::pbePrtoPurgeMutations(unsigned int nodeId,
   ContinuationMap2::iterator ci;
   ImmAttrValueMap::iterator oavi;
   ObjectInfo* afim = NULL;
+  std::set<SaUint32T> connSet;
   TRACE_ENTER();
   bool dummy = false;
   bool dummy2 = false;
@@ -2504,7 +2505,11 @@ void ImmModel::pbePrtoPurgeMutations(unsigned int nodeId,
            be the only proper reply, so we let the client
            timeout by not replying.
         */
-        connVector.push_back(ci->second.mConn);
+        if(connSet.find(ci->second.mConn) == connSet.end()) {
+          /* Don't add a connection more that once */
+          connSet.insert(ci->second.mConn);
+          connVector.push_back(ci->second.mConn);
+        }
       }
       sPbeRtReqContinuationMap.erase(ci);
     }
@@ -10384,7 +10389,8 @@ SaAisErrorT ImmModel::ccbObjectDelete(
 
     err = deleteObject(oi, reqConn, adminOwner, ccb, doIt, objNameVector,
                        connVector, continuations,
-                       pbeConnPtr ? (*pbeConnPtr) : 0, &readLockedObject);
+                       pbeConnPtr ? (*pbeConnPtr) : 0, &readLockedObject,
+                       true);
 
     if (err == SA_AIS_OK && readLockedObject != NULL) {
       safeReadObjSet.insert(readLockedObject);
@@ -10406,7 +10412,8 @@ SaAisErrorT ImmModel::ccbObjectDelete(
           --childCount;
           err = deleteObject(oi2, reqConn, adminOwner, ccb, doIt, 
objNameVector,
                              connVector, continuations,
-                             pbeConnPtr ? (*pbeConnPtr) : 0, 
&readLockedObject);
+                             pbeConnPtr ? (*pbeConnPtr) : 0, &readLockedObject,
+                             false);
           if (err == SA_AIS_OK && readLockedObject != NULL) {
             safeReadObjSet.insert(readLockedObject);
           }
@@ -10437,7 +10444,8 @@ SaAisErrorT ImmModel::deleteObject(ObjectMap::iterator& 
oi, SaUint32T reqConn,
                                    ConnVector& connVector,
                                    IdVector& continuations,
                                    unsigned int pbeIsLocal,
-                                   ObjectInfo** readLockedObject) {
+                                   ObjectInfo** readLockedObject,
+                                   bool sendToPbe) {
   /*TRACE_ENTER();*/
   bool configObj = true;
   std::string objAdminOwnerName;
@@ -10738,7 +10746,7 @@ SaAisErrorT ImmModel::deleteObject(ObjectMap::iterator& 
oi, SaUint32T reqConn,
 
     if (nonPersistentRto) {
       TRACE_7("Not incrementing op-count for ccb delete of non-persistent 
RTO");
-    } else {
+    } else if(sendToPbe) {
       ccb->mOpCount++;
     }
 
diff --git a/src/imm/immnd/ImmModel.h b/src/imm/immnd/ImmModel.h index 
9e4c54a..8657f7c 100644
--- a/src/imm/immnd/ImmModel.h
+++ b/src/imm/immnd/ImmModel.h
@@ -219,7 +219,8 @@ class ImmModel {
                            ObjectNameVector& objNameVector,
                            ConnVector& connVector, IdVector& continuations,
                            unsigned int pbeIsLocal,
-                           ObjectInfo** readLockedObject);
+                           ObjectInfo** readLockedObject,
+                           bool sendToPbe);
 
   void setCcbErrorString(CcbInfo* ccb, const char* errorString, va_list vl);
 
diff --git a/src/imm/immnd/immnd_evt.c b/src/imm/immnd/immnd_evt.c index 
52d33dc..47f10d6 100644
--- a/src/imm/immnd/immnd_evt.c
+++ b/src/imm/immnd/immnd_evt.c
@@ -8281,15 +8281,6 @@ static void immnd_evt_proc_object_delete(IMMND_CB *cb, 
IMMND_EVT *evt,
                osafassert(pbeNodeId);
                osafassert(pbeNodeId == cb->node_id);
                implHandle = m_IMMSV_PACK_HANDLE(pbeConn, pbeNodeId);
-               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
-               send_evt.type = IMMSV_EVT_TYPE_IMMA;
-               /* PBE is internal => can handle long DNs */
-               send_evt.info.imma.type = IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
-               send_evt.info.imma.info.objDelete.ccbId =
-                   evt->info.objDelete.ccbId;
-               send_evt.info.imma.info.objDelete.immHandle = implHandle;
-               send_evt.info.imma.info.objDelete.adminOwnerId =
-                   0; /* No reply!*/
 
                /*Fetch client node for PBE */
                immnd_client_node_get(cb, implHandle, &oi_cl_node); @@ -8314,28 
+8305,35 @@ static void immnd_evt_proc_object_delete(IMMND_CB *cb, IMMND_EVT 
*evt,
                           upcalls are generated for cached non-persistent
                           runtime objects that are delete as a side effect.
                         */
-                       int ix = 0;
-                       for (; ix < arrSize && err == SA_AIS_OK; ++ix) {
-                               send_evt.info.imma.info.objDelete.objectName
-                                   .size =
-                                   (SaUint32T)strlen(objNameArr[ix]) + 1;
-                               send_evt.info.imma.info.objDelete.objectName
-                                   .buf = objNameArr[ix];
 
-                               TRACE_2(
-                                   "MAKING PBE-IMPLEMENTER OBJ DELETE upcall");
-                               if (immnd_mds_msg_send(
-                                       cb, NCSMDS_SVC_ID_IMMA_OI,
-                                       oi_cl_node->agent_mds_dest,
-                                       &send_evt) != NCSCC_RC_SUCCESS) {
-                                       LOG_ER(
-                                           "Immnd upcall over MDS for 
ccbObjectDelete "
-                                           "to PBE failed! - aborting ccb %u",
-                                           evt->info.objDelete.ccbId);
-                                       err = SA_AIS_ERR_FAILED_OPERATION;
-                                       immnd_proc_global_abort_ccb(
-                                           cb, evt->info.objDelete.ccbId);
-                               }
+                       /* PBE will handle children objects */
+                       memset(&send_evt, '\0', sizeof(IMMSV_EVT));
+                       send_evt.type = IMMSV_EVT_TYPE_IMMA;
+                       /* PBE is internal => can handle long DNs */
+                       send_evt.info.imma.type = 
IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
+                       send_evt.info.imma.info.objDelete.ccbId =
+                           evt->info.objDelete.ccbId;
+                       send_evt.info.imma.info.objDelete.immHandle = 
implHandle;
+                       send_evt.info.imma.info.objDelete.adminOwnerId =
+                           0; /* No reply!*/
+                       send_evt.info.imma.info.objDelete.objectName
+                           .size = evt->info.objDelete.objectName.size;
+                       send_evt.info.imma.info.objDelete.objectName
+                           .buf = evt->info.objDelete.objectName.buf;
+
+                       TRACE_2(
+                           "MAKING PBE-IMPLEMENTER OBJ DELETE upcall");
+                       if (immnd_mds_msg_send(
+                               cb, NCSMDS_SVC_ID_IMMA_OI,
+                               oi_cl_node->agent_mds_dest,
+                               &send_evt) != NCSCC_RC_SUCCESS) {
+                               LOG_ER(
+                                   "Immnd upcall over MDS for ccbObjectDelete "
+                                   "to PBE failed! - aborting ccb %u",
+                                   evt->info.objDelete.ccbId);
+                               err = SA_AIS_ERR_FAILED_OPERATION;
+                               immnd_proc_global_abort_ccb(
+                                   cb, evt->info.objDelete.ccbId);
                        }
                }
        } /* End of PersistentBackEnd handling. */ @@ -8700,16 +8698,6 @@ 
static void immnd_evt_proc_rt_object_delete(IMMND_CB *cb, IMMND_EVT *evt,
                        osafassert(cb->mIsCoord);
                        osafassert(pbeNodeId == cb->node_id);
                        implHandle = m_IMMSV_PACK_HANDLE(pbeConn, pbeNodeId);
-                       memset(&send_evt, '\0', sizeof(IMMSV_EVT));
-                       send_evt.type = IMMSV_EVT_TYPE_IMMA;
-                       /* PBE is internal => can handle long DNs */
-                       send_evt.info.imma.type =
-                           IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
-                       send_evt.info.imma.info.objDelete.ccbId = 0;
-                       send_evt.info.imma.info.objDelete.adminOwnerId =
-                           continuationId;
-                       send_evt.info.imma.info.objDelete.immHandle =
-                           implHandle;
 
                        /*Fetch client node for PBE */
                        immnd_client_node_get(cb, implHandle, &pbe_cl_node); @@ 
-8726,52 +8714,60 @@ static void immnd_evt_proc_rt_object_delete(IMMND_CB *cb, 
IMMND_EVT *evt,
                                goto done;
                        } else {
                                /* We have obtained PBE handle & dest info for
-                                  PBE. Iterate through objNameArray and send
-                                  delete upcalls to PBE.
+                                  PBE. Send delete upcalls to PBE.
                                */
-                               int ix = 0;
-                               for (; ix < arrSize && err == SA_AIS_OK; ++ix) {
-                                       send_evt.info.imma.info.objDelete
-                                           .objectName.size =
-                                           (SaUint32T)strlen(objNameArr[ix]) +
-                                           1;
-                                       send_evt.info.imma.info.objDelete
-                                           .objectName.buf = objNameArr[ix];
+                               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
+                               send_evt.type = IMMSV_EVT_TYPE_IMMA;
+                               /* PBE is internal => can handle long DNs */
+                               send_evt.info.imma.type =
+                                   IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
+                               send_evt.info.imma.info.objDelete.ccbId = 0;
+                               send_evt.info.imma.info.objDelete.adminOwnerId =
+                                   continuationId;
+                               send_evt.info.imma.info.objDelete.immHandle =
+                                   implHandle;
 
-                                       TRACE_2(
-                                           "MAKING PBE-IMPLEMENTER PERSISTENT 
RT-OBJ DELETE upcalls");
-                                       if (immnd_mds_msg_send(
-                                               cb, NCSMDS_SVC_ID_IMMA_OI,
-                                               pbe_cl_node->agent_mds_dest,
-                                               &send_evt) !=
-                                           NCSCC_RC_SUCCESS) {
-                                               LOG_WA(
-                                                   "Upcall over MDS for 
persistent rt obj delete "
-                                                   "to PBE failed!");
-                                               /* TODO: we could possibly
-                                                  revert the delete here an
-                                                  return TRY_AGAIN. We may have
-                                                  succeeded in sending some
-                                                  deletes, but since we did not
-                                                  send the completed, the PRTO
-                                                  deletes will not be commited
-                                                  by the PBE.
-                                                */
-                                               goto done;
-                                       }
+                               send_evt.info.imma.info.objDelete
+                                       .objectName.size = 
evt->info.objDelete.objectName.size;
+                               send_evt.info.imma.info.objDelete
+                                       .objectName.buf = 
evt->info.objDelete.objectName.buf;
+
+                               if (immnd_mds_msg_send(
+                                       cb, NCSMDS_SVC_ID_IMMA_OI,
+                                       pbe_cl_node->agent_mds_dest,
+                                       &send_evt) !=
+                                       NCSCC_RC_SUCCESS) {
+                                       LOG_WA(
+                                               "Upcall over MDS for persistent 
rt obj delete "
+                                               "to PBE failed!");
+                                       /* TODO: we could possibly
+                                          revert the delete here an
+                                          return TRY_AGAIN. We may have
+                                          succeeded in sending some
+                                          deletes, but since we did not
+                                          send the completed, the PRTO
+                                          deletes will not be commited
+                                          by the PBE.
+                                        */
+                                       goto done;
                                }
 
+                               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
                                send_evt.info.imma.type =
                                    IMMA_EVT_ND2A_OI_CCB_COMPLETED_UC;
                                send_evt.info.imma.info.ccbCompl.ccbId = 0;
                                send_evt.info.imma.info.ccbCompl.immHandle =
                                    implHandle;
                                send_evt.info.imma.info.ccbCompl.implId =
-                                   arrSize;
+                                   1;
                                /* ^^Hack: Use implId to store objCount, see
                                   #1809.^^ This avoids having to change the
                                   protocol.
                                 */
+                               /* It will be always 1 for number of delete 
objects.
+                                * Cascade delete is done on PBE size, and only
+                                * parent DN is sent to PBE
+                                */
                                send_evt.info.imma.info.ccbCompl.invocation =
                                    continuationId;
 
@@ -8801,17 +8797,6 @@ static void immnd_evt_proc_rt_object_delete(IMMND_CB 
*cb, IMMND_EVT *evt,
                        implHandle =
                            m_IMMSV_PACK_HANDLE(pbe2BConn, cb->node_id);
 
-                       memset(&send_evt, '\0', sizeof(IMMSV_EVT));
-                       send_evt.type = IMMSV_EVT_TYPE_IMMA;
-
-                       send_evt.info.imma.type =
-                           IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
-                       send_evt.info.imma.info.objDelete.ccbId = 0;
-                       send_evt.info.imma.info.objDelete.adminOwnerId =
-                           continuationId;
-                       send_evt.info.imma.info.objDelete.immHandle =
-                           implHandle;
-
                        /*Fetch client node for Slave PBE */
                        immnd_client_node_get(cb, implHandle, &pbe_cl_node);
                        osafassert(pbe_cl_node);
@@ -8821,39 +8806,43 @@ static void immnd_evt_proc_rt_object_delete(IMMND_CB 
*cb, IMMND_EVT *evt,
                                goto done;
                        } else {
                                /* We have obtained handle & dest info for Slave
-                                  PBE. Iterate through objNameArray and send
-                                  delete upcalls to Slave PBE.
+                                  PBE. Send delete upcalls to Slave PBE.
                                */
-                               int ix = 0;
-                               for (; ix < arrSize && err == SA_AIS_OK; ++ix) {
-                                       send_evt.info.imma.info.objDelete
-                                           .objectName.size =
-                                           (SaUint32T)strlen(objNameArr[ix]) +
-                                           1;
-                                       send_evt.info.imma.info.objDelete
-                                           .objectName.buf = objNameArr[ix];
+                               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
+                               send_evt.type = IMMSV_EVT_TYPE_IMMA;
 
-                                       TRACE_2(
-                                           "MAKING PBE-SLAVE PERSISTENT RT-OBJ 
DELETE upcalls");
-                                       if (immnd_mds_msg_send(
-                                               cb, NCSMDS_SVC_ID_IMMA_OI,
-                                               pbe_cl_node->agent_mds_dest,
-                                               &send_evt) !=
-                                           NCSCC_RC_SUCCESS) {
-                                               LOG_WA(
-                                                   "Upcall over MDS for 
persistent rt obj delete "
-                                                   "to Slave PBE failed!");
-                                               /* TODO: we could possibly
-                                                  revert the delete here an
-                                                  return TRY_AGAIN. We may have
-                                                  succeeded in sending some
-                                                  deletes, but since we did not
-                                                  send the completed, the PRTO
-                                                  deletes will not be commited
-                                                  by the PBE.
-                                                */
-                                               goto done;
-                                       }
+                               send_evt.info.imma.type =
+                                   IMMA_EVT_ND2A_OI_OBJ_DELETE_UC;
+                               send_evt.info.imma.info.objDelete.ccbId = 0;
+                               send_evt.info.imma.info.objDelete.adminOwnerId =
+                                   continuationId;
+                               send_evt.info.imma.info.objDelete.immHandle =
+                                   implHandle;
+                               send_evt.info.imma.info.objDelete
+                                       .objectName.size = 
evt->info.objDelete.objectName.size;
+                               send_evt.info.imma.info.objDelete
+                                       .objectName.buf = 
evt->info.objDelete.objectName.buf;
+
+                               TRACE_2(
+                                       "MAKING PBE-SLAVE PERSISTENT RT-OBJ 
DELETE upcalls");
+                               if (immnd_mds_msg_send(
+                                       cb, NCSMDS_SVC_ID_IMMA_OI,
+                                       pbe_cl_node->agent_mds_dest,
+                                       &send_evt) !=
+                                       NCSCC_RC_SUCCESS) {
+                                       LOG_WA(
+                                               "Upcall over MDS for persistent 
rt obj delete "
+                                               "to Slave PBE failed!");
+                                       /* TODO: we could possibly
+                                          revert the delete here an
+                                          return TRY_AGAIN. We may have
+                                          succeeded in sending some
+                                          deletes, but since we did not
+                                          send the completed, the PRTO
+                                          deletes will not be commited
+                                          by the PBE.
+                                        */
+                                       goto done;
                                }
                        }
                        implHandle = 0LL;
--
1.9.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to