This commit is contained in:
Jeff Hill
2002-02-06 15:48:49 +00:00
parent 5fc667f7f4
commit 89c9a956a7
15 changed files with 0 additions and 2078 deletions
-15
View File
@@ -1,15 +0,0 @@
# $Log$
# Revision 1.3 1999/09/13 14:09:37 mrk
# for 3.14 only a single Makefile
#
# Revision 1.2 1997/05/13 14:22:58 jbk
# added comments at top
#
TOP=../../../..
include $(TOP)/configure/CONFIG
include $(TOP)/configure/RULES_ARCHS
-29
View File
@@ -1,29 +0,0 @@
# $Log$
# Revision 1.4 1999/11/18 14:39:46 mrk
# new way to build
#
# Revision 1.3 1999/09/13 14:09:37 mrk
# for 3.14 only a single Makefile
#
# Revision 1.2 1997/05/13 14:22:58 jbk
# added comments at top
#
TOP=../../../..
include $(TOP)/configure/CONFIG
PROD_LIBS := cas ca gdd Com
SRCS += mon.cc monAdl.cc monNode.cc monServer.cc
PROD := iocMonitor
include $(TOP)/config/RULES_BUILD
clean::
@$(RM) iocMonitor
@$(RM) -rf Templates.DB
@$(RM) core
-343
View File
@@ -1,343 +0,0 @@
// Author: Jim Kowalkowski
// Date: 1/97
//
// $Id$
// $Log$
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include "caProto.h"
// use lower 11 bits of address as index
#define ADDR_MASK 0x000007ff
#define ADDR_CHECK 10
#define ADDR_WARNING 20
#define ADDR_DEATH 40
#define REPEATER_PORT 5065
typedef enum { nodeAlive=0, nodeUnknown, nodeDead } nodeState;
// ----------------------------- host node ------------------------------
class netNode
{
public:
netNode(unsigned long a,const char* pre);
~netNode(void);
void report(void);
void ping(void);
nodeState state(void);
nodeState state(time_t);
unsigned long addr;
time_t last_ping;
const char* name;
struct netNode* next;
};
netNode::netNode(unsigned long a,const char* pre)
{
struct in_addr& in = (struct in_addr&)a;
struct hostent* entry;
char *n,*x;
addr=a;
time(&last_ping);
if((entry=gethostbyaddr((char*)&a,sizeof(a),AF_INET))==NULL)
n=inet_ntoa(in);
else
n=entry->h_name;
x=new char[strlen(n)+1+strlen(pre)];
strcpy(x,pre);
strcat(x,n);
name=x;
next=NULL;
}
netNode::~netNode(void)
{
char* n = (char*)name;
delete [] n;
}
void netNode::ping(void)
{
time(&last_ping);
}
nodeState netNode::state(void)
{
time_t t;
time(&t);
return state(t);
}
nodeState netNode::state(time_t t)
{
nodeState s;
time_t x;
x=t-last_ping;
if(x<ADDR_WARNING)
s=nodeAlive;
else if(x<ADDR_DEATH)
s=nodeUnknown;
else
s=nodeDead;
return s;
}
void netNode::report(void)
{
switch(state())
{
case nodeDead: printf(" IOC %s Dead\n",name); break;
case nodeAlive: printf(" IOC %s Alive\n",name); break;
case nodeUnknown: printf(" IOC %s Unknown\n",name); break;
}
}
// -------------------------- database ---------------------------
class addrDb
{
public:
addrDb(const char* p);
~addrDb(void);
void report(void);
netNode* findNode(unsigned long addr);
netNode* addNode(unsigned long addr);
private:
const char* prefix;
netNode** db;
};
addrDb::addrDb(const char* p)
{
int i;
const char* x = p?p:"_";
char* y;
y=new char[strlen(x)+1];
strcpy(y,x);
prefix=y;
db=new netNode*[ADDR_MASK];
for(i=0;i<ADDR_MASK;i++) db[i]=NULL;
}
addrDb::~addrDb(void)
{
int i;
netNode *c,*p;
for(i=0;i<ADDR_MASK;i++)
{
for(c=db[i];c;)
{
p=c->next;
delete c;
c=p;
}
}
delete [] db;
}
void addrDb::report(void)
{
int i;
netNode* n;
for(i=0;i<ADDR_MASK;i++)
{
for(n=db[i];n;n=n->next)
n->report();
}
}
netNode* addrDb::findNode(unsigned long addr)
{
netNode* t;
for(t=db[addr&ADDR_MASK];t && t->addr!=addr;t=t->next);
return t;
}
netNode* addrDb::addNode(unsigned long addr)
{
unsigned long i;
netNode* t;
if((t=findNode(addr))==NULL)
{
i=addr&ADDR_MASK;
t=new netNode(addr,prefix);
t->next=db[i];
db[i]=t;
}
else
t->ping();
return t;
}
// ------------------------------------------------------------------------
addrDb* db;
int main(int argc, char* argv[] )
{
caHdr msg;
struct sockaddr_in tsin;
struct sockaddr ssin;
struct timeval tout;
struct hostent* entry;
fd_set fds;
char* name;
netNode* node;
int soc,retry,done,rlen,len;
unsigned short cmd;
unsigned long* iaddr;
time_t curr,last;
if(argc<2)
{
fprintf(stderr,"Must enter a prefix for PVs on command line\n");
return -1;
}
db=new addrDb(argv[1]);
tsin.sin_port=htons(0);
tsin.sin_family=AF_INET;
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
if((soc=socket(AF_INET,SOCK_DGRAM,17))<0)
{
perror("open socket failed");
return -1;
}
if((bind(soc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
{
perror("local bind failed to soc failed");
close(soc);
return -1;
}
memset((char*)&msg,0,sizeof(msg));
msg.m_cmmd = htons(REPEATER_REGISTER);
msg.m_available = tsin.sin_addr.s_addr;
tsin.sin_port=htons(REPEATER_PORT);
for(done=0,retry=0;done==0 && retry<3;retry++)
{
if(sendto(soc,(char*)&msg,sizeof(msg),0,
(struct sockaddr*)&tsin,sizeof(tsin))<0)
{
perror("sendto failed");
close(soc);
return -1;
}
FD_ZERO(&fds);
FD_SET(soc,&fds);
tout.tv_sec=0;
tout.tv_usec=500000;
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
{
case -1: /* bad */
perror("first select failed");
return -1;
case 0: /* timeout */
break;
default: /* data ready */
done=1;
}
}
if(done==1)
{
rlen=0;
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
{
perror("first recvfrom failed");
return -1;
}
cmd=ntohs(msg.m_cmmd);
if(cmd==REPEATER_CONFIRM)
printf("Connected to repeater\n");
else
{
printf("Cannot connect to repeater (%d)\n",(int)cmd);
return -1;
}
}
else
{
printf("Cannot connect to repeater\n");
return -1;
}
/* ---------------- ready ---------------- */
last=0;
while(1)
{
FD_ZERO(&fds);
FD_SET(soc,&fds);
tout.tv_sec=ADDR_CHECK;
tout.tv_usec=0;
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
{
case -1: /* bad */
perror("main select failed");
case 0: /* timeout */
// db->report();
break;
default: /* data ready */
{
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
{
perror("first recvfrom failed");
return -1;
}
iaddr=(unsigned long*)&msg.m_available;
node=db->addNode(*iaddr);
// cmd=ntohs(msg.m_cmmd);
// if(cmd==CA_PROTO_RSRV_IS_UP)
// {
// printf("Alive\n");
// }
// else
// printf("Unidentified Command from 0x%8.8x\n",*iaddr);
break;
}
}
time(&curr);
if((curr-last)>=ADDR_CHECK)
{
db->report();
last=curr;
}
}
return 0;
}
-95
View File
@@ -1,95 +0,0 @@
// Author: Jim Kowalkowski
// Date: 1/97
//
// $Id$
// $Log$
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "monNode.h"
#include "monServer.h"
#define WIDTH 180
#define HEIGHT 10
#define MAX_WIDTH 1000
#define MAX_HEIGHT 700
#define TOTAL_X (MAX_WIDTH/WIDTH)
#define TOTAL_Y (MAX_HEIGHT/HEIGHT)
int monAdl(monNode** head, char* fname,const char* prefix)
{
FILE *fdout;
int dh;
int i,j,k;
monNode* node;
if((fdout=fopen(fname,"w"))==NULL)
{
fprintf(stderr,"Cannot open the ADL file %s\n",fname);
return -1;
}
dh=monNode::total/TOTAL_X;
if((dh*TOTAL_X)!=monNode::total) ++dh;
fprintf(fdout,"\nfile { name=\"ioc_status.adl\" version=020209 }\n");
fprintf(fdout,"display {\n");
fprintf(fdout," object { x=0 y=0 width=%d height=%d }\n",
MAX_WIDTH,dh*HEIGHT+40);
fprintf(fdout," clr=37 bclr=14 cmap=\"\"\n}\n");
fprintf(fdout,"\"color map\" { ncolors=65 colors {\n");
fprintf(fdout,"ffffff, ececec, dadada, c8c8c8, bbbbbb, aeaeae, 9e9e9e,\n");
fprintf(fdout,"919191, 858585, 787878, 696969, 5a5a5a, 464646, 2d2d2d,\n");
fprintf(fdout,"000000, 00d800, 1ebb00, 339900, 2d7f00, 216c00, fd0000,\n");
fprintf(fdout,"de1309, be190b, a01207, 820400, 5893ff, 597ee1, 4b6ec7,\n");
fprintf(fdout,"3a5eab, 27548d, fbf34a, f9da3c, eeb62b, e19015, cd6100,\n");
fprintf(fdout,"ffb0ff, d67fe2, ae4ebc, 8b1a96, 610a75, a4aaff, 8793e2,\n");
fprintf(fdout,"6a73c1, 4d52a4, 343386, c7bb6d, b79d5c, a47e3c, 7d5627,\n");
fprintf(fdout,"58340f, 99ffff, 73dfff, 4ea5f9, 2a63e4, 0a00b8, ebf1b5,\n");
fprintf(fdout,"d4db9d, bbc187, a6a462, 8b8239, 73ff6b, 52da3b, 3cb420,\n");
fprintf(fdout,"289315, 1a7309,\n");
fprintf(fdout,"} }\n");
// ----------------------- heading ----------------------------------
i=(MAX_WIDTH/2)-(300/2);
fprintf(fdout," text { object { x=%d y=2 width=300 height=25 }\n",i);
fprintf(fdout," \"basic attribute\" { clr=37 }\n");
fprintf(fdout," textix=\"%d IOC STATUS MONITOR\"\n",monNode::total);
fprintf(fdout," align=\"horiz. centered\"\n}\n");
// ---------------------- generate new file button -------------------
fprintf(fdout,"\"message button\" { object\n");
fprintf(fdout," { x=%d y=2 width=180 height=22 }\n",MAX_WIDTH-180);
fprintf(fdout," control { chan=\"%smakeScreen\" clr=31 bclr=47 }\n",prefix);
fprintf(fdout," label=\"Make New Screen\" press_msg=\"1\"\n}\n");
fprintf(fdout,"\"text update\" { object { x=1 y=2 width=180 height=22 }\n");
fprintf(fdout," monitor { chan=\"%siocCount\" clr=31 bclr=14 }\n",prefix);
fprintf(fdout,"}\n");
// -------------- make all the buttons
i=0;j=0;
for(k=0;k<ADDR_TOTAL;k++)
{
for(node=head[k];node;node=node->next)
{
fprintf(fdout,"\"text update\" {\n");
fprintf(fdout," object { x=%d y=%d width=%d height=%d }\n",
i*WIDTH,j*HEIGHT+30,WIDTH,HEIGHT);
if(++i>=TOTAL_X) { i=0; ++j; }
fprintf(fdout," monitor { chan=\"%s\" clr=0 bclr=14 }\n",
node->name);
fprintf(fdout," clrmod=\"alarm\"\n}\n");
}
}
fclose(fdout);
return 0;
}
-283
View File
@@ -1,283 +0,0 @@
// Author: Jim Kowalkowski
// Date: 1/97
//
// $Id$
// $Log$
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "gddAppTable.h"
#include "monServer.h"
#include "monNode.h"
// --------------------------- monPv ----------------------------
monPv::monPv(const casCtx& c,monServer& s,monNode* n,const char* name):
casPV(c,name),node(n),mrg(s)
{
monDebug1(5,"monPV: Creating PV for %s\n",name);
data=NULL;
markNotInterested();
node->setPv(this);
}
monPv::~monPv(void)
{
node->clearPv();
if(data) data->unreference();
monDebug1(5,"monPV: Deleting PV for %s\n",node->name);
}
unsigned monPv::maxSimultAsyncOps(void) const { return 5000u; }
void monPv::interestDelete(void) { markNotInterested(); }
aitEnum monPv::bestExternalType(void) const { return aitEnumString; }
unsigned monPv::maxDimension(void) const { return 0; }
aitIndex monPv::maxBound(unsigned dim) const { return 0; }
void monPv::destroy(void) { casPV::destroy(); }
caStatus monPv::interestRegister(void)
{
markInterested();
return S_casApp_success;
}
caStatus monPv::read(const casCtx& ctx, gdd& dd)
{
monDebug1(5,"monPV: Read PV data=0x%8.8x\n",(int)data);
gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();
if(data) table.smartCopy(&dd,data);
return S_casApp_success;
}
caStatus monPv::write(const casCtx& /*ctx*/, gdd& /*dd*/)
{
// cannot write to these PVs
return S_casApp_success;
}
void monPv::eventData(void)
{
struct tm* t;
char val[40];
char str[10];
aitTimeStamp stamp(node->state_ping,0);
// prepare a new gdd used for posting and reads
if(data) data->unreference();
data=new gddScalar(mrg.appValue,aitEnumString);
t=localtime(&node->state_ping);
switch(node->state())
{
case monAlive:
strcpy(str,"Up");
data->setStatSevr(0,NO_ALARM);
break;
case monUnknown:
strcpy(str,"?");
data->setStatSevr(TIMEOUT_ALARM,MINOR_ALARM);
break;
case monDead:
strcpy(str,"Down");
data->setStatSevr(COMM_ALARM,MAJOR_ALARM);
break;
}
/*
sprintf(val,"(%s %s %2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d)",
&node->name[mrg.prefix_length],str,
t->tm_mon+1,t->tm_mday,t->tm_year,t->tm_hour,t->tm_min,t->tm_sec);
*/
sprintf(val,"(%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s)",
t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec,
&node->name[mrg.prefix_length]);
data->reference();
data->setTimeStamp(&stamp);
data->put(val);
monDebug1(5,"monPV: eventData data=0x%8.8x\n",(int)data);
if(debugLevel>6) data->dump();
if(isMonitored())
{
monDebug0(5,"monPV: PV monitored\n");
casEventMask select(
mrg.alarmEventMask|mrg.valueEventMask|mrg.logEventMask);
postEvent(select,*data);
}
}
// --------------------------- monNode ----------------------------
monNode::monNode(unsigned long a,const char* prefix)
{
struct in_addr& in = (struct in_addr&)a;
struct hostent* entry;
char *n,*x;
addr=a;
time(&last_ping);
state_ping=last_ping;
if((entry=gethostbyaddr((char*)&a,sizeof(a),AF_INET))==NULL)
n=inet_ntoa(in);
else
n=entry->h_name;
x=new char[strlen(n)+1+strlen(prefix)];
strcpy(x,prefix);
strcat(x,n);
name=x;
next=NULL;
pv=NULL;
last_state=monAlive;
++monNode::total;
monDebug1(5,"monNode: Created node %s\n",name);
}
monNode::~monNode(void)
{
monDebug1(5,"monNode: Deleted node %s\n",name);
char* n = (char*)name;
delete [] n;
}
int monNode::total=0;
void monNode::ping(void)
{
time(&last_ping);
}
monState monNode::state(void)
{
return last_state;
}
monState monNode::state(time_t t)
{
monState s;
time_t x;
x=t-last_ping;
if(x<ADDR_WARNING)
s=monAlive;
else if(x<ADDR_DEATH)
s=monUnknown;
else
s=monDead;
return s;
}
void monNode::check(time_t t)
{
monState s = state(t);
monDebug1(9,"monNode: Checking node %s\n",name);
if(s!=last_state)
{
last_state=s;
// only change boot time if going from/to dead
if(s==monDead || last_state==monDead) state_ping=t;
if(pv) pv->eventData();
}
}
void monNode::setPv(monPv* p)
{
int need;
monDebug1(9,"monNode: Setting PV for %s\n",name);
if(pv==NULL)
need=1;
else
need=0;
pv=p;
if(need) pv->eventData();
}
void monNode::clearPv(void) { pv=NULL; }
void monNode::report(FILE* fd)
{
struct in_addr* ia = (struct in_addr*)&addr;
switch(state())
{
case monDead:
fprintf(fd,"%s %s Dead\n",name,inet_ntoa(*ia));
break;
case monAlive:
fprintf(fd,"%s %s Alive\n",name,inet_ntoa(*ia));
break;
case monUnknown:
fprintf(fd,"%s %s Unknown\n",name,inet_ntoa(*ia));
break;
}
}
// -------------------- status PVs -----------------------
makeScreenPV::~makeScreenPV(void) { }
aitEnum makeScreenPV::bestExternalType(void) const { return aitEnumInt32; }
caStatus makeScreenPV::read(const casCtx& /*ctx*/, gdd& /*dd*/)
{
return S_casApp_success;
}
caStatus makeScreenPV::write(const casCtx& /*ctx*/, gdd& /*dd*/)
{
mrg.makeADL();
return S_casApp_success; // cannot write to these PVs
}
// -------------
iocCountPV::~iocCountPV(void) { mrg.count_pv=NULL; }
void iocCountPV::interestDelete(void) { monitored=0; }
aitEnum iocCountPV::bestExternalType(void) const { return aitEnumInt32; }
void iocCountPV::postValue(void)
{
gdd* value=new gddScalar(mrg.appValue,aitEnumInt32);
value->put(monNode::total);
if(monitored)
{
casEventMask select(
mrg.alarmEventMask|mrg.valueEventMask|mrg.logEventMask);
postEvent(select,*value);
}
}
caStatus iocCountPV::interestRegister(void)
{
monitored=1;
return S_casApp_success;
}
caStatus iocCountPV::read(const casCtx& ctx, gdd& dd)
{
// this is bad, should check for dd to be scalar, if it is not a scalar,
// then find the value gdd within the container
dd.put(monNode::total);
return S_casApp_success;
}
caStatus iocCountPV::write(const casCtx& /*ctx*/, gdd& /*dd*/)
{
return S_casApp_success; // cannot write to these PVs
}
-118
View File
@@ -1,118 +0,0 @@
#ifndef MONNODE_H
#define MONNODE_H
/*
* Author: Jim Kowalkowski
* Date: 1/97
*
* $Id$
* $Log$
*/
#include <time.h>
#include "aitTypes.h"
#include "casdef.h"
typedef enum { monAlive=0, monUnknown, monDead } monState;
#define ADDR_CHECK 10
#define ADDR_WARNING 20
#define ADDR_DEATH 40
class monNode;
class monServer;
class gdd;
class monPv : public casPV
{
public:
monPv(const casCtx&,monServer&,monNode*,const char* pv_name);
virtual ~monPv(void);
// CA server interface functions
virtual caStatus interestRegister(void);
virtual void interestDelete(void);
virtual aitEnum bestExternalType(void) const;
virtual caStatus read(const casCtx &ctx, gdd &prototype);
virtual caStatus write(const casCtx &ctx, gdd &value);
virtual void destroy(void);
virtual unsigned maxSimultAsyncOps(void) const;
virtual unsigned maxDimension(void) const;
virtual aitIndex maxBound(unsigned dim) const;
void eventData(void);
void markInterested(void) { monitor=1; }
void markNotInterested(void) { monitor=0; }
int isMonitored(void) { return monitor; }
monServer& mrg;
monNode* node;
int monitor;
gdd* data;
};
class monNode
{
public:
monNode(unsigned long a, const char* prefix);
~monNode(void);
void report(FILE*);
void ping(void);
void check(time_t);
monState state(void);
monState state(time_t);
void setPv(monPv*);
void clearPv(void);
unsigned long addr;
time_t last_ping;
time_t state_ping;
const char* name;
monPv* pv;
monNode* next;
monState last_state;
static int total;
};
// ---------------------------- status PVs --------------------------
class makeScreenPV : public casPV
{
public:
makeScreenPV(const casCtx& c,const char* pv_name,monServer& s):
casPV(c,pv_name),mrg(s){}
virtual ~makeScreenPV(void);
// CA server interface functions
virtual aitEnum bestExternalType(void) const;
virtual caStatus read(const casCtx &ctx, gdd &prototype);
virtual caStatus write(const casCtx &ctx, gdd &value);
monServer& mrg;
};
class iocCountPV : public casPV
{
public:
iocCountPV(const casCtx& c,const char* pv_name,monServer& s):
casPV(c,pv_name),mrg(s),monitored(0) {}
virtual ~iocCountPV(void);
// CA server interface functions
virtual caStatus interestRegister(void);
virtual void interestDelete(void);
virtual aitEnum bestExternalType(void) const;
virtual caStatus read(const casCtx &ctx, gdd &prototype);
virtual caStatus write(const casCtx &ctx, gdd &value);
void postValue(void);
int monitored;
monServer& mrg;
};
#endif
-361
View File
@@ -1,361 +0,0 @@
// Author: Jim Kowalkowski
// Date: 1/97
//
// $Id$
// $Log$
// Revision 1.2 1997/05/13 14:23:02 jbk
// added comments at top
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include "caProto.h"
#include "gddAppTable.h"
#include "monServer.h"
#include "monNode.h"
int debugLevel=0;
int makeReport=0;
int keepGoing=1;
typedef void (*SIG_FUNC)(int);
static SIG_FUNC save_hup = NULL;
static SIG_FUNC save_int = NULL;
static SIG_FUNC save_term = NULL;
static SIG_FUNC save_usr1 = NULL;
static void sig_end(int)
{
signal(SIGHUP,sig_end);
signal(SIGTERM,sig_end);
signal(SIGINT,sig_end);
keepGoing=0;
}
static void sig_usr1(int) { makeReport=1; signal(SIGUSR1,sig_usr1); }
extern int monAdl(monNode**,char*,const char*);
// ------------------------- file descriptor servicing ----------------------
monFd::~monFd(void) { }
void monFd::callBack(void) { server.dataReady(); }
// -------------------------- server -----------------------------
monServer::monServer(unsigned namelen,unsigned pvcount,unsigned simio,
const char* p):caServer(namelen,pvcount,simio)
{
int i;
count_pv=NULL;
const char* x = p?p:"_";
prefix=new char[strlen(x)+1];
strcpy(prefix,x);
prefix_length=strlen(prefix);
soc_fd=NULL;
db=new monNode*[ADDR_TOTAL];
for(i=0;i<ADDR_TOTAL;i++) db[i]=NULL;
gddApplicationTypeTable& tt = gddApplicationTypeTable::AppTable();
appValue=tt.getApplicationType("value");
sprintf(ioc_count_name,"%siocCount",prefix);
sprintf(make_screen_name,"%smakeScreen",prefix);
}
monServer::~monServer(void)
{
int i;
monNode *c,*p;
for(i=0;i<ADDR_TOTAL;i++)
{
for(c=db[i];c;)
{
p=c->next;
delete c;
c=p;
}
}
delete [] db;
}
void monServer::report(FILE* fd)
{
int i;
monNode* n;
for(i=0;i<ADDR_TOTAL;i++)
{
for(n=db[i];n;n=n->next)
n->report(fd);
}
}
monNode* monServer::findNode(unsigned long addr)
{
monNode* t;
for(t=db[addr&ADDR_MASK];t && t->addr!=addr;t=t->next);
return t;
}
monNode* monServer::addNode(unsigned long addr)
{
unsigned long i;
monNode* t;
if((t=findNode(addr))==NULL)
{
i=addr&ADDR_MASK;
t=new monNode(addr,prefix);
t->next=db[i];
db[i]=t;
pv_list.add(t->name,*t);
if(count_pv) count_pv->postValue();
}
else
t->ping();
return t;
}
void monServer::checkEvent(void)
{
// go through all the nodes and send out monitors on PV if required
time_t t;
int i;
monNode* n;
time(&t);
for(i=0;i<ADDR_TOTAL;i++)
{
for(n=db[i];n;n=n->next)
n->check(t);
}
}
pvExistReturn monServer::pvExistTest(const casCtx& c,const char* pvname)
{
monNode* node;
if(strcmp(pvname,ioc_count_name)==0)
return pvExistReturn(S_casApp_success,ioc_count_name);
if(strcmp(pvname,make_screen_name)==0)
return pvExistReturn(S_casApp_success,make_screen_name);
if(pv_list.find(pvname,node)==0)
return pvExistReturn(S_casApp_success,node->name);
else
return pvExistReturn(S_casApp_pvNotFound);
}
casPV* monServer::pvAttach(const casCtx& c,const char* pvname)
{
monNode* node;
if(strcmp(pvname,ioc_count_name)==0)
return count_pv=new iocCountPV(c,pvname,*this);
if(strcmp(pvname,make_screen_name)==0)
return new makeScreenPV(c,pvname,*this);
if(pv_list.find(pvname,node)==0)
return new monPv(c,*this,node,pvname);
else
return NULL;
}
int monServer::repeaterConnect(void)
{
caHdr msg;
struct sockaddr_in tsin;
struct sockaddr ssin;
struct timeval tout;
fd_set fds;
int retry,done,rlen,len;
tsin.sin_port=htons(0);
tsin.sin_family=AF_INET;
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
if((soc=socket(AF_INET,SOCK_DGRAM,17))<0)
{
perror("open socket failed");
return -1;
}
if((bind(soc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
{
perror("local bind failed to soc failed");
close(soc);
return -1;
}
memset((char*)&msg,0,sizeof(msg));
msg.m_cmmd = htons(REPEATER_REGISTER);
msg.m_available = tsin.sin_addr.s_addr;
tsin.sin_port=htons(REPEATER_PORT);
for(done=0,retry=0;done==0 && retry<3;retry++)
{
if(sendto(soc,(char*)&msg,sizeof(msg),0,
(struct sockaddr*)&tsin,sizeof(tsin))<0)
{
perror("sendto failed");
close(soc);
return -1;
}
FD_ZERO(&fds);
FD_SET(soc,&fds);
tout.tv_sec=0;
tout.tv_usec=500000;
switch(select(FD_SETSIZE,&fds,NULL,NULL,&tout))
{
case -1: /* bad */
perror("first select failed");
return -1;
case 0: /* timeout */
break;
default: /* data ready */
done=1;
}
}
if(done==1)
{
rlen=0;
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
{
perror("first recvfrom failed");
return -1;
}
if(ntohs(msg.m_cmmd)==REPEATER_CONFIRM)
printf("Connected to repeater\n");
else
{
printf("Cannot connect to repeater (%d)\n",(int)ntohs(msg.m_cmmd));
return -1;
}
}
else
{
printf("Cannot connect to repeater\n");
return -1;
}
soc_fd=new monFd(soc,fdrRead,*this);
return 0;
}
void monServer::dataReady(void)
{
caHdr msg;
struct sockaddr ssin;
monNode* node;
int rlen,len;
unsigned long* iaddr;
rlen=0;
if((len=recvfrom(soc,(char*)&msg,sizeof(msg),0,&ssin,&rlen))<0)
{
perror("first recvfrom failed");
}
else if(ntohs(msg.m_cmmd)==CA_PROTO_RSRV_IS_UP)
{
iaddr=(unsigned long*)&msg.m_available;
node=addNode(*iaddr);
}
}
void monServer::mainLoop(void)
{
osiTime delay(ADDR_CHECK,0u);
time_t curr,prev;
if(repeaterConnect()<0) return;
prev=0;
while(keepGoing)
{
fileDescriptorManager.process(delay);
time(&curr);
if((curr-prev)>=ADDR_CHECK)
{
checkEvent();
prev=curr;
}
if(makeReport)
{
FILE* fd;
if((fd=fopen("PV_REPORT","w")))
{
report(fd);
fclose(fd);
}
makeADL();
makeReport=0;
}
}
}
void monServer::makeADL(void) { monAdl(db,"ioc_status.adl",prefix); }
// ------------------------------------------------------------------------
int main(int argc, char* argv[])
{
if(argc<2)
{
fprintf(stderr,"Must enter a prefix for PVs on command line\n");
return -1;
}
if(argc==3) sscanf(argv[2],"%d",&debugLevel);
// disassociate from parent
switch(fork())
{
case -1: // error
perror("Cannot create gateway processes");
return -1;
case 0: // child
#if defined linux || defined SOLARIS
setpgrp();
#else
setpgrp(0,0);
#endif
setsid();
break;
default: // parent
return 0;
break;
}
save_hup=signal(SIGHUP,sig_end);
save_term=signal(SIGTERM,sig_end);
save_int=signal(SIGINT,sig_end);
save_usr1=signal(SIGUSR1,sig_usr1);
monServer* ms = new monServer(32u,5u,2000u,argv[1]);
ms->mainLoop();
delete ms;
return 0;
}
-100
View File
@@ -1,100 +0,0 @@
#ifndef MONSERVER_H
#define MONSERVER_H
/*
* Author: Jim Kowalkowski
* Date: 1/97
*
* $Id$
* $Log$
* Revision 1.3 1998/12/19 00:04:46 jhill
* renamed createPV() to pvAttach()
*
* Revision 1.2 1997/05/13 14:23:02 jbk
* added comments at top
*
*/
#include "casdef.h"
#include "tsHash.h"
#include "fdManager.h"
#include "monNode.h"
class gdd;
class monServer;
// use lower 11 bits of address as index
#define ADDR_MASK 0x0000001f
#define ADDR_TOTAL (ADDR_MASK+1)
#define REPEATER_PORT 5065
// ---------------------- fd manager ------------------------
class monFd : public fdReg
{
public:
monFd (const int fdIn,const fdRegType typ,monServer& s) :
fdReg (fdIn,typ),server(s) { }
virtual ~monFd (void);
private:
virtual void callBack (void);
monServer& server;
};
// ---------------------------- server -------------------------------
class monServer : public caServer
{
public:
monServer(unsigned max_name_len,unsigned pv_count_est,unsigned max_sim_io,
const char* pre);
virtual ~monServer(void);
// CAS virtual overloads
virtual pvExistReturn pvExistTest(const casCtx& c,const char* pvname);
virtual casPV* pvAttach(const casCtx& c,const char* pvname);
// CAS application management functions
int repeaterConnect(void);
void checkEvent(void);
void dataReady(void);
void mainLoop(void);
void report(FILE*);
void makeADL(void);
monNode* findNode(unsigned long addr);
monNode* addNode(unsigned long addr);
int appValue;
char* prefix;
int prefix_length;
iocCountPV* count_pv;
private:
tsHash<monNode> pv_list; // client pv list
monNode** db;
monFd* soc_fd;
int soc;
char ioc_count_name[40];
char make_screen_name[40];
};
extern int debugLevel;
/* debug macro creation */
#ifdef NODEBUG
#define monDebug(l,f,v) ;
#else
#define monDebug(l,f,v) { if(l<=debugLevel) \
{ fprintf(stderr,f,v); fflush(stderr); }}
#define monDebug0(l,f) { if(l<=debugLevel) \
{ fprintf(stderr,f); fflush(stderr); } }
#define monDebug1(l,f,v) { if(l<=debugLevel) \
{ fprintf(stderr,f,v); fflush(stderr); }}
#define monDebug2(l,f,v1,v2) { if(l<=debugLevel) \
{ fprintf(stderr,f,v1,v2); fflush(stderr); }}
#define monDebug3(l,f,v1,v2,v3) { if(l<=debugLevel) \
{ fprintf(stderr,f,v1,v2,v3); fflush(stderr); }}
#endif
#endif
-115
View File
@@ -1,115 +0,0 @@
#ifndef tsDLHashList_H
#define tsDLHashList_H
/*
* Author: Jim Kowalkowski
* Date: 1/97
*
* $Id$
* $Log$
*/
extern "C" {
#include "gpHash.h"
}
template <class T>
class tsHash
{
private:
void* hash_table;
public:
gpHash(void)
{
hash_table=NULL;
gphInitPvt(&hash_table);
}
~gateHash(void) { gphFreeMem(hash_table); }
int add(const char* key, T& item);
{
GPHENTRY* entry;
int rc;
entry=gphAdd(hash_table,(char*)key,hash_table);
if(entry==(GPHENTRY*)NULL)
rc=-1;
else
{
entry->userPvt=(void*)&item;
rc=0;
}
return rc;
}
int remove(const char* key,T*& item);
{
int rc;
if(find(key,item)<0)
rc=-1;
else
{
gphDelete(hash_table,(char*)key,hash_table);
rc=0;
}
return rc;
}
int find(const char* key, T*& item);
{
GPHENTRY* entry;
int rc;
entry=gphFind(hash_table,(char*)key,hash_table);
if(entry==(GPHENTRY*)NULL)
rc=-1;
else
{
item=(T*)entry->userPvt;
rc=0;
}
return rc;
}
};
template <class T>
class tsDLHashList : public tsDLList<T>
{
private:
tsHash<T> h;
public:
int add(const char* key, T& item)
{
int rc;
rc=h.add(key,item);
add(item);
return rc;
}
int find(const char* key, T*& item);
{
int rc=0;
if(h.find(key,item)!=0)
rc=-1;
return rc;
}
int remove(const char* key,T*& item);
{
int rc=0;
if(h.find(key,item)==0)
{
h.remove(key,item);
remove(*item);
}
else
rc=-1;
return rc;
}
};
#endif
-136
View File
@@ -1,136 +0,0 @@
#ifndef tsDLHashList_H
#define tsDLHashList_H
/*
* Author: Jim Kowalkowski
* Date: 7/96
*
* $Id$
*
* $Log$
*/
extern "C" {
#include "gpHash.h"
}
#include "tsDLList.h"
template <class T>
class tsHash
{
private:
void* hash_table;
friend class tsDLHashIter<T>;
public:
tsHash(void)
{
hash_table=0;
gphInitPvt(&hash_table,2048); // 2048 is a guess
}
~tsHash(void)
{
gphFreeMem(hash_table);
}
int add(const char* key, T& item)
{
GPHENTRY* entry;
int rc;
entry=gphAdd(hash_table,(char*)key,hash_table);
if(entry==0)
rc=-1;
else
{
entry->userPvt=(void*)&item;
rc=0;
}
return rc;
}
int remove(const char* key,T*& item)
{
int rc;
if(find(key,item)<0)
rc=-1;
else
{
gphDelete(hash_table,(char*)key,hash_table);
rc=0;
}
return rc;
}
int find(const char* key, T*& item)
{
GPHENTRY* entry;
int rc;
entry=gphFind(hash_table,(char*)key,hash_table);
if(entry==0)
rc=-1;
else
{
item=(T*)entry->userPvt;
rc=0;
}
return rc;
}
};
template <class T>
class tsDLHashList : public tsDLList<T>
{
private:
tsHash<T> h;
friend class tsDLHashIter<T>;
public:
tsDLHashList(void) { }
~tsDLHashList(void) { }
int add(const char* key, T& item)
{
int rc;
rc=h.add(key,item);
tsDLList<T>::add(item);
return rc;
}
int find(const char* key, T*& item)
{
int rc=0;
if(h.find(key,item)!=0)
rc=-1;
return rc;
}
int remove(const char* key,T*& item)
{
int rc=0;
if(h.find(key,item)==0)
{
h.remove(key,item);
tsDLList<T>::remove(*item);
}
else
rc=-1;
return rc;
}
};
template <class T>
class tsDLHashNode : public tsDLNode<T>
{
public:
T* getNext(void) { return tsDLNode<T>::getNext(); }
T* getPrev(void) { return tsDLNode<T>::getPrev(); }
};
#endif
-15
View File
@@ -1,15 +0,0 @@
# $Log$
# Revision 1.3 1999/09/13 14:09:40 mrk
# for 3.14 only a single Makefile
#
# Revision 1.2 1997/03/05 21:16:21 jbk
# Fixes cvs log id at top
#
TOP=../../../..
include $(TOP)/configure/CONFIG
include $(TOP)/configure/RULES_ARCHS
-24
View File
@@ -1,24 +0,0 @@
# $Log$
# Revision 1.4 1999/11/18 14:39:48 mrk
# new way to build
#
# Revision 1.3 1999/09/13 14:09:40 mrk
# for 3.14 only a single Makefile
#
# Revision 1.2 1997/03/05 21:16:21 jbk
# Fixes cvs log id at top
#
TOP=../../../..
include $(TOP)/configure/CONFIG
PROD_LIBS := cas ca gdd Com
SRCS += pvServ.cc
PROD :=pvServ
include $(TOP)/configure/RULES_BUILD
-8
View File
@@ -1,8 +0,0 @@
This server does not set the precision, limits,
units, etc and this may cause clients that use
these attributes to not work correctly. For example
clients that convert real values to strings using
the precision attribute may truncate real
values stored as strings.
-315
View File
@@ -1,315 +0,0 @@
// $Id$
// $Log$
// Revision 1.5 1998/12/19 00:04:48 jhill
// renamed createPV() to pvAttach()
//
// Revision 1.4 1997/06/25 05:56:38 jhill
// align with API changes
//
// Revision 1.3 1997/06/13 09:15:47 jhill
// connect proto changes
//
// Revision 1.2 1997/03/05 21:16:22 jbk
// Fixes cvs log id at top
//
#include <stdio.h>
#include "pvServ.h"
#include "fdManager.h"
#include "gdd.h"
#include "gddAppTable.h"
#include "alarm.h"
static int appValue;
void dBase::eventReady(void)
{
if(counter+1.0 > 100.0)
writeData(0.0);
else
writeData(counter+1.0);
}
void dBase::writeData(double x)
{
counter=x;
time((time_t*)&ts.tv_sec);
if(counter>hihi)
{ sevr=MAJOR_ALARM; stat=HIHI_ALARM; }
else if(counter<lolo)
{ sevr=MAJOR_ALARM; stat=LOLO_ALARM; }
else if(counter>high)
{ sevr=MINOR_ALARM; stat=HIGH_ALARM; }
else if(counter<low)
{ sevr=MINOR_ALARM; stat=LOW_ALARM; }
else
{ sevr=NO_ALARM; stat=0; }
if(node) node->eventReady();
}
int main(int argc, char* argv[])
{
gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();
int rc;
int total_pv;
double rate;
serv* server;
char* name;
if(argc<3)
{
fprintf(stderr,"Usage %s pv_total monitor_rate optional_pv_prefix\n",
argv[0]);
fprintf(stderr," pv_total is the number of PVs to generate (int)\n");
fprintf(stderr," monitor_rate is events per second (float)\n");
fprintf(stderr," optional_pv_prefix defaults to your login name\n");
fprintf(stderr,"\n");
fprintf(stderr," PVs are named <PREFIX>_#\n");
fprintf(stderr," where # is an integer is the range [0,pv_total)\n");
return -1;
}
if(sscanf(argv[1],"%d",&total_pv)!=1)
{
fprintf(stderr,"Failed to convert pv_total argument to number\n");
return -1;
}
if(sscanf(argv[2],"%lf",&rate)!=1)
{
fprintf(stderr,"Failed to convert monitor_rate argument to number\n");
return -1;
}
if(argc<=4)
name=argv[3];
else
name=NULL;
appValue=table.getApplicationType("value");
Debug3("total=%d,rate=%lf,prefix=%s\n",total_pv,rate,name);
server = new serv(total_pv,rate,name,total_pv);
rc=server->Main();
delete server;
return rc;
}
int serv::InitDB(void)
{
unsigned i;
db_sync=new dBase[pv_total];
for(i=0;i<pv_total;i++)
sprintf(db_sync[i].pvname,"%s_%d",prefix,i);
return 0;
}
int serv::Main(void)
{
int not_done=1;
if (event_rate>0) {
Debug1("Update every %f sec\n", inv);
double inv=(1.0/event_rate);
pScanTimer = new scanTimer (inv, *this);
}
while(not_done)
{
osiTime delay(10.0);
fileDescriptorManager.process(delay);
}
return 0;
}
// ------------------------- server stuff ----------------------------
serv::serv(int tot,double rate,char* name,unsigned pv_count_est):
caServer(pv_count_est),
db_sync(NULL),pv_total(tot),event_rate(rate),prefix(name),
pScanTimer(NULL)
{
event_mask|=(alarmEventMask|valueEventMask|logEventMask);
if(name)
prefix=name;
else if((prefix=getenv("LOGNAME"))==NULL)
prefix="noname";
prefix_len=strlen(prefix);
InitDB();
}
serv::~serv(void)
{
delete [] db_sync;
if (pScanTimer) delete pScanTimer;
}
pvExistReturn serv::pvExistTest(const casCtx&,const char* pvname)
{
int val;
dBase* node=NULL;
pvExistReturnEnum rc=pverDoesNotExistHere;
if(strncmp(pvname,prefix,prefix_len)==0)
{
// we may have this one, number is after underscore
if(sscanf(&pvname[prefix_len+1],"%d",&val)==1)
{
if(val>=0 && val<pv_total)
{
Debug("ExistTest: I have this PV\n");
node=&db_sync[val];
rc=pverExistsHere;
}
}
}
return pvExistReturn(rc);
}
pvAttachReturn serv::pvAttach(const casCtx& in,const char* pvname)
{
casPV* pPV=NULL;
int val;
Debug1("pvAttach: %s\n",pvname);
if(strncmp(pvname,prefix,prefix_len)==0)
{
// we may have this one, number is after underscore
if(sscanf(&pvname[prefix_len+1],"%d",&val)==1)
{
Debug("pvAttach: I am making this PV\n");
if(val>=0 && val<pv_total)
pPV=new servPV(*this,pvname,db_sync[val]);
}
}
if (pPV) {
return pvAttachReturn(*pPV);
}
else {
return pvAttachReturn(S_casApp_pvNotFound);
}
}
void serv::scan(void)
{
unsigned i;
for(i=0;i<pv_total;i++)
db_sync[i].eventReady();
}
// -----------------------PV stuff -------------------------------
servPV::servPV(serv& m,const char* n,dBase& x):
casPV(m),db(x),mgr(m),monitored(0)
{
db.node=this;
value=new gddScalar(appValue,aitEnumFloat64);
pName=new char [strlen(n)+1];
assert(pName);
strcpy(pName,n);
}
servPV::~servPV(void)
{
value->unreference();
db.node=NULL;
delete [] pName;
}
caStatus servPV::interestRegister()
{
if(!monitored) monitored=1;
return S_casApp_success;
}
void servPV::interestDelete()
{
if(monitored) monitored=0;
}
aitEnum servPV::bestExternalType() const
{
return aitEnumFloat64;
}
const char *servPV::getName() const
{
return pName;
}
caStatus servPV::read(const casCtx&, gdd &dd)
{
Debug1("read: %s\n",db.pvname);
gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();
// this is a cheesy way to do this
value->put(db.counter);
value->setStatSevr(db.stat,db.sevr);
value->setTimeStamp(&db.ts);
table.smartCopy(&dd,value);
return S_casApp_success;
}
caStatus servPV::write(const casCtx&, gdd &dd)
{
Debug1("write: %s\n",db.pvname);
gddApplicationTypeTable& table=gddApplicationTypeTable::AppTable();
// this is also cheesy
table.smartCopy(value,&dd);
db.writeData((double)*value);
return S_casApp_success;
}
void servPV::destroy()
{
casPV::destroy();
}
void servPV::eventReady(void)
{
value->put(db.counter);
value->setStatSevr(db.stat,db.sevr);
value->setTimeStamp(&db.ts);
postEvent(mgr.event_mask,*value);
}
//
// scanTimer::expire ()
//
void scanTimer::expire ( const epicsTime & currentTime )
{
serv.scan();
}
//
// scanTimer::again()
//
osiBool scanTimer::again() const
{
return osiTrue;
}
//
// scanTimer::delay()
//
const osiTime scanTimer::delay() const
{
return period;
}
-121
View File
@@ -1,121 +0,0 @@
/*
* $Id$
* $Log$
* Revision 1.4 1998/12/19 00:04:48 jhill
* renamed createPV() to pvAttach()
*
* Revision 1.3 1997/06/13 09:15:48 jhill
* connect proto changes
*
* Revision 1.2 1997/03/05 21:16:23 jbk
* Fixes cvs log id at top
*
*/
#include "casdef.h"
#include "osiTimer.h"
class gdd;
class servPV;
#ifdef PVDEBUG
#define Debug(str) { fprintf(stderr,str); }
#define Debug1(str,val) { fprintf(stderr,str,val); }
#define Debug2(str,val1,val2) { fprintf(stderr,str,val1,val2); }
#define Debug3(str,val1,val2,val3) { fprintf(stderr,str,val1,val2,val3); }
#else
#define Debug(str) ;
#define Debug1(str,val) ;
#define Debug2(str,val1,val2) ;
#define Debug3(str,val1,val2,val3) ;
#endif
class dBase
{
public:
dBase(void)
{
pvname[0]='\0';counter=0;
hihi=90.0;high=80.0;low=20.0;lolo=10.0;
ts.tv_sec=0; ts.tv_nsec=0;
stat=0; sevr=0;
node=NULL;
}
void eventReady(void);
void writeData(double);
char pvname[50];
double counter;
double hihi,high,low,lolo;
aitTimeStamp ts;
aitInt16 stat,sevr;
servPV* node;
};
class serv;
//
// scanTimer
//
class scanTimer : public osiTimer {
public:
scanTimer (double delayIn, serv &servIn) :
osiTimer(delayIn), serv(servIn),
period(delayIn) {}
private:
serv &serv;
double period;
void expire ( const epicsTime & currentTime );
};
class serv : public caServer
{
public:
serv(int totpv,double rate,char* prefix,unsigned pvtotalest);
virtual ~serv(void);
virtual pvExistReturn pvExistTest(const casCtx& c,const char* pvname);
virtual pvAttachReturn pvAttach(const casCtx& c,const char* pvname);
int InitDB(void);
int Main(void);
void scan();
// sloppy
char* prefix;
int prefix_len;
int pv_total;
double event_rate;
casEventMask event_mask;
dBase* db_sync;
scanTimer *pScanTimer;
};
class servPV : public casPV
{
public:
servPV(serv&,const char* pvname,dBase&);
virtual ~servPV(void);
virtual caStatus interestRegister(void);
virtual void interestDelete(void);
virtual aitEnum bestExternalType(void) const;
virtual caStatus read(const casCtx &ctx, gdd &prototype);
virtual caStatus write(const casCtx &ctx, gdd &value);
virtual void destroy(void);
virtual const char *getName() const;
void eventReady(void);
private:
serv& mgr;
dBase& db;
gdd* value;
int monitored;
char *pName;
};