From 9192b12a33dc07d4a4f3d88c323ac373dd8f6367 Mon Sep 17 00:00:00 2001 From: Roland Veloz Date: Tue, 11 Jun 2019 12:41:40 -0500 Subject: [PATCH] Reworked the AttributeTank::Attribute API Once I made the Attribute structure public, I exposed the API. It was no longer sufferance to allow users to just modify the properties of the structure openly. It was time to encapsulate the data and provide a proper API. Removed the 'virtual' keyword from the class AttributeTank. This class is not being used polymorphically any where, therefore the keyword 'virtual' was just adding to it's memory size foot print for no reason. Change-Id: I073aa5dbef1eba911afb95392de5e580f6aac100 RTC:208343 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/78756 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Nicholas E. Bofferding Reviewed-by: Zachary Clark Reviewed-by: Daniel M. Crowell --- src/include/runtime/hbrt_utilities.H | 122 ++++-- src/include/usr/runtime/runtime_reasoncodes.H | 2 + .../usr/targeting/common/attributeTank.H | 370 ++++++++++++++++-- src/usr/targeting/common/attributeTank.C | 239 ++++++----- 4 files changed, 542 insertions(+), 191 deletions(-) diff --git a/src/include/runtime/hbrt_utilities.H b/src/include/runtime/hbrt_utilities.H index 87a9cc708ee..1764dedb15d 100644 --- a/src/include/runtime/hbrt_utilities.H +++ b/src/include/runtime/hbrt_utilities.H @@ -184,8 +184,8 @@ errlHndl_t sendAttributes(const std::vector // If caller passes in an empty list, then nothing to do if (!i_attributeList.size()) { - TRACFCOMP(g_trac_runtime, "sendAttributes: attribute list is empty," - "nothing to do ..."); + TRACFCOMP(g_trac_runtime, "sendAttributes: attribute list is " + "empty,nothing to do ..."); break; } @@ -210,28 +210,29 @@ errlHndl_t sendAttributes(const std::vector * @custdesc Internal firmware error */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_RT_FIRMWARE_REQUEST, - RUNTIME::RC_FW_REQUEST_RT_NULL_PTR, - i_attributeList.size(), - 0, - ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + RUNTIME::MOD_RT_FIRMWARE_REQUEST, + RUNTIME::RC_FW_REQUEST_RT_NULL_PTR, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } - /// Calculate the size requirements needed to serialize the Attribute info - // Start with the size of 'struct AttributeSetter_t' itself - uint16_t l_dataSize(sizeof(AttributeSetter_t)); - - // Then add in the individual attributes themselves + /// Calculate the size requirements needed to serialize + /// the Attribute info + // Aggregate the size of the incoming Attributes + uint32_t l_aggregatedAttributeSize(0); for (auto l_attribute: i_attributeList) { - // Add in the size of `struct AttributeHeader` - l_dataSize += sizeof(l_attribute.iv_hdr); - // Finally add in the size of the attribute value - l_dataSize += l_attribute.iv_hdr.iv_valSize; + l_aggregatedAttributeSize += l_attribute.getSize(); } + // Combine the size of the AttributeSetter_t itself to the size of + // incoming Attributes to get the full size requirement needed + uint32_t l_dataSize(sizeof(AttributeSetter_t) + + l_aggregatedAttributeSize); + // Create and initialize to zero a few needed variables uint32_t l_fullFspDataSize(0); uint64_t l_fwRequestMsgSize(0), l_fwResponseMsgSize(0); @@ -257,11 +258,11 @@ errlHndl_t sendAttributes(const std::vector * @custdesc Internal firmware error */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, - RUNTIME::RC_NULL_FIRMWARE_MSG_PTR, - i_attributeList.size(), - 0, - ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_NULL_FIRMWARE_MSG_PTR, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } @@ -269,7 +270,7 @@ errlHndl_t sendAttributes(const std::vector // Populate the 'message queue' and 'message type' for this message l_fwRequestMsg->generic_msg.msgq = MBOX::FSP_NVDIMM_KEYS_MSGQ_ID; l_fwRequestMsg->generic_msg.msgType = - GenericFspMboxMessage_t::MSG_DECONFIG_TARGET; + GenericFspMboxMessage_t::MSG_DECONFIG_TARGET; // Create a useful struct to populate the generic_msg::data field AttributeSetter_t* l_attributeSetter = @@ -286,22 +287,71 @@ errlHndl_t sendAttributes(const std::vector // Retrieve the individual attributes (header and value) // Create a useful struct to poulate attribute data uint8_t* l_attributeData = l_attributeSetter->iv_attrData; + uint32_t l_sizeOfDataCopied(0); for (const auto & l_attribute: i_attributeList) { - // Copy the attribute header - memcpy(l_attributeData, - &(l_attribute.iv_hdr), - sizeof(l_attribute.iv_hdr)); - // Advance pointer, one beyond the attribute header - l_attributeData += sizeof(l_attribute.iv_hdr); - - // Copy the attribute value - memcpy(l_attributeData, - l_attribute.iv_pVal, - l_attribute.iv_hdr.iv_valSize); - // Advance pointer, one beyond the attribute value - l_attributeData += l_attribute.iv_hdr.iv_valSize; - } + if (l_aggregatedAttributeSize >= l_attribute.getSize()) + { + l_sizeOfDataCopied = l_attribute.serialize( + l_attributeData, l_aggregatedAttributeSize); + + if (!l_sizeOfDataCopied) + { + TRACFCOMP(g_trac_runtime, ERR_MRK"sendAttributes: " + "Serialization of an Attribute failed, " + "should never happen") + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_SEND_ATTRIBUTES_TO_FSP + * @reasoncode RC_SERIALIZE_ATTRIBUTE_FAILED + * @userdata1 Number of Attributes to serialize and send + * @devdesc Serialization of an Attribute Failed + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_SERIALIZE_ATTRIBUTE_FAILED, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + break; + } // end if (!l_sizeOfDataCopied) + } + else + { + TRACFCOMP(g_trac_runtime, ERR_MRK"sendAttributes: " + "Miscalculation of aggregated size of attributes, " + "should never happen") + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_SEND_ATTRIBUTES_TO_FSP + * @reasoncode RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION + * @userdata1 Number of Attributes to serialize and send + * @devdesc Serialization data of Attribute to large + * for given buffer + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + break; + } + + // Decrement/increment our counters/pointers + l_aggregatedAttributeSize -= l_sizeOfDataCopied; + l_attributeData += l_sizeOfDataCopied; + } // end for (const auto & l_attribute: i_attributeList) // Make the firmware_request call l_err = firmware_request_helper(l_fwRequestMsgSize, diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index 735a4ec6c59..7aa6a114da1 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -141,6 +141,8 @@ namespace RUNTIME RC_SP_ATTN_AREA1_SIZE_OVERFLOW = RUNTIME_COMP_ID | 0x43, RC_UNKNOWN_LABEL = RUNTIME_COMP_ID | 0x44, RC_NULL_FIRMWARE_MSG_PTR = RUNTIME_COMP_ID | 0x45, + RC_SERIALIZE_ATTRIBUTE_FAILED = RUNTIME_COMP_ID | 0x46, + RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION = RUNTIME_COMP_ID | 0x47, }; enum UserDetailsTypes diff --git a/src/include/usr/targeting/common/attributeTank.H b/src/include/usr/targeting/common/attributeTank.H index ccb56888922..9561b9b8302 100644 --- a/src/include/usr/targeting/common/attributeTank.H +++ b/src/include/usr/targeting/common/attributeTank.H @@ -155,14 +155,314 @@ namespace AttributeTank /** * @brief Constructor */ - Attribute(); + Attribute() + : iv_hdr(), + iv_pVal(NULL) + { + } /** * @brief Destructor. Frees memory */ - ~Attribute(); + ~Attribute() + { + delete[] iv_pVal; + iv_pVal = NULL; + } - // Public data + /** + * @brief Set the Attribute ID + */ + void setId(const uint32_t i_attrId) + { + iv_hdr.iv_attrId = i_attrId; + } + + /** + * @brief Set the Attribute Target Type + */ + void setTargetType(const uint32_t i_targetType) + { + iv_hdr.iv_targetType = i_targetType; + } + + /** + * @brief Set the Attribute Position + */ + void setPosition(const uint16_t i_pos) + { + iv_hdr.iv_pos = i_pos; + } + + /** + * @brief Set the Attribute Unit Position + */ + void setUnitPosition(const uint8_t i_unitPos) + { + iv_hdr.iv_unitPos = i_unitPos; + } + + /** + * @brief Set the Attribute Node + */ + void setNode(const uint8_t i_node) + { + iv_hdr.iv_node = i_node; + } + + /** + * @brief Set the Attribute Flags + */ + void setFlags(const uint8_t i_flags) + { + iv_hdr.iv_flags = i_flags; + } + + /** + * @brief Get the size of all the Attribute's data members, + * aggregated together + * + * return Aggregated size of the Attribute's data members + */ + uint32_t getSize() const + { + return (sizeof(iv_hdr) + iv_hdr.iv_valSize); + } + + /** + * @brief Get a constant reference to the Attribute Header. + * Returning a reference for fast retrieval. + * + * @note Caller should not attempt to modify contents of the + * Attribute Header. Use appropriate Attribute set methods + * + * return A constant reference to the Attribute Header + */ + const AttributeHeader & getHeader() const + { + return iv_hdr; + } + + /** + * @brief Set the Attribute Value to a copy of the given buffer + * + * @pre Passing in nonsensical parameters will produce unpredictable + * results, ie passing in a null buffer with size > 0 + * + * @note Passing in a null buffer with size 0 will clear the value + * + * @param[in] i_buffer The buffer that contains the value to + * be copied + * @param[in] i_bufferSize Size of the given buffer + * + * return The size of the data that was copied + */ + uint32_t setValue(const void * const i_buffer, + const uint32_t i_bufferSize) + + { + // Reuse storage when possible + if (i_bufferSize != iv_hdr.iv_valSize) + { + // Clean up current Attribute Value + delete []iv_pVal; + iv_pVal = NULL; + + // Set size and allocate memory space + iv_hdr.iv_valSize = i_bufferSize; + if (iv_hdr.iv_valSize) + { + iv_pVal = new uint8_t[iv_hdr.iv_valSize]; + } + } + + // Make a copy of the data. Passing in a size of 0 + // or NULL turns this call to no-op + memcpy(iv_pVal, i_buffer, iv_hdr.iv_valSize); + + return iv_hdr.iv_valSize; + } + + /** + * @brief Get a constant pointer to the Attribute Value. + * Returning a constant pointer for fast retrieval. + * + * @note Caller should not attempt to modify the contents nor + * delete the pointer, use method setValue if + * need be. + * + * return A constant pointer to the Attribute Value + */ + const void* const getValue() const + { + return iv_pVal; + } + + /** + * @brief Return a copy of the Attribute Value into caller's bufffer + * + * @param[in] i_buffer The buffer to copy Attribute Value into + * @param[in] i_bufferSize Size of the given buffer + * + * return The size of the Attribute Value that was copied + * or 0 if unable to copy the Attribute Value - buffer + * size to small will cause this + */ + uint32_t cloneValue(void* const o_buffer, + const uint32_t i_bufferSize) const + { + // Return the size of the cloned data + uint32_t l_attributeValueSize(0); + + // Is the buffer large enough to contain the Attribute Value? + if (i_bufferSize >= iv_hdr.iv_valSize) + { + // Buffer is large enough to contain the Attribute Value - + // copy the Attribute Value to given buffer + memcpy(o_buffer, iv_pVal, iv_hdr.iv_valSize); + + // Return the size of the cloned data + l_attributeValueSize = iv_hdr.iv_valSize; + } + + return l_attributeValueSize; + } + + /** + * @brief Serialize the Attribute, if the buffer given is large + * enough to contain the Attribute's data members + * + * @param[out] o_buffer The buffer to contain the serialized + * data members + * @param[in] i_bufferSize Size of the given buffer + * + * return 0 if buffer is to small to contain the data members; + * otherwise the aggregated size of the Attribute's data + * members copied + */ + uint32_t serialize(void* const o_buffer, + const uint32_t i_bufferSize) const + { + // Return the size of the serialized data + uint32_t l_attributeSize(0); + + // If buffer size greater than or equal to the size of the + // Attribute's data members aggregated together then + // copy the data members to buffer + if (i_bufferSize >= getSize()) + { + // Get an Attribute handle to buffer for easy access + uint8_t* l_attribute = static_cast(o_buffer); + + // Copy the Attribute Header + memcpy(l_attribute, &iv_hdr, sizeof(iv_hdr)); + l_attribute += sizeof(iv_hdr); + + // Copy the Attribute Value + memcpy(l_attribute, iv_pVal, iv_hdr.iv_valSize); + + // Return the size of the serialized data + l_attributeSize = sizeof(iv_hdr) + iv_hdr.iv_valSize; + } + + return l_attributeSize; + } + + /** + * @brief Deserialize the buffer, if the buffer given is at least + * the same size as an Attribute + * + * @param[out] i_buffer The buffer to deserialize + * @param[in] i_bufferSize Size of the given buffer + * + * @post If the buffer is large enough to populate the Attribute, then + * the Attribute will be populated, with it's own copy of the + * data. If the buffer is too small, then the Attribute is + * untouched. + * + * return 0 if buffer is to small to populate an Attribute; + * otherwise the aggregated size of the Attribute's data + * members deserialized + */ + uint32_t deserialize(const void* const i_buffer, + const uint32_t i_bufferSize) + { + // Return the size of the Attribute + uint32_t l_attributeSize(0); + + // Get an Attribute handle to buffer for easy access + const Attribute* const l_attribute = + reinterpret_cast(i_buffer); + + // Get the minimum size needed to check for values + uint32_t l_attributeHeaderSize(sizeof(iv_hdr)); + + // Make sure the buffer is not just large enough to inspect the + // Attribute Header but large enough to read Values if they exist + // Need to make sure size is at minimum threshold before calling + // getSize(), because getSize assumes the data is there to read + if ( (i_bufferSize >= l_attributeHeaderSize) && + (i_bufferSize >= (l_attribute->getSize())) ) + { + // Get an uint8_t handle to buffer for easy access + const uint8_t* l_attributeData = + reinterpret_cast(i_buffer); + + // Copy header data + memcpy(&iv_hdr, l_attributeData, l_attributeHeaderSize); + + // Free iv_pVal data, if it currently has data, and set to NULL + delete []iv_pVal; // OK to delete a NULL ptr + iv_pVal = NULL; + + // Populate values if they exist + uint32_t l_valueSize = iv_hdr.iv_valSize; + if (l_valueSize) + { + // Copy the Attribute Value + iv_pVal = new uint8_t[l_valueSize]; + l_attributeData += l_attributeHeaderSize; + memcpy(iv_pVal, l_attributeData, l_valueSize); + } + + // Return the size of the Attribute + l_attributeSize = getSize(); + } + + return l_attributeSize; + } + + + /** + * @brief Assignment operator defined + */ + Attribute& operator=(const Attribute& rhs) + { + // check for self-assignment + if (&rhs != this) + { + // Deep copy the attribute value + setValue(rhs.iv_pVal, rhs.iv_hdr.iv_valSize); + // Copy the Attribute header + iv_hdr = rhs.iv_hdr; + } + + return *this; + } + + /** + * @brief Copy constructor defined + */ + Attribute(const Attribute& rhs) + : iv_hdr(), + iv_pVal(NULL) + { + // Call the assignment operator to do the work + *this = rhs; + } + + // Private data + private: AttributeHeader iv_hdr; uint8_t * iv_pVal; // Pointer to attribute value }; @@ -205,7 +505,7 @@ namespace AttributeTank /** * @brief Destructor. Deletes all Attributes */ - virtual ~AttributeTank(); + ~AttributeTank(); /** * @brief Checks if the platform has enabled synchronization @@ -231,9 +531,8 @@ namespace AttributeTank * specific node (i_node) * @param[in] i_node See i_nodeFilter */ - virtual void clearAllAttributes( - const NodeFilter i_nodeFilter = NODE_FILTER_NONE, - const uint8_t i_node = ATTR_NODE_NA); + void clearAllAttributes(const NodeFilter i_nodeFilter = NODE_FILTER_NONE, + const uint8_t i_node = ATTR_NODE_NA); /** * @brief Clear any non-const attribute for a specified ID and Target @@ -247,11 +546,11 @@ namespace AttributeTank * @param[in] i_unitPos Target Unit Position * @param[in] i_node Target Node */ - virtual void clearNonConstAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node); + void clearNonConstAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node); /** * @brief Set an Attribute @@ -273,14 +572,14 @@ namespace AttributeTank * @param[in] i_valSize Size of attribute value in bytes * @param[in] i_pVal Pointer to attribute value */ - virtual void setAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node, - const uint8_t i_flags, - const uint32_t i_valSize, - const void * i_pVal); + void setAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node, + const uint8_t i_flags, + const uint32_t i_valSize, + const void * i_pVal); /** * @brief Get a copy of an Attribute @@ -288,21 +587,24 @@ namespace AttributeTank * This is called on an OverrideAttributeTank to query/get an Attribute * Override when an attribute is got * + * @note Caller's responsibility to ensure the passed in buffer + * is large enough to contain the Attribute Value. + * * @param[in] i_attrId Attribute ID * @param[in] i_targetType Target Type attribute is for * @param[in] i_pos Target Position * @param[in] i_unitPos Target Unit Position * @param[in] i_node Target Node - * @param[out] o_pVal Pointer to attribute value + * @param[out] o_pVal Pointer to a copy of the attribute value * * return true if attribute exists and a copy was written to o_pVal */ - virtual bool getAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node, - void * o_pVal) const; + bool getAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node, + void * o_pVal) const; /** * @brief Serialize all Attributes into newly allocated memory chunks @@ -332,7 +634,7 @@ namespace AttributeTank * specific node (i_node) * @param[in] i_node See i_nodeFilter */ - virtual void serializeAttributes( + void serializeAttributes( const AllocType i_allocType, const uint32_t i_chunkSize, std::vector & o_attributes, @@ -349,8 +651,7 @@ namespace AttributeTank * @param[in] i_attributes Reference to AttributeSerializedChunk containing * attributes. */ - virtual void deserializeAttributes( - const AttributeSerializedChunk & i_attributes); + void deserializeAttributes(const AttributeSerializedChunk & i_attributes); /** @@ -366,9 +667,8 @@ namespace AttributeTank * * @param[in] i_echoAttributes Select whether or not to echo the attributes */ - virtual void deserializeAttributes( - const AttributeSerializedChunk & i_attributes, - bool i_echoAttributes ); + void deserializeAttributes(const AttributeSerializedChunk & i_attributes, + bool i_echoAttributes ); /** @@ -381,7 +681,7 @@ namespace AttributeTank * * return true if any attributes exist */ - virtual bool attributesExist() const { return iv_attributesExist; } + bool attributesExist() const { return iv_attributesExist; } /** * @brief Check if an attribute exists in the tank @@ -396,7 +696,7 @@ namespace AttributeTank * * return true if any attributes exist */ - virtual bool attributeExists(const uint32_t i_attrId) const; + bool attributeExists(const uint32_t i_attrId) const; /** * @brief This function writes attributes in an AttributeTank to targeting diff --git a/src/usr/targeting/common/attributeTank.C b/src/usr/targeting/common/attributeTank.C index 07ccff9820e..a9718b7890d 100644 --- a/src/usr/targeting/common/attributeTank.C +++ b/src/usr/targeting/common/attributeTank.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -99,10 +99,12 @@ void AttributeTank::clearAllAttributes( while (l_itr != iv_attributes.end()) { + // Get a copy of the Attribute's node for quick access + uint8_t l_node = (*l_itr)->getHeader().iv_node; if (i_nodeFilter == NODE_FILTER_NOT_ALL_NODES) { // Only clear attributes that are not for all nodes - if ((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) + if (l_node == ATTR_NODE_NA) { l_itr++; continue; @@ -111,8 +113,8 @@ void AttributeTank::clearAllAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE_AND_ALL) { // Only clear attributes associated with i_node or all - if ( ((*l_itr)->iv_hdr.iv_node != ATTR_NODE_NA) && - ((*l_itr)->iv_hdr.iv_node != i_node) ) + if ( (l_node != ATTR_NODE_NA) && + (l_node != i_node) ) { l_itr++; continue; @@ -121,7 +123,7 @@ void AttributeTank::clearAllAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE) { // Only clear attributes associated with i_node - if ((*l_itr)->iv_hdr.iv_node != i_node) + if (l_node != i_node) { l_itr++; continue; @@ -153,13 +155,18 @@ void AttributeTank::clearNonConstAttribute(const uint32_t i_attrId, for (AttributesItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - ((*l_itr)->iv_hdr.iv_pos == i_pos) && - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos) && - ((*l_itr)->iv_hdr.iv_node == i_node) ) + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + (l_attributeHeader.iv_pos == i_pos) && + (l_attributeHeader.iv_unitPos == i_unitPos) && + (l_attributeHeader.iv_node == i_node) ) { - if (!((*l_itr)->iv_hdr.iv_flags & ATTR_FLAG_CONST)) + if (!(l_attributeHeader.iv_flags & ATTR_FLAG_CONST)) { delete (*l_itr); (*l_itr) = NULL; @@ -196,20 +203,25 @@ void AttributeTank::setAttribute(const uint32_t i_attrId, for (AttributesItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - ((*l_itr)->iv_hdr.iv_pos == i_pos) && - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos) && - ((*l_itr)->iv_hdr.iv_node == i_node) && - ((*l_itr)->iv_hdr.iv_valSize == i_valSize) ) + // Get a reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + (l_attributeHeader.iv_pos == i_pos) && + (l_attributeHeader.iv_unitPos == i_unitPos) && + (l_attributeHeader.iv_node == i_node) && + (l_attributeHeader.iv_valSize == i_valSize) ) { // Found existing attribute, update it unless the existing attribute // is const and the new attribute is non-const - if (!( ((*l_itr)->iv_hdr.iv_flags & ATTR_FLAG_CONST) && + if (!( (l_attributeHeader.iv_flags & ATTR_FLAG_CONST) && (!(i_flags & ATTR_FLAG_CONST)) ) ) { - (*l_itr)->iv_hdr.iv_flags = i_flags; - memcpy((*l_itr)->iv_pVal, i_pVal, i_valSize); + (*l_itr)->setFlags(i_flags); + (*l_itr)->setValue(i_pVal, i_valSize); } l_found = true; break; @@ -221,15 +233,13 @@ void AttributeTank::setAttribute(const uint32_t i_attrId, // Add a new attribute to the tank Attribute * l_pAttr = new Attribute(); - l_pAttr->iv_hdr.iv_attrId = i_attrId; - l_pAttr->iv_hdr.iv_targetType = i_targetType; - l_pAttr->iv_hdr.iv_pos = i_pos; - l_pAttr->iv_hdr.iv_unitPos = i_unitPos; - l_pAttr->iv_hdr.iv_node = i_node; - l_pAttr->iv_hdr.iv_flags = i_flags; - l_pAttr->iv_hdr.iv_valSize = i_valSize; - l_pAttr->iv_pVal = new uint8_t[i_valSize]; - memcpy(l_pAttr->iv_pVal, i_pVal, i_valSize); + l_pAttr->setId(i_attrId); + l_pAttr->setTargetType(i_targetType); + l_pAttr->setPosition(i_pos); + l_pAttr->setUnitPosition(i_unitPos); + l_pAttr->setNode(i_node); + l_pAttr->setFlags(i_flags); + l_pAttr->setValue(i_pVal, i_valSize); iv_attributesExist = true; iv_attributes.push_back(l_pAttr); @@ -253,18 +263,22 @@ bool AttributeTank::getAttribute(const uint32_t i_attrId, for (AttributesCItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - // Allow match if attribute applies to all positions - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - (((*l_itr)->iv_hdr.iv_pos == ATTR_POS_NA) || - ((*l_itr)->iv_hdr.iv_pos == i_pos)) && - (((*l_itr)->iv_hdr.iv_unitPos == ATTR_UNIT_POS_NA) || - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos)) && - (((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) || - ((*l_itr)->iv_hdr.iv_node == i_node)) ) + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + ((l_attributeHeader.iv_pos == ATTR_POS_NA) || + (l_attributeHeader.iv_pos == i_pos)) && + ((l_attributeHeader.iv_unitPos == ATTR_UNIT_POS_NA) || + (l_attributeHeader.iv_unitPos == i_unitPos)) && + ((l_attributeHeader.iv_node == ATTR_NODE_NA) || + (l_attributeHeader.iv_node == i_node)) ) { l_found = true; - memcpy(o_pVal, (*l_itr)->iv_pVal, (*l_itr)->iv_hdr.iv_valSize); + (*l_itr)->cloneValue(o_pVal, l_attributeHeader.iv_valSize); break; } } @@ -293,10 +307,18 @@ void AttributeTank::serializeAttributes( // Fill up the buffer with as many attributes as possible while (l_itr != iv_attributes.end()) { + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = + (*l_itr)->getHeader(); + + // Get a copy of the node for quick access + uint8_t l_node = l_attributeHeader.iv_node; + if (i_nodeFilter == NODE_FILTER_NOT_ALL_NODES) { // Only want attributes that are not for all nodes - if ((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) + if (l_node == ATTR_NODE_NA) { l_itr++; continue; @@ -305,8 +327,8 @@ void AttributeTank::serializeAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE_AND_ALL) { // Only want attributes associated with i_node or all - if ( ((*l_itr)->iv_hdr.iv_node != ATTR_NODE_NA) && - ((*l_itr)->iv_hdr.iv_node != i_node) ) + if ( (l_node != ATTR_NODE_NA) && + (l_node != i_node) ) { l_itr++; continue; @@ -315,15 +337,14 @@ void AttributeTank::serializeAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE) { // Only want attributes associated with i_node - if ((*l_itr)->iv_hdr.iv_node != i_node) + if (l_node != i_node) { l_itr++; continue; } } - if ((l_index + sizeof(AttributeHeader) + - (*l_itr)->iv_hdr.iv_valSize) > i_chunkSize) + if ((l_index + (*l_itr)->getSize()) > i_chunkSize) { // Attribute will not fit into the buffer if (l_index == 0) @@ -334,7 +355,7 @@ void AttributeTank::serializeAttributes( TRACFCOMP(g_trac_targeting, "serializeAttributes: Error, attr too big to serialize " "(0x%x)", - (*l_itr)->iv_hdr.iv_valSize); + l_attributeHeader.iv_valSize); l_itr++; } else @@ -346,17 +367,8 @@ void AttributeTank::serializeAttributes( } else { - // Copy the attribute header to the buffer - AttributeHeader * l_pHeader = - reinterpret_cast(l_pBuffer + l_index); - *l_pHeader = (*l_itr)->iv_hdr; - l_index += sizeof(AttributeHeader); - - // Copy the attribute value to the buffer - memcpy((l_pBuffer + l_index), (*l_itr)->iv_pVal, - (*l_itr)->iv_hdr.iv_valSize); - l_index += (*l_itr)->iv_hdr.iv_valSize; - + l_index += (*l_itr)->serialize(l_pBuffer + l_index, + (*l_itr)->getSize()); l_itr++; } } @@ -404,7 +416,7 @@ bool AttributeTank::attributeExists(const uint32_t i_attrId) const for (AttributesCItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ((*l_itr)->iv_hdr.iv_attrId == i_attrId) + if ((*l_itr)->getHeader().iv_attrId == i_attrId) { l_found = true; break; @@ -424,60 +436,57 @@ void AttributeTank::deserializeAttributes( uint32_t l_index = 0; + // Get a handle to the serialized Attributes + uint8_t* l_serializedData = + reinterpret_cast(i_attributes.iv_pAttributes); + + // Iterate thru the Attributes while (l_index < i_attributes.iv_size) { - AttributeHeader * l_pAttrHdr = - reinterpret_cast - (i_attributes.iv_pAttributes + l_index); + // Progress the offset to the serialized data + l_serializedData += l_index; - if (sizeof(AttributeHeader) > (i_attributes.iv_size - l_index)) - { - // Remaining chunk smaller than attribute header, quit - TRACFCOMP(g_trac_targeting, - "deserializeAttributes: Error, header too big for chunk " - "(0x%x)", - (i_attributes.iv_size - l_index)); - break; - } + // Create a new Attribute + Attribute * l_pAttribute = new Attribute(); - l_index += sizeof(AttributeHeader); + // Deserialize the data, if possible + uint32_t l_deserializedDataSize = l_pAttribute->deserialize( + l_serializedData, + i_attributes.iv_size - l_index); - if (l_pAttrHdr->iv_valSize > (i_attributes.iv_size - l_index)) + if (!l_deserializedDataSize) { - // Remaining chunk smaller than attribute value, quit + // Unable to deserialize data, delete Attribute + delete l_pAttribute; + l_pAttribute = NULL; + + // Remaining chunk smaller than attribute header, quit TRACFCOMP(g_trac_targeting, - "deserializeAttributes: Error, attr too big for chunk " - "(0x%x:0x%x)", - l_pAttrHdr->iv_valSize, (i_attributes.iv_size - l_index)); + "deserializeAttributes: Error, attribute too big for " + "chunk (0x%x)", + (i_attributes.iv_size - l_index)); break; } - // Create a new Attribute and add it to the tank - Attribute * l_pAttr = new Attribute(); - l_pAttr->iv_hdr = *l_pAttrHdr; - l_pAttr->iv_pVal = new uint8_t[l_pAttrHdr->iv_valSize]; - memcpy(l_pAttr->iv_pVal, (i_attributes.iv_pAttributes + l_index), - l_pAttrHdr->iv_valSize); - - l_index += l_pAttrHdr->iv_valSize; + // Was able to deserialize data, add Attribute to the tank iv_attributesExist = true; - iv_attributes.push_back(l_pAttr); + iv_attributes.push_back(l_pAttribute); - if // attributes should be echo'd - ( i_echoAttributes == true ) + // Increment the index after deserializing an attribute + l_index += l_deserializedDataSize; + + if ( i_echoAttributes == true ) // attributes should be echo'd { // extract individual fields from attribute - uint32_t attrId = l_pAttr->iv_hdr.iv_attrId; - uint32_t targetType = l_pAttr->iv_hdr.iv_targetType; - uint16_t pos = l_pAttr->iv_hdr.iv_pos; - uint8_t unitPos = l_pAttr->iv_hdr.iv_unitPos; - - const uint8_t * pNodeFlags = (&(l_pAttr->iv_hdr.iv_unitPos)) + 1; + uint32_t attrId(l_pAttribute->getHeader().iv_attrId); + uint32_t targetType(l_pAttribute->getHeader().iv_targetType); + uint16_t pos(l_pAttribute->getHeader().iv_pos); + uint8_t unitPos(l_pAttribute->getHeader().iv_unitPos); - uint8_t node = (*pNodeFlags) >> 4; // isolate hi nibble - uint8_t flags = (*pNodeFlags) & 0x0F; // isolate lo nibble + uint8_t node(l_pAttribute->getHeader().iv_node); + uint8_t flags(l_pAttribute->getHeader().iv_flags); - uint32_t valueLen = l_pAttr->iv_hdr.iv_valSize; + uint32_t valueLen(l_pAttribute->getHeader().iv_valSize); TRACFCOMP(g_trac_targeting, "deserializeAttributes: Attribute Hdr: " @@ -488,7 +497,7 @@ void AttributeTank::deserializeAttributes( TRACFBIN(g_trac_targeting, "deserializeAttributes: Parm Value: ", - l_pAttr->iv_pVal, valueLen); + l_pAttribute->getValue(), valueLen); } // end echo attributes } @@ -504,20 +513,6 @@ void AttributeTank::deserializeAttributes( false ); } -//****************************************************************************** -AttributeTank::Attribute::Attribute() : - iv_pVal(NULL) -{ - -} - -//****************************************************************************** -AttributeTank::Attribute::~Attribute() -{ - delete[] iv_pVal; - iv_pVal = NULL; -} - //****************************************************************************** errlHndl_t AttributeTank::writePermAttributes() { @@ -526,8 +521,10 @@ errlHndl_t AttributeTank::writePermAttributes() for(AttributesCItr_t l_attrIter = iv_attributes.begin(); l_attrIter != iv_attributes.end(); ++l_attrIter) { - Attribute* l_attr = *l_attrIter; - AttributeHeader l_attrHdr = l_attr->iv_hdr; + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attrHdr = (*l_attrIter)->getHeader(); + PredicatePostfixExpr l_permAttrOverrides; // Predicate to match target type @@ -553,7 +550,7 @@ errlHndl_t AttributeTank::writePermAttributes() bool l_success = (*l_permTargetList)->_trySetAttr( static_cast(l_attrHdr.iv_attrId), l_attrHdr.iv_valSize, - l_attr->iv_pVal ); + (*l_attrIter)->getValue() ); if (l_success) { @@ -561,16 +558,17 @@ errlHndl_t AttributeTank::writePermAttributes() "permanent override of Attr ID:0x%X Value:0x%llX applied " "to target 0x%X", l_attrHdr.iv_attrId, - *reinterpret_cast(l_attr->iv_pVal), + *reinterpret_cast + ((*l_attrIter)->getValue()), (*l_permTargetList)->getAttr() ); } else { - uint8_t * io_pAttrData = NULL; + uint8_t * l_pAttrData(NULL); bool l_found = (*l_permTargetList)->_tryGetAttr( static_cast(l_attrHdr.iv_attrId), l_attrHdr.iv_valSize, - io_pAttrData); + l_pAttrData); if (l_found) { @@ -579,9 +577,10 @@ errlHndl_t AttributeTank::writePermAttributes() "ID:0x%X Value:0x%llX on target 0x%X - current value " "0x%llX", l_attrHdr.iv_attrId, - *reinterpret_cast(l_attr->iv_pVal), + *reinterpret_cast + ((*l_attrIter)->getValue()), (*l_permTargetList)->getAttr(), - *reinterpret_cast(io_pAttrData) ); + *reinterpret_cast(l_pAttrData) ); /*@ * @errortype * @moduleid TARG_WRITE_PERM_ATTR @@ -616,7 +615,7 @@ errlHndl_t AttributeTank::writePermAttributes() * @devdesc Given target does not have given attribute * to apply override */ - UTIL::createTracingError( + UTIL::createTracingError( TARG_WRITE_PERM_ATTR, TARG_RC_WRITE_PERM_ATTR_TARGET_FAIL, (*l_permTargetList)->getAttr(),