enhanced MessageMap to allow duplicates for full check, fix to avoid multiple identical derived messages

This commit is contained in:
john30
2015-10-25 19:44:16 +01:00
parent 7d8966400c
commit 6814cdf3a1
2 changed files with 77 additions and 30 deletions
+54 -25
View File
@@ -66,14 +66,13 @@ Message::Message(const string circuit, const string name, const bool isWrite,
Message::Message(const bool isWrite, const bool isPassive, Message::Message(const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, DataField* data, const bool deleteData)
Condition* condition)
: m_circuit(), m_name(), m_isWrite(isWrite), : m_circuit(), m_name(), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(), m_isPassive(isPassive), m_comment(),
m_srcAddress(SYN), m_dstAddress(SYN), m_srcAddress(SYN), m_dstAddress(SYN),
m_data(data), m_deleteData(true), m_data(data), m_deleteData(true),
m_pollPriority(0), m_pollPriority(0),
m_usedByCondition(false), m_condition(condition), m_usedByCondition(false), m_condition(NULL),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0)
{ {
m_id.push_back(pb); m_id.push_back(pb);
@@ -303,6 +302,11 @@ Message* Message::derive(const unsigned char dstAddress)
m_pollPriority, m_condition); m_pollPriority, m_condition);
} }
unsigned long long Message::getDerivedKey(const unsigned char dstAddress)
{
return (m_key & ~(0xffLL << (8*6))) | (unsigned long long)dstAddress << (8*6);
}
bool Message::setPollPriority(unsigned char priority) bool Message::setPollPriority(unsigned char priority)
{ {
if (priority == m_pollPriority || m_isPassive) if (priority == m_pollPriority || m_isPassive)
@@ -636,6 +640,13 @@ string strtolower(const string& str)
return ret; return ret;
} }
Message* getFirstAvailable(vector<Message*> &messages) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++)
if ((*msgIt)->isAvailable())
return *msgIt;
return NULL;
}
result_t Condition::create(vector<string>::iterator& it, const vector<string>::iterator end, SimpleCondition*& returnValue) result_t Condition::create(vector<string>::iterator& it, const vector<string>::iterator end, SimpleCondition*& returnValue)
{ {
@@ -733,8 +744,19 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
errorMessage << "condition " << m_circuit << " " << m_name << ": destination address missing"; errorMessage << "condition " << m_circuit << " " << m_name << ": destination address missing";
return RESULT_ERR_INVALID_ADDR; return RESULT_ERR_INVALID_ADDR;
} }
// clone the message with dedicated dstAddress // clone the message with dedicated dstAddress if necessary
message = message->derive(m_dstAddress); unsigned long long key = message->getDerivedKey(m_dstAddress);
vector<Message*>* derived = messages->getByKey(key);
if (derived==NULL) {
message = message->derive(m_dstAddress);
messages->add(message);
} else {
message = getFirstAvailable(*derived);
if (message==NULL) {
errorMessage << "condition " << m_circuit << " " << m_name << ": conditional derived message";
return RESULT_ERR_INVALID_ARG;
}
}
} }
if (!m_valueRanges.empty()) { if (!m_valueRanges.empty()) {
@@ -800,24 +822,28 @@ result_t MessageMap::add(Message* message)
{ {
unsigned long long key = message->getKey(); unsigned long long key = message->getKey();
bool conditional = message->isConditional(); bool conditional = message->isConditional();
map<unsigned long long, vector<Message*> >::iterator keyIt = m_messagesByKey.find(key); if (!m_addAll) {
if (keyIt != m_messagesByKey.end()) { map<unsigned long long, vector<Message*> >::iterator keyIt = m_messagesByKey.find(key);
if (!conditional) if (keyIt != m_messagesByKey.end()) {
return RESULT_ERR_DUPLICATE; // duplicate key if (!conditional)
vector<Message*>* messages = &keyIt->second; return RESULT_ERR_DUPLICATE; // duplicate key
if (!messages->front()->isConditional()) vector<Message*>* messages = &keyIt->second;
return RESULT_ERR_DUPLICATE; // duplicate key if (!messages->front()->isConditional())
return RESULT_ERR_DUPLICATE; // duplicate key
}
} }
bool isPassive = message->isPassive(); bool isPassive = message->isPassive();
bool isWrite = message->isWrite(); bool isWrite = message->isWrite();
string circuit = strtolower(message->getCircuit()); string circuit = strtolower(message->getCircuit());
string name = strtolower(message->getName()); string name = strtolower(message->getName());
string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name; string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name;
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey); if (!m_addAll) {
if (nameIt != m_messagesByName.end()) { map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
vector<Message*>* messages = &nameIt->second; if (nameIt != m_messagesByName.end()) {
if (!messages->front()->isConditional() || !message->isConditional()) vector<Message*>* messages = &nameIt->second;
return RESULT_ERR_DUPLICATE_NAME; // duplicate key if (!message->isConditional() || !messages->front()->isConditional())
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
}
} }
m_messagesByName[nameKey].push_back(message); m_messagesByName[nameKey].push_back(message);
m_messageCount++; m_messageCount++;
@@ -827,13 +853,16 @@ result_t MessageMap::add(Message* message)
m_passiveMessageCount++; m_passiveMessageCount++;
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
nameIt = m_messagesByName.find(nameKey); map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
if (nameIt == m_messagesByName.end()) if (nameIt == m_messagesByName.end())
m_messagesByName[nameKey].push_back(message); // always store first message without circuit m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name)
else { else {
vector<Message*>* messages = &nameIt->second; vector<Message*>* messages = &nameIt->second;
if (messages->front()->isConditional() && conditional) Message* first = messages->front();
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional if (circuit < first->getCircuit())
m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name)
else if (m_addAll || (conditional && first->isConditional()))
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything
} }
unsigned char idLength = (unsigned char)(message->getId().size() - 2); unsigned char idLength = (unsigned char)(message->getId().size() - 2);
if (idLength < m_minIdLength) if (idLength < m_minIdLength)
@@ -984,10 +1013,10 @@ result_t MessageMap::resolveConditions(bool verbose) {
return overallResult; return overallResult;
} }
Message* getFirstAvailable(vector<Message*> &messages) { vector<Message*>* MessageMap::getByKey(const unsigned long long key) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++) map<unsigned long long, vector<Message*> >::iterator it = m_messagesByKey.find(key);
if ((*msgIt)->isAvailable()) if (it != m_messagesByKey.end())
return *msgIt; return &it->second;
return NULL; return NULL;
} }
+23 -5
View File
@@ -77,12 +77,11 @@ public:
* @param pb the primary ID byte. * @param pb the primary ID byte.
* @param sb the secondary ID byte. * @param sb the secondary ID byte.
* @param data the @a DataField for encoding/decoding the message. * @param data the @a DataField for encoding/decoding the message.
* @param condition the @a Condition for this message, or NULL. * @param deleteData whether to delete the @a DataField during destruction.
*/ */
Message(const bool isWrite, const bool isPassive, Message(const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, DataField* data, const bool deleteData);
Condition* condition=NULL);
/** /**
* Destructor. * Destructor.
@@ -167,6 +166,13 @@ public:
*/ */
unsigned long long getKey() { return m_key; } unsigned long long getKey() { return m_key; }
/**
* Return the derived key for storing in @a MessageMap.
* @param dstAddress the destination address for the derivation.
* @return the derived key for storing in @a MessageMap.
*/
unsigned long long getDerivedKey(const unsigned char dstAddress);
/** /**
* Get the polling priority, or 0 for no polling at all. * Get the polling priority, or 0 for no polling at all.
* @return the polling priority, or 0 for no polling at all. * @return the polling priority, or 0 for no polling at all.
@@ -596,9 +602,10 @@ public:
/** /**
* Construct a new instance. * Construct a new instance.
* @param addAll whether to add all messages, even if duplicate.
*/ */
MessageMap() : FileReader<DataFieldTemplates*>::FileReader(true), MessageMap(const bool addAll=false) : FileReader<DataFieldTemplates*>::FileReader(true),
m_minIdLength(4), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) {} m_addAll(addAll), m_minIdLength(4), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) {}
/** /**
* Destructor. * Destructor.
@@ -639,6 +646,14 @@ public:
*/ */
result_t resolveConditions(bool verbose=false); result_t resolveConditions(bool verbose=false);
/**
* Get the stored @a Message instances for the key.
* @param key the key of the @a Message.
* @return the found @a Message instances, or NULL.
* Note: the caller may not free the returned instances.
*/
vector<Message*>* getByKey(const unsigned long long key);
/** /**
* Find the @a Message instance for the specified circuit and name. * Find the @a Message instance for the specified circuit and name.
* @param circuit the optional circuit name. * @param circuit the optional circuit name.
@@ -750,6 +765,9 @@ public:
private: private:
/** whether to add all messages, even if duplicate. */
const bool m_addAll;
/** the minimum ID length used by any of the known @a Message instances. */ /** the minimum ID length used by any of the known @a Message instances. */
unsigned char m_minIdLength; unsigned char m_minIdLength;