|
From: <pra...@or...> - 2014-12-11 04:35:53
|
osaf/services/saf/amf/amfd/csi.cc | 194 ++++++++++++++++++++++++++++++-
osaf/services/saf/amf/amfd/include/csi.h | 1 +
osaf/services/saf/amf/amfd/si.cc | 44 -------
3 files changed, 194 insertions(+), 45 deletions(-)
At present AMF verifies cyclic CSI dependency in CCB apply callback for CSI.
If any cyclic CSI dependency is found, AMFD asserts.
Patch ensures that cyclic CSI dependency is detected as a part
of configuration validation and if found configuration is rejected.
diff --git a/osaf/services/saf/amf/amfd/csi.cc b/osaf/services/saf/amf/amfd/csi.cc
--- a/osaf/services/saf/amf/amfd/csi.cc
+++ b/osaf/services/saf/amf/amfd/csi.cc
@@ -26,6 +26,10 @@
AmfDb<std::string, AVD_CSI> *csi_db = NULL;
+//Temporary database of csis to check invalid configuration during ccb create operationi for csi.
+AmfDb<std::pair<std::string, std::string>, AVD_CSI> *csi_db_tmp = NULL;
+static bool cyclic_csi_dep_check_status = false;
+
void avd_csi_delete(AVD_CSI *csi)
{
AVD_CSI_ATTR *temp;
@@ -80,6 +84,172 @@ void csi_cmplt_delete(AVD_CSI *csi, bool
}
/**
+ * @brief Checks if cyclic csi dependency exists among the CSIs of same SI.
+ * During modification of csi for saAmfCSIDependencies AMF csi_db
+ * will be used and during the creation of csi, since original
+ * csi_db is not available, a temporary db will be used.
+ *
+ * @param[in] csi to be added/modified.
+ * @param[in] sponsor csi.
+ *
+ * @return true if csi deps exists.
+ * @return false if csi deps not exists.
+ */
+
+static bool is_cyclic_csideps_configured(AVD_CSI* csi_add, AVD_CSI *depcsi, CcbUtilOperationType type)
+{
+ AVD_CSI *sponsor_csi = NULL;
+
+ //First check horizontally: check among my own sponsors.
+ for (AVD_CSI_DEPS *sponsor_deps = depcsi->saAmfCSIDependencies; sponsor_deps != NULL;
+ sponsor_deps = sponsor_deps->csi_dep_next) {
+ if (type == CCBUTIL_CREATE) {
+ const char *si_dn = strchr((char*)&sponsor_deps->csi_dep_name_value.value, ',') + 1;
+ sponsor_csi = csi_db_tmp->find(make_pair(si_dn, Amf::to_string(&sponsor_deps->csi_dep_name_value)));
+ }
+ else
+ sponsor_csi = csi_db->find(Amf::to_string(&sponsor_deps->csi_dep_name_value));
+ if ((sponsor_csi != NULL) && (csi_add == sponsor_csi)) {
+ LOG_NO("cyclic deps found while adding/modifying :%s with %s",
+ csi_add->name.value,depcsi->name.value);
+ return true;
+ }
+ }
+
+ sponsor_csi = NULL;
+ //Second check vertically: among our sponsor's sponsors.
+ for (AVD_CSI_DEPS *sponsor_deps = depcsi->saAmfCSIDependencies; sponsor_deps != NULL;
+ sponsor_deps = sponsor_deps->csi_dep_next) {
+
+ if (type == CCBUTIL_CREATE) {
+ const char *si_dn = strchr((char*)&sponsor_deps->csi_dep_name_value.value, ',') + 1;
+ sponsor_csi = csi_db_tmp->find(make_pair(si_dn, Amf::to_string(&sponsor_deps->csi_dep_name_value)));
+ }
+ else
+ sponsor_csi = csi_db->find(Amf::to_string(&sponsor_deps->csi_dep_name_value));
+ if ((sponsor_csi !=NULL) && (is_cyclic_csideps_configured(csi_add, sponsor_csi, type) == true)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief Creates a temporary database of csis from ccb operations data.
+ * During the creation of csi, since original
+ * csi_db is not available, this temporary csi_db_tmp will be used.
+ *
+ * @param[in] ccb operation data.
+ *
+ */
+static void create_tmp_csidatabase(CcbUtilOperationData_t *opdata_in)
+{
+ csi_db_tmp = new AmfDb<std::pair<std::string, std::string>, AVD_CSI>;
+ CcbUtilOperationData_t *opdata = NULL;
+ while ((opdata = ccbutil_getNextCcbOp(opdata_in->ccbId, opdata)) != NULL) {
+
+ //Check for csis in CCB
+ if (strncmp((char *)&opdata->objectName.value, "safCsi=", 7) != 0)
+ continue;
+
+ unsigned int values_number = 0;
+ AVD_CSI *csi = new AVD_CSI();
+ csi->saAmfCSIDependencies = NULL;
+ memcpy(csi->name.value, opdata->objectName.value, opdata->objectName.length);
+ csi->name.length = opdata->objectName.length;
+ const char *si_dn = strchr((char*)&opdata->objectName.value, ',') + 1;
+ if ((immutil_getAttrValuesNumber(const_cast<SaImmAttrNameT>("saAmfCSIDependencies"),
+ opdata->param.create.attrValues, &values_number) == SA_AIS_OK)) {
+ if (values_number != 0) {
+ unsigned int i;
+ bool found;
+ AVD_CSI_DEPS *new_csi_dep = NULL;
+
+ for (i = 0; i < values_number; i++) {
+ new_csi_dep = new AVD_CSI_DEPS();
+ if (immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCSIDependencies"),
+ opdata->param.create.attrValues, i,
+ &new_csi_dep->csi_dep_name_value) != SA_AIS_OK) {
+ delete new_csi_dep;
+ goto done;
+ }
+ found = csi_add_csidep(csi,new_csi_dep);
+ if (found == true)
+ delete new_csi_dep;
+ }
+ }
+ }
+
+ if (csi_db_tmp->insert(make_pair(si_dn,Amf::to_string(&csi->name)), csi) != NCSCC_RC_SUCCESS)
+ goto done;
+ }
+done:
+ return;
+}
+/**
+ * @brief Frees the memory for all temporary created csis.
+ *
+ */
+static void delete_tmp_csidatabase()
+{
+ for (std::map<std::pair<std::string,std::string>, AVD_CSI*>::const_iterator it = csi_db_tmp->begin();
+ it != csi_db_tmp->end(); it++) {
+ AVD_CSI *csi = it->second;
+ for (AVD_CSI_DEPS *csi_deps = csi->saAmfCSIDependencies; csi_deps != NULL;
+ csi_deps = csi_deps->csi_dep_next)
+ delete csi_deps;
+ delete csi;
+ }
+ delete csi_db_tmp;
+}
+
+/*
+ * @brief Checks if cyclic csi dependency exists among the CSIs of same SI.
+ * Also makes sure that this check should be done only once per ccb.
+ *
+ * @param[in] ccb opeartion data.
+ *
+ * @return true if csi deps exists.
+ * @return false if csi deps not exists.
+ */
+
+static bool detect_cyclic_csidpes(CcbUtilOperationData_t *opdata_in)
+{
+ TRACE_ENTER();
+ bool is_cyclic = false;
+
+ if (opdata_in->operationType == CCBUTIL_CREATE) {
+ /*CSI deps will be checked once per ccb operation and not per invocation
+ of completed callback.*/
+ if (cyclic_csi_dep_check_status == true) {
+ return false;
+ }
+ create_tmp_csidatabase(opdata_in);
+ for (std::map<std::pair<std::string,std::string>, AVD_CSI*>::const_iterator it = csi_db_tmp->begin();
+ it != csi_db_tmp->end(); it++) {
+ AVD_CSI *csi = it->second;
+ //Detect any cyclic csi deps
+ is_cyclic = is_cyclic_csideps_configured(csi,csi, opdata_in->operationType);
+ if (is_cyclic == true)
+ break;
+ }
+ delete_tmp_csidatabase();
+ //Ensure cyclic csi deps should not be further verified in same ccb.
+ if (is_cyclic == false)
+ cyclic_csi_dep_check_status = true;
+
+ } else if (opdata_in->operationType == CCBUTIL_MODIFY) {
+ AVD_CSI *csi_tmp = NULL;
+ csi_tmp = csi_db->find(Amf::to_string(&opdata_in->objectName));
+ //Detect any cyclic csi deps
+ is_cyclic = is_cyclic_csideps_configured(csi_tmp,csi_tmp, opdata_in->operationType);
+ }
+
+ TRACE_LEAVE2("is_cyclic csi deps exist:%u",is_cyclic);
+ return is_cyclic;
+
+}
+/**
* Validate configuration attributes for an AMF CSI object
* @param csi
*
@@ -168,6 +338,11 @@ static int is_config_valid(const SaNameT
}
}
+ //Check if cyclic csi dependency exists.
+ if (opdata != NULL)
+ if (detect_cyclic_csidpes(opdata) == true)
+ return 0;
+
/* Verify that the SI can contain this CSI */
{
AVD_SI *avd_si;
@@ -220,7 +395,7 @@ static int is_config_valid(const SaNameT
*
* @return true/false
*/
-static bool csi_add_csidep(AVD_CSI *csi,AVD_CSI_DEPS *new_csi_dep)
+bool csi_add_csidep(AVD_CSI *csi,AVD_CSI_DEPS *new_csi_dep)
{
AVD_CSI_DEPS *temp_csi_dep;
bool csi_added = false;
@@ -621,6 +796,19 @@ static SaAisErrorT csi_ccb_completed_mod
"dependency for '%s' to itself", csi->name.value);
goto done;
}
+
+ //This new csi deps should not create cyclic deps.
+ AVD_CSI_DEPS *new_csi_dep = new AVD_CSI_DEPS();
+ new_csi_dep->csi_dep_name_value = *required_dn;
+ csi_add_csidep(csi, new_csi_dep);
+
+ if (detect_cyclic_csidpes(opdata) == true) {
+ csi_remove_csidep(csi, required_dn);
+ report_ccb_validation_error(opdata,
+ "cyclic dependency while modifying'%s'", csi->name.value);
+ goto done;
+ }
+ csi_remove_csidep(csi, required_dn);
} else if (attr_mod->modType == SA_IMM_ATTR_VALUES_DELETE) {
if (attr_mod->modAttr.attrValuesNumber > 1) {
report_ccb_validation_error(opdata, "only one dep can be removed at a time");
@@ -927,6 +1115,9 @@ static void csi_ccb_apply_create_hdlr(st
if (avd_cb->avail_state_avd != SA_AMF_HA_ACTIVE)
goto done;
+ //Whenever a csi is added it should not create cyclic csi deps.
+ cyclic_csi_dep_check_status = false;
+
csi_assign_hdlr(csi);
done:
@@ -1383,3 +1574,4 @@ bool csi_assignment_validate(AVD_SG *sg)
return true;
return false;
}
+
diff --git a/osaf/services/saf/amf/amfd/include/csi.h b/osaf/services/saf/amf/amfd/include/csi.h
--- a/osaf/services/saf/amf/amfd/include/csi.h
+++ b/osaf/services/saf/amf/amfd/include/csi.h
@@ -162,5 +162,6 @@ extern void csi_cmplt_delete(struct avd_
extern AVD_CSI *csi_create(const SaNameT *csi_name);
extern bool csi_assignment_validate(AVD_SG *sg);
extern SaAisErrorT csi_assign_hdlr(AVD_CSI *csi);
+extern bool csi_add_csidep(AVD_CSI *csi,AVD_CSI_DEPS *new_csi_dep);
#endif
diff --git a/osaf/services/saf/amf/amfd/si.cc b/osaf/services/saf/amf/amfd/si.cc
--- a/osaf/services/saf/amf/amfd/si.cc
+++ b/osaf/services/saf/amf/amfd/si.cc
@@ -29,45 +29,6 @@
AmfDb<std::string, AVD_SI> *si_db = NULL;
-/**
- * @brief Checks if the dependencies configured leads to loop
- * If loop is detected amf will just osafassert
- *
- * @param name
- * @param csi
- */
-static void osafassert_if_loops_in_csideps(SaNameT *csi_name, struct avd_csi_tag* csi)
-{
- AVD_CSI *temp_csi = NULL;
- AVD_CSI_DEPS *csi_dep_ptr;
-
- TRACE_ENTER2("%s", csi->name.value);
-
- /* Check if the CSI has any dependency on the csi_name
- * if yes then loop is there and osafassert
- */
- for(csi_dep_ptr = csi->saAmfCSIDependencies; csi_dep_ptr; csi_dep_ptr = csi_dep_ptr->csi_dep_next) {
- if (0 == memcmp(csi_name, &csi_dep_ptr->csi_dep_name_value, sizeof(SaNameT))) {
- LOG_ER("%s: %u: Looping detected in the CSI dependencies configured for csi:%s, osafasserting",
- __FILE__, __LINE__, csi->name.value);
- osafassert(0);
- }
- }
-
- /* Check if any of the dependents of CSI has dependency on csi_name */
- for (csi_dep_ptr = csi->saAmfCSIDependencies; csi_dep_ptr; csi_dep_ptr = csi_dep_ptr->csi_dep_next) {
- for (temp_csi = csi->si->list_of_csi; temp_csi; temp_csi = temp_csi->si_list_of_csi_next) {
- if(0 == memcmp(&temp_csi->name, &csi_dep_ptr->csi_dep_name_value, sizeof(SaNameT))) {
- /* Again call the loop detection function to check whether this temp_csi
- * has the dependency on the given csi_name
- */
- osafassert_if_loops_in_csideps(csi_name, temp_csi);
- }
- }
- }
- TRACE_LEAVE();
-}
-
void AVD_SI::arrange_dep_csi(struct avd_csi_tag* csi)
{
AVD_CSI *temp_csi = NULL;
@@ -83,11 +44,6 @@ void AVD_SI::arrange_dep_csi(struct avd_
/* Go through the all the dependencies of exising CSI */
for (csi_dep_ptr=temp_csi->saAmfCSIDependencies; csi_dep_ptr; csi_dep_ptr = csi_dep_ptr->csi_dep_next) {
if ((0 == memcmp(&csi_dep_ptr->csi_dep_name_value, &csi->name, sizeof(SaNameT)))) {
- /* Try finding out any loops in the dependency configuration with this temp_csi
- * and osafassert if any loop found
- */
- osafassert_if_loops_in_csideps(&temp_csi->name, csi);
-
/* Existing CSI is dependant on the new CSI, so its rank should be more
* than one of the new CSI. But increment the rank only if its rank is
* less than or equal the new CSI, since it can depend on multiple CSIs
|