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 @@ ...@@ -42,6 +42,26 @@
#define sev_cGarbageInterval 120 #define sev_cGarbageInterval 120
#define sev_cGarbageCycle 86400 #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) int sev_server::init( int noneth)
{ {
qcom_sNode node; qcom_sNode node;
...@@ -111,6 +131,8 @@ int sev_server::init( int noneth) ...@@ -111,6 +131,8 @@ int sev_server::init( int noneth)
m_db->get_items( &m_sts); m_db->get_items( &m_sts);
m_db->get_objectitems(&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 // Create a queue to server
qcom_sQattr attr; qcom_sQattr attr;
qcom_sQid qid; qcom_sQid qid;
...@@ -518,10 +540,16 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size) ...@@ -518,10 +540,16 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
// Remove all refid's for this node // Remove all refid's for this node
pwr_tNid nid = msg->Items[0].sevid.nid; 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++) { rp = succ_rp;
if ( it->first.id.nid == nid)
m_refid.erase( it);
} }
for ( int i = 0; i < item_cnt; i++) { for ( int i = 0; i < item_cnt; i++) {
...@@ -596,6 +624,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size) ...@@ -596,6 +624,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
newattr.elem = 0; newattr.elem = 0;
newattrVec.push_back(newattr); newattrVec.push_back(newattr);
bool tableChange = false;
if ( !m_db->check_objectitemattr( &m_sts, if ( !m_db->check_objectitemattr( &m_sts,
tablename, tablename,
buffP->oid, buffP->oid,
...@@ -639,8 +668,14 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size) ...@@ -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].old_value = malloc(m_db->m_items[idx].value_size);
m_db->m_items[idx].sevid = buffP->sevid; 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; int numberOfAttributes = buffP->attrnum;
...@@ -663,6 +698,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size) ...@@ -663,6 +698,7 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size)
msg->Items[i].deadband, msg->Items[i].options, &idx); msg->Items[i].deadband, msg->Items[i].options, &idx);
if ( EVEN(m_sts)) return m_sts; if ( EVEN(m_sts)) return m_sts;
} }
if ( ODD(m_sts) ) {
//Create space for the old values used if we have deadband active //Create space for the old values used if we have deadband active
if ( m_db->m_items[idx].old_value != 0 ) { if ( m_db->m_items[idx].old_value != 0 ) {
free(m_db->m_items[idx].old_value); free(m_db->m_items[idx].old_value);
...@@ -676,15 +712,19 @@ int sev_server::check_histitems( sev_sMsgHistItems *msg, unsigned int size) ...@@ -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].first_storage = 1;
m_db->m_items[idx].sevid = msg->Items[i].sevid; 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); 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; return 1;
} }
/*
int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size) int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size)
{ {
sev_sHistData *dp = (sev_sHistData *)&msg->Data; sev_sHistData *dp = (sev_sHistData *)&msg->Data;
...@@ -704,6 +744,31 @@ int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size) ...@@ -704,6 +744,31 @@ int sev_server::receive_histdata( sev_sMsgHistDataStore *msg, unsigned int size)
} }
return 1; 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 { ...@@ -34,7 +34,8 @@ class sev_node {
char name[80]; char name[80];
}; };
class sev_refid { typedef struct {
#if 0
public: public:
sev_refid( pwr_tRefId rid) : id(rid) {} sev_refid( pwr_tRefId rid) : id(rid) {}
bool operator<(const sev_refid& x) const { bool operator<(const sev_refid& x) const {
...@@ -44,20 +45,11 @@ class sev_refid { ...@@ -44,20 +45,11 @@ class sev_refid {
return true; return true;
return false; return false;
} }
pwr_tRefId id; #endif
};
// Struct for binary tree item
typedef struct {
pwr_tOid oid;
pwr_tAName aname;
} sev_sItemKey;
typedef struct {
tree_sNode node; tree_sNode node;
sev_sItemKey key; pwr_tRefId id;
int idx; int idx;
} sev_sItem; } sev_sRefid;
class sev_server { class sev_server {
public: public:
...@@ -67,12 +59,15 @@ class sev_server { ...@@ -67,12 +59,15 @@ class sev_server {
sev_server() : m_server_status(0), m_msg_id(0) {} 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_sts;
pwr_tStatus m_server_status; pwr_tStatus m_server_status;
vector<sev_node> m_nodes; 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; unsigned int m_msg_id;
sev_db *m_db; sev_db *m_db;
int m_noneth; int m_noneth;
......
...@@ -1278,6 +1278,35 @@ int sev_dbms::get_values( pwr_tStatus *sts, pwr_tOid oid, pwr_tMask options, flo ...@@ -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]); 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); cdh_StringToAttrValue( type, row[j++], ((char *)*vbuf)+ bcnt * size);
bcnt++; bcnt++;
...@@ -1326,6 +1355,35 @@ int sev_dbms::get_values( pwr_tStatus *sts, pwr_tOid oid, pwr_tMask options, flo ...@@ -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]); 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); cdh_StringToAttrValue( type, row[j++], ((char *)*vbuf)+ bcnt * size);
bcnt++; bcnt++;
...@@ -1361,20 +1419,58 @@ int sev_dbms::check_item( pwr_tStatus *sts, pwr_tOid oid, char *oname, char *ana ...@@ -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) && if ( cdh_ObjidIsEqual( oid, m_items[i].oid) &&
cdh_NoCaseStrcmp( aname, m_items[i].attr[0].aname) == 0) { 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 "); 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); 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); 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); sprintf( &query[strlen(query)], "vtype=%d,", type);
if ( size != m_items[i].attr[0].size) m_items[i].attr[i].type = type;
sprintf( &query[strlen(query)], "size=%d,", size); }
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)], "uptime=\'%s\' ", timestr);
sprintf( &query[strlen(query)], "where id=%d;", m_items[i].id); 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); int rc = mysql_query( m_env->con(), query);
if (rc) { if (rc) {
printf( "Store item: %s\n", mysql_error(m_env->con())); 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) ...@@ -1532,6 +1628,10 @@ char *sev_dbms::oid_to_table( pwr_tOid oid, char *aname)
for ( char *s = tbl; *s; s++) { for ( char *s = tbl; *s; s++) {
if ( *s == '.') if ( *s == '.')
*s = '_'; *s = '_';
if ( *s == '[')
*s = '$';
if ( *s == ']')
*s = '$';
} }
return tbl; return tbl;
} }
...@@ -1767,36 +1867,9 @@ int sev_dbms::check_objectitemattr( pwr_tStatus *sts, char *tablename, pwr_tOid ...@@ -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 (cdh_NoCaseStrcmp( aname, item->attr[j].aname) == 0) {
if (type != item->attr[j].type || if (type != item->attr[j].type ||
size != item->attr[j].size) { size != item->attr[j].size) {
//Same name new type or size what to do? if( !handle_attrchange(sts, tablename, oid, aname,oname,type,size, *idx, j) ) {
//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;
return 1; return 1;
} }
}
item->attr[j].type = type; item->attr[j].type = type;
item->attr[j].size = size; item->attr[j].size = size;
update_objectitemattr(sts, tablename, aname, type, size); update_objectitemattr(sts, tablename, aname, type, size);
...@@ -2932,6 +3005,43 @@ int sev_dbms::get_objectvalues( pwr_tStatus *sts, sev_item *item, ...@@ -2932,6 +3005,43 @@ int sev_dbms::get_objectvalues( pwr_tStatus *sts, sev_item *item,
return 1; 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() sev_dbms::~sev_dbms()
{ {
printf("Freeing memory\n"); printf("Freeing memory\n");
......
...@@ -172,6 +172,8 @@ class sev_dbms : public sev_db { ...@@ -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 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); int maxsize, pwr_tTime **tbuf, void **vbuf, unsigned int *bsize);
pwr_tUInt64 get_minFromIntegerColumn( char *tablename, char *colname ); 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
#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