Hi Zoran,

Ack with few comments and some questions, tagged [Vu]. Thanks!

Regards, Vu

> -----Original Message-----
> From: Zoran Milinkovic [mailto:[email protected]]
> Sent: Wednesday, November 1, 2017 9:44 PM
> To: [email protected]
> Cc: [email protected]; Zoran Milinkovic
> <[email protected]>
> Subject: [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) {
[Vu] Consider using `const` for read-only parameter objects.

> +  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);
[Vu] Any reason of not invoking " prepareReverseDNs(dbHandle);" here?

> 
>    *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;
> +  }
[Vu] In case of "re-attach", is there any possibility that these tables
`mem.reverse_dn` or ` mem.delete_obj` already exist in the database?
if so, any problem if re-creating these tables?

> +
>    prepareSqlStatements(dbHandle);
> 
> +  prepareReverseDNs(dbHandle);
> +
>    TRACE_LEAVE();
>    return dbHandle;
> 
> @@ -2032,6 +2220,192 @@ bailout:
>    exit(1);
>  }
> 
> +static void oneObjectDeleteToPBE(std::string objectNameString, void
> *db_handle) {
[Vu] parameter 'objectNameString' should be passed by reference ?

> +  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(&objectNa
> me)),
>                        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
> +                              */
[Vu] Move this comment up one code line? I guess this comment is for the
code line " send_evt.info.imma.info.ccbCompl.implId = 1"? 

Thanks,
Vu

> 
>       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

Reply via email to