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
