Commit 50bfa0e5 authored by claes's avatar claes

rt_elog implemented for Linux

parent 9fc052fe
include $(pwre_dir_symbols)
-include $(pwre_sroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_sroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_sroot)/tools/bld/src/$(type_name)_generic.mk
endif
-include ../../special.mk
-include ../special.mk
-include special.mk
ifndef link_rule_mk
link_rule_mk := 1
link = $(ld) $(linkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_objs) \
$(pwr_obj)/rt_io_user.o \
-lpwr_rt -lpwr_co \
-lpwr_msg_dummy \
-ldb -lrpcsvc -lpthread -lm -lrt
endif
/* rt_eventlogger.c -- <short description>
Author Jonas Nylund.
Receives events from the local MH and stores them in a
historical event log database on disk. */
#include "rt_elog.h"
#include "twolist.h"
#define Log_Error(a, b) errh_Error("%s\n%m",b, a)
#define Log(b) errh_Info(b)
#define Log_Error_Exit(a, b) {Log_Error(a, b); exit(a);}
#define Log_Error_Return(a, b) {Log_Error(a, b); return (a);}
#define If_Error_Log(a, b) if ((a & 1) != 1) Log_Error(a, b)
#define If_Error_Log_Return(a, b) if ((a & 1) != 1) Log_Error_Return(a, b)
#define If_Error_Log_Exit(a, b) if ((a & 1) != 1) Log_Error_Exit(a, b)
#define KEY_ARRAY_SIZE 50
void Init();
static pwr_tStatus Insert(mh_sMsgInfo *ip);
pwr_tInt32 GetOldestEvents(pwr_tUInt32 *nrOfEvents, pwr_tUInt32 *nrOfKeys);
void Store ( pwr_tBoolean *firstTime, pwr_tUInt32 *nrOfEvents, pwr_tUInt32 *nrOfKeys );
static sEvent *CopyEvent(
mh_sMsgInfo *ip
);
int compTime(sKey d1, sKey d2);
sHelCB lHelCB;
DB *dataBaseP = NULL;
pwr_tUInt32 nrOfInsertsSinceLastTime = 0;
headtyp *listhead;
linktyp *lanklank;
int
main ()
{
pwr_tUInt32 sts;
pwr_tObjid oid;
pwr_tBoolean firstTime = TRUE;
pwr_tUInt32 nrOfEvents = 0;
pwr_tUInt32 nrOfKeys = 0;
errh_Init("pwr_elog");
memset(&lHelCB, 0, sizeof(lHelCB));
/* Declare process */
sts = gdh_Init("pwr_elog");
If_Error_Log_Exit(sts, "gdh_Init");
Init();
oid.vid = lHelCB.Nid;
oid.oix = pwr_cNVolumeId;
sts = mh_OutunitConnect(
oid,
mh_eOutunitType_Logger,
mh_mOutunitFlags_ReadWait,
(mh_cbOutunitAck)Insert,
(mh_cbOutunitAlarm)Insert,
(mh_cbOutunitBlock)Insert,
(mh_cbOutunitCancel)Insert,
NULL,
NULL,
(mh_cbOutunitInfo)Insert,
(mh_cbOutunitReturn)Insert
);
If_Error_Log_Exit(sts, "mh_OutunitConnect");
sts = mh_OutunitSetTimeout(lHelCB.ScanTime);
for (;;) {
sts = mh_OutunitReceive();
if (EVEN(sts) && sts != MH__TMO)
Log_Error(sts, "mh_OutunitReceive");
Store(&firstTime, &nrOfEvents, &nrOfKeys);
}
}
void
Init ()
{
pwr_tUInt32 sts;
pwr_tInt32 ret;
char msg[80];
pwr_tObjid MHObjId;
pwr_sAttrRef AttrRef;
pwr_tDlid DLId;
pwr_sClass_MessageHandler *MH;
char fname[200];
dcli_translate_filename( fname, DATABASE);
sts = gdh_GetNodeIndex(&lHelCB.Nid);
If_Error_Log_Exit(sts, "gdh_GetNodeIndex");
sts = gdh_GetClassList(pwr_cClass_MessageHandler, &MHObjId);
If_Error_Log_Exit(sts, "Couldn't find message handler object");
AttrRef.Objid = MHObjId;
AttrRef.Body = 0;
AttrRef.Offset = 0;
AttrRef.Size = sizeof(pwr_sClass_MessageHandler);
AttrRef.Flags.m = 0;
sts = gdh_DLRefObjectInfoAttrref(&AttrRef, (pwr_tAddress *)&MH, &DLId);
If_Error_Log_Exit(sts,"Couldn't get direct link to message handler object");
if (MH->EventLogSize == 0) {
Log("EventLogSize = 0, no event logger will run on this node.");
exit(1);
}
lHelCB.MaxCardinality = MH->EventLogSize;
lHelCB.MaxStoreLSize = 1000; /*not used*/
lHelCB.ScanTime = 2000; /* 5 seconds */
/*create the database if it's not already created*/
if((ret = db_create(&dataBaseP, NULL, 0)) != 0)
{
/*error creating db-handle send the mess to errh, then exit*/
sprintf(msg, "db_create: %s, no eventlogger will run", db_strerror(ret));
errh_Error(msg);
exit(1);
}
/*open the database*/
if((ret = dataBaseP->open(dataBaseP, fname, NULL, DATABASETYPE, DB_CREATE, 0664)) != 0)
{
/*error opening/creating db send the mess to errh, then exit*/
sprintf(msg, "db_open: %s, no eventlogger will run", db_strerror(ret));
Log(msg);
exit(1);
}
newhead(&listhead);
}
/* Inserts an event into the DBs cache. */
static pwr_tStatus
Insert (
mh_sMsgInfo *ip
)
{
sEvent *sp;
char msg[80];
pwr_tInt32 ret;
sKey eventKey;
DBT key, data;
/*copy the event into the struct that is to be stored*/
sp = CopyEvent(ip);
/*clear the DBT-structs for future avoidance of errors(if DB is upgraded)*/
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
eventKey.Id = ip->Id;
eventKey.EventTime = ip->EventTime;
/* copy the data do the DBT-structs*/
key.data = (void *)&eventKey;
key.size = sizeof(sKey);
data.data = (void *)sp;
data.size = sizeof(sEvent);
switch(ret = dataBaseP->put(dataBaseP, NULL, &key, &data, DB_NOOVERWRITE))
{
case 0:
/*everything is good*/
nrOfInsertsSinceLastTime++;
break;
case DB_KEYEXIST:
/*data elready stored*/
break;
default:
/*error storing the event in DB send errormess to errh*/
sprintf(msg, "dbp->put: %s, no mess stored", db_strerror(ret));
Log(msg);
break;
}
free(sp);
return MH__SUCCESS;
}
void Store( pwr_tBoolean *firstTime, pwr_tUInt32 *nrOfEvents, pwr_tUInt32 *nrOfKeys )
{
char msg[80];
pwr_tInt32 ret = 0;
DBT key;
sKey skey;
/*flush the cache to the DB-file*/
dataBaseP->sync(dataBaseP, 0);
/*check if it's time to clean the DB*/
if( *firstTime || ((*nrOfEvents + nrOfInsertsSinceLastTime) > lHelCB.MaxCardinality ) )
{
*firstTime = FALSE;
if(nrOfInsertsSinceLastTime > 0)
{
nrOfInsertsSinceLastTime--;
*nrOfEvents = *nrOfEvents + 1;
}
if( *nrOfKeys <= 0)
{
ret = GetOldestEvents(nrOfEvents, nrOfKeys);
nrOfInsertsSinceLastTime = 0;
switch(ret)
{
case RT_ELOG_UNKNOWN_ERROR:
errh_Error("RT_ELOG_UNKNOWN_ERROR");
break;
case RT_ELOG_OK:
break;
case RT_ELOG_DB_EMPTY:
break;
default:
errh_Error("Undefined return: %d", ret);
break;
}
}
else
{
lanklank = firstlink(listhead);
skey = getlink(lanklank);
memset(&key, 0, sizeof(key));
key.data = &skey;
key.size = sizeof(sKey);
if( (ret = dataBaseP->del(dataBaseP, NULL, &key, 0)) != 0 )
{
sprintf(msg, "Error deleting Record in HistDB nrOfKeys = %d Errmess=%s\n", *nrOfKeys, db_strerror(ret));
// printf("\n%s\n", msg);
Log(msg);
}
else
{
*nrOfEvents = *nrOfEvents - 1;
// printf("Stdar, nrOfEvents= %d, nrOfKeys = %d, nrOfinssin= %d\n", *nrOfEvents,
// *nrOfKeys, nrOfInsertsSinceLastTime);
}
elimlink(&lanklank);
*nrOfKeys = *nrOfKeys - 1;
}
}
}
pwr_tInt32 GetOldestEvents(pwr_tUInt32 *nrOfEvents , pwr_tUInt32 *nrOfKeys)
{
sKey *tmpData;
pwr_tInt32 ret;
DBT data, key;
DBC *dbcp;
pwr_tUInt32 evCount = 0;
pwr_tUInt32 tmp = 0;
dbcp = NULL;
/* Acquire a cursor for the database. */
if ((ret = dataBaseP->cursor(dataBaseP, NULL, &dbcp, 0)) != 0)
{
errh_Error("error dataBaseP->cursor: %s\n", db_strerror(ret));
return RT_ELOG_UNKNOWN_ERROR;
}
/* Initialize the key/data return pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/*Get the first event*/
if((ret = dbcp->c_get(dbcp, &key, &data, DB_FIRST)) != 0)
{
*nrOfEvents = 0;
return RT_ELOG_DB_EMPTY;
}
evCount++;
tmpData = (sKey *)key.data;
newlink(&lanklank);
putlink(*tmpData, lanklank);
insort(lanklank, listhead, &compTime);
tmp++;
while((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
{
evCount++;
tmpData = (sKey *)key.data;
newlink(&lanklank);
putlink(*tmpData, lanklank);
insort(lanklank, listhead, &compTime);
tmp++;
if(nrlinks(listhead) > KEY_ARRAY_SIZE)
{
tmp--;
lanklank = lastlink(listhead);
elimlink(&lanklank);
}
}
if(ret != DB_NOTFOUND)
{
errh_Error("Error dbcp->c_get(DB_NEXT): %s\n", db_strerror(ret));
return RT_ELOG_UNKNOWN_ERROR;
}
/*Close the cursor*/
if((ret = dbcp->c_close(dbcp)) != 0)
{
errh_Error("Error dbcp_oldest->c_close(): %s\n", db_strerror(ret));
}
*nrOfEvents = evCount;
*nrOfKeys = tmp;
return RT_ELOG_OK;
}
sEvent *
CopyEvent (
mh_sMsgInfo *ip
)
{
sEvent *sp;
mh_sMessage *mp = (mh_sMessage*) ip;
mh_sAck *ap = (mh_sAck*) ip;
mh_sReturn *rp = (mh_sReturn*) ip;
mh_sBlock *bp = (mh_sBlock*) ip;
sp = malloc(sizeof(sEvent));
sp->EventType = ip->EventType;
sp->EventTime = ip->EventTime;
switch (ip->EventType) {
case mh_eEvent_Alarm:
case mh_eEvent_Info:
sp->Mess.message = *mp;
break;
case mh_eEvent_Ack:
sp->Mess.ack = *ap;
break;
case mh_eEvent_Cancel:
case mh_eEvent_Return:
sp->Mess.ret = *rp;
break;
case mh_eEvent_Block:
case mh_eEvent_Unblock:
case mh_eEvent_Reblock:
case mh_eEvent_CancelBlock:
sp->Mess.block = *bp;
break;
default:
Log("rt_elog: Error in CopyEvent unknown EventType");
break;
}
return sp;
}
int compTime(sKey d1, sKey d2)
{
if(time_Acomp( &(d1.EventTime), &(d2.EventTime)) < 0 )
{
return 1;
}
return 0;
}
#ifndef rt_elog_h
#define rt_elog_h
#ifndef pwr_h
#include "pwr.h"
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <db.h>
#include "co_time.h"
#include "rt_errh.h"
#include "rt_gdh.h"
#include "rt_gdh_msg.h"
#include "rt_mh_def.h"
#include "rt_mh_outunit.h"
#include "co_dcli.h"
#define DUMPFILE "rt_eventlog.dump"
#define DATABASE "$pwrp_db/rt_eventlog.db"
#define DATABASETYPE DB_HASH
#define DATABASESTAT_STRUCT DB_BTREE_STAT
#define RT_ELOG_UNKNOWN_ERROR -2
#define RT_ELOG_OK 0
#define RT_ELOG_DB_EMPTY 1
/*typedef struct s_Event sEvent;
typedef struct s_Key sKey;
typedef struct s_HelCB sHelCB;
*/
typedef struct s_Event {
mh_eEvent EventType;
pwr_tTime EventTime;
union {
mh_sMessage message;
mh_sAck ack;
mh_sReturn ret;
mh_sBlock block;
} Mess;
}sEvent;
typedef struct s_Key {
mh_sEventId Id;
pwr_tTime EventTime;
}sKey;
typedef struct s_HelCB {
int MaxStoreLSize;
int StoreLSize;
int Cardinality;
int MaxCardinality;
pwr_tInt32 ScanTime;
pwr_tNodeId Nid;
pwr_tInt64 StoreIdx;
}sHelCB;
#endif
/* Implementation av tvvgslistrutiner -- twolist.c */
#include "twolist.h"
#include <stdlib.h>
void newhead(headtyp **hpp)
/* Skapar en ny tom lista */
{
*hpp = malloc(sizeof(headtyp));
(*hpp)->kind = head;
(*hpp)->befo = (*hpp)->next = *hpp;
}
void newlink(linktyp **lpp)
/* Skapar en ny tom lnk */
{
*lpp = malloc(sizeof(linktyp));
(*lpp)->kind = lank;
(*lpp)->befo = (*lpp)->next = NULL;
}
void putlink(datatyp d, linktyp *lp)
/* Stter in data i en lnk */
{
if (lp != NULL)
lp->data = d;
}
datatyp getlink(linktyp *lp)
/* Returnerar data frn en lnk */
{
datatyp d;
if (lp != NULL)
d = lp->data;
return d;
}
void inlast(linktyp *lp, headtyp *hp)
/* Stter in lnk sist i lista */
{
hp->befo->next = lp;
lp->befo = hp->befo;
hp->befo = lp;
lp->next = hp;
}
void infirst(linktyp *lp, headtyp *hp)
/* Stter in lnk frst i lista */
{
hp->next->befo = lp;
lp->next = hp->next;
hp->next = lp;
lp->befo = hp;
}
void inpred(linktyp *lp, linktyp *ep)
/* Stter in frsta lnken fre den andra */
{
ep->befo->next = lp;
lp->befo = ep->befo;
ep->befo = lp;
lp->next = ep;
}
void insucc(linktyp *lp, linktyp *ep)
/* Stter in frsta lnken efter den andra */
{
ep->next->befo = lp;
lp->next = ep->next;
ep->next = lp;
lp->befo = ep;
}
void insort(linktyp *lp, headtyp *hp, int (*is_less)(datatyp d1, datatyp d2))
/* Stter in lnken sorterad enligt is_less */
{
linktyp *sp, *ep;
newlink(&sp);
*sp = *lp;
infirst(sp, hp);
ep = lastlink(hp);
// if(ep == NULL) return;
while ( is_less(lp->data, ep->data) )
ep = predlink(ep);
insucc(lp, ep);
elimlink(&sp);
}
linktyp *firstlink(headtyp *hp)
/* Returnerar pekare till frsta lnken i listan */
{
linktyp *ep;
if ( !empty(hp) )
ep = hp->next;
else
ep = NULL;
return ep;
}
linktyp *lastlink(headtyp *hp)
/* Returnerar pekare till sista lnken i listan */
{
linktyp *ep;
if ( !empty(hp) )
ep = hp->befo;
else
ep = NULL;
return ep;
}
linktyp *predlink(linktyp *lp)
/* Returnerar pekare till lnken fre */
{
linktyp *ep;
if ( is_link(lp->befo) )
ep = lp->befo;
else
ep = NULL;
return ep;
}
linktyp *succlink(linktyp *lp)
/* Returnerar pekare till lnken efter */
{
linktyp *ep;
if ( is_link(lp->next) )
ep = lp->next;
else
ep = NULL;
return ep;
}
int is_link(linktyp *lp)
/* Returnerar 1 om lnk annars 0 */
{
return (lp->kind == lank);
}
int empty(headtyp *hp)
/* Returnerar 1 om listan tom annars 0 */
{
return ( hp->next->kind == head );
}
int nrlinks(headtyp *hp)
/* Returnerar antalet lnkar i listan */
{
int sum = 0;
linktyp *ep;
ep = firstlink(hp);
while ( ep != NULL )
{
sum++;
ep = succlink(ep);
}
return sum;
}
void outlist(linktyp *lp)
/* Tar bort lnken frn listan */
{
if (lp->befo != NULL && lp->next !=NULL)
{
lp->befo->next = lp->next;
lp->next->befo = lp->befo;
lp->befo = NULL;
lp->next = NULL;
}
}
void elimlink(linktyp **lpp)
/* Tar bort, avallokerar och NULL-stller lnken */
{
outlist(*lpp);
free(*lpp);
*lpp = NULL;
}
void clearhead(headtyp *hp)
/* Eliminerar alla lnkar frn listan */
{
linktyp *ep;
while ( !empty(hp) )
{
ep = firstlink(hp);
elimlink(&ep);
}
}
void elimhead(headtyp **hpp)
/* Eliminerar och NULL-stller listan */
{
clearhead(*hpp);
free(*hpp);
*hpp = NULL;
}
/* Specifikation av tvvgslista -- twolist.h */
#ifndef TWOLISTH
#define TWOLISTH
#ifndef rt_elog_h
#include "rt_elog.h"
#endif
typedef sKey datatyp; /* Exempelvis */
typedef
struct twolink
{
enum {head, lank} kind;
struct twolink *befo, *next;
datatyp data;
} headtyp, linktyp;
void newhead(headtyp **hpp);
/* Skapar en ny tom lista */
void newlink(linktyp **lpp);
/* Skapar en ny tom lnk */
void putlink(datatyp d, linktyp *lp);
/* Stter in data i en lnk */
datatyp getlink(linktyp *lp);
/* Returnerar data frn lnk */
void inlast(linktyp *lp, headtyp *hp);
/* Stter in lnken sist i listan */
void infirst(linktyp *lp, headtyp *hp);
/* Stter in lnken frst i listan */
void inpred(linktyp *lp, linktyp *ep);
/* Stter in frsta lnken fre den andra */
void insucc(linktyp *lp, linktyp *ep);
/* Stter in frsta lnken efter den andra */
void insort(linktyp *lp, headtyp *hp, int (*is_less)(datatyp d1, datatyp d2));
/* Stter in lnken sorterad enligt is_less */
linktyp *firstlink(headtyp *hp);
/* Returnerar pekare till frsta lnken i listan */
linktyp *lastlink(headtyp *hp);
/* Returnerar pekare till sista lnken i listan */
linktyp *predlink(linktyp *lp);
/* Returnerar pekare till lnken fre */
linktyp *succlink(linktyp *lp);
/* Returnerar pekare till lnken efter */
int is_link(linktyp *lp);
/* Returnerar 1 om lnk annars 0 */
int empty(headtyp *hp);
/* Returnerar 1 om listan tom annars 0 */
int nrlinks(headtyp *hp);
/* Returnerar antalet lnkar i listan */
void outlist(linktyp *lp);
/* Tar bort lnken frn listan */
void elimlink(linktyp **lpp);
/* Tar bort, avallokerar och NULL-stller lnken */
void clearhead(headtyp *hp);
/* Tar bort alla lnkar frn listan */
void elimhead(headtyp **hpp);
/* Eliminerar och NULL-stller listan */
#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