When replacing value of an attribute which has default-value tag with NULL during runtime, NULL value will be replaced with its default value after cluster is rebooted; in other words, that value is not persisted.
This patch makes some changes in immdump/immloader/imm om library/immnd to handle such requirement. --- src/imm/README | 10 +--- src/imm/agent/imma_om_api.cc | 7 ++- src/imm/immloadd/imm_loader.cc | 23 +++++--- src/imm/immloadd/imm_pbe_load.cc | 16 ++++-- src/imm/immnd/ImmModel.cc | 9 ++- src/imm/tools/imm_xmlw_dump.cc | 96 ++++++++++++++++++++------------ 6 files changed, 100 insertions(+), 61 deletions(-) diff --git a/src/imm/README b/src/imm/README index 7ace34741..132ee0ac0 100644 --- a/src/imm/README +++ b/src/imm/README @@ -351,14 +351,8 @@ as part of an attribute definition. (i) A default declaration is only allowed for single valued attributes (no concept of a multivalued default exists). -(ii) Default values are assigned at object creation. Default values are NOT -assigned if an attribute is set to the empty/null value by a modification. - -(iii) Default values are assigned at cluster restart for any attributes that -are null/empty and that have a default. This is a special case of (i) because -imm loading actually uses the regular imm API to recreate the imm contents. -In particular, saImmOmCcbObjectCreate is used to recreate all objects from -the file-system image. +(ii) Default values are assigned at object creation, except the creation comes +from IMM loader. Common missunderstandings about "system attributes" of an imm object. --------------------------------------------------------------------- diff --git a/src/imm/agent/imma_om_api.cc b/src/imm/agent/imma_om_api.cc index 7155799d9..0d24b2335 100644 --- a/src/imm/agent/imma_om_api.cc +++ b/src/imm/agent/imma_om_api.cc @@ -2037,7 +2037,7 @@ static SaAisErrorT ccb_object_create_common( TRACE_2("ERR_INVALID_PARAM: Not allowed to set attribute %s", sysaImplName); goto mds_send_fail; - } else if (attr->attrValuesNumber == 0) { + } else if (attr->attrValuesNumber == 0 && !immOmIsLoader) { TRACE("CcbObjectCreate ignoring attribute %s with no values", attr->attrName); continue; @@ -2065,7 +2065,9 @@ static SaAisErrorT ccb_object_create_common( const SaImmAttrValueT *avarr = attr->attrValues; /*alloc-5 */ - imma_copyAttrValue(&(p->n.attrValue), attr->attrValueType, avarr[0]); + if (attr->attrValuesNumber > 0) { + imma_copyAttrValue(&(p->n.attrValue), attr->attrValueType, avarr[0]); + } if (attr->attrValuesNumber > 1) { unsigned int numAdded = attr->attrValuesNumber - 1; @@ -2087,6 +2089,7 @@ static SaAisErrorT ccb_object_create_common( } } + rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout, cl_node->handle, &locked, false); cl_node = NULL; diff --git a/src/imm/immloadd/imm_loader.cc b/src/imm/immloadd/imm_loader.cc index e9a985c22..3bd3e2b2e 100644 --- a/src/imm/immloadd/imm_loader.cc +++ b/src/imm/immloadd/imm_loader.cc @@ -117,6 +117,7 @@ typedef struct ParserStateStruct { SaImmAttrFlagsT attrFlags; SaUint32T attrNtfId; char *attrDefaultValueBuffer; + bool is_null_value; int attrValueTypeSet; int attrNtfIdSet; @@ -925,6 +926,13 @@ static void startElementHandler(void *userData, const xmlChar *name, state->state[state->depth] = VALUE; state->valueContinue = 0; state->isBase64Encoded = isBase64Encoded(attrs); + state->is_null_value = false; + if (attrs) { + char* null_value = getAttributeValue("xsi:nil", attrs); + if (null_value && std::string{null_value} == "true") { + state->is_null_value = true; + } + } /* <category> */ } else if (strcmp((const char *)name, "category") == 0) { state->state[state->depth] = CATEGORY; @@ -982,7 +990,7 @@ static void endElementHandler(void *userData, const xmlChar *name) { /* </value> */ if (strcmp((const char *)name, "value") == 0) { - if (state->attrValueBuffers.empty()) { + if (state->attrValueBuffers.empty() && !state->is_null_value) { char *str = (char *)malloc(1); str[0] = '\0'; @@ -1759,14 +1767,13 @@ void addObjectAttributeDefinition( SaImmAttrValuesT_2 attrValues; int i; size_t len; + bool null_value = attrValueBuffers->empty(); + TRACE_ENTER2("attrValueBuffers size:%u", (unsigned int)attrValueBuffers->size()); /* The attrName must be set */ assert(attrName); - /* The value array can not be empty */ - assert(!attrValueBuffers->empty()); - /* The object class must be set */ assert(objectClass); @@ -1778,15 +1785,15 @@ void addObjectAttributeDefinition( /* For each value, convert from char* to SaImmAttrValuesT_2 and store an array pointing to all in attrValues */ - attrValues.attrValuesNumber = attrValueBuffers->size(); - attrValues.attrValues = (SaImmAttrValueT *)malloc( + attrValues.attrValuesNumber = null_value ? 0 : attrValueBuffers->size(); + attrValues.attrValues = null_value ? nullptr : (SaImmAttrValueT *)malloc( sizeof(SaImmAttrValuesT_2) * attrValues.attrValuesNumber + 1); - attrValues.attrValues[attrValues.attrValuesNumber] = NULL; + if (!null_value) attrValues.attrValues[attrValues.attrValuesNumber] = NULL; it = attrValueBuffers->begin(); i = 0; - while (it != attrValueBuffers->end()) { + while (!null_value && it != attrValueBuffers->end()) { charsToValueHelper(&attrValues.attrValues[i], attrValues.attrValueType, *it); i++; diff --git a/src/imm/immloadd/imm_pbe_load.cc b/src/imm/immloadd/imm_pbe_load.cc index d9e1c4d83..72b926383 100644 --- a/src/imm/immloadd/imm_pbe_load.cc +++ b/src/imm/immloadd/imm_pbe_load.cc @@ -524,7 +524,8 @@ bool loadObjectFromPbe(void *pbeHandle, SaImmHandleT immHandle, const unsigned char *res; for (c = 0; c < ncols; ++c) { res = sqlite3_column_text(stmt, c); - if (res) { + bool is_null = false; + if (true) { SaImmValueTypeT attrType = (SaImmValueTypeT)0; const char *colname = sqlite3_column_name(stmt, c); assert(colname != NULL); @@ -544,7 +545,7 @@ bool loadObjectFromPbe(void *pbeHandle, SaImmHandleT immHandle, assert(it != class_info->attrInfoVector.end()); char *val; - if (attrType == SA_IMM_ATTR_SADOUBLET) { + if (res && attrType == SA_IMM_ATTR_SADOUBLET) { double dbl = sqlite3_column_double(stmt, c); val = (char *)malloc(30); @@ -555,12 +556,16 @@ bool loadObjectFromPbe(void *pbeHandle, SaImmHandleT immHandle, snprintf(val, size, "%.17g", dbl); } } else { - val = strdup((const char *)res); + if (res) { + val = strdup((const char *)res); + } } + is_null = (res == nullptr); std::list<char *> attrValueBuffers; - attrValueBuffers.push_front(val); - + if (!is_null) { + attrValueBuffers.push_front(val); + } addObjectAttributeDefinition((char *)class_info->className.c_str(), (SaImmAttrNameT)colname, &attrValueBuffers, attrType, &attrValuesList); @@ -669,7 +674,6 @@ bool loadObjectFromPbe(void *pbeHandle, SaImmHandleT immHandle, (char *)(*it)->attrName.c_str(), &attrValueBuffers, (*it)->attrValueType, &attrValuesList); - sqlite3_reset(stmt); } /*if(attr_is_multi && !attr_is_pure_rt)*/ ++it; diff --git a/src/imm/immnd/ImmModel.cc b/src/imm/immnd/ImmModel.cc index 8e3f338dc..747b406c6 100644 --- a/src/imm/immnd/ImmModel.cc +++ b/src/imm/immnd/ImmModel.cc @@ -8393,8 +8393,13 @@ SaAisErrorT ImmModel::ccbObjectCreate( ImmAttrValue* attrValue = i6->second; IMMSV_OCTET_STRING tmpos; // temporary octet string - eduAtValToOs(&tmpos, &(p->n.attrValue), - (SaImmValueTypeT)p->n.attrValueType); + memset(&tmpos, 0, sizeof(tmpos)); + // Attribute value will be assigned null value or <empty> + // if having `attrValuesNumber=0` goes with it. + if (p->n.attrValuesNumber) { + eduAtValToOs(&tmpos, &(p->n.attrValue), + (SaImmValueTypeT)p->n.attrValueType); + } attrValue->setValue(tmpos); if (p->n.attrValuesNumber > 1) { /* diff --git a/src/imm/tools/imm_xmlw_dump.cc b/src/imm/tools/imm_xmlw_dump.cc index 2e7fcda86..e6fdd279f 100644 --- a/src/imm/tools/imm_xmlw_dump.cc +++ b/src/imm/tools/imm_xmlw_dump.cc @@ -419,11 +419,6 @@ void objectToXMLw(std::string objectNameString, SaImmAttrValuesT_2** attrs, exit(1); } for (SaImmAttrValuesT_2** p = attrs; *p != NULL; p++) { - /* Skip attributes with attrValues = NULL */ - if ((*p)->attrValues == NULL) { - continue; - } - if (classRDNMap.find(classNameString) != classRDNMap.end() && classRDNMap[classNameString] == std::string((*p)->attrName)) { continue; @@ -469,10 +464,6 @@ static void StoreObject(const std::string& objectName, /* Add attributes to list */ for (SaImmAttrValuesT_2** p = attrs; *p != NULL; p++) { - /* Skip attributes with attrValues = NULL */ - if ((*p)->attrValues == NULL) { - continue; - } /* Skip RDN */ if (classRDNMap.find(obj.className) != classRDNMap.end() && classRDNMap[obj.className] == std::string((*p)->attrName)) { @@ -544,42 +535,62 @@ static void ObjectSetToXMLw(std::set<Object, ObjectComp>& objectSet, } /* Write attribute values */ - for (std::list<std::string>::const_iterator value_it = - attr_it->second.begin(); - value_it != attr_it->second.end(); ++value_it) { + std::list<std::string> values = attr_it->second; + if (values.empty()) { if (xmlTextWriterStartElement(writer, (xmlChar*)"value") < 0) { std::cout << "Error at xmlTextWriterStartElement (value)" << std::endl; exit(1); } - if (osaf_is_valid_xml_utf8((*value_it).c_str())) { - if (xmlTextWriterWriteString(writer, (xmlChar*)(*value_it).c_str()) < - 0) { - std::cout << "Error at xmlTextWriterWriteString (value)" - << std::endl; - exit(1); - } - } else { - if (xmlTextWriterWriteAttribute(writer, (xmlChar*)"xsi:type", - (xmlChar*)"xs:base64Binary") < 0) { - std::cout << "Error at xmlTextWriterWriteAttribute (value)" - << std::endl; - exit(1); - } - if (xmlTextWriterWriteBase64(writer, (*value_it).c_str(), 0, - (*value_it).size()) < 0) { - std::cout << "Error at xmlTextWriterWriteBase64 (value)" - << std::endl; - exit(1); - } + if (xmlTextWriterWriteAttribute(writer, (xmlChar*)"xsi:nil", + (xmlChar*)"true") < 0) { + std::cout << "Error at xmlTextWriterWriteAttribute (value)" + << std::endl; + exit(1); } if (xmlTextWriterEndElement(writer) < 0) { std::cout << "Error at xmlTextWriterWriteEndElement (value)" << std::endl; exit(1); } - } /* Attribute values loop */ + } else { + for (std::list<std::string>::const_iterator value_it = + attr_it->second.begin(); + value_it != attr_it->second.end(); ++value_it) { + if (xmlTextWriterStartElement(writer, (xmlChar*)"value") < 0) { + std::cout << "Error at xmlTextWriterStartElement (value)" + << std::endl; + exit(1); + } + if (osaf_is_valid_xml_utf8((*value_it).c_str())) { + if (xmlTextWriterWriteString(writer, (xmlChar*)(*value_it).c_str()) < + 0) { + std::cout << "Error at xmlTextWriterWriteString (value)" + << std::endl; + exit(1); + } + } else { + if (xmlTextWriterWriteAttribute(writer, (xmlChar*)"xsi:type", + (xmlChar*)"xs:base64Binary") < 0) { + std::cout << "Error at xmlTextWriterWriteAttribute (value)" + << std::endl; + exit(1); + } + if (xmlTextWriterWriteBase64(writer, (*value_it).c_str(), 0, + (*value_it).size()) < 0) { + std::cout << "Error at xmlTextWriterWriteBase64 (value)" + << std::endl; + exit(1); + } + } + if (xmlTextWriterEndElement(writer) < 0) { + std::cout << "Error at xmlTextWriterWriteEndElement (value)" + << std::endl; + exit(1); + } + } /* Attribute values loop */ + } if (xmlTextWriterEndElement(writer) < 0) { std::cout << "Error at xmlTextWriterEndElement (attr-object)" << std::endl; @@ -597,8 +608,23 @@ static void ObjectSetToXMLw(std::set<Object, ObjectComp>& objectSet, } void valuesToXMLw(SaImmAttrValuesT_2* p, xmlTextWriterPtr writer) { - if (!p->attrValues) { - // std::cout << "No values!" << std::endl; + if (p->attrValuesNumber == 0) { + if (xmlTextWriterStartElement(writer, (xmlChar*)"value") < 0) { + std::cout << "Error at xmlTextWriterStartElement (value)" + << std::endl; + exit(1); + } + if (xmlTextWriterWriteAttribute(writer, (xmlChar*)"xsi:nil", + (xmlChar*)"true") < 0) { + std::cout << "Error at xmlTextWriterWriteAttribute (value)" + << std::endl; + exit(1); + } + if (xmlTextWriterEndElement(writer) < 0) { + std::cout << "Error at xmlTextWriterWriteEndElement (value)" + << std::endl; + exit(1); + } return; } -- 2.19.2 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel