+= connection status reporting (based on Jeff's suggestions plus timestamps for connection loss events)

This commit is contained in:
Ralph Lange
2004-09-23 15:47:57 +00:00
parent 889d8bc6c2
commit 6c12088e2a
3 changed files with 130 additions and 94 deletions

View File

@@ -27,6 +27,7 @@
#define VALID_DOUBLE_DIGITS 18 /* Max usable precision for a double */
static unsigned long reqElems = 0;
static int nConn = 0; /* Number of connected PVs */
static unsigned long eventMask = DBE_VALUE | DBE_ALARM; /* Event mask used */
@@ -91,82 +92,70 @@ void event_handler (evargs args)
}
}
/*+**************************************************************************
*
* Function: camonitor
* Function: connection_handler
*
* Description: Issue read requests, wait for incoming data
* and print the data according to the selected format
* Description: CA connection_handler
*
* Arg(s) In: pvs - Pointer to an array of pv structures
* nPvs - Number of elements in the pvs array
* reqElems - Requested number of (array) elements
*
* Return(s): Error code: 0 = OK, 1 = Error
* Arg(s) In: args - connection_handler_args (see CA manual)
*
**************************************************************************-*/
int camonitor (pv *pvs, int nPvs, unsigned long reqElems)
void connection_handler ( struct connection_handler_args args )
{
int n, result;
chtype dbrType;
for (n = 0; n < nPvs; n++) {
/* Set up pvs structure */
/* -------------------- */
pv *ppv = ( pv * ) ca_puser ( args.chid );
if ( args.op == CA_OP_CONN_UP ) {
int dbrType;
/* Set up pv structure */
/* ------------------- */
/* Get natural type and array count */
pvs[n].nElems = ca_element_count(pvs[n].chid);
pvs[n].dbfType = ca_field_type(pvs[n].chid);
ppv->nElems = ca_element_count(ppv->chid);
ppv->dbfType = ca_field_type(ppv->chid);
/* Set up value structures */
dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
if (dbr_type_is_ENUM(dbrType)) /* Enums honour -n option */
{
if (enumAsNr) dbrType = DBR_TIME_INT;
else dbrType = DBR_TIME_STRING;
}
/* Adjust array count */
if (reqElems == 0 || pvs[n].nElems < reqElems)
reqElems = pvs[n].nElems;
if (reqElems == 0 || ppv->nElems < reqElems)
reqElems = ppv->nElems;
/* Remember dbrType and reqElems */
pvs[n].dbrType = dbrType;
pvs[n].reqElems = reqElems;
ppv->dbrType = dbrType;
ppv->reqElems = reqElems;
nConn++;
/* Issue CA request */
/* ---------------- */
if (ca_state(pvs[n].chid) == cs_conn)
{
nConn++;
/* Allocate value structure */
pvs[n].value = calloc(1, dbr_size_n(dbrType, reqElems));
result = ca_create_subscription(dbrType,
reqElems,
pvs[n].chid,
eventMask,
event_handler,
(void*)&pvs[n],
NULL);
pvs[n].status = result;
} else {
pvs[n].status = ECA_DISCONN;
/* install monitor once with first connect */
if ( ! ppv->value ) {
/* Allocate value structure */
ppv->value = calloc(1, dbr_size_n(dbrType, reqElems));
if ( ppv->value ) {
ppv->status = ca_create_subscription(dbrType,
reqElems,
ppv->chid,
eventMask,
event_handler,
(void*)ppv,
NULL);
if ( ppv->status != ECA_NORMAL ) {
free ( ppv->value );
}
}
}
}
if (nConn)
/* Wait for callbacks */
/* ------------------ */
while (1) ca_pend_event(caTimeout);
else
return 1; /* No connection? We're done. */
else if ( args.op == CA_OP_CONN_DOWN ) {
nConn--;
ppv->status = ECA_DISCONN;
print_time_val_sts(ppv, ppv->reqElems);
}
}
/*+**************************************************************************
*
@@ -186,10 +175,10 @@ int camonitor (pv *pvs, int nPvs, unsigned long reqElems)
int main (int argc, char *argv[])
{
int returncode = 0;
int n = 0;
int result; /* CA result */
int count = 0; /* 0 = not specified by -# option */
int opt; /* getopt() current option */
int digits = 0; /* getopt() no. of float digits */
@@ -224,11 +213,11 @@ int main (int argc, char *argv[])
}
break;
case '#': /* Array count */
if (sscanf(optarg,"%d", &count) != 1)
if (sscanf(optarg,"%ld", &reqElems) != 1)
{
fprintf(stderr, "'%s' is not a valid array element count "
"- ignored. ('caget -h' for help.)\n", optarg);
count = 0;
reqElems = 0;
}
break;
case 'm': /* Select CA event mask */
@@ -316,14 +305,27 @@ int main (int argc, char *argv[])
}
/* Connect channels */
/* Copy PV names from command line */
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
{
pvs[n].name = argv[optind];
pvs[n].status = ECA_NEWCONN;
}
/* Create CA connections */
returncode = create_pvs(pvs, nPvs, connection_handler);
if ( returncode ) {
return returncode;
}
/* Check for channels that didn't connect */
ca_pend_event(caTimeout);
for (n = 0; n < nPvs; n++)
{
if (pvs[n].status == ECA_NEWCONN)
print_time_val_sts(&pvs[n], pvs[n].reqElems);
}
connect_pvs(pvs, nPvs);
/* Read and print data */
result = camonitor(pvs, nPvs, count);
/* Read and print data forever */
ca_pend_event(0);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -426,6 +426,7 @@ void print_time_val_sts (pv* pv, int nElems)
int i, printAbs;
void* value = pv->value;
epicsTimeStamp *ptsRef = &tsStart;
epicsTimeStamp tsNow;
if (!tsInit) /* Initialize start timestamp */
{
@@ -434,15 +435,20 @@ void print_time_val_sts (pv* pv, int nElems)
tsInit = 1;
}
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, &tsNow);
printf("%-30s ", pv->name);
if (pv->status == ECA_DISCONN)
printf("*** not connected\n");
if (pv->status == ECA_NEWCONN)
printf("*** Not connected (PV not found)\n");
else if (pv->status == ECA_DISCONN)
printf("%s *** disconnected\n", timeText);
else if (pv->status == ECA_NORDACCESS)
printf("*** no read access\n");
printf("%s *** no read access\n", timeText);
else if (pv->status != ECA_NORMAL)
printf("*** CA error %s\n", ca_message(pv->status));
printf("%s *** CA error %s\n", timeText, ca_message(pv->status));
else if (pv->value == 0)
printf("*** no data available (timeout)\n");
printf("%s *** no data available (timeout)\n", timeText);
else
switch (pv->dbrType) {
case DBR_TIME_STRING:
@@ -470,6 +476,48 @@ void print_time_val_sts (pv* pv, int nElems)
}
}
/*+**************************************************************************
*
* Function: create_pvs
*
* Description: Creates an arbitrary number of PVs
*
* Arg(s) In: pvs - Pointer to an array of pv structures
* nPvs - Number of elements in the pvs array
* pCB - Connection state change callback
*
* Arg(s) Out: none
*
* Return(s): Error code:
* 0 - All PVs created
* 1 - Some PV(s) not created
*
**************************************************************************-*/
int create_pvs (pv* pvs, int nPvs, caCh *pCB)
{
int n;
int result;
int returncode = 0;
/* Issue channel connections */
for (n = 0; n < nPvs; n++) {
result = ca_create_channel (pvs[n].name,
pCB,
&pvs[n],
CA_PRIORITY,
&pvs[n].chid);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
"to create channel '%s'.\n", ca_message(result), pvs[n].name);
pvs[n].status = result;
returncode = 1;
}
}
return returncode;
}
/*+**************************************************************************
*
@@ -490,36 +538,21 @@ void print_time_val_sts (pv* pv, int nElems)
int connect_pvs (pv* pvs, int nPvs)
{
int n;
int result;
int returncode = 0;
/* Issue channel connections */
for (n = 0; n < nPvs; n++) {
result = ca_create_channel (pvs[n].name,
0,
0,
CA_PRIORITY,
&pvs[n].chid);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
"to create channel '%s'.\n", ca_message(result), pvs[n].name);
pvs[n].status = result;
int returncode = create_pvs ( pvs, nPvs, 0);
if ( returncode == 0 ) {
/* Wait for channels to connect */
int result = ca_pend_io (caTimeout);
if (result == ECA_TIMEOUT)
{
if (nPvs > 1)
{
fprintf(stderr, "Channel connect timed out: some PV(s) not found.\n");
} else {
fprintf(stderr, "Channel connect timed out: '%s' not found.\n",
pvs[0].name);
}
returncode = 1;
}
}
/* Wait for channels to connect */
result = ca_pend_io (caTimeout);
if (result == ECA_TIMEOUT)
{
if (nPvs > 1)
{
fprintf(stderr, "Channel connect timed out: some PV(s) not found.\n");
} else {
fprintf(stderr, "Channel connect timed out: '%s' not found.\n",
pvs[0].name);
}
returncode = 1;
}
return returncode;
}

View File

@@ -80,7 +80,8 @@ extern char dblFormatStr[]; /* Format string to print doubles (see -e -f option)
extern char *val2str (const void *v, unsigned type, int index);
extern char *dbr2str (const void *value, unsigned type);
extern void print_time_val_sts (pv *pv, int nElems);
extern int connect_pvs (pv *pvs, int nPvs);
extern int create_pvs (pv *pvs, int nPvs, caCh *pCB );
extern int connect_pvs (pv *pvs, int nPvs );
/*
* no additions below this endif