Integrating change by Malcolm Waters: += put_callback option - heavily based on caget

This commit is contained in:
Ralph Lange
2006-02-06 16:04:55 +00:00
parent 4074b45a30
commit d6b6955903

View File

@@ -1,4 +1,5 @@
/*************************************************************************\
* Copyright (c) 2006 Diamond Light Source Ltd.
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
@@ -14,6 +15,10 @@
*
* Author: Ralph Lange (BESSY)
*
* Modification History
* 2006/01/17 Malcolm Walters (Tessella/Diamond Light Source)
* Added put_callback option Heavily based on caput
*
*/
#include <stdio.h>
@@ -26,16 +31,20 @@
#include "tool_lib.h"
#define VALID_DOUBLE_DIGITS 18 /* Max usable precision for a double */
#define PEND_EVENT_SLICES 5 /* No. of pend_event slices for callback requests */
/* Different output formats */
typedef enum { plain, terse } OutputT;
typedef enum { plain, terse, all } OutputT;
/* Different request types */
typedef enum { get, callback } RequestT;
/* Valid EPICS string */
typedef char EpicsStr[MAX_STRING_SIZE];
static int nConn = 0; /* Number of connected PVs */
static int nDone = 0; /* Number of callbacks done */
void usage (void)
{
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value>\n"
@@ -43,8 +52,10 @@ void usage (void)
" -h: Help: Print this message\n"
"Channel Access options:\n"
" -w <sec>: Wait time, specifies longer CA timeout, default is %f second\n"
" -c: Use put_callback to wait for completion\n"
"Format options:\n"
" -t: Terse mode - print only sucessfully written value, without name\n"
" -l: Long mode \"name timestamp value stat sevr\" (read PVs as DBR_TIME_xxx)\n"
"Enum format:\n"
" Default: Auto - try value as ENUM string, then as index number\n"
" -n: Force interpretation of values as numbers\n"
@@ -57,6 +68,27 @@ void usage (void)
, DEFAULT_TIMEOUT);
}
/*+**************************************************************************
*
* Function: put_event_handler
*
* Description: CA event_handler for request type callback
* Sets status flags and marks as done.
*
* Arg(s) In: args - event handler args (see CA manual)
*
**************************************************************************-*/
void put_event_handler ( struct event_handler_args args )
{
/* Retrieve pv from event handler structure */
pv* pPv = args.usr;
/* Set done count and store status*/
nDone++;
pPv->status = args.status;
}
/*+**************************************************************************
@@ -92,11 +124,11 @@ int caget (pv *pvs, int nPvs, OutputT format,
pvs[n].dbfType = ca_field_type(pvs[n].chid);
/* Set up value structures */
dbrType = dbf_type_to_DBR(pvs[n].dbfType); /* Use native type */
dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */
if (dbr_type_is_ENUM(dbrType)) /* Enums honour -n option */
{
if (enumAsNr) dbrType = DBR_INT;
else dbrType = DBR_STRING;
if (enumAsNr) dbrType = DBR_TIME_INT;
else dbrType = DBR_TIME_STRING;
}
/* Adjust array count */
@@ -112,6 +144,7 @@ int caget (pv *pvs, int nPvs, OutputT format,
if (ca_state(pvs[n].chid) == cs_conn)
{
nConn++;
pvs[n].onceConnected = 1;
/* Allocate value structure */
pvs[n].value = calloc(1, dbr_size_n(dbrType, reqElems));
result = ca_array_get(dbrType,
@@ -159,6 +192,9 @@ int caget (pv *pvs, int nPvs, OutputT format,
printf("\n");
}
break;
case all:
print_time_val_sts(&pvs[n], reqElems);
break;
default :
break;
}
@@ -190,6 +226,7 @@ int main (int argc, char *argv[])
int i;
int result; /* CA result */
OutputT format = plain; /* User specified format */
RequestT request = get; /* User specified request type */
int isArray = 0; /* Flag for array operation */
int enumAsString = 0; /* Force ENUM values to be strings */
@@ -210,7 +247,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
while ((opt = getopt(argc, argv, ":nhats#:w:")) != -1) {
while ((opt = getopt(argc, argv, ":cnlhats#:w:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -226,9 +263,15 @@ int main (int argc, char *argv[])
case 't': /* Select terse output format */
format = terse;
break;
case 'l': /* Select long output format */
format = all;
break;
case 'a': /* Select array mode */
isArray = 1;
break;
case 'c': /* Select put_callback mode */
request = callback;
break;
case 'w': /* Set CA timeout value */
if(epicsScanDouble(optarg, &caTimeout) != 1)
{
@@ -408,7 +451,7 @@ int main (int argc, char *argv[])
}
/* Read and print old data */
if (format == plain) {
if (format != terse) {
printf("Old : ");
result = caget(pvs, nPvs, format, 0, count);
}
@@ -418,15 +461,49 @@ int main (int argc, char *argv[])
if (dbrType == DBR_STRING) pbuf = sbuf;
else pbuf = dbuf;
result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
if (request == callback) {
/* Use callback version of put */
pvs[0].status = ECA_NORMAL; /* All ok at the moment */
result = ca_array_put_callback (dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *)pvs);
} else {
/* Use standard put with defined timeout */
result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
}
result = ca_pend_io(caTimeout);
if (result == ECA_TIMEOUT) {
fprintf(stderr, "Write operation timed out: Data was not written.\n");
return 1;
}
if (request == callback) /* Also wait for callbacks */
{
nDone = 0; /* Not done yet */
if (caTimeout != 0){
double slice = caTimeout / PEND_EVENT_SLICES;
for (n = 0; n < PEND_EVENT_SLICES; n++)
{
ca_pend_event(slice);
if (nDone == 1) break; /* Have done, therefore break */
}
} else {
while (nDone == 0){
ca_pend_event(1);
}
}
if (nDone != 1)
fprintf(stderr, "Write callback operation timed out.\n");
/* retrieve status from callback */
result=pvs[0].status;
}
if ( result != ECA_NORMAL ) {
fprintf(stderr, "Error occured writing data.\n");
return 1;
}
/* Read and print new data */
if (format == plain)
if (format != terse)
printf("New : ");
result = caget(pvs, nPvs, format, 0, count);