***********************
** FILE NAME : message.cpp
** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring
-** VERSION NUMBER : $Revision: 1.17 $
+** VERSION NUMBER : $Revision: 1.18 $
**
** DESCRIPTION : Implementation of the message handling classes
**
********************************
** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
** CREATION DATE : Sep 16, 2002
-** LAST UPDATE : Nov 28, 2003
+** LAST UPDATE : Nov 02, 2007
** MODIFICATIONS :
**************************************************************************/
/*****************************
$Log: message.cpp,v $
- Revision 1.17 2005-05-31 05:51:41 arjen
+ Revision 1.18 2007-11-03 10:23:53 arjen
+ Handling of parameters is greatly improved.
+ When creating a new parameter from an XML report which is fed into
+ gcm_input, the class definition is used as a template to fill in
+ the default values for the properties.
+ The class is also used as a template when a new property is added
+ to an existing parameter.
+
+ DYNAMIC properties are now handled properly. Instead of making a
+ 'changed property' notification, the value is checked against the
+ defined range for the property. An 'out of range' notification
+ is created when this condition is detected.
+
+ Revision 1.17 2005/05/31 05:51:41 arjen
Textual changes in parameter notifications
Revision 1.16 2003/12/04 10:38:09 arjen
*****************************/
-static const char *RCSID = "$Id: message.cpp,v 1.17 2005-05-31 05:51:41 arjen Exp $";
+static const char *RCSID = "$Id: message.cpp,v 1.18 2007-11-03 10:23:53 arjen Exp $";
#include <algorithm>
#include <libxml/xpath.h>
uncertainty = 1.0;
- while (input >> line && uncertainty > 0.1)
+ while (input >> line && uncertainty > epsilon)
{
if (verbose)
{
}
}
- //TODO: If uncertainty is still too great, pick the least uncertain.
-
input.rewind();
certainty = 1.0 - uncertainty;
** VARS CHANGED :
** FUNCTIONS USED :
** SEE ALSO :
-** LAST MODIFIED : Nov 28, 2003
+** LAST MODIFIED : Nov 02, 2007
**=========================================================================
*/
{
String name;
String value;
+ String type;
+ double minimum;
+ double maximum;
};
void client_message::enterXML()
String qry;
String insertion;
String change_notification("");
+ String out_of_range_notification("");
String create_notification("");
String remove_notification("");
bool initial_entry = false;
String param_class((const char *)xmlGetProp(node, (const xmlChar *)"class"));
+ std::list<param_property> parameter_template;
+ int nr_properties;
+
+ // Obtain a list of properties from the parameter's class.
+ // This list is used to create new parameters.
+
+ qry = "select * from parameter_class where name='";
+ qry += param_class + "'";
+ nr_properties = database.Query(qry);
+ for (int i = 0; i < nr_properties; i++)
+ {
+ param_property pp;
+
+ pp.name = database.Field(i, "property_name");
+ pp.type = database.Field(i, "property_type");
+ pp.minimum = database.Field(i, "min");
+ pp.maximum = database.Field(i, "max");
+
+ parameter_template.push_back(pp);
+ }
+
#ifdef DEBUG
*Log << "Entering a list of " << param_class << " parameters.\n";
#endif
pathcontext->node = node;
- // If we don;t have any parameters of this class, this will be
+ // If we don't have any parameters of this class, this will be
// an initial entry.
qry = "select name from parameter where objectid='";
// The parameter exists in the database; check all properties.
bool param_changed = false;
+ bool out_of_range = false;
paramid = database.Field(0, "paramid");
while (pi != properties.end())
{
- qry = "select value from property where paramid='";
+ qry = "select * from property where paramid='";
qry += paramid + "' and name='";
qry += pi->name + "'";
if (database.Query(qry) == 0)
{
*Log << "Property " << pi->name << " of "
<< param_name << " does not exist.\n";
- }
- else if (database.Field(0, "value") != pi->value)
- {
- *Log << "Property " << pi->name << " of "
- << param_name << " is different.\n";
+ // Find the property in the template from the class.
- insertion = "update property set value='";
- insertion += pi->value + "' where paramid='";
- insertion += paramid + "' and name='";
- insertion += pi->name + "'";
+ String property_type("STATIC");
+ double property_minimum = 0.0;
+ double property_maximum = 0.0;
+ std::list<param_property>::iterator ti = parameter_template.begin();
+ while (ti != parameter_template.end() && ti->name != pi->name)
+ {
+ ti++;
+ }
+ if (ti != parameter_template.end())
+ {
+ property_type = ti->type;
+ property_minimum = ti->minimum;
+ property_maximum = ti->maximum;
+ }
+
+ insertion = "insert into property (paramid, name, value, type, min, max) values ('";
+ insertion += paramid + "', '";
+ insertion += pi->name + "', '";
+ insertion += pi->value + "', '";
+ insertion += property_type + "', '";
+ insertion += String(property_minimum) + "', '";
+ insertion += String(property_maximum) + "')";
database.Query(insertion);
insertion = "insert into history (paramid, modified,";
insertion += " change_nature, changed_property, new_value)";
insertion += " values ('";
insertion += paramid + "', '" + arrival.format("%Y-%m-%d %T")
- + "', 'MODIFIED', '";
+ + "', 'CREATED', '";
insertion += pi->name + "', '";
insertion += pi->value + "')";
-
database.Query(insertion);
+ }
+ else
+ {
+ param_property stored_property;
+
+ stored_property.value = database.Field(0, "value");
+ stored_property.type = database.Field(0, "type");
+ stored_property.minimum = database.Field(0, "min");
+ stored_property.maximum = database.Field(0, "max");
- param_changed = true;
+ if (stored_property.value != pi->value)
+ {
+ *Log << "Property " << pi->name << " of "
+ << param_name << " is different.\n";
+
+ insertion = "update property set value='";
+ insertion += pi->value + "' where paramid='";
+ insertion += paramid + "' and name='";
+ insertion += pi->name + "'";
+
+ database.Query(insertion);
+ insertion = "insert into history (paramid, modified,";
+ insertion += " change_nature, changed_property, new_value)";
+ insertion += " values ('";
+ insertion += paramid + "', '" + arrival.format("%Y-%m-%d %T")
+ + "', 'MODIFIED', '";
+ insertion += pi->name + "', '";
+ insertion += pi->value + "')";
+ database.Query(insertion);
+ if (stored_property.type == "DYNAMIC")
+ {
+ // Check the value against the range of the property.
+
+ double numeric_value = pi->value;
+ if (numeric_value < stored_property.minimum || numeric_value > stored_property.maximum)
+ {
+ out_of_range = true;
+ }
+ }
+ else
+ {
+ // A STATIC property changed.
+ param_changed = true;
+ }
+
+ }
}
pi++;
}
*Log << "gcm_input ERROR: Cannot create 'property modified' notification.\n";
}
}
+
+ if (out_of_range)
+ {
+ if (out_of_range_notification == "")
+ {
+ remark = "Gnucomo detected that a property value is out of range.";
+ out_of_range_notification = database.new_notification(objectid,
+ "property out of range", remark);
+ }
+
+ if (out_of_range_notification != "")
+ {
+ qry = "select * from parameter_notification where notificationid='";
+ qry += out_of_range_notification + "' and paramid='";
+ qry += paramid + "'";
+
+ if (database.Query(qry) == 0)
+ {
+ insertion = "insert into parameter_notification";
+ insertion += " (notificationid, paramid) values ('";
+ insertion += out_of_range_notification + "', '";
+ insertion += paramid + "')";
+
+ database.Query(insertion);
+ }
+ }
+ else
+ {
+ *Log << "gcm_input ERROR: Cannot create 'property out of range' notification.\n";
+ }
+ }
}
else
{
while (pi != properties.end())
{
- insertion = "insert into property (paramid, name, value, type) values ('";
+ // Find the property in the template from the class.
+
+ String property_type("STATIC");
+ double property_minimum = 0.0;
+ double property_maximum = 0.0;
+ std::list<param_property>::iterator ti = parameter_template.begin();
+
+ while (ti != parameter_template.end() && ti->name != pi->name)
+ {
+ ti++;
+ }
+ if (ti != parameter_template.end())
+ {
+ property_type = ti->type;
+ property_minimum = ti->minimum;
+ property_maximum = ti->maximum;
+ }
+
+ insertion = "insert into property (paramid, name, value, type, min, max) values ('";
insertion += paramid + "', '";
insertion += pi->name + "', '";
- insertion += pi->value + "', 'STATIC')";
+ insertion += pi->value + "', '";
+ insertion += property_type + "', '";
+ insertion += String(property_minimum) + "', '";
+ insertion += String(property_maximum) + "')";
database.Query(insertion);
insertion = "insert into history (paramid, modified,";