Commit 72e34299 authored by Jonas Nylund's avatar Jonas Nylund

Added support for changing type and/or size in an item with only one...

Added support for changing type and/or size in an item with only one attribute, bugfix in oid_to_table for array attributes
parent 78b734f0
......@@ -42,6 +42,26 @@
#define sev_cGarbageInterval 120
#define sev_cGarbageCycle 86400
static int sev_comp_refid(tree_sTable *tp, tree_sNode *x, tree_sNode *y)
{
sev_sRefid *xp = (sev_sRefid *) x;
sev_sRefid *yp = (sev_sRefid *) y;
if (xp->id.nid > yp->id.nid)
return 1;
if (xp->id.nid < yp->id.nid)
return -1;
if (xp->id.rix > yp->id.rix)
return 1;
if (xp->id.rix < yp->id.rix)
return -1;
return 0;
}
int sev_server::init( int noneth)
{
qcom_sNode node;
......@@ -111,6 +131,8 @@ int sev_server::init( int noneth)
m_db->get_items( &m_sts);
m_db->get_objectitems(&m_sts);
m_refid = tree_CreateTable(&sts, sizeof(pwr_tRefId), offsetof(sev_sRefid, id), sizeof(sev_sRefid), 100, sev_comp_refid);
// Create a queue to server
qcom_sQattr attr;
qcom_sQid qid;
......@@ -518,10 +540,16 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
// Remove all refid's for this node
pwr_tNid nid = msg->Items[0].sevid.nid;
pwr_tStatus sts;
sev_sRefid *rp = (sev_sRefid *)tree_Minimum(&sts, m_refid);
sev_sRefid *succ_rp;
while ( rp) {
succ_rp = (sev_sRefid *)tree_Successor(&sts, m_refid, rp);
if ( rp->id.nid == nid)
tree_Remove( &sts, m_refid, &rp->id);
for ( iterator_refid it = m_refid.begin(); it != m_refid.end(); it++) {
if ( it->first.id.nid == nid)
m_refid.erase( it);
rp = succ_rp;
}
for ( int i = 0; i < item_cnt; i++) {
......@@ -596,6 +624,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
newattr.elem = 0;
newattrVec.push_back(newattr);
bool tableChange = false;
if ( !m_db->check_objectitemattr( &m_sts,
tablename,
buffP->oid,
......@@ -639,8 +668,14 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
m_db->m_items[idx].old_value = malloc(m_db->m_items[idx].value_size);
m_db->m_items[idx].sevid = buffP->sevid;
sev_refid sevid(buffP->sevid);
m_refid[sevid] = idx;
pwr_tRefId rk;
sev_sRefid *rp;
rk = buffP->sevid;
rp = (sev_sRefid *) tree_Insert(&sts, m_refid, &rk);
rp->idx = idx;
}
int numberOfAttributes = buffP->attrnum;
......@@ -663,6 +698,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
msg->Items[i].deadband, msg->Items[i].options, &idx);
if ( EVEN(m_sts)) return m_sts;
}
if ( ODD(m_sts) ) {
//Create space for the old values used if we have deadband active
if ( m_db->m_items[idx].old_value != 0 ) {
free(m_db->m_items[idx].old_value);
......@@ -676,15 +712,19 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
m_db->m_items[idx].first_storage = 1;
m_db->m_items[idx].sevid = msg->Items[i].sevid;
sev_refid sevid(msg->Items[i].sevid);
m_refid[sevid] = idx;
pwr_tRefId rk;
sev_sRefid *rp;
rk = msg->Items[i].sevid;
rp = (sev_sRefid *) tree_Insert(&sts, m_refid, &rk);
rp->idx = idx;
}
}
printf( "---- Node up (%d) ----\n", nid);
for ( iterator_refid it = m_refid.begin(); it != m_refid.end(); it++)
printf( "Refid: %d,%d Idx: %d Name %s\n", it->first.id.nid, it->first.id.rix, it->second, m_db->m_items[it->second].oname);
return 1;
}
/*
int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size)
{
sev_sHistData *dp = (sev_sHistData *)&msg->Data;
......@@ -704,6 +744,31 @@ int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size)
}
return 1;
}
*/
int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size)
{
pwr_tStatus sts;
sev_sHistData *dp = (sev_sHistData *)&msg->Data;
pwr_tTime time;
while ( (char *)dp - (char *)msg < (int)size) {
sev_sRefid *rp;
pwr_tRefId rk = dp->sevid;
rp = (sev_sRefid *) tree_Find(&sts, m_refid, &rk);
if ( !rp) {
dp = (sev_sHistData *)((char *)dp + sizeof( *dp) - sizeof(dp->data) + dp->size);
continue;
}
unsigned int idx = rp->idx;
time = net_NetTimeToTime( &msg->Time);
m_db->store_value( &m_sts, idx, 0, time, &dp->data, dp->size);
dp = (sev_sHistData *)((char *)dp + sizeof( *dp) - sizeof(dp->data) + dp->size);
}
return 1;
}
......
......@@ -34,7 +34,8 @@ class sev_node {
char name[80];
};
class sev_refid {
typedef struct {
#if 0
public:
sev_refid( pwr_tRefId rid) : id(rid) {}
bool operator<(const sev_refid& x) const {
......@@ -44,20 +45,11 @@ class sev_refid {
return true;
return false;
}
pwr_tRefId id;
};
// Struct for binary tree item
typedef struct {
pwr_tOid oid;
pwr_tAName aname;
} sev_sItemKey;
typedef struct {
#endif
tree_sNode node;
sev_sItemKey key;
pwr_tRefId id;
int idx;
} sev_sItem;
} sev_sRefid;
class sev_server {
public:
......@@ -67,12 +59,15 @@ class sev_server {
sev_server() : m_server_status(0), m_msg_id(0) {}
typedef map<sev_refid, unsigned int>::iterator iterator_refid;
// typedef map<sev_refid, unsigned int>::iterator iterator_refid;
pwr_tStatus m_sts;
pwr_tStatus m_server_status;
vector<sev_node> m_nodes;
map<sev_refid, unsigned int> m_refid;
// map<sev_refid, unsigned int> m_refid;
tree_sTable *m_refid;
unsigned int m_msg_id;
sev_db *m_db;
int m_noneth;
......
......@@ -1278,6 +1278,35 @@ int sev_dbms::get_values( pwr_tStatus *sts, pwr_tOid oid, pwr_tMask options, flo
timestr_to_time( row[j++], &(*tbuf)[bcnt]);
}
if(row[j] == 0) {
//Null value
switch(type) {
case pwr_eType_Float32:
case pwr_eType_Float64:
case pwr_eType_Int8:
case pwr_eType_Int16:
case pwr_eType_Int32:
case pwr_eType_Int64:
case pwr_eType_UInt8:
case pwr_eType_UInt16:
case pwr_eType_UInt32:
case pwr_eType_UInt64:
case pwr_eType_Mask:
case pwr_eType_Enum:
cdh_StringToAttrValue( type, "0", ((char *)*vbuf)+ bcnt * size);
break;
case pwr_eType_Time:
case pwr_eType_DeltaTime:
//TODO deltatime??
cdh_StringToAttrValue( type, "1970-01-01 00:00:00", ((char *)*vbuf)+ bcnt * size);
break;
default:
cdh_StringToAttrValue( type, " ", ((char *)*vbuf)+ bcnt * size);
break;
}
j++;
}
else
cdh_StringToAttrValue( type, row[j++], ((char *)*vbuf)+ bcnt * size);
bcnt++;
......@@ -1326,6 +1355,35 @@ int sev_dbms::get_values( pwr_tStatus *sts, pwr_tOid oid, pwr_tMask options, flo
timestr_to_time( row[j++], &(*tbuf)[bcnt]);
}
if(row[j] == 0) {
//Null value
switch(type) {
case pwr_eType_Float32:
case pwr_eType_Float64:
case pwr_eType_Int8:
case pwr_eType_Int16:
case pwr_eType_Int32:
case pwr_eType_Int64:
case pwr_eType_UInt8:
case pwr_eType_UInt16:
case pwr_eType_UInt32:
case pwr_eType_UInt64:
case pwr_eType_Mask:
case pwr_eType_Enum:
cdh_StringToAttrValue( type, "0", ((char *)*vbuf)+ bcnt * size);
break;
case pwr_eType_Time:
case pwr_eType_DeltaTime:
//TODO deltatime??
cdh_StringToAttrValue( type, "1970-01-01 00:00:00", ((char *)*vbuf)+ bcnt * size);
break;
default:
cdh_StringToAttrValue( type, " ", ((char *)*vbuf)+ bcnt * size);
break;
}
j++;
}
else
cdh_StringToAttrValue( type, row[j++], ((char *)*vbuf)+ bcnt * size);
bcnt++;
......@@ -1361,20 +1419,58 @@ int sev_dbms::check_item( pwr_tStatus *sts, pwr_tOid oid, char *oname, char *ana
if ( cdh_ObjidIsEqual( oid, m_items[i].oid) &&
cdh_NoCaseStrcmp( aname, m_items[i].attr[0].aname) == 0) {
char query[400];
char query[600];
if ( type != m_items[i].attr[0].type ||
size != m_items[i].attr[0].size)
{
//Size or type changed what to do?
if( !handle_attrchange(sts, m_items[i].tablename, oid, (char *)"value", oname, type, size, i, 0) ) {
return 1;
}
}
sprintf( query, "update items set ");
if ( storagetime.tv_sec != m_items[i].storagetime.tv_sec)
if ( storagetime.tv_sec != m_items[i].storagetime.tv_sec) {
sprintf( &query[strlen(query)], "storagetime=%ld,", (long int)storagetime.tv_sec);
if ( strcmp( oname, m_items[i].oname) != 0)
m_items[i].storagetime = storagetime;
}
if ( strcmp( oname, m_items[i].oname) != 0) {
sprintf( &query[strlen(query)], "oname=\'%s\',", oname);
if ( type != m_items[i].attr[0].type)
strncpy(m_items[i].oname , oname, sizeof(m_items[i].oname));
}
if ( type != m_items[i].attr[0].type) {
sprintf( &query[strlen(query)], "vtype=%d,", type);
if ( size != m_items[i].attr[0].size)
sprintf( &query[strlen(query)], "size=%d,", size);
m_items[i].attr[i].type = type;
}
if ( size != m_items[i].attr[0].size) {
sprintf( &query[strlen(query)], "vsize=%d,", size);
m_items[i].attr[i].size = size;
}
if ( scantime != m_items[i].scantime) {
sprintf( &query[strlen(query)], "scantime=%.1f,", scantime);
m_items[i].scantime = scantime;
}
if ( deadband != m_items[i].deadband) {
sprintf( &query[strlen(query)], "deadband=%.4f,", deadband);
m_items[i].deadband = deadband;
}
if ( strcmp( description, m_items[i].description) != 0) {
sprintf( &query[strlen(query)], "description=\'%s\',", description);
strncpy(m_items[i].description , description, sizeof(m_items[i].description));
}
if ( strcmp( unit, m_items[i].attr[0].unit) != 0) {
sprintf( &query[strlen(query)], "unit=\'%s\',", unit);
strncpy(m_items[i].attr[0].unit, unit, sizeof(m_items[i].attr[0].unit));
}
sprintf( &query[strlen(query)], "uptime=\'%s\' ", timestr);
sprintf( &query[strlen(query)], "where id=%d;", m_items[i].id);
//This won't work!! We have to alter the table to be able to change this
//m_items[i].options = options;
int rc = mysql_query( m_env->con(), query);
if (rc) {
printf( "Store item: %s\n", mysql_error(m_env->con()));
......@@ -1532,6 +1628,10 @@ char *sev_dbms::oid_to_table( pwr_tOid oid, char *aname)
for ( char *s = tbl; *s; s++) {
if ( *s == '.')
*s = '_';
if ( *s == '[')
*s = '$';
if ( *s == ']')
*s = '$';
}
return tbl;
}
......@@ -1767,36 +1867,9 @@ int sev_dbms::check_objectitemattr( pwr_tStatus *sts, char *tablename, pwr_tOid
if (cdh_NoCaseStrcmp( aname, item->attr[j].aname) == 0) {
if (type != item->attr[j].type ||
size != item->attr[j].size) {
//Same name new type or size what to do?
//We try to alter the table if it is possible(float->double int->long or little_string->bigger_string probably works).
//If we can't alter the table we rename the column and create a new one
printf("Column:%s in %s has been changed from Type/size %d/%d to %d/%d\n",
aname, tablename, item->attr[j].type, item->attr[j].size, type, size );
errh_Warning("Column:%s in %s has been changed from Type/size %d/%d to %d/%d",
aname, tablename, item->attr[j].type, item->attr[j].size, type, size );
if (!alter_attrcolumn(sts, tablename, aname, type, size, item->attr[j].type, item->attr[j].size)) {
//We were not able to alter the column then we should rename the column and create a new one
if (!rename_attrcolumn(sts, tablename, aname, item->attr[j].type, item->attr[j].size)) {
//Very very bad this should not happen
errh_Error("Could not rename column that has been changed tablename:%s columnname:%s", tablename, aname);
//m_items[i].attr[j].status = -1; //TODO Skip this attribute during logging
*sts = SEV__DBERROR;
return 1;
}
errh_Warning("Column:%s in %s renamed to:%s_before_xxxx xx:xx:xx", aname, tablename, aname );
char query[2000];
sprintf( query, "alter table %s add `%s` %s;",
tablename, aname, pwrtype_to_type( type, size));
int rc = mysql_query( m_env->con(), query);
if (rc) {
printf( "%s: %s\n", __FUNCTION__,mysql_error(m_env->con()));
*sts = SEV__DBERROR;
if( !handle_attrchange(sts, tablename, oid, aname,oname,type,size, *idx, j) ) {
return 1;
}
}
item->attr[j].type = type;
item->attr[j].size = size;
update_objectitemattr(sts, tablename, aname, type, size);
......@@ -2932,6 +3005,43 @@ int sev_dbms::get_objectvalues( pwr_tStatus *sts, sev_item *item,
return 1;
}
int sev_dbms::handle_attrchange(pwr_tStatus *sts, char *tablename, pwr_tOid oid, char *aname, char *oname,
pwr_eType type, unsigned int size, unsigned int item_idx, unsigned int attr_idx)
{
//We try to alter the table if it is possible(float->double int->long or little_string->bigger_string probably works).
//If we can't alter the table we rename the column and create a new one
sev_item *item = &m_items[item_idx];
printf("Column:%s in %s has been changed from Type/size %d/%d to %d/%d\n",
aname, tablename, item->attr[attr_idx].type, item->attr[attr_idx].size, type, size );
errh_Warning("Column:%s in %s has been changed from Type/size %d/%d to %d/%d",
aname, tablename, item->attr[attr_idx].type, item->attr[attr_idx].size, type, size );
if (!alter_attrcolumn(sts, tablename, aname, type, size, item->attr[attr_idx].type, item->attr[attr_idx].size)) {
//We were not able to alter the column then we should rename the column and create a new one
if (!rename_attrcolumn(sts, tablename, aname, item->attr[attr_idx].type, item->attr[attr_idx].size)) {
//Very very bad this should not happen
errh_Error("Could not rename column that has been changed tablename:%s columnname:%s", tablename, aname);
//item->attr[attr_idx].status = -1; //TODO Skip this attribute during logging
*sts = SEV__DBERROR;
return 0;
}
errh_Warning("Column:%s in %s renamed to:%s_before_xxxx xx:xx:xx", aname, tablename, aname );
char query[2000];
sprintf( query, "alter table %s add `%s` %s;",
tablename, aname, pwrtype_to_type( type, size));
int rc = mysql_query( m_env->con(), query);
if (rc) {
printf( "%s: %s\n", __FUNCTION__,mysql_error(m_env->con()));
*sts = SEV__DBERROR;
return 0;
}
}
return 1;
}
sev_dbms::~sev_dbms()
{
printf("Freeing memory\n");
......
......@@ -172,6 +172,8 @@ class sev_dbms : public sev_db {
int get_objectvalues( pwr_tStatus *sts, sev_item *item, unsigned int size, pwr_tTime *starttime, pwr_tTime *endtime,
int maxsize, pwr_tTime **tbuf, void **vbuf, unsigned int *bsize);
pwr_tUInt64 get_minFromIntegerColumn( char *tablename, char *colname );
int handle_attrchange(pwr_tStatus *sts, char *tablename, pwr_tOid oid, char *aname, char *oname,
pwr_eType type, unsigned int size, unsigned int item_idx, unsigned int attr_idx);
};
#endif
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment