Hi Zoran, Please find my comments inline.
BR, Hung Nguyen - DEK Technologies -------------------------------------------------------------------------------- From: Zoran Milinkovic zoran.milinko...@ericsson.com Sent: Tuesday, December 22, 2015 9:14PM To: Neelakanta Reddy reddy.neelaka...@oracle.com Cc: Opensaf-devel opensaf-devel@lists.sourceforge.net Subject: [devel] [PATCH 1 of 5] imm: add common library support for cloud resilience feature [#1625] osaf/libs/common/immsv/immpbe_dump.cc | 378 +++++++++++++++++++++++++- osaf/libs/common/immsv/immsv_evt.c | 43 ++ osaf/libs/common/immsv/include/immpbe_dump.hh | 2 +- osaf/libs/common/immsv/include/immsv_api.h | 1 + osaf/libs/common/immsv/include/immsv_evt.h | 17 +- 5 files changed, 430 insertions(+), 11 deletions(-) The patch contains IMM common library code for cloud resilience feature diff --git a/osaf/libs/common/immsv/immpbe_dump.cc b/osaf/libs/common/immsv/immpbe_dump.cc --- a/osaf/libs/common/immsv/immpbe_dump.cc +++ b/osaf/libs/common/immsv/immpbe_dump.cc @@ -1185,6 +1185,359 @@ bailout: exit(1); } +static bool verifyAttributeValuePBE(const char *attrVal, + SaImmAttrValueT value, SaImmValueTypeT attrType) { + + if(!attrVal && !value) { + return true; + } + if(!attrVal || !value) { + return false; + } + + switch(attrType) { + case SA_IMM_ATTR_SADOUBLET: { + char val[50]; + snprintf(val, 50, "%.15g", *(double *)value); + return strtod(attrVal, NULL) == strtod(val, NULL); + } + + case SA_IMM_ATTR_SAFLOATT: + return strtof(attrVal, NULL) == *(float *)value; + + case SA_IMM_ATTR_SAUINT32T: + return strtoul(attrVal, NULL, 10) == *(SaUint32T *)value; + + case SA_IMM_ATTR_SAINT32T: + return strtol(attrVal, NULL, 10) == *(SaInt32T *)value; + + case SA_IMM_ATTR_SAUINT64T: + return strtoull(attrVal, NULL, 10) == *(SaUint64T *)value; + + case SA_IMM_ATTR_SATIMET: + case SA_IMM_ATTR_SAINT64T: + return strtoll(attrVal, NULL, 10) == *(SaInt64T *)value; + + case SA_IMM_ATTR_SASTRINGT: + return strcmp(attrVal, *(SaStringT *)value) == 0; + + case SA_IMM_ATTR_SANAMET: + return strcmp(attrVal, osaf_extended_name_borrow((SaNameT *)value)) == 0; + + case SA_IMM_ATTR_SAANYT: { + std::ostringstream ost; + SaAnyT *any = (SaAnyT *)value; + + for (unsigned int i = 0; i < any->bufferSize; i++) { + ost << std::hex + << (((int)any->bufferAddr[i] < 0x10)? "0":"") + << (int)any->bufferAddr[i]; + } + + return strcmp(ost.str().c_str(), attrVal) == 0; + } + + default: + LOG_ER("UNKNOWN ATTRIBUTE TYPE: %d", attrType); + abort(); + } + + return false; +} + +static bool verifyObjectAttributePBE(const char *attrVal, SaImmAttrValuesT_2 *attr) { + unsigned int i; + + if(!attrVal && attr->attrValuesNumber == 0) { + return true; + } + + for(i=0; i<attr->attrValuesNumber; i++) { + if(verifyAttributeValuePBE(attrVal, attr->attrValues[i], attr->attrValueType)) { + return true; + } + } + + return false; +} + +static bool verifyClassObjectsPBE(std::string classNameString, + SaImmHandleT immHandle, + void* db_handle) +{ + sqlite3* dbHandle = (sqlite3 *) db_handle; + SaImmSearchHandleT searchHandle = 0; + SaImmSearchParametersT_2 searchParam; + const char *className = classNameString.c_str(); + SaAisErrorT err; + std::string sql; + char **result = NULL; + int nrow; + int ncol; + char *errmsg; + int n, c, r, i; + int attrPos; + int objectCounter = 0; + std::map<std::string, int> rdnMap; // <RDN, row in the result> + std::map<std::string, int>::iterator rmi; + SaStringT objectName; + SaImmAttrValuesT_2 **attributes; + SaImmAttrDefinitionT_2 **attrDefinitions = NULL; + SaImmClassCategoryT classCategory; + int rdnAttrDefIndex = -1; + bool ok = true; + int rc; + + TRACE_ENTER(); + + err = saImmOmClassDescriptionGet_2(immHandle, (SaImmClassNameT)className, &classCategory, &attrDefinitions); + if(err != SA_AIS_OK) { + LOG_ER("Cannot fetch class description for class '%s': %d", className, err); + TRACE_LEAVE(); + return false; + } + + // Skip runtime classes + if(classCategory == SA_IMM_CLASS_RUNTIME) { + saImmOmClassDescriptionMemoryFree_2(immHandle, attrDefinitions); + TRACE_LEAVE(); + return true; + } + + for(i=0; attrDefinitions[i]; i++) { + if(attrDefinitions[i]->attrFlags & SA_IMM_ATTR_RDN) { + rdnAttrDefIndex = i; + } + } + + if(attrDefinitions[i]) { + // This should never happen + LOG_ER("Cannot find RDN attribute in search result for class '%s'", className); + abort(); + } + + searchParam.searchOneAttr.attrName = (SaImmAttrNameT)"SaImmAttrClassName"; + searchParam.searchOneAttr.attrValue = &className; + searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT; + + err = saImmOmSearchInitialize_2(immHandle, NULL, SA_IMM_SUBTREE, + SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_ALL_ATTR | SA_IMM_SEARCH_PERSISTENT_ATTRS, + &searchParam, NULL, &searchHandle); + if(err != SA_AIS_OK) { + LOG_ER("Cannot fetch objects of class '%s' from IMM: %d", className, err); + goto bailout; + } + + sql = "SELECT o.dn, c.* FROM objects o, "; + sql.append(className); + sql.append(" c WHERE o.obj_id = c.obj_id"); + rc = sqlite3_get_table(dbHandle, sql.c_str(), &result, &nrow, &ncol, &errmsg); + if(rc) { + LOG_ER("SQL statement ('%s') failed. Reason: %s", sql.c_str(), errmsg); + goto bailout; + } + + // Map object DNs for fast search + for(n=1; n<=nrow; n++) { + rdnMap[result[n * ncol]] = n; + } + + // Iterate through IMM search result and check attributes + while((err = saImmOmSearchNext_o3(searchHandle, &objectName, &attributes)) == SA_AIS_OK) { + // Increase object counter + objectCounter++; + + // Skip checking IMM object + if(!strcmp(objectName, "opensafImm=opensafImm,safApp=safImmService") || + !strcmp(objectName, "safRdn=immManagement,safApp=safImmService")) { + continue; + } + + // Find object index in the fetched result + rmi = rdnMap.find(objectName); + if(rmi == rdnMap.end()) { + LOG_ER("IMM object '%s' cannot be found in PBE database", objectName); + goto bailout; + } + + // Check each attribute + for(i=0; attrDefinitions[i]; i++) { + // Don't check RDN attribute + if(i == rdnAttrDefIndex) { + continue; + } + + /* Skip persistent attributes. + * TODO: Should persistent runtime data be checked ??? + */ + if(attrDefinitions[i]->attrFlags & SA_IMM_ATTR_RUNTIME) { + continue; + } + + // Skip default attributes + if(!strcmp(attrDefinitions[i]->attrName, "SaImmAttrImplementerName") || + !strcmp(attrDefinitions[i]->attrName, "SaImmAttrClassName") || + !strcmp(attrDefinitions[i]->attrName, "SaImmAttrAdminOwnerName")) { + continue; + } + + // Find attribute from the search result + for(attrPos=0; attributes[attrPos]; attrPos++) { + if(!strcmp(attributes[attrPos]->attrName, attrDefinitions[i]->attrName)) { + break; + } + } + if(!attributes[attrPos]) { + LOG_ER("Cannot find attribute '%s' in object '%s' in the search result", + attrDefinitions[i]->attrName, objectName); + goto bailout; + } + + if(attrDefinitions[i]->attrFlags & SA_IMM_ATTR_MULTI_VALUE) { + // Check multi value attribute + char **res; + int nr, nc; // number of rows and columns + + // Create SQL statements to fetch multi values + switch(attrDefinitions[i]->attrValueType) { + case SA_IMM_ATTR_SADOUBLET: + case SA_IMM_ATTR_SAFLOATT: + sql = "SELECT real_val FROM objects_real_multi WHERE obj_id = "; + sql.append(result[rmi->second * ncol + 1]); + sql.append(" AND attr_name = '"); + sql.append(attrDefinitions[i]->attrName); + sql.append("'"); + break; + + case SA_IMM_ATTR_SAINT32T: + case SA_IMM_ATTR_SAINT64T: + case SA_IMM_ATTR_SAUINT32T: + case SA_IMM_ATTR_SAUINT64T: + case SA_IMM_ATTR_SATIMET: + sql = "SELECT int_val FROM objects_int_multi WHERE obj_id = "; + sql.append(result[rmi->second * ncol + 1]); + sql.append(" AND attr_name = '"); + sql.append(attrDefinitions[i]->attrName); + sql.append("'"); + break; + + case SA_IMM_ATTR_SASTRINGT: + case SA_IMM_ATTR_SANAMET: + sql = "SELECT text_val FROM objects_text_multi WHERE obj_id = "; + sql.append(result[rmi->second * ncol + 1]); + sql.append(" AND attr_name = '"); + sql.append(attrDefinitions[i]->attrName); + sql.append("'"); + break; + + case SA_IMM_ATTR_SAANYT: + sql = "SELECT real_val FROM objects_real_multi WHERE obj_id = "; + sql.append(result[rmi->second * ncol + 1]); + sql.append(" AND attr_name = '"); + sql.append(attrDefinitions[i]->attrName); + sql.append("'"); + break; + + default: + LOG_ER("UNKOWN attribute type: %d", attrDefinitions[i]->attrValueType); + abort(); + } + + // Execute SQL + if(sqlite3_get_table(dbHandle, sql.c_str(), &res, &nr, &nc, &errmsg) != SQLITE_OK) { + LOG_ER("Cannot fetch values for attribute '%s' in class '%s'. Reason: %s", + attrDefinitions[i]->attrName, className, errmsg); + goto bailout; + } + + // First multi value check. Check number of values + if(nr != (int)attributes[attrPos]->attrValuesNumber) { + LOG_ER("Mismatch in number of multi value attributes in attribute '%s' in object '%s'", + attributes[attrPos]->attrName, objectName); + ok = false; + goto finish; + } + + for(r=1; r<=nr; r++) { + // First loop. res vs. attributes + if(!verifyObjectAttributePBE(res[r], attributes[attrPos])) { + LOG_ER("Cannot match value for multi value attribute '%s' in object '%s'", + attributes[attrPos]->attrName, objectName); + // Values do not match + ok = false; + goto finish; + } + // Second loop. attributes vs. res + for(n=0; n<nr; n++) { + if(verifyAttributeValuePBE(res[r], attributes[attrPos]->attrValues[n], attributes[attrPos]->attrValueType)) { + // Found value + break; + } + } + if(n == nr) { + LOG_ER("Cannot match value for multi value attribute '%s' in object '%s'.", + attributes[attrPos]->attrName, objectName); + // Values didn't match in the second loop + ok = false; + goto finish; + } + } + +finish: + sqlite3_free_table(res); + if(!ok) { + goto bailout; + } + } else { // Check non-multi value attribute + // Find column in 'result' + for(c=2; c<ncol; c++) { + if(!strcmp(attrDefinitions[i]->attrName, result[c])) { + break; + } + } + + // Verify fetched value against value from the search result + if(!verifyObjectAttributePBE(result[rmi->second * ncol + c], attributes[attrPos])) { + LOG_ER("Cannot match attribute value for attribute '%s' in object '%s'", + attributes[attrPos]->attrName, objectName); + goto bailout; + } + } + } + } + + saImmOmSearchFinalize(searchHandle); + sqlite3_free_table(result); + saImmOmClassDescriptionMemoryFree_2(immHandle, attrDefinitions); + + if(objectCounter != nrow) { + LOG_ER("Mismatch in number of objects between IMM database and PBE database"); + TRACE_LEAVE(); + return false; + } + + TRACE_LEAVE(); + + return true; + +bailout: + if(result) { + sqlite3_free_table(result); + } + + if(searchHandle) { + saImmOmSearchFinalize(searchHandle); + } + + if(attrDefinitions) { + saImmOmClassDescriptionMemoryFree_2(immHandle, attrDefinitions); + } + + TRACE_LEAVE(); + + return false; +} + static ClassInfo* verifyClassPBE(std::string classNameString, SaImmHandleT immHandle, void* db_handle) @@ -1199,11 +1552,9 @@ static ClassInfo* verifyClassPBE(std::st SaImmAttrDefinitionT_2 **attrDefinitions; SaAisErrorT errorCode; /* - This function does very little verification right now. It should do more. - Reason is we are re-attaching to a DB file after a gap during which we do not know - what has happened to that file. We should at least verify that the number of classes - and number of objects match. Each object should really have a checksum. - Verification of objects should be a separate function verifyObjectPBE. + We are re-attaching to a DB file after a gap during which we do not know + what has happened to that file. We should at least verify that the number + of classes and number of objects match. */ TRACE_ENTER(); @@ -2509,7 +2860,7 @@ bool dumpClassesToPbe(SaImmHandleT immHa return false; } -int verifyPbeState(SaImmHandleT immHandle, ClassMap *classIdMap, void* db_handle) +int verifyPbeState(SaImmHandleT immHandle, ClassMap *classIdMap, void* db_handle, bool pbeVerifyObjects) { /* Function used only when re-connecting to an already existing DB file. */ std::list<std::string> classNameList; @@ -2524,6 +2875,8 @@ int verifyPbeState(SaImmHandleT immHandl int nrows=0; int ncols=0; bool badfile=false; + bool verified; + TRACE_ENTER(); classNameList = getClassNames(immHandle); @@ -2542,11 +2895,20 @@ int verifyPbeState(SaImmHandleT immHandl ClassInfo* cl_info = verifyClassPBE((*it), immHandle, dbHandle); if(cl_info) { (*classIdMap)[(*it)] = cl_info; - it++; } else { badfile=true; goto bailout; } + + if(pbeVerifyObjects) { + verified = verifyClassObjectsPBE((*it), immHandle, dbHandle); + if(!verified) { + badfile=true; + goto bailout; + } + } + + it++; } rc = sqlite3_get_table(dbHandle, sqlQ.c_str(), &result, &nrows, &ncols, &qErr); @@ -3816,7 +4178,7 @@ SaAisErrorT getCcbOutcomeFromPbe(void* d return SA_AIS_ERR_LIBRARY; } -int verifyPbeState(SaImmHandleT immHandle, ClassMap *classIdMap, void* db_handle) +int verifyPbeState(SaImmHandleT immHandle, ClassMap *classIdMap, void* db_handle, bool pbeVerifyObjects) { abort(); return 0; diff --git a/osaf/libs/common/immsv/immsv_evt.c b/osaf/libs/common/immsv/immsv_evt.c --- a/osaf/libs/common/immsv/immsv_evt.c +++ b/osaf/libs/common/immsv/immsv_evt.c @@ -2908,6 +2908,27 @@ static uint32_t immsv_evt_enc_toplevel(I ncs_enc_claim_space(o_ub, 4); /* immdevt->info.ctrl_msg.pbeFile.buf encoded by sublevel */ } + + if((immdevt->info.ctrl_msg.refresh == 2) && + (immdevt->type == IMMD_EVT_ND2D_INTRO)) { /* Intro after IMMD restart. */ + + IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 8); + ncs_encode_64bit(&p8, immdevt->info.ctrl_msg.fevs_count); + ncs_enc_claim_space(o_ub, 8); + + IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4); + ncs_encode_32bit(&p8, immdevt->info.ctrl_msg.admo_id_count); + ncs_enc_claim_space(o_ub, 4); + + IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4); + ncs_encode_32bit(&p8, immdevt->info.ctrl_msg.ccb_id_count); + ncs_enc_claim_space(o_ub, 4); + + IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4); + ncs_encode_32bit(&p8, immdevt->info.ctrl_msg.impl_count); + ncs_enc_claim_space(o_ub, 4); + } + break; case IMMD_EVT_ND2D_SYNC_FEVS_BASE: @@ -4283,6 +4304,28 @@ static uint32_t immsv_evt_dec_toplevel(N ncs_dec_skip_space(i_ub, 4); /* immdevt->info.ctrl_msg.pbeFile.buf decoded by sublevel */ } + + + if((immdevt->info.ctrl_msg.refresh == 2) && + (immdevt->type == IMMD_EVT_ND2D_INTRO)) { /* Intro after IMMD restart. */ + + IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 8); + immdevt->info.ctrl_msg.fevs_count = ncs_decode_64bit(&p8); + ncs_dec_skip_space(i_ub, 8); + + IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4); + immdevt->info.ctrl_msg.admo_id_count = ncs_decode_32bit(&p8); + ncs_dec_skip_space(i_ub, 4); + + IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4); + immdevt->info.ctrl_msg.ccb_id_count = ncs_decode_32bit(&p8); + ncs_dec_skip_space(i_ub, 4); + + IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4); + immdevt->info.ctrl_msg.impl_count = ncs_decode_32bit(&p8); + ncs_dec_skip_space(i_ub, 4); + } + break; case IMMD_EVT_ND2D_SYNC_FEVS_BASE: diff --git a/osaf/libs/common/immsv/include/immpbe_dump.hh b/osaf/libs/common/immsv/include/immpbe_dump.hh --- a/osaf/libs/common/immsv/include/immpbe_dump.hh +++ b/osaf/libs/common/immsv/include/immpbe_dump.hh @@ -81,7 +81,7 @@ void deleteClassToPBE(std::string classN ClassInfo* theClass); int verifyPbeState(SaImmHandleT immHandle, ClassMap *classIdMap, - void* db_handle); + void* db_handle, bool pbeVerifyObjects); int dumpObjectsToPbe(SaImmHandleT immHandle, ClassMap* classIdMap, void* db_handle); diff --git a/osaf/libs/common/immsv/include/immsv_api.h b/osaf/libs/common/immsv/include/immsv_api.h --- a/osaf/libs/common/immsv/include/immsv_api.h +++ b/osaf/libs/common/immsv/include/immsv_api.h @@ -61,6 +61,7 @@ extern "C" { #define OPENSAF_IMM_LONG_DNS_ALLOWED "longDnsAllowed" #define OPENSAF_IMM_ACCESS_CONTROL_MODE "accessControlMode" #define OPENSAF_IMM_AUTHORIZED_GROUP "authorizedGroup" +#define OPENSAF_IMM_SC_ABSENCE_ALLOWED "scAbsenceAllowed" typedef enum { ACCESS_CONTROL_DISABLED = 0, diff --git a/osaf/libs/common/immsv/include/immsv_evt.h b/osaf/libs/common/immsv/include/immsv_evt.h --- a/osaf/libs/common/immsv/include/immsv_evt.h +++ b/osaf/libs/common/immsv/include/immsv_evt.h @@ -412,7 +412,9 @@ typedef struct immsv_d2nd_control { IMMSV_OCTET_STRING dir; IMMSV_OCTET_STRING xmlFile; - IMMSV_OCTET_STRING pbeFile; + IMMSV_OCTET_STRING pbeFile; + + } IMMSV_D2ND_CONTROL; /**************************************************************************** @@ -422,7 +424,7 @@ typedef struct immsv_d2nd_control { typedef struct immsv_nd2d_control { SaUint32T ndExecPid; SaUint32T epoch; - uint8_t refresh; //TRUE=> This is a refresh of epoch. + uint8_t refresh; /* refresh>0 => Refresh of epoch; refresh==2 => IMMD restart intro.*/ uint8_t pbeEnabled;/* OpenSaf4.4: 2:not-enabled-not-configured can be convertred to 0 in immd. 3:not-enabled-configured @@ -435,6 +437,17 @@ typedef struct immsv_nd2d_control { IMMSV_OCTET_STRING dir; IMMSV_OCTET_STRING xmlFile; IMMSV_OCTET_STRING pbeFile; + + /* OpenSaf4.6: At restart of IMMD sv-id, IMMND gives feeedback on: [Hung] Not OpenSaf4.6 :) + - fevs_count + - admo_id_count + - ccb_id_count + - impl_count + */ + SaUint64T fevs_count; //Max received at IMMND for Fevs Count + SaUint32T admo_id_count;//Max received at IMMND for AdminOwner ID + SaUint32T ccb_id_count; //Max received at IMMND for CCB ID + SaUint32T impl_count; //Max received at IMMND for Implementer ID } IMMSV_ND2D_CONTROL; typedef struct immsv_nd2d_2_pbe { ------------------------------------------------------------------------------ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel