Merged Michael Abbott's dynamic-array branch, rebased.
I added Perl support, and wrote some release notes.
This commit is contained in:
@@ -12,6 +12,33 @@
|
||||
<h2 align="center">Changes between 3.14.11 and 3.14.12</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h4>Dynamic arrays over CA</h4>
|
||||
|
||||
<p>Dymanic array sizing was developed by Michael Abbott at the 2010 EPICS
|
||||
Codeathon. It permits a CA client to fetch only the currently valid elements of
|
||||
an array by specifying a COUNT of zero to either of the ca_array_get_callback()
|
||||
or ca_create_subscription() routines. It has never before been legal to pass a
|
||||
COUNT of zero to the ca_array_get_callback() routine, but this development does
|
||||
introduce a subtle change to the published API of the ca_create_subscription()
|
||||
routine.</p>
|
||||
|
||||
<p>In previous releases a COUNT of zero for a subscription meant use the
|
||||
ca_element_count() for the channel, but from this release it can return fewer
|
||||
elements (never more), at the behest of the server. The number of elements can
|
||||
vary with subsequent array update events, so a client that uses this technique
|
||||
must use the count field of the event_handler_args in its callback function each
|
||||
time it is called to obtain the correct element count from the server. Note that
|
||||
the ca_element_count() value for a channel is only updated at connection time,
|
||||
and supplies the maximum number of elements that the server array variable can
|
||||
hold.</p>
|
||||
|
||||
<p>Dynamic arrays are currently only supported by the CA client library and IOC
|
||||
server RSRV, the Perl CA library and the catools programs. The portable CAS does
|
||||
not understand them, and database links that connect over CA do not attempt to
|
||||
use them either. CA clients that try to use this functionality with a server
|
||||
that does not support it will receive the same full-sized zero-filled arrays
|
||||
that previous releases supported.</p>
|
||||
|
||||
<h4>CA over TCP connections</h4>
|
||||
|
||||
<p>Merged the CA-over-TCP changes developed by Ralph and Jeff at the 2008 EPICS
|
||||
|
||||
@@ -2297,11 +2297,11 @@ ca_put_callback, ca_get_callback, and ca_add_event all request notification of
|
||||
asynchronous completion via this mechanism. The <code>event_handler_args
|
||||
</code>structure is passed <em>by value</em> to the application supplied
|
||||
callback. In this structure the <code>dbr</code> field is a void pointer to any
|
||||
data that might be returned. The <code>s</code><code>tatus </code>field will be
|
||||
data that might be returned. The <code>status</code> field will be
|
||||
set to one of the CA error codes in caerr.h and will indicate the status of the
|
||||
operation performed in the IOC. If the status field isn't set to ECA_NORMAL or
|
||||
data isn't normally returned from the operation (i.e. put call back) then you
|
||||
should expect that the <code>dbr </code>field will be set to a nill pointer
|
||||
should expect that the <code>dbr</code> field will be set to a nill pointer
|
||||
(zero). The fields <code>usr</code>, <code>chid</code>, and <code>type</code>
|
||||
are set to the values specified when the request was made by the application.
|
||||
The "dbr" pointer, and any data that it points to, are valid only when
|
||||
@@ -2352,8 +2352,8 @@ library functions that request them.</p>
|
||||
<p>For routines that require an argument specifying the number of array
|
||||
elements, no more than the process variable's maximum native element count may
|
||||
be requested. The process variable's maximum native element count is available
|
||||
from ca_element_count() when the channel is connected. If less elements than
|
||||
the process variable's native element count are requested the requested values
|
||||
from ca_element_count() when the channel is connected. If fewer elements than
|
||||
the process variable's native element count are requested, the requested values
|
||||
will be fetched beginning at element zero. By default CA limits the number of
|
||||
elements in an array to be no more than approximately 16k divided by the size
|
||||
of one element in the array. Starting with EPICS R3.14 the maximum array size
|
||||
@@ -2381,12 +2381,12 @@ href="#ca_create_channel">ca_create_channel</a></code>. The <code><a
|
||||
href="#ca_pend_io">ca_pend_io</a></code> approach is best suited to simple
|
||||
command line programs with short runtime duration, and the connection callback
|
||||
method is best suited to toolkit components with long runtime duration. Use of
|
||||
<code><a href="#ca_state">ca_state</a> </code>is appropriate only in programs
|
||||
<code><a href="#ca_state">ca_state</a></code> is appropriate only in programs
|
||||
that prefer to poll for connection state changes instead of opting for
|
||||
asynchronous notification. The <code>ca_pend_io</code> function blocks only for
|
||||
channels created specifying a nill connection handler callback function. The
|
||||
user's connection state change function will be run immediately from within
|
||||
<code><a href="#ca_create_channel">ca_create_channel</a> </code>if the CA
|
||||
<code><a href="#ca_create_channel">ca_create_channel</a></code> if the CA
|
||||
client and CA server are both hosted within the same address space (within the
|
||||
same process).</p>
|
||||
|
||||
@@ -2709,9 +2709,9 @@ time.</p>
|
||||
<p>The following structure is passed <em>by value </em>to the user's
|
||||
connection connection callback function. The <code>op</code> field will
|
||||
be set by the CA client library to <code>CA_OP_CONN_UP</code> when the
|
||||
channel connects, and to <code>CA_OP_CONN_DOWN </code>when the channel
|
||||
channel connects, and to <code>CA_OP_CONN_DOWN</code> when the channel
|
||||
disconnects. See <code><a href="#ca_puser">ca_puser</a></code> if the
|
||||
<code>PUSER </code>argument is required in your callback
|
||||
<code>PUSER</code> argument is required in your callback
|
||||
handler<code>.</code></p>
|
||||
<pre>struct ca_connection_handler_args {
|
||||
chanId chid; /* channel id */
|
||||
@@ -2973,7 +2973,8 @@ when a CA get request is initiated.</p>
|
||||
<dl>
|
||||
<dt><code>COUNT</code></dt>
|
||||
<dd>Element count to be read from the specified channel. Must match the
|
||||
array pointed to by PVALUE.</dd>
|
||||
array pointed to by PVALUE. For ca_array_get_callback a count of zero
|
||||
means use the current element count from the server.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
@@ -3081,7 +3082,7 @@ indicating the current state of the channel.</p>
|
||||
<dl>
|
||||
<dt><code>COUNT</code></dt>
|
||||
<dd>The element count to be read from the specified channel. A count of
|
||||
zero specifies the native elemnt count.</dd>
|
||||
zero means use the current element count from the server.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
@@ -3391,7 +3392,7 @@ field should not be used.</p>
|
||||
<dd>Address of user callback function to be executed when an exceptions
|
||||
occur. Passing a nil value causes the default exception handler to be
|
||||
reinstalled. The following structure is passed by value to the user's
|
||||
callback function. Currently, the <code>op </code>field can be one of
|
||||
callback function. Currently, the <code>op</code> field can be one of
|
||||
<code>CA_OP_GET, CA_OP_PUT, CA_OP_CREATE_CHANNEL, CA_OP_ADD_EVENT,
|
||||
CA_OP_CLEAR_EVENT, or CA_OP_OTHER.</code>
|
||||
<pre>struct exception_handler_args {
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
|
||||
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
|
||||
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
|
||||
# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
|
||||
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
|
||||
# define CA_V41(MINOR) ( 1u )
|
||||
# define CA_V42(MINOR) ( 1u )
|
||||
@@ -54,6 +55,7 @@
|
||||
# define CA_V410(MINOR) ( 1u )
|
||||
# define CA_V411(MINOR) ( 1u )
|
||||
# define CA_V412(MINOR) ( 1u )
|
||||
# define CA_V413(MINOR) ( 1u )
|
||||
#else
|
||||
# define CA_V41(MINOR) ( 0u )
|
||||
# define CA_V42(MINOR) ( 0u )
|
||||
@@ -67,6 +69,7 @@
|
||||
# define CA_V410(MINOR) ( 0u )
|
||||
# define CA_V411(MINOR) ( 0u )
|
||||
# define CA_V412(MINOR) ( 0u )
|
||||
# define CA_V413(MINOR) ( 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -524,16 +524,16 @@ struct dbr_ctrl_double{
|
||||
dbr_double_t value; /* current value */
|
||||
};
|
||||
|
||||
#ifndef db_accessHFORdb_accessC
|
||||
#define dbr_size_n(TYPE,COUNT)\
|
||||
((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))
|
||||
|
||||
/* size for each type - array indexed by the DBR_ type code */
|
||||
epicsShareExtern const unsigned short dbr_size[LAST_BUFFER_TYPE+1];
|
||||
epicsShareExtern const unsigned short dbr_size[];
|
||||
|
||||
/* size for each type's value - array indexed by the DBR_ type code */
|
||||
epicsShareExtern const unsigned short dbr_value_size[LAST_BUFFER_TYPE+1];
|
||||
epicsShareExtern const unsigned short dbr_value_size[];
|
||||
|
||||
#ifndef db_accessHFORdb_accessC
|
||||
/* class for each type's value */
|
||||
enum dbr_value_class {
|
||||
dbr_class_int,
|
||||
|
||||
@@ -291,9 +291,6 @@ cacChannel::ioStatus nciu::read (
|
||||
if ( countIn > this->count ) {
|
||||
throw cacChannel::outOfBounds ();
|
||||
}
|
||||
if ( countIn == 0 ) {
|
||||
countIn = this->count;
|
||||
}
|
||||
|
||||
//
|
||||
// fail out if their arguments are invalid
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#define CA_MINOR_PROTOCOL_REVISION 12
|
||||
#define CA_MINOR_PROTOCOL_REVISION 13
|
||||
#include "caProto.h"
|
||||
|
||||
#include "cacIO.h"
|
||||
@@ -205,6 +205,7 @@ public:
|
||||
void disconnectAllIO (
|
||||
epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & );
|
||||
bool connected ( epicsGuard < epicsMutex > & ) const;
|
||||
unsigned getcount() const { return count; }
|
||||
|
||||
private:
|
||||
tsDLList < class baseNMIU > eventq;
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
arrayElementCount getCount (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
epicsGuard < epicsMutex > &, bool allow_zero ) const;
|
||||
unsigned getType (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
unsigned getMask (
|
||||
@@ -242,11 +242,11 @@ inline netSubscription * netSubscription::factory (
|
||||
}
|
||||
|
||||
inline arrayElementCount netSubscription::getCount (
|
||||
epicsGuard < epicsMutex > & guard ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361
|
||||
{
|
||||
//guard.assertIdenticalMutex ( this->mutex );
|
||||
arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );
|
||||
if ( this->count == 0u || this->count > nativeCount ) {
|
||||
if ( (this->count == 0u && !allow_zero) || this->count > nativeCount ) {
|
||||
return nativeCount;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -280,6 +280,9 @@ int epicsShareAPI ca_array_get ( chtype type,
|
||||
if ( type < 0 ) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
if ( count == 0 )
|
||||
return ECA_BADCOUNT;
|
||||
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
|
||||
@@ -1464,6 +1464,8 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
if ( nElem > maxElem ) {
|
||||
throw cacChannel::msgBodyCacheTooSmall ();
|
||||
}
|
||||
if (nElem == 0 && !CA_V413(this->minorProtocolVersion))
|
||||
nElem = chan.getcount();
|
||||
comQueSendMsgMinder minder ( this->sendQue, guard );
|
||||
this->sendQue.insertRequestHeader (
|
||||
CA_PROTO_READ_NOTIFY, 0u,
|
||||
@@ -1559,7 +1561,8 @@ void tcpiiu::subscriptionRequest (
|
||||
if ( mask > 0xffff ) {
|
||||
throw cacChannel::badEventSelection ();
|
||||
}
|
||||
arrayElementCount nElem = subscr.getCount ( guard );
|
||||
arrayElementCount nElem = subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) );
|
||||
arrayElementCount maxBytes;
|
||||
if ( CA_V49 ( this->minorProtocolVersion ) ) {
|
||||
maxBytes = this->cacRef.largeBufferSizeTCP ();
|
||||
@@ -1605,7 +1608,8 @@ void tcpiiu::subscriptionUpdateRequest (
|
||||
if ( this->state != iiucs_connected ) {
|
||||
return;
|
||||
}
|
||||
arrayElementCount nElem = subscr.getCount ( guard );
|
||||
arrayElementCount nElem = subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) );
|
||||
arrayElementCount maxBytes;
|
||||
if ( CA_V49 ( this->minorProtocolVersion ) ) {
|
||||
maxBytes = this->cacRef.largeBufferSizeTCP ();
|
||||
@@ -1643,7 +1647,8 @@ void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard, // X
|
||||
this->sendQue.insertRequestHeader (
|
||||
CA_PROTO_EVENT_CANCEL, 0u,
|
||||
static_cast < ca_uint16_t > ( subscr.getType ( guard ) ),
|
||||
static_cast < ca_uint16_t > ( subscr.getCount ( guard ) ),
|
||||
static_cast < ca_uint16_t > ( subscr.getCount (
|
||||
guard, CA_V413(this->minorProtocolVersion) ) ),
|
||||
chan.getSID(guard), subscr.getId(),
|
||||
CA_V49 ( this->minorProtocolVersion ) );
|
||||
minder.commit ();
|
||||
|
||||
@@ -210,8 +210,9 @@ data type requested will be the widened form of the channel's native type
|
||||
fetch all available elements.
|
||||
|
||||
The element count can be overridden by providing an integer argument in the
|
||||
range 1 .. C<element_count>. Note that the count argument must be an integer;
|
||||
add 0 to it if it is necessary to convert it from a string.
|
||||
range 0 .. C<element_count>, where zero means use the current length from the
|
||||
server. Note that the count argument must be an integer; add 0 to it if it is
|
||||
necessary to convert it from a string.
|
||||
The optional data type I<TYPE> should be a string naming
|
||||
the desired C<DBR_xxx_yyy> type; the actual type used will have the C<yyy> part
|
||||
widened to one of C<STRING>, C<CHAR>, C<LONG> or C<DOUBLE>. The valid type
|
||||
|
||||
@@ -782,7 +782,7 @@ void CA_get(SV *ca_ref) {
|
||||
New(0, pch->sdata, count + 1, char);
|
||||
pch->ssize = count;
|
||||
}
|
||||
status = ca_array_get(DBF_CHAR, count, pch->chan, pch->sdata);
|
||||
status = ca_array_get(DBF_CHAR, 0, pch->chan, pch->sdata);
|
||||
} else {
|
||||
status = ca_get(best_type(pch), pch->chan, &pch->data);
|
||||
}
|
||||
@@ -818,16 +818,16 @@ void CA_get_callback(SV *ca_ref, SV *sub, ...) {
|
||||
SV *get_sub = newSVsv(sub);
|
||||
int status;
|
||||
chtype type = best_type(pch);
|
||||
int count = ca_element_count(pch->chan);
|
||||
int count = 0;
|
||||
int i = 2;
|
||||
const char *croak_msg;
|
||||
|
||||
while (items > i
|
||||
&& SvOK(ST(i))) {
|
||||
if (SvIOK(ST(i))) {
|
||||
/* Interger => Count arg */
|
||||
/* Interger => Count arg, zero means current size */
|
||||
count = SvIV(ST(i));
|
||||
if (count < 1 || count > ca_element_count(pch->chan)) {
|
||||
if (count < 0 || count > ca_element_count(pch->chan)) {
|
||||
croak_msg = "Requested array size is out of range";
|
||||
goto exit_croak;
|
||||
}
|
||||
@@ -901,7 +901,7 @@ SV * CA_create_subscription(SV *ca_ref, const char *mask_str, SV *sub, ...) {
|
||||
while (items > i
|
||||
&& SvOK(ST(i))) {
|
||||
if (SvIOK(ST(i))) {
|
||||
/* Interger => Count arg, zero means native size */
|
||||
/* Interger => Count arg, zero means current size */
|
||||
count = SvIV(ST(i));
|
||||
if (count < 0 || count > ca_element_count(pch->chan)) {
|
||||
croak_msg = "Requested array size is out of range";
|
||||
|
||||
@@ -6,10 +6,12 @@ use FindBin qw($Bin);
|
||||
use lib "$Bin/../../lib/perl";
|
||||
|
||||
use Getopt::Std;
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
use CA;
|
||||
|
||||
our ($opt_0, $opt_a, $opt_c, $opt_d, $opt_e, $opt_f, $opt_g, $opt_h, $opt_n);
|
||||
our ($opt_0, $opt_a, $opt_d, $opt_e, $opt_f, $opt_g, $opt_h, $opt_n);
|
||||
our ($opt_s, $opt_S, $opt_t);
|
||||
our $opt_c = 0;
|
||||
our $opt_F = ' ';
|
||||
our $opt_w = 1;
|
||||
|
||||
@@ -18,6 +20,9 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "caget: -c option takes a positive number\n"
|
||||
unless looks_like_number($opt_c) && $opt_c >= 0;
|
||||
|
||||
die "No pv name specified. ('caget -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
@@ -51,9 +56,7 @@ map {
|
||||
if $opt_a;
|
||||
}
|
||||
$rtype{$_} = $type;
|
||||
my $count = $_->element_count;
|
||||
$count = +$opt_c if $opt_c && $opt_c <= $count;
|
||||
$_->get_callback(\&get_callback, $type, $count);
|
||||
$_->get_callback(\&get_callback, $type, 0+$opt_c);
|
||||
} @chans;
|
||||
|
||||
my $incomplete = @chans;
|
||||
|
||||
@@ -6,9 +6,11 @@ use FindBin qw($Bin);
|
||||
use lib "$Bin/../../lib/perl";
|
||||
|
||||
use Getopt::Std;
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
use CA;
|
||||
|
||||
our ($opt_0, $opt_c, $opt_e, $opt_f, $opt_g, $opt_h, $opt_n, $opt_s, $opt_S);
|
||||
our ($opt_0, $opt_e, $opt_f, $opt_g, $opt_h, $opt_n, $opt_s, $opt_S);
|
||||
our $opt_c = 0;
|
||||
our $opt_F = ' ';
|
||||
our $opt_w = 1;
|
||||
our $opt_m = 'va';
|
||||
@@ -18,6 +20,9 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
|
||||
HELP_MESSAGE() if $opt_h;
|
||||
|
||||
die "caget: -c option takes a positive number\n"
|
||||
unless looks_like_number($opt_c) && $opt_c >= 0;
|
||||
|
||||
die "No pv name specified. ('camonitor -h' gives help.)\n"
|
||||
unless @ARGV;
|
||||
|
||||
@@ -45,11 +50,8 @@ sub conn_callback {
|
||||
|| (!$opt_S && $type eq 'DBR_CHAR');
|
||||
$type =~ s/^DBR_/DBR_TIME_/;
|
||||
|
||||
my $count = $chan->element_count;
|
||||
$count = +$opt_c if $opt_c && $opt_c <= $count;
|
||||
|
||||
$monitors{$chan} =
|
||||
$chan->create_subscription($opt_m, \&mon_callback, $type, $count);
|
||||
$chan->create_subscription($opt_m, \&mon_callback, $type, 0+$opt_c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ static void event_handler (evargs args)
|
||||
ppv->value = calloc(1, dbr_size_n(args.type, args.count));
|
||||
memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));
|
||||
ppv->onceConnected = 1;
|
||||
ppv->nElems = args.count;
|
||||
nRead++;
|
||||
}
|
||||
}
|
||||
@@ -183,11 +184,9 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
}
|
||||
}
|
||||
/* Adjust array count */
|
||||
if (reqElems == 0 || pvs[n].nElems < reqElems){
|
||||
pvs[n].reqElems = pvs[n].nElems; /* Use full number of points */
|
||||
} else {
|
||||
pvs[n].reqElems = reqElems; /* Limit to specified number */
|
||||
}
|
||||
if (reqElems > pvs[n].nElems)
|
||||
reqElems = pvs[n].nElems;
|
||||
pvs[n].reqElems = reqElems;
|
||||
|
||||
/* Issue CA request */
|
||||
/* ---------------- */
|
||||
@@ -205,13 +204,13 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
(void*)&pvs[n]);
|
||||
} else {
|
||||
/* Allocate value structure */
|
||||
pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems));
|
||||
pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
|
||||
if(!pvs[n].value) {
|
||||
fprintf(stderr,"Allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
result = ca_array_get(pvs[n].dbrType,
|
||||
pvs[n].reqElems,
|
||||
pvs[n].nElems,
|
||||
pvs[n].chid,
|
||||
pvs[n].value);
|
||||
}
|
||||
@@ -253,10 +252,13 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
/* -------------- */
|
||||
|
||||
for (n = 0; n < nPvs; n++) {
|
||||
/* Truncate the data printed to what was requested. */
|
||||
if (pvs[n].reqElems != 0 && pvs[n].nElems > pvs[n].reqElems)
|
||||
pvs[n].nElems = pvs[n].reqElems;
|
||||
|
||||
switch (format) {
|
||||
case plain: /* Emulate old caget behaviour */
|
||||
if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
|
||||
if (pvs[n].nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
|
||||
else printf("%s", pvs[n].name);
|
||||
printf("%c", fieldSeparator);
|
||||
case terse:
|
||||
@@ -270,7 +272,7 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
printf("*** no data available (timeout)\n");
|
||||
else
|
||||
{
|
||||
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
|
||||
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) {
|
||||
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
|
||||
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
|
||||
char *d = calloc(dlen+1, sizeof(char));
|
||||
@@ -282,8 +284,8 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
fprintf(stderr,"Failed to allocate space for escaped string\n");
|
||||
}
|
||||
} else {
|
||||
if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator);
|
||||
for (i=0; i<pvs[n].reqElems; ++i) {
|
||||
if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].nElems, fieldSeparator);
|
||||
for (i=0; i<pvs[n].nElems; ++i) {
|
||||
if (i) printf ("%c", fieldSeparator);
|
||||
printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
|
||||
}
|
||||
@@ -315,8 +317,8 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
else {
|
||||
printf(" Element count: %lu\n"
|
||||
" Value: ",
|
||||
pvs[n].reqElems);
|
||||
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {
|
||||
pvs[n].nElems);
|
||||
if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) {
|
||||
dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
|
||||
int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
|
||||
char *d = calloc(dlen+1, sizeof(char));
|
||||
@@ -328,7 +330,7 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
fprintf(stderr,"Failed to allocate space for escaped string\n");
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<pvs[n].reqElems; ++i) {
|
||||
for (i=0; i<pvs[n].nElems; ++i) {
|
||||
if (i) printf ("%c", fieldSeparator);
|
||||
printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ static void event_handler (evargs args)
|
||||
if (args.status == ECA_NORMAL)
|
||||
{
|
||||
pv->dbrType = args.type;
|
||||
pv->nElems = args.count;
|
||||
memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));
|
||||
|
||||
print_time_val_sts(pv, reqElems);
|
||||
@@ -150,11 +151,9 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
ppv->dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
/* Adjust array count */
|
||||
if (reqElems == 0 || ppv->nElems < reqElems){
|
||||
ppv->reqElems = ppv->nElems; /* Use full number of points */
|
||||
} else {
|
||||
ppv->reqElems = reqElems; /* Limit to specified number */
|
||||
}
|
||||
if (reqElems > ppv->nElems)
|
||||
reqElems = ppv->nElems;
|
||||
ppv->reqElems = reqElems;
|
||||
|
||||
ppv->onceConnected = 1;
|
||||
nConn++;
|
||||
@@ -163,7 +162,7 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
/* install monitor once with first connect */
|
||||
if ( ! ppv->value ) {
|
||||
/* Allocate value structure */
|
||||
ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->reqElems));
|
||||
ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->nElems));
|
||||
if ( ppv->value ) {
|
||||
ppv->status = ca_create_subscription(ppv->dbrType,
|
||||
ppv->reqElems,
|
||||
|
||||
@@ -455,8 +455,8 @@ char *dbr2str (const void *value, unsigned type)
|
||||
printf("Failed to allocate for print_time_val_sts\n"); \
|
||||
} \
|
||||
} else { \
|
||||
if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->reqElems); \
|
||||
for (i=0; i<pv->reqElems; ++i) { \
|
||||
if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->nElems); \
|
||||
for (i=0; i<pv->nElems; ++i) { \
|
||||
printf("%c%s", fieldSeparator, val2str(value, TYPE_ENUM, i)); \
|
||||
} \
|
||||
} \
|
||||
@@ -492,7 +492,7 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
|
||||
tsInitS = 1;
|
||||
}
|
||||
|
||||
if (pv->reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
|
||||
if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
|
||||
else printf("%s", pv->name);
|
||||
printf("%c", fieldSeparator);
|
||||
if (!pv->onceConnected)
|
||||
|
||||
@@ -64,8 +64,8 @@ typedef struct
|
||||
chid chid;
|
||||
long dbfType;
|
||||
long dbrType;
|
||||
unsigned long nElems;
|
||||
unsigned long reqElems;
|
||||
unsigned long nElems; // True length of data in value
|
||||
unsigned long reqElems; // Requested length of data
|
||||
int status;
|
||||
void* value;
|
||||
epicsTimeStamp tsPreviousC;
|
||||
|
||||
@@ -148,95 +148,58 @@ int epicsShareAPI db_name_to_addr(const char *pname, struct dbAddr *paddr)
|
||||
|
||||
int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
int buffer_type, void *pbuffer, int no_elements, void *pfl)
|
||||
{
|
||||
long nRequest = no_elements;
|
||||
int result = db_get_field_and_count(
|
||||
paddr, buffer_type, pbuffer, &nRequest, pfl);
|
||||
if (nRequest < no_elements)
|
||||
/* If the database request returned fewer elements than requested then
|
||||
* fill out the remainder of the array with zeros. */
|
||||
memset(
|
||||
(char *)pbuffer + dbr_size_n(buffer_type, nRequest), 0,
|
||||
(no_elements - nRequest) * dbr_value_size[buffer_type]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Performs the work of the public db_get_field API, but also returns the number
|
||||
* of elements actually copied to the buffer. The caller is responsible for
|
||||
* zeroing the remaining part of the buffer. */
|
||||
int epicsShareAPI db_get_field_and_count(
|
||||
struct dbAddr *paddr, int buffer_type,
|
||||
void *pbuffer, long *nRequest, void *pfl)
|
||||
{
|
||||
long status;
|
||||
long options;
|
||||
long nRequest;
|
||||
long i;
|
||||
long zero = 0;
|
||||
|
||||
/* The order of the DBR* elements in the "new" structures below is
|
||||
/* The order of the DBR* elements in the "newSt" structures below is
|
||||
* very important and must correspond to the order of processing
|
||||
* in the dbAccess.c dbGet() and getOptions() routines.
|
||||
*/
|
||||
|
||||
switch(buffer_type) {
|
||||
case(oldDBR_STRING):
|
||||
{
|
||||
DBSTRING *pvalue = (DBSTRING *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_STRING, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_STRING, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
/* case(oldDBR_INT): */
|
||||
case(oldDBR_SHORT):
|
||||
{
|
||||
dbr_short_t *pvalue = (dbr_short_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_SHORT, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
case(oldDBR_FLOAT):
|
||||
{
|
||||
dbr_float_t *pvalue = (dbr_float_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_FLOAT, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
case(oldDBR_ENUM):
|
||||
{
|
||||
dbr_enum_t *pvalue = (dbr_enum_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_ENUM, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
case(oldDBR_CHAR):
|
||||
{
|
||||
dbr_char_t *pvalue = (dbr_char_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_CHAR, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
case(oldDBR_LONG):
|
||||
{
|
||||
dbr_long_t *pvalue = (dbr_long_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_LONG, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_LONG, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
case(oldDBR_DOUBLE):
|
||||
{
|
||||
dbr_double_t *pvalue = (dbr_double_t *)pbuffer;
|
||||
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &options, &nRequest,
|
||||
pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
}
|
||||
status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
|
||||
break;
|
||||
|
||||
case(oldDBR_STS_STRING):
|
||||
@@ -247,19 +210,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
DBSTRING *pvalue = (DBSTRING *)pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_STRING, pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
|
||||
status = dbGetField(paddr, DBR_STRING, pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
/* case(oldDBR_STS_INT): */
|
||||
@@ -269,19 +226,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_short_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
status = dbGetField(paddr, DBR_SHORT, &pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_STS_FLOAT):
|
||||
@@ -290,19 +241,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_float_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_STS_ENUM):
|
||||
@@ -311,19 +256,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_enum_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
status = dbGetField(paddr, DBR_ENUM, &pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_STS_CHAR):
|
||||
@@ -332,19 +271,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_char_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_STS_LONG):
|
||||
@@ -353,19 +286,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_long_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
status = dbGetField(paddr, DBR_LONG, &pold->value, &zero,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_STS_DOUBLE):
|
||||
@@ -374,19 +301,14 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
dbr_double_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -397,20 +319,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
DBSTRING *pvalue = (DBSTRING *)(pold->value);
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_STRING, pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
|
||||
status = dbGetField(paddr, DBR_STRING, pold->value, &options,
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
/* case(oldDBR_TIME_INT): */
|
||||
@@ -421,20 +338,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_short_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_TIME_FLOAT):
|
||||
@@ -444,20 +356,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_float_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_TIME_ENUM):
|
||||
@@ -467,20 +374,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_enum_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_TIME_CHAR):
|
||||
@@ -490,20 +392,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_char_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_CHAR, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_CHAR, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_CHAR, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_TIME_LONG):
|
||||
@@ -513,20 +410,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_long_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_TIME_DOUBLE):
|
||||
@@ -536,20 +428,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRstatus
|
||||
DBRtime
|
||||
} newSt;
|
||||
dbr_double_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_TIME;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->stamp = newSt.time; /* structure copy */
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -564,12 +451,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRgrLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_short_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -581,10 +465,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->lower_warning_limit = newSt.lower_warning_limit;
|
||||
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_GR_FLOAT):
|
||||
@@ -597,13 +479,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRgrDouble
|
||||
DBRalDouble
|
||||
} newSt;
|
||||
dbr_float_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
||||
DBR_AL_DOUBLE;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->precision = newSt.precision.dp;
|
||||
@@ -616,10 +495,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
|
||||
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
/* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */
|
||||
@@ -632,12 +509,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRgrLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_char_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -649,10 +523,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->lower_warning_limit = newSt.lower_warning_limit;
|
||||
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_GR_LONG):
|
||||
@@ -664,12 +536,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRgrLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_long_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -681,10 +550,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->lower_warning_limit = newSt.lower_warning_limit;
|
||||
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_GR_DOUBLE):
|
||||
@@ -697,13 +564,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRgrDouble
|
||||
DBRalDouble
|
||||
} newSt;
|
||||
dbr_double_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
||||
DBR_AL_DOUBLE;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->precision = newSt.precision.dp;
|
||||
@@ -716,10 +580,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->lower_warning_limit = newSt.lower_warning_limit;
|
||||
pold->lower_alarm_limit = newSt.lower_alarm_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -734,13 +596,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRctrlLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_short_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
||||
DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -754,10 +613,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
||||
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_CTRL_FLOAT):
|
||||
@@ -771,13 +628,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRctrlDouble
|
||||
DBRalDouble
|
||||
} newSt;
|
||||
dbr_float_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
||||
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->precision = newSt.precision.dp;
|
||||
@@ -792,10 +646,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit);
|
||||
pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit);
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_GR_ENUM):
|
||||
@@ -807,14 +659,11 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRenumStrs
|
||||
} newSt;
|
||||
short no_str;
|
||||
dbr_enum_t *pvalue = &pold->value;
|
||||
|
||||
memset(pold, '\0', sizeof(struct dbr_ctrl_enum));
|
||||
/* first get status and severity */
|
||||
options = DBR_STATUS | DBR_ENUM_STRS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
no_str = newSt.no_str;
|
||||
@@ -824,10 +673,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i]));
|
||||
/*now get values*/
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_CTRL_CHAR):
|
||||
@@ -840,13 +687,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRctrlLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_char_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
||||
DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -860,10 +704,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
||||
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_CTRL_LONG):
|
||||
@@ -876,13 +718,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRctrlLong
|
||||
DBRalLong
|
||||
} newSt;
|
||||
dbr_long_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
|
||||
DBR_AL_LONG;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
|
||||
@@ -896,10 +735,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
||||
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
case(oldDBR_CTRL_DOUBLE):
|
||||
@@ -913,13 +750,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
DBRctrlDouble
|
||||
DBRalDouble
|
||||
} newSt;
|
||||
dbr_double_t *pvalue = &pold->value;
|
||||
|
||||
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
|
||||
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->precision = newSt.precision.dp;
|
||||
@@ -934,10 +768,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
|
||||
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
|
||||
&nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
|
||||
nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -947,21 +779,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
|
||||
struct {
|
||||
DBRstatus
|
||||
} newSt;
|
||||
DBSTRING *pvalue = (DBSTRING *)(pold->value);
|
||||
|
||||
options = DBR_STATUS;
|
||||
nRequest = 0;
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
|
||||
pfl);
|
||||
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &zero, pfl);
|
||||
pold->status = newSt.status;
|
||||
pold->severity = newSt.severity;
|
||||
pold->ackt = newSt.ackt;
|
||||
pold->acks = newSt.acks;
|
||||
options = 0;
|
||||
nRequest = no_elements;
|
||||
status = dbGetField(paddr, DBR_STRING, pold->value,
|
||||
&options, &nRequest, pfl);
|
||||
for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
|
||||
&options, nRequest, pfl);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ epicsShareFunc int epicsShareAPI db_put_field(
|
||||
DBADDR *paddr, int src_type,const void *psrc, int no_elements);
|
||||
epicsShareFunc int epicsShareAPI db_get_field(
|
||||
DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl);
|
||||
epicsShareFunc int db_get_field_and_count(
|
||||
struct dbAddr *paddr, int buffer_type,
|
||||
void *pbuffer, long *nRequest, void *pfl);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -507,6 +507,9 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
const int readAccess = asCheckGet ( pciu->asClientPVT );
|
||||
int status;
|
||||
int v41;
|
||||
int autosize;
|
||||
long item_count;
|
||||
ca_uint32_t payload_size;
|
||||
|
||||
SEND_LOCK ( pClient );
|
||||
|
||||
@@ -528,12 +531,21 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
cid = pciu->cid;
|
||||
}
|
||||
|
||||
status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size,
|
||||
pevext->msg.m_dataType, pevext->msg.m_count, cid, pevext->msg.m_available,
|
||||
/* If the client has requested a zero element count we interpret this as a
|
||||
* request for all avaiable elements. In this case we initialise the
|
||||
* header with the maximum element size specified by the database. */
|
||||
autosize = pevext->msg.m_count == 0;
|
||||
item_count =
|
||||
autosize ? paddr->no_elements : pevext->msg.m_count;
|
||||
payload_size = dbr_size_n(pevext->msg.m_dataType, item_count);
|
||||
status = cas_copy_in_header(
|
||||
pClient, pevext->msg.m_cmmd, payload_size,
|
||||
pevext->msg.m_dataType, item_count, cid, pevext->msg.m_available,
|
||||
&pPayload );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
send_err ( &pevext->msg, status, pClient,
|
||||
"server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u",
|
||||
"server unable to load read (or subscription update) response "
|
||||
"into protocol buffer PV=\"%s\" max bytes=%u",
|
||||
RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );
|
||||
if ( ! eventsRemaining )
|
||||
cas_send_bs_msg ( pClient, FALSE );
|
||||
@@ -552,8 +564,8 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
return;
|
||||
}
|
||||
|
||||
status = db_get_field ( paddr, pevext->msg.m_dataType,
|
||||
pPayload, pevext->msg.m_count, pfl);
|
||||
status = db_get_field_and_count(
|
||||
paddr, pevext->msg.m_dataType, pPayload, &item_count, pfl);
|
||||
if ( status < 0 ) {
|
||||
/*
|
||||
* I cant wait to redesign this protocol from scratch!
|
||||
@@ -567,58 +579,52 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* New clients recv the status of the
|
||||
* operation directly to the
|
||||
/* New clients recv the status of the operation directly to the
|
||||
* event/put/get callback.
|
||||
*
|
||||
* Fetched value is set to zero in case they
|
||||
* use it even when the status indicates
|
||||
* failure.
|
||||
* Fetched value is set to zero in case they use it even when the
|
||||
* status indicates failure -- unless the client selected autosizing
|
||||
* data, in which case they'd better know what they're doing!
|
||||
*
|
||||
* The m_cid field in the protocol
|
||||
* header is abused to carry the status
|
||||
*/
|
||||
memset ( pPayload, 0, pevext->size );
|
||||
* The m_cid field in the protocol header is abused to carry the
|
||||
* status */
|
||||
if (autosize) {
|
||||
payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
|
||||
cas_set_header_count(pClient, 0);
|
||||
}
|
||||
memset ( pPayload, 0, payload_size );
|
||||
cas_set_header_cid ( pClient, ECA_GETFAIL );
|
||||
cas_commit_msg ( pClient, pevext->size );
|
||||
cas_commit_msg ( pClient, payload_size );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ca_uint32_t payloadSize = pevext->size;
|
||||
int cacStatus = caNetConvert (
|
||||
pevext->msg.m_dataType, pPayload, pPayload,
|
||||
TRUE /* host -> net format */, pevext->msg.m_count );
|
||||
if ( cacStatus == ECA_NORMAL ) {
|
||||
/*
|
||||
* force string message size to be the true size rounded to even
|
||||
* boundary
|
||||
*/
|
||||
if ( pevext->msg.m_dataType == DBR_STRING
|
||||
&& pevext->msg.m_count == 1 ) {
|
||||
char * pStr = (char *) pPayload;
|
||||
size_t strcnt = strlen ( pStr );
|
||||
if ( strcnt < payloadSize ) {
|
||||
payloadSize = ( ca_uint32_t ) ( strcnt + 1u );
|
||||
}
|
||||
else {
|
||||
pStr[payloadSize-1] = '\0';
|
||||
errlogPrintf (
|
||||
"caserver: read_reply: detected DBR_STRING w/o nill termination "
|
||||
"in response from db_get_field, pPayload = \"%s\"\n",
|
||||
pStr );
|
||||
}
|
||||
TRUE /* host -> net format */, item_count );
|
||||
if ( cacStatus == ECA_NORMAL ) {
|
||||
ca_uint32_t data_size =
|
||||
dbr_size_n(pevext->msg.m_dataType, item_count);
|
||||
if (autosize) {
|
||||
payload_size = data_size;
|
||||
cas_set_header_count(pClient, item_count);
|
||||
}
|
||||
else if (payload_size > data_size)
|
||||
memset(
|
||||
(char *) pPayload + data_size, 0, payload_size - data_size);
|
||||
}
|
||||
else {
|
||||
memset ( pPayload, 0, payloadSize );
|
||||
if (autosize) {
|
||||
payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
|
||||
cas_set_header_count(pClient, 0);
|
||||
}
|
||||
memset ( pPayload, 0, payload_size );
|
||||
cas_set_header_cid ( pClient, cacStatus );
|
||||
}
|
||||
cas_commit_msg ( pClient, payloadSize );
|
||||
}
|
||||
cas_commit_msg ( pClient, payload_size );
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures timely response for events, but does que
|
||||
* Ensures timely response for events, but does queue
|
||||
* them up like db requests when the OPI does not keep up.
|
||||
*/
|
||||
if ( ! eventsRemaining )
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include "server.h"
|
||||
|
||||
/* As an optimisation, any message allocated with a large header is resized to
|
||||
* use a small header if the payload size is below this threshold. */
|
||||
#define SMALL_MESSAGE_THRESHOLD 65
|
||||
|
||||
/*
|
||||
* cas_send_bs_msg()
|
||||
*
|
||||
@@ -253,6 +257,7 @@ int cas_copy_in_header (
|
||||
{
|
||||
unsigned msgSize;
|
||||
ca_uint32_t alignedPayloadSize;
|
||||
caHdr *pMsg;
|
||||
|
||||
if ( payloadSize > UINT_MAX - sizeof ( caHdr ) - 8u ) {
|
||||
return ECA_TOLARGE;
|
||||
@@ -292,32 +297,25 @@ int cas_copy_in_header (
|
||||
}
|
||||
}
|
||||
|
||||
if ( alignedPayloadSize < 0xffff && nElem < 0xffff ) {
|
||||
caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk];
|
||||
pMsg->m_cmmd = htons ( response );
|
||||
pMsg->m_postsize = htons ( ( ( ca_uint16_t ) alignedPayloadSize ) );
|
||||
pMsg->m_dataType = htons ( dataType );
|
||||
pMsg->m_count = htons ( ( ( ca_uint16_t ) nElem ) );
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
pMsg->m_available = htonl ( responseSpecific );
|
||||
if ( ppPayload ) {
|
||||
*ppPayload = ( void * ) ( pMsg + 1 );
|
||||
}
|
||||
pMsg = (caHdr *) &pclient->send.buf[pclient->send.stk];
|
||||
pMsg->m_cmmd = htons(response);
|
||||
pMsg->m_dataType = htons(dataType);
|
||||
pMsg->m_cid = htonl(cid);
|
||||
pMsg->m_available = htonl(responseSpecific);
|
||||
if (alignedPayloadSize < 0xffff && nElem < 0xffff) {
|
||||
pMsg->m_postsize = htons(((ca_uint16_t) alignedPayloadSize));
|
||||
pMsg->m_count = htons(((ca_uint16_t) nElem));
|
||||
if (ppPayload)
|
||||
*ppPayload = (void *) (pMsg + 1);
|
||||
}
|
||||
else {
|
||||
caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk];
|
||||
ca_uint32_t *pW32 = ( ca_uint32_t * ) ( pMsg + 1 );
|
||||
pMsg->m_cmmd = htons ( response );
|
||||
pMsg->m_postsize = htons ( 0xffff );
|
||||
pMsg->m_dataType = htons ( dataType );
|
||||
pMsg->m_count = htons ( 0u );
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
pMsg->m_available = htonl ( responseSpecific );
|
||||
pW32[0] = htonl ( alignedPayloadSize );
|
||||
pW32[1] = htonl ( nElem );
|
||||
if ( ppPayload ) {
|
||||
*ppPayload = ( void * ) ( pW32 + 2 );
|
||||
}
|
||||
ca_uint32_t *pW32 = (ca_uint32_t *) (pMsg + 1);
|
||||
pMsg->m_postsize = htons(0xffff);
|
||||
pMsg->m_count = htons(0u);
|
||||
pW32[0] = htonl(alignedPayloadSize);
|
||||
pW32[1] = htonl(nElem);
|
||||
if (ppPayload)
|
||||
*ppPayload = (void *) (pW32 + 2);
|
||||
}
|
||||
|
||||
/* zero out pad bytes */
|
||||
@@ -336,6 +334,22 @@ void cas_set_header_cid ( struct client *pClient, ca_uint32_t cid )
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
}
|
||||
|
||||
void cas_set_header_count (struct client *pClient, ca_uint32_t count)
|
||||
{
|
||||
caHdr *pMsg = (caHdr *) &pClient->send.buf[pClient->send.stk];
|
||||
if (pMsg->m_postsize == htons(0xffff)) {
|
||||
ca_uint32_t *pLW;
|
||||
|
||||
assert(pMsg->m_count == 0);
|
||||
pLW = (ca_uint32_t *) (pMsg + 1);
|
||||
pLW[1] = htonl(count);
|
||||
}
|
||||
else {
|
||||
assert(count < 65536);
|
||||
pMsg->m_count = htons((ca_uint16_t) count);
|
||||
}
|
||||
}
|
||||
|
||||
void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
|
||||
{
|
||||
caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
|
||||
@@ -343,8 +357,19 @@ void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
|
||||
if ( pMsg->m_postsize == htons ( 0xffff ) ) {
|
||||
ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 );
|
||||
assert ( size <= ntohl ( *pLW ) );
|
||||
pLW[0] = htonl ( size );
|
||||
size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );
|
||||
if (size < SMALL_MESSAGE_THRESHOLD) {
|
||||
/* If the message is sufficiently small it can be worth converting a
|
||||
* large message header into a small header. This saves us all of 8
|
||||
* bytes over the wire, so it's not such a big deal. */
|
||||
pMsg->m_postsize = htons((ca_uint16_t) size);
|
||||
pMsg->m_count = htons((ca_uint16_t) ntohl(pLW[1]));
|
||||
memmove(pLW, pLW + 2, size);
|
||||
size += sizeof(caHdr);
|
||||
}
|
||||
else {
|
||||
pLW[0] = htonl ( size );
|
||||
size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert ( size <= ntohs ( pMsg->m_postsize ) );
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "asLib.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbNotify.h"
|
||||
#define CA_MINOR_PROTOCOL_REVISION 12
|
||||
#define CA_MINOR_PROTOCOL_REVISION 13
|
||||
#include "caProto.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsTime.h"
|
||||
@@ -226,6 +226,7 @@ int cas_copy_in_header (
|
||||
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
|
||||
ca_uint32_t responseSpecific, void **pPayload );
|
||||
void cas_set_header_cid ( struct client *pClient, ca_uint32_t );
|
||||
void cas_set_header_count (struct client *pClient, ca_uint32_t count);
|
||||
void cas_commit_msg ( struct client *pClient, ca_uint32_t size );
|
||||
|
||||
#endif /*INCLserverh*/
|
||||
|
||||
Reference in New Issue
Block a user