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
