Merge lp:~michael-abbott/epics-base/dynamic-array into lp:~epics-core/epics-base/3.14

Proposed by Michael Abbott
Status: Merged
Merge reported by: Andrew Johnson
Merged at revision: not available
Proposed branch: lp:~michael-abbott/epics-base/dynamic-array
Merge into: lp:~epics-core/epics-base/3.14
Diff against target: 1647 lines (+406/-538)
17 files modified
.bzrignore (+2/-0)
src/ca/caProto.h (+3/-0)
src/ca/db_access.h (+3/-3)
src/ca/nciu.cpp (+0/-3)
src/ca/nciu.h (+2/-1)
src/ca/netIO.h (+3/-3)
src/ca/oldChannelNotify.cpp (+3/-0)
src/ca/tcpiiu.cpp (+8/-3)
src/catools/caget.c (+16/-14)
src/catools/camonitor.c (+5/-6)
src/catools/tool_lib.c (+3/-3)
src/catools/tool_lib.h (+2/-2)
src/db/db_access.c (+259/-432)
src/db/db_access_routines.h (+3/-0)
src/rsrv/camessage.c (+44/-41)
src/rsrv/caserverio.c (+48/-26)
src/rsrv/server.h (+2/-1)
To merge this branch: bzr merge lp:~michael-abbott/epics-base/dynamic-array
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+26796@code.launchpad.net

Description of the change

This is the dynamic array functionality already described in an earlier e-mail to epics-core.

I hope I'm doing this right. Hugely underwhelmed by bzr+launchpad so far...

To post a comment you must log in.
Revision history for this message
Michael Abbott (michael-abbott) wrote :

Oh crap. Commit 12071 isn't meant to be part of this patch series. Rebase it out if bzr lets you.

Also, ideally, patches 12075 and 12076 should be treated quite separately, as they've little or nothing to do with the core of this work which is just patches 12072 & 12073, plus an application in 12074.

Revision history for this message
Michael Abbott (michael-abbott) wrote :
Download full text (3.1 KiB)

Here's the original message I sent with the motivation for this change.

Subject: [PATCH 0/4] Adding dynamic arrays to EPICS Channel Access

Following on from last week's EPICS codeathon at Diamond I have
prepared the attached series of patches for review.

The basic idea is to extend the server's understanding of the EPICS CA
protocol with one further idea: a request for a zero length array is
interpreted as, instead, a request for an autoresizing array, where
the server sends the true "intrinsic" length of the data with each
update.

The motivation is to efficiently support the handling of large
waveforms such as images or long oscilloscope waveforms, where it is
undesirable to have to always send the entire data. There are
workarounds involving monitoring the .NORD field and resubscribing on
changes, but I believe the approach described here is preferable.
Also, this new functionality opens up the possiblity of sending
complex structured data of unpredictable length packaged as EPICS
waveforms -- something that has already been started with support for
long strings.

It turns out that the implementation of this extension is reasonably
straightforward and that EPICS is mostly already ready for it. The
following detailed changes are implemented:

* A zero length Data Count in a CA_PROTO_EVENT_ADD or CA_PROTO_READ
message is now interpreted so that the "intrinsic" data count is sent
in all replies. A new minor protocol version, V4.12, is defined to
enable this behaviour.

* When processing the request for dynamically sized data the server is
able to make use of two items of information for each value: its
dynamic size, as returned by dbGetField(), and its maximum field size,
as stored in the no_elements field of the associated dbAddr structure.

* The channel access client now passes through a zero length request
to the server (if the server reports minor protocol >= 4.12), and the
true data size is now reported in the associated callbacks. This
means that ca_array_get_callback and ca_create_subscription may now
receive variable size updates in response to a zero length request
count.

I have also updated the caget and camonitor tools to support this new
functionality.

The attached patches are based on bzr revision 12070.

Michael Abbott (4):
  Client side support for automatic resizing arrays.
  Update rsrv to support V4.12 protocol extension.
  Add autosizing array support for caget and camonitor.
  Drive-by refactoring in caserverio.c
 src/ca/caProto.h | 3 +
 src/ca/db_access.h | 6 +-
 src/ca/nciu.cpp | 3 -
 src/ca/nciu.h | 3 +-
 src/ca/netIO.h | 6 +-
 src/ca/oldChannelNotify.cpp | 3 +
 src/ca/tcpiiu.cpp | 11 +-
 src/catools/caget.c | 30 ++--
 src/catools/camonitor.c | 11 +-
 src/catools/tool_lib.c | 6 +-
 src/catools/tool_lib.h | 4 +-
 src/db/db_access.c | 345 +++++++++++--------------------------------
 src/db/db_access_routines.h | 3 +
 src/rsrv/camessage.c | 85 ++++++-----
 src/rsrv/caserverio.c | 55 ++++---
 src/rsrv/server.h | 3 +-
 16 files changed, 214 insertions(+...

Read more...

Revision history for this message
Jeff Hill (johill-lanl) wrote :

Hi Michael,

Thanks for your help.

Please add a client side initiated regression test to acctst.c that verifies that the new feature works properly. Sorry, that acctst.c is a messy code for certain but it does serve its purpose of preventing introduction of bugs that have been seen before. This will also have the benefit of not allowing my neglect of parallel changes for these features in the new server :^). Also, running acctst might even help to test the features you have added.

changes in ca/caProto.h
> +# define CA_V412(MINOR) ((MINOR)>=12u) /* Allow zero length in
> requests. */

The following is what I have on the Bazaar branch which was based on the cvs main trunk (this is where I have always added new features in the past so that I didn't mix together patch level changes in the R3.14 branch (i.e. fixes) with feature upgrades).

# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
# define CA_V413(MINOR) ((MINOR)>=13u) /* channel connectivity response messages */

So we have some conflicts with the new TCP search protocol and some capabilities I have in the new server which allow the service to report the current state of the connectivity it has with its channel.

I propose the following based on the order (in time) that each upgrade might be installed into base (the TCP based search request changes were completed a long time ago):

o V412 - TCP based search requests
o V413 - dynamic payload sized subscription / get callback response message
o V414 - connectivity response messages

I am confused about the purpose of this change (presumably the old code was safer because the client code's compiler can check for access past the end of the array)?

diff --git a/src/ca/db_access.h b/src/ca/db_access.h
-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[];

Changes to rssrv/camessage.c

I am a bit concerned that if for whatever reason db_get_field_and_count returns an item_count greater than requested then we could have data_size greater than payload_size which could cause the unsigned subtract to overflow here. That could cause memset to copy many (way too many) elements which would almost certainly profoundly crash the IOC. Can we afford the risk? I would add an "if (payload_size - data_size)" sanity check here. Yes, nannying but robust.

returns data_size greater
+ memset(
+ (char *) pPayload + data_size, 0, payload_size - data_size);

Otherwise, I did finally have a very close look today, and it looks good.

Revision history for this message
Michael Abbott (michael-abbott) wrote :
Download full text (3.8 KiB)

A first response before I dig into the code.

From: <email address hidden> [mailto:<email address hidden>] On Behalf Of Jeff Hill
> Please add a client side initiated regression test to
> acctst.c that verifies that the new feature works properly.
> Sorry, that acctst.c is a messy code for certain but it does
> serve its purpose of preventing introduction of bugs that
> have been seen before. This will also have the benefit of not
> allowing my neglect of parallel changes for these features in
> the new server :^). Also, running acctst might even help to
> test the features you have added.

Good idea. Ouch, though. Guess it's not going to be a small amount of work...

> changes in ca/caProto.h
> > +# define CA_V412(MINOR) ((MINOR)>=12u) /* Allow zero length in requests. */
>
> I propose the following based on the order (in time) that
> each upgrade might be installed into base (the TCP based
> search request changes were completed a long time ago):
>
> o V412 - TCP based search requests
> o V413 - dynamic payload sized subscription / get callback response message
> o V414 - connectivity response messages

Ok, so I'll just change my CA_V412 tests to CA_V413.

It's a slight nuisance now that we're going by version number rather than using capability bits, but at the end of the day the history of the code will have to be serialised and presumably as you say the 4.12 stuff is ready to be merged with mainstream?

> I am confused about the purpose of this change (presumably
> the old code was safer because the client code's compiler can
> check for access past the end of the array)?
>
> diff --git a/src/ca/db_access.h b/src/ca/db_access.h
> -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[];

I'll hunt out the precise detail, but basically what happened here was that I needed to import db_access.h into a C file where LAST_BUFFER_TYPE wasn't defined (there are all sorts of exciting definition conflicts around in this area) -- indeed, I think I moved the definition out of a #ifdef block. So rather than fight further with more potential conflicts I removed the size definition which, as far as I can tell, would only affect applications of sizeof(dbr_size), which there aren't any -- I don't think leaving these out has any other effect.

I'm pretty sure that the C compiler never checks array sizes when generating access code, so I can't think of any impact apart from making sizeof(dbr_size) fail.

> Changes to rssrv/camessage.c
>
> I am a bit concerned that if for whatever reason
> db_get_field_and_count returns an item_count greater than
> requested then we could have data_size greater than
> payload_size which could cause the unsigned subtract to
> overflow here. That could cause memset to copy many (way too
> many) elements which would almost certainly profoundly crash
> the IOC. Can we aff...

Read more...

12077. By Michael Abbott

Apply responses to code review

Advance associated EPICS protocol revision from 4.12 to 4.13 leaving room
for TCP based search requests to occupy revision 12.

Guard memset in camessage.c to prevent wild memory overrun if mismatch
between payload and data size.

12078. By Michael Abbott

Merged with EPICS base as of 2010/07/05

Removed gratuitous renames in db_access.c as resulted in massive merge
conflict.

Revision history for this message
Michael Abbott (michael-abbott) wrote :

Well, I've responded to Jeff's review comments.

* I've updated the version number and guard from 4.12 to 4.13. Of course, this means that this branch really does need to be merged after the TCP-based search requests feature.

* Rather than think very hard (and maybe make a stupid mistake) I've just guarded the memset() that Jeff flagged with the obvious sanity test.

* I've re-merged with EPICS base. As I noted on the mailing list, this introduced a massive merge conflict with the variable renaming in db_access.c, but as the renaming is quite gratuitous I simply dropped that part of the merge.

* I'm sorry, I've not done anything to acctst.c. As far as I can see it's client side only, and I don't really see where to get started without spending a *lot* of time on it. I'll try and look at this again another time.

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Michael,

I have rebased your dynamic-array commits from 12072 to 12077 onto the latest 3.14 branch, dropping 12071 and handling the db_access.c renames from 12078 properly in the earlier commits. I also changed all references to the CA minor version number from 12 to 13 in the earlier commits. You are still credited as the author in the Bazaar history, although your original commit dates were lost in the manual rebase. There are a few changes I'll need to work on before I can merge it into 3.14 though:
 * Update the Perl5 interface to provide dynamic array support from Perl (almost complete)
 * Make src/catools/caput.c use dynamic arrays for before & after value displays
 * Documentation in both the CAref.html and RELEASE_NOTES.html files

Would you prefer that I publish my branch for public examination while I'm working on it, or just merge the result without referring back to you?

- Andrew

review: Approve
Revision history for this message
Michael Abbott (michael-abbott) wrote :

Hi Andrew,

I'm on holiday until the start of September, so just a quick reply. I'll try and catch up when I get back.

If you're happy to merge, please go ahead. I though I'd already changed the minor version to 13, but maybe I messed up my update?

From: <email address hidden> [mailto:<email address hidden>] On Behalf Of Andrew Johnson
> I have rebased your dynamic-array commits from 12072 to 12077
> onto the latest 3.14 branch, dropping 12071 and handling the
> db_access.c renames from 12078 properly in the earlier
> commits. I also changed all references to the CA minor
> version number from 12 to 13 in the earlier commits. You are
> still credited as the author in the Bazaar history, although
> your original commit dates were lost in the manual rebase.
> There are a few changes I'll need to work on before I can
> merge it into 3.14 though:
> * Update the Perl5 interface to provide dynamic array
> support from Perl (almost complete)
> * Make src/catools/caput.c use dynamic arrays for before &
> after value displays
> * Documentation in both the CAref.html and RELEASE_NOTES.html files
>
> Would you prefer that I publish my branch for public
> examination while I'm working on it, or just merge the result
> without referring back to you?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2009-12-23 21:06:44 +0000
+++ .bzrignore 2010-07-05 08:47:25 +0000
@@ -1,3 +1,5 @@
1./.git
2./.gitignore
1./bin3./bin
2./lib4./lib
3./db5./db
46
=== modified file 'src/ca/caProto.h'
--- src/ca/caProto.h 2004-10-04 18:55:40 +0000
+++ src/ca/caProto.h 2010-07-05 08:47:25 +0000
@@ -40,6 +40,7 @@
40# define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */40# define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */
41# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */41# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
42# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */42# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
43# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
43#elif CA_MAJOR_PROTOCOL_REVISION > 4u44#elif CA_MAJOR_PROTOCOL_REVISION > 4u
44# define CA_V41(MINOR) ( 1u )45# define CA_V41(MINOR) ( 1u )
45# define CA_V42(MINOR) ( 1u )46# define CA_V42(MINOR) ( 1u )
@@ -52,6 +53,7 @@
52# define CA_V49(MINOR) ( 1u )53# define CA_V49(MINOR) ( 1u )
53# define CA_V410(MINOR) ( 1u )54# define CA_V410(MINOR) ( 1u )
54# define CA_V411(MINOR) ( 1u )55# define CA_V411(MINOR) ( 1u )
56# define CA_V413(MINOR) ( 1u )
55#else57#else
56# define CA_V41(MINOR) ( 0u )58# define CA_V41(MINOR) ( 0u )
57# define CA_V42(MINOR) ( 0u )59# define CA_V42(MINOR) ( 0u )
@@ -64,6 +66,7 @@
64# define CA_V49(MINOR) ( 0u )66# define CA_V49(MINOR) ( 0u )
65# define CA_V410(MINOR) ( 0u )67# define CA_V410(MINOR) ( 0u )
66# define CA_V411(MINOR) ( 0u )68# define CA_V411(MINOR) ( 0u )
69# define CA_V413(MINOR) ( 0u )
67#endif 70#endif
6871
69/*72/*
7073
=== modified file 'src/ca/db_access.h'
--- src/ca/db_access.h 2009-08-14 00:29:56 +0000
+++ src/ca/db_access.h 2010-07-05 08:47:25 +0000
@@ -524,16 +524,16 @@
524 dbr_double_t value; /* current value */524 dbr_double_t value; /* current value */
525};525};
526526
527#ifndef db_accessHFORdb_accessC
528#define dbr_size_n(TYPE,COUNT)\527#define dbr_size_n(TYPE,COUNT)\
529((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))528((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))
530529
531/* size for each type - array indexed by the DBR_ type code */530/* size for each type - array indexed by the DBR_ type code */
532epicsShareExtern const unsigned short dbr_size[LAST_BUFFER_TYPE+1];531epicsShareExtern const unsigned short dbr_size[];
533532
534/* size for each type's value - array indexed by the DBR_ type code */533/* size for each type's value - array indexed by the DBR_ type code */
535epicsShareExtern const unsigned short dbr_value_size[LAST_BUFFER_TYPE+1];534epicsShareExtern const unsigned short dbr_value_size[];
536535
536#ifndef db_accessHFORdb_accessC
537/* class for each type's value */537/* class for each type's value */
538enum dbr_value_class { 538enum dbr_value_class {
539 dbr_class_int, 539 dbr_class_int,
540540
=== modified file 'src/ca/nciu.cpp'
--- src/ca/nciu.cpp 2009-08-24 17:03:17 +0000
+++ src/ca/nciu.cpp 2010-07-05 08:47:25 +0000
@@ -291,9 +291,6 @@
291 if ( countIn > this->count ) {291 if ( countIn > this->count ) {
292 throw cacChannel::outOfBounds ();292 throw cacChannel::outOfBounds ();
293 }293 }
294 if ( countIn == 0 ) {
295 countIn = this->count;
296 }
297294
298 //295 //
299 // fail out if their arguments are invalid296 // fail out if their arguments are invalid
300297
=== modified file 'src/ca/nciu.h'
--- src/ca/nciu.h 2008-07-28 16:19:50 +0000
+++ src/ca/nciu.h 2010-07-05 08:47:25 +0000
@@ -41,7 +41,7 @@
41# include "shareLib.h"41# include "shareLib.h"
42#endif42#endif
4343
44#define CA_MINOR_PROTOCOL_REVISION 1144#define CA_MINOR_PROTOCOL_REVISION 13
45#include "caProto.h"45#include "caProto.h"
4646
47#include "cacIO.h"47#include "cacIO.h"
@@ -205,6 +205,7 @@
205 void disconnectAllIO ( 205 void disconnectAllIO (
206 epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & );206 epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & );
207 bool connected ( epicsGuard < epicsMutex > & ) const; 207 bool connected ( epicsGuard < epicsMutex > & ) const;
208 unsigned getcount() const { return count; }
208209
209private:210private:
210 tsDLList < class baseNMIU > eventq;211 tsDLList < class baseNMIU > eventq;
211212
=== modified file 'src/ca/netIO.h'
--- src/ca/netIO.h 2004-10-04 18:55:40 +0000
+++ src/ca/netIO.h 2010-07-05 08:47:25 +0000
@@ -83,7 +83,7 @@
83 void show ( 83 void show (
84 epicsGuard < epicsMutex > &, unsigned level ) const;84 epicsGuard < epicsMutex > &, unsigned level ) const;
85 arrayElementCount getCount (85 arrayElementCount getCount (
86 epicsGuard < epicsMutex > & ) const;86 epicsGuard < epicsMutex > &, bool allow_zero ) const;
87 unsigned getType (87 unsigned getType (
88 epicsGuard < epicsMutex > & ) const;88 epicsGuard < epicsMutex > & ) const;
89 unsigned getMask (89 unsigned getMask (
@@ -242,11 +242,11 @@
242}242}
243243
244inline arrayElementCount netSubscription::getCount (244inline arrayElementCount netSubscription::getCount (
245 epicsGuard < epicsMutex > & guard ) const // X aCC 361245 epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361
246{246{
247 //guard.assertIdenticalMutex ( this->mutex );247 //guard.assertIdenticalMutex ( this->mutex );
248 arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );248 arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );
249 if ( this->count == 0u || this->count > nativeCount ) {249 if ( (this->count == 0u && !allow_zero) || this->count > nativeCount ) {
250 return nativeCount;250 return nativeCount;
251 }251 }
252 else {252 else {
253253
=== modified file 'src/ca/oldChannelNotify.cpp'
--- src/ca/oldChannelNotify.cpp 2007-01-11 21:45:58 +0000
+++ src/ca/oldChannelNotify.cpp 2010-07-05 08:47:25 +0000
@@ -280,6 +280,9 @@
280 if ( type < 0 ) {280 if ( type < 0 ) {
281 return ECA_BADTYPE;281 return ECA_BADTYPE;
282 }282 }
283 if ( count == 0 )
284 return ECA_BADCOUNT;
285
283 unsigned tmpType = static_cast < unsigned > ( type );286 unsigned tmpType = static_cast < unsigned > ( type );
284 epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );287 epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
285 pChan->eliminateExcessiveSendBacklog ( guard );288 pChan->eliminateExcessiveSendBacklog ( guard );
286289
=== modified file 'src/ca/tcpiiu.cpp'
--- src/ca/tcpiiu.cpp 2009-09-11 00:49:02 +0000
+++ src/ca/tcpiiu.cpp 2010-07-05 08:47:25 +0000
@@ -1443,6 +1443,8 @@
1443 if ( nElem > maxElem ) {1443 if ( nElem > maxElem ) {
1444 throw cacChannel::msgBodyCacheTooSmall ();1444 throw cacChannel::msgBodyCacheTooSmall ();
1445 }1445 }
1446 if (nElem == 0 && !CA_V413(this->minorProtocolVersion))
1447 nElem = chan.getcount();
1446 comQueSendMsgMinder minder ( this->sendQue, guard );1448 comQueSendMsgMinder minder ( this->sendQue, guard );
1447 this->sendQue.insertRequestHeader ( 1449 this->sendQue.insertRequestHeader (
1448 CA_PROTO_READ_NOTIFY, 0u, 1450 CA_PROTO_READ_NOTIFY, 0u,
@@ -1538,7 +1540,8 @@
1538 if ( mask > 0xffff ) {1540 if ( mask > 0xffff ) {
1539 throw cacChannel::badEventSelection ();1541 throw cacChannel::badEventSelection ();
1540 }1542 }
1541 arrayElementCount nElem = subscr.getCount ( guard );1543 arrayElementCount nElem = subscr.getCount (
1544 guard, CA_V413(this->minorProtocolVersion) );
1542 arrayElementCount maxBytes;1545 arrayElementCount maxBytes;
1543 if ( CA_V49 ( this->minorProtocolVersion ) ) {1546 if ( CA_V49 ( this->minorProtocolVersion ) ) {
1544 maxBytes = this->cacRef.largeBufferSizeTCP ();1547 maxBytes = this->cacRef.largeBufferSizeTCP ();
@@ -1584,7 +1587,8 @@
1584 if ( this->state != iiucs_connected ) {1587 if ( this->state != iiucs_connected ) {
1585 return;1588 return;
1586 }1589 }
1587 arrayElementCount nElem = subscr.getCount ( guard );1590 arrayElementCount nElem = subscr.getCount (
1591 guard, CA_V413(this->minorProtocolVersion) );
1588 arrayElementCount maxBytes;1592 arrayElementCount maxBytes;
1589 if ( CA_V49 ( this->minorProtocolVersion ) ) {1593 if ( CA_V49 ( this->minorProtocolVersion ) ) {
1590 maxBytes = this->cacRef.largeBufferSizeTCP ();1594 maxBytes = this->cacRef.largeBufferSizeTCP ();
@@ -1622,7 +1626,8 @@
1622 this->sendQue.insertRequestHeader ( 1626 this->sendQue.insertRequestHeader (
1623 CA_PROTO_EVENT_CANCEL, 0u, 1627 CA_PROTO_EVENT_CANCEL, 0u,
1624 static_cast < ca_uint16_t > ( subscr.getType ( guard ) ), 1628 static_cast < ca_uint16_t > ( subscr.getType ( guard ) ),
1625 static_cast < ca_uint16_t > ( subscr.getCount ( guard ) ), 1629 static_cast < ca_uint16_t > ( subscr.getCount (
1630 guard, CA_V413(this->minorProtocolVersion) ) ),
1626 chan.getSID(guard), subscr.getId(), 1631 chan.getSID(guard), subscr.getId(),
1627 CA_V49 ( this->minorProtocolVersion ) );1632 CA_V49 ( this->minorProtocolVersion ) );
1628 minder.commit ();1633 minder.commit ();
16291634
=== modified file 'src/catools/caget.c'
--- src/catools/caget.c 2009-12-15 22:05:55 +0000
+++ src/catools/caget.c 2010-07-05 08:47:25 +0000
@@ -127,6 +127,7 @@
127 ppv->value = calloc(1, dbr_size_n(args.type, args.count));127 ppv->value = calloc(1, dbr_size_n(args.type, args.count));
128 memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));128 memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));
129 ppv->onceConnected = 1;129 ppv->onceConnected = 1;
130 ppv->nElems = args.count;
130 nRead++;131 nRead++;
131 }132 }
132}133}
@@ -183,11 +184,9 @@
183 }184 }
184 }185 }
185 /* Adjust array count */186 /* Adjust array count */
186 if (reqElems == 0 || pvs[n].nElems < reqElems){187 if (reqElems > pvs[n].nElems)
187 pvs[n].reqElems = pvs[n].nElems; /* Use full number of points */188 reqElems = pvs[n].nElems;
188 } else {189 pvs[n].reqElems = reqElems;
189 pvs[n].reqElems = reqElems; /* Limit to specified number */
190 }
191190
192 /* Issue CA request */191 /* Issue CA request */
193 /* ---------------- */192 /* ---------------- */
@@ -205,13 +204,13 @@
205 (void*)&pvs[n]);204 (void*)&pvs[n]);
206 } else {205 } else {
207 /* Allocate value structure */206 /* Allocate value structure */
208 pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems));207 pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
209 if(!pvs[n].value) {208 if(!pvs[n].value) {
210 fprintf(stderr,"Allocation failed\n");209 fprintf(stderr,"Allocation failed\n");
211 return 1;210 return 1;
212 }211 }
213 result = ca_array_get(pvs[n].dbrType,212 result = ca_array_get(pvs[n].dbrType,
214 pvs[n].reqElems,213 pvs[n].nElems,
215 pvs[n].chid,214 pvs[n].chid,
216 pvs[n].value);215 pvs[n].value);
217 }216 }
@@ -253,10 +252,13 @@
253 /* -------------- */252 /* -------------- */
254253
255 for (n = 0; n < nPvs; n++) {254 for (n = 0; n < nPvs; n++) {
255 /* Truncate the data printed to what was requested. */
256 if (pvs[n].reqElems != 0 && pvs[n].nElems > pvs[n].reqElems)
257 pvs[n].nElems = pvs[n].reqElems;
256258
257 switch (format) {259 switch (format) {
258 case plain: /* Emulate old caget behaviour */260 case plain: /* Emulate old caget behaviour */
259 if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);261 if (pvs[n].nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name);
260 else printf("%s", pvs[n].name);262 else printf("%s", pvs[n].name);
261 printf("%c", fieldSeparator);263 printf("%c", fieldSeparator);
262 case terse:264 case terse:
@@ -270,7 +272,7 @@
270 printf("*** no data available (timeout)\n");272 printf("*** no data available (timeout)\n");
271 else273 else
272 {274 {
273 if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {275 if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) {
274 dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);276 dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
275 int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));277 int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
276 char *d = calloc(dlen+1, sizeof(char));278 char *d = calloc(dlen+1, sizeof(char));
@@ -282,8 +284,8 @@
282 fprintf(stderr,"Failed to allocate space for escaped string\n");284 fprintf(stderr,"Failed to allocate space for escaped string\n");
283 }285 }
284 } else {286 } else {
285 if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator);287 if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].nElems, fieldSeparator);
286 for (i=0; i<pvs[n].reqElems; ++i) {288 for (i=0; i<pvs[n].nElems; ++i) {
287 if (i) printf ("%c", fieldSeparator);289 if (i) printf ("%c", fieldSeparator);
288 printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));290 printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
289 }291 }
@@ -315,8 +317,8 @@
315 else {317 else {
316 printf(" Element count: %lu\n"318 printf(" Element count: %lu\n"
317 " Value: ",319 " Value: ",
318 pvs[n].reqElems);320 pvs[n].nElems);
319 if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) {321 if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) {
320 dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);322 dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType);
321 int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));323 int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s));
322 char *d = calloc(dlen+1, sizeof(char));324 char *d = calloc(dlen+1, sizeof(char));
@@ -328,7 +330,7 @@
328 fprintf(stderr,"Failed to allocate space for escaped string\n");330 fprintf(stderr,"Failed to allocate space for escaped string\n");
329 }331 }
330 } else {332 } else {
331 for (i=0; i<pvs[n].reqElems; ++i) {333 for (i=0; i<pvs[n].nElems; ++i) {
332 if (i) printf ("%c", fieldSeparator);334 if (i) printf ("%c", fieldSeparator);
333 printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));335 printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i));
334 }336 }
335337
=== modified file 'src/catools/camonitor.c'
--- src/catools/camonitor.c 2009-12-15 22:05:55 +0000
+++ src/catools/camonitor.c 2010-07-05 08:47:25 +0000
@@ -107,6 +107,7 @@
107 if (args.status == ECA_NORMAL)107 if (args.status == ECA_NORMAL)
108 {108 {
109 pv->dbrType = args.type;109 pv->dbrType = args.type;
110 pv->nElems = args.count;
110 memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));111 memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));
111112
112 print_time_val_sts(pv, reqElems);113 print_time_val_sts(pv, reqElems);
@@ -150,11 +151,9 @@
150 ppv->dbrType = DBR_TIME_STRING;151 ppv->dbrType = DBR_TIME_STRING;
151 }152 }
152 /* Adjust array count */153 /* Adjust array count */
153 if (reqElems == 0 || ppv->nElems < reqElems){154 if (reqElems > ppv->nElems)
154 ppv->reqElems = ppv->nElems; /* Use full number of points */155 reqElems = ppv->nElems;
155 } else {156 ppv->reqElems = reqElems;
156 ppv->reqElems = reqElems; /* Limit to specified number */
157 }
158157
159 ppv->onceConnected = 1;158 ppv->onceConnected = 1;
160 nConn++;159 nConn++;
@@ -163,7 +162,7 @@
163 /* install monitor once with first connect */162 /* install monitor once with first connect */
164 if ( ! ppv->value ) {163 if ( ! ppv->value ) {
165 /* Allocate value structure */164 /* Allocate value structure */
166 ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->reqElems));165 ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->nElems));
167 if ( ppv->value ) {166 if ( ppv->value ) {
168 ppv->status = ca_create_subscription(ppv->dbrType,167 ppv->status = ca_create_subscription(ppv->dbrType,
169 ppv->reqElems,168 ppv->reqElems,
170169
=== modified file 'src/catools/tool_lib.c'
--- src/catools/tool_lib.c 2009-12-15 22:05:55 +0000
+++ src/catools/tool_lib.c 2010-07-05 08:47:25 +0000
@@ -455,8 +455,8 @@
455 printf("Failed to allocate for print_time_val_sts\n"); \455 printf("Failed to allocate for print_time_val_sts\n"); \
456 } \456 } \
457 } else { \457 } else { \
458 if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->reqElems); \458 if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->nElems); \
459 for (i=0; i<pv->reqElems; ++i) { \459 for (i=0; i<pv->nElems; ++i) { \
460 printf("%c%s", fieldSeparator, val2str(value, TYPE_ENUM, i)); \460 printf("%c%s", fieldSeparator, val2str(value, TYPE_ENUM, i)); \
461 } \461 } \
462 } \462 } \
@@ -492,7 +492,7 @@
492 tsInitS = 1;492 tsInitS = 1;
493 }493 }
494494
495 if (pv->reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);495 if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
496 else printf("%s", pv->name);496 else printf("%s", pv->name);
497 printf("%c", fieldSeparator);497 printf("%c", fieldSeparator);
498 if (!pv->onceConnected)498 if (!pv->onceConnected)
499499
=== modified file 'src/catools/tool_lib.h'
--- src/catools/tool_lib.h 2009-12-15 22:05:55 +0000
+++ src/catools/tool_lib.h 2010-07-05 08:47:25 +0000
@@ -64,8 +64,8 @@
64 chid chid;64 chid chid;
65 long dbfType;65 long dbfType;
66 long dbrType;66 long dbrType;
67 unsigned long nElems;67 unsigned long nElems; // True length of data in value
68 unsigned long reqElems;68 unsigned long reqElems; // Requested length of data
69 int status;69 int status;
70 void* value;70 void* value;
71 epicsTimeStamp tsPreviousC;71 epicsTimeStamp tsPreviousC;
7272
=== modified file 'src/db/db_access.c'
--- src/db/db_access.c 2010-06-16 19:58:00 +0000
+++ src/db/db_access.c 2010-07-05 08:47:25 +0000
@@ -149,10 +149,29 @@
149int epicsShareAPI db_get_field(struct dbAddr *paddr,149int epicsShareAPI db_get_field(struct dbAddr *paddr,
150 int buffer_type, void *pbuffer, int no_elements, void *pfl)150 int buffer_type, void *pbuffer, int no_elements, void *pfl)
151{151{
152 long nRequest = no_elements;
153 int result = db_get_field_and_count(
154 paddr, buffer_type, pbuffer, &nRequest, pfl);
155 if (nRequest < no_elements)
156 /* If the database request returned fewer elements than requested then
157 * fill out the remainder of the array with zeros. */
158 memset(
159 (char *)pbuffer + dbr_size_n(buffer_type, nRequest), 0,
160 (no_elements - nRequest) * dbr_value_size[buffer_type]);
161 return result;
162}
163
164/* Performs the work of the public db_get_field API, but also returns the number
165 * of elements actually copied to the buffer. The caller is responsible for
166 * zeroing the remaining part of the buffer. */
167int epicsShareAPI db_get_field_and_count(
168 struct dbAddr *paddr, int buffer_type,
169 void *pbuffer, long *nRequest, void *pfl)
170{
152 long status;171 long status;
153 long options;172 long options;
154 long nRequest;
155 long i;173 long i;
174 long zero = 0;
156175
157 /* The order of the DBR* elements in the "new" structures below is176 /* The order of the DBR* elements in the "new" structures below is
158 * very important and must correspond to the order of processing177 * very important and must correspond to the order of processing
@@ -161,82 +180,26 @@
161180
162 switch(buffer_type) {181 switch(buffer_type) {
163 case(oldDBR_STRING):182 case(oldDBR_STRING):
164 {183 status = dbGetField(paddr, DBR_STRING, pbuffer, &zero, nRequest, pfl);
165 DBSTRING *pvalue = (DBSTRING *)pbuffer;
166
167 options = 0;
168 nRequest = no_elements;
169 status = dbGetField(paddr, DBR_STRING, pbuffer, &options, &nRequest,
170 pfl);
171 for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
172 }
173 break;184 break;
174/* case(oldDBR_INT): */185/* case(oldDBR_INT): */
175 case(oldDBR_SHORT):186 case(oldDBR_SHORT):
176 {187 status = dbGetField(paddr, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
177 dbr_short_t *pvalue = (dbr_short_t *)pbuffer;
178
179 options = 0;
180 nRequest = no_elements;
181 status = dbGetField(paddr, DBR_SHORT, pbuffer, &options, &nRequest,
182 pfl);
183 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
184 }
185 break;188 break;
186 case(oldDBR_FLOAT):189 case(oldDBR_FLOAT):
187 {190 status = dbGetField(paddr, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
188 dbr_float_t *pvalue = (dbr_float_t *)pbuffer;
189
190 options = 0;
191 nRequest = no_elements;
192 status = dbGetField(paddr, DBR_FLOAT, pbuffer, &options, &nRequest,
193 pfl);
194 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
195 }
196 break;191 break;
197 case(oldDBR_ENUM):192 case(oldDBR_ENUM):
198 {193 status = dbGetField(paddr, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
199 dbr_enum_t *pvalue = (dbr_enum_t *)pbuffer;
200
201 options = 0;
202 nRequest = no_elements;
203 status = dbGetField(paddr, DBR_ENUM, pbuffer, &options, &nRequest,
204 pfl);
205 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
206 }
207 break;194 break;
208 case(oldDBR_CHAR):195 case(oldDBR_CHAR):
209 {196 status = dbGetField(paddr, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
210 dbr_char_t *pvalue = (dbr_char_t *)pbuffer;
211
212 options = 0;
213 nRequest = no_elements;
214 status = dbGetField(paddr, DBR_CHAR, pbuffer, &options, &nRequest,
215 pfl);
216 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
217 }
218 break;197 break;
219 case(oldDBR_LONG):198 case(oldDBR_LONG):
220 {199 status = dbGetField(paddr, DBR_LONG, pbuffer, &zero, nRequest, pfl);
221 dbr_long_t *pvalue = (dbr_long_t *)pbuffer;
222
223 options = 0;
224 nRequest = no_elements;
225 status = dbGetField(paddr, DBR_LONG, pbuffer, &options, &nRequest,
226 pfl);
227 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
228 }
229 break;200 break;
230 case(oldDBR_DOUBLE):201 case(oldDBR_DOUBLE):
231 {202 status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
232 dbr_double_t *pvalue = (dbr_double_t *)pbuffer;
233
234 options = 0;
235 nRequest = no_elements;
236 status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &options, &nRequest,
237 pfl);
238 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
239 }
240 break;203 break;
241204
242 case(oldDBR_STS_STRING):205 case(oldDBR_STS_STRING):
@@ -246,20 +209,14 @@
246 struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer;209 struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer;
247 struct {210 struct {
248 DBRstatus211 DBRstatus
249 } newSt;212 } new;
250 DBSTRING *pvalue = (DBSTRING *)pold->value;
251213
252 options = DBR_STATUS;214 options = DBR_STATUS;
253 nRequest = 0;215 status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
254 status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,216 pold->status = new.status;
255 pfl);217 pold->severity = new.severity;
256 pold->status = newSt.status;218 status = dbGetField(paddr, DBR_STRING, pold->value, &zero,
257 pold->severity = newSt.severity;219 nRequest, pfl);
258 options = 0;
259 nRequest = no_elements;
260 status = dbGetField(paddr, DBR_STRING, pold->value, &options,
261 &nRequest, pfl);
262 for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
263 }220 }
264 break;221 break;
265/* case(oldDBR_STS_INT): */222/* case(oldDBR_STS_INT): */
@@ -268,20 +225,14 @@
268 struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer;225 struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer;
269 struct {226 struct {
270 DBRstatus227 DBRstatus
271 } newSt;228 } new;
272 dbr_short_t *pvalue = &pold->value;
273229
274 options = DBR_STATUS;230 options = DBR_STATUS;
275 nRequest = 0;231 status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
276 status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,232 pold->status = new.status;
277 pfl);233 pold->severity = new.severity;
278 pold->status = newSt.status;234 status = dbGetField(paddr, DBR_SHORT, &pold->value, &zero,
279 pold->severity = newSt.severity;235 nRequest, pfl);
280 options = 0;
281 nRequest = no_elements;
282 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
283 &nRequest, pfl);
284 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
285 }236 }
286 break;237 break;
287 case(oldDBR_STS_FLOAT):238 case(oldDBR_STS_FLOAT):
@@ -289,20 +240,14 @@
289 struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer;240 struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer;
290 struct {241 struct {
291 DBRstatus242 DBRstatus
292 } newSt;243 } new;
293 dbr_float_t *pvalue = &pold->value;
294244
295 options = DBR_STATUS;245 options = DBR_STATUS;
296 nRequest = 0;246 status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
297 status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,247 pold->status = new.status;
298 pfl);248 pold->severity = new.severity;
299 pold->status = newSt.status;249 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &zero,
300 pold->severity = newSt.severity;250 nRequest, pfl);
301 options = 0;
302 nRequest = no_elements;
303 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
304 &nRequest, pfl);
305 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
306 }251 }
307 break;252 break;
308 case(oldDBR_STS_ENUM):253 case(oldDBR_STS_ENUM):
@@ -310,20 +255,14 @@
310 struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer;255 struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer;
311 struct {256 struct {
312 DBRstatus257 DBRstatus
313 } newSt;258 } new;
314 dbr_enum_t *pvalue = &pold->value;
315259
316 options = DBR_STATUS;260 options = DBR_STATUS;
317 nRequest = 0;261 status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
318 status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,262 pold->status = new.status;
319 pfl);263 pold->severity = new.severity;
320 pold->status = newSt.status;264 status = dbGetField(paddr, DBR_ENUM, &pold->value, &zero,
321 pold->severity = newSt.severity;265 nRequest, pfl);
322 options = 0;
323 nRequest = no_elements;
324 status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
325 &nRequest, pfl);
326 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
327 }266 }
328 break;267 break;
329 case(oldDBR_STS_CHAR):268 case(oldDBR_STS_CHAR):
@@ -331,20 +270,14 @@
331 struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer;270 struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer;
332 struct {271 struct {
333 DBRstatus272 DBRstatus
334 } newSt;273 } new;
335 dbr_char_t *pvalue = &pold->value;
336274
337 options = DBR_STATUS;275 options = DBR_STATUS;
338 nRequest = 0;276 status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
339 status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,277 pold->status = new.status;
340 pfl);278 pold->severity = new.severity;
341 pold->status = newSt.status;279 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &zero,
342 pold->severity = newSt.severity;280 nRequest, pfl);
343 options = 0;
344 nRequest = no_elements;
345 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
346 &nRequest, pfl);
347 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
348 }281 }
349 break;282 break;
350 case(oldDBR_STS_LONG):283 case(oldDBR_STS_LONG):
@@ -352,20 +285,14 @@
352 struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer;285 struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer;
353 struct {286 struct {
354 DBRstatus287 DBRstatus
355 } newSt;288 } new;
356 dbr_long_t *pvalue = &pold->value;
357289
358 options = DBR_STATUS;290 options = DBR_STATUS;
359 nRequest = 0;291 status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
360 status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,292 pold->status = new.status;
361 pfl);293 pold->severity = new.severity;
362 pold->status = newSt.status;294 status = dbGetField(paddr, DBR_LONG, &pold->value, &zero,
363 pold->severity = newSt.severity;295 nRequest, pfl);
364 options = 0;
365 nRequest = no_elements;
366 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
367 &nRequest, pfl);
368 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
369 }296 }
370 break;297 break;
371 case(oldDBR_STS_DOUBLE):298 case(oldDBR_STS_DOUBLE):
@@ -373,20 +300,15 @@
373 struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer;300 struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer;
374 struct {301 struct {
375 DBRstatus302 DBRstatus
376 } newSt;303 } new;
377 dbr_double_t *pvalue = &pold->value;
378304
379 options = DBR_STATUS;305 options = DBR_STATUS;
380 nRequest = 0;306 status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
381 status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,307 pold->status = new.status;
382 pfl);308 pold->severity = new.severity;
383 pold->status = newSt.status;
384 pold->severity = newSt.severity;
385 options = 0;309 options = 0;
386 nRequest = no_elements;
387 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,310 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
388 &nRequest, pfl);311 nRequest, pfl);
389 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
390 }312 }
391 break;313 break;
392314
@@ -396,21 +318,16 @@
396 struct {318 struct {
397 DBRstatus319 DBRstatus
398 DBRtime320 DBRtime
399 } newSt;321 } new;
400 DBSTRING *pvalue = (DBSTRING *)(pold->value);
401322
402 options = DBR_STATUS | DBR_TIME;323 options = DBR_STATUS | DBR_TIME;
403 nRequest = 0;324 status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
404 status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,325 pold->status = new.status;
405 pfl);326 pold->severity = new.severity;
406 pold->status = newSt.status;327 pold->stamp = new.time; /* structure copy */
407 pold->severity = newSt.severity;
408 pold->stamp = newSt.time; /* structure copy */
409 options = 0;328 options = 0;
410 nRequest = no_elements;329 status = dbGetField(paddr, DBR_STRING, pold->value, &options,
411 status = dbGetField(paddr, DBR_STRING, pold->value, &options,330 nRequest, pfl);
412 &nRequest, pfl);
413 for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
414 }331 }
415 break;332 break;
416/* case(oldDBR_TIME_INT): */333/* case(oldDBR_TIME_INT): */
@@ -420,21 +337,16 @@
420 struct {337 struct {
421 DBRstatus338 DBRstatus
422 DBRtime339 DBRtime
423 } newSt;340 } new;
424 dbr_short_t *pvalue = &pold->value;
425341
426 options = DBR_STATUS | DBR_TIME;342 options = DBR_STATUS | DBR_TIME;
427 nRequest = 0;343 status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
428 status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,344 pold->status = new.status;
429 pfl);345 pold->severity = new.severity;
430 pold->status = newSt.status;346 pold->stamp = new.time; /* structure copy */
431 pold->severity = newSt.severity;
432 pold->stamp = newSt.time; /* structure copy */
433 options = 0;347 options = 0;
434 nRequest = no_elements;
435 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,348 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
436 &nRequest, pfl);349 nRequest, pfl);
437 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
438 }350 }
439 break;351 break;
440 case(oldDBR_TIME_FLOAT):352 case(oldDBR_TIME_FLOAT):
@@ -443,21 +355,16 @@
443 struct {355 struct {
444 DBRstatus356 DBRstatus
445 DBRtime357 DBRtime
446 } newSt;358 } new;
447 dbr_float_t *pvalue = &pold->value;
448359
449 options = DBR_STATUS | DBR_TIME;360 options = DBR_STATUS | DBR_TIME;
450 nRequest = 0;361 status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
451 status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,362 pold->status = new.status;
452 pfl);363 pold->severity = new.severity;
453 pold->status = newSt.status;364 pold->stamp = new.time; /* structure copy */
454 pold->severity = newSt.severity;
455 pold->stamp = newSt.time; /* structure copy */
456 options = 0;365 options = 0;
457 nRequest = no_elements;
458 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,366 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
459 &nRequest, pfl);367 nRequest, pfl);
460 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
461 }368 }
462 break;369 break;
463 case(oldDBR_TIME_ENUM):370 case(oldDBR_TIME_ENUM):
@@ -466,21 +373,16 @@
466 struct {373 struct {
467 DBRstatus374 DBRstatus
468 DBRtime375 DBRtime
469 } newSt;376 } new;
470 dbr_enum_t *pvalue = &pold->value;
471377
472 options = DBR_STATUS | DBR_TIME;378 options = DBR_STATUS | DBR_TIME;
473 nRequest = 0;379 status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
474 status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,380 pold->status = new.status;
475 pfl);381 pold->severity = new.severity;
476 pold->status = newSt.status;382 pold->stamp = new.time; /* structure copy */
477 pold->severity = newSt.severity;
478 pold->stamp = newSt.time; /* structure copy */
479 options = 0;383 options = 0;
480 nRequest = no_elements;
481 status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,384 status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
482 &nRequest, pfl);385 nRequest, pfl);
483 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
484 }386 }
485 break;387 break;
486 case(oldDBR_TIME_CHAR):388 case(oldDBR_TIME_CHAR):
@@ -489,21 +391,16 @@
489 struct {391 struct {
490 DBRstatus392 DBRstatus
491 DBRtime393 DBRtime
492 } newSt;394 } new;
493 dbr_char_t *pvalue = &pold->value;
494395
495 options = DBR_STATUS | DBR_TIME;396 options = DBR_STATUS | DBR_TIME;
496 nRequest = 0;397 status = dbGetField(paddr, DBR_CHAR, &new, &options, &zero, pfl);
497 status = dbGetField(paddr, DBR_CHAR, &newSt, &options, &nRequest,398 pold->status = new.status;
498 pfl);399 pold->severity = new.severity;
499 pold->status = newSt.status;400 pold->stamp = new.time; /* structure copy */
500 pold->severity = newSt.severity;
501 pold->stamp = newSt.time; /* structure copy */
502 options = 0;401 options = 0;
503 nRequest = no_elements;
504 status = dbGetField(paddr, DBR_CHAR, &pold->value, &options,402 status = dbGetField(paddr, DBR_CHAR, &pold->value, &options,
505 &nRequest, pfl);403 nRequest, pfl);
506 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
507 }404 }
508 break;405 break;
509 case(oldDBR_TIME_LONG):406 case(oldDBR_TIME_LONG):
@@ -512,21 +409,16 @@
512 struct {409 struct {
513 DBRstatus410 DBRstatus
514 DBRtime411 DBRtime
515 } newSt;412 } new;
516 dbr_long_t *pvalue = &pold->value;
517413
518 options = DBR_STATUS | DBR_TIME;414 options = DBR_STATUS | DBR_TIME;
519 nRequest = 0;415 status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
520 status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,416 pold->status = new.status;
521 pfl);417 pold->severity = new.severity;
522 pold->status = newSt.status;418 pold->stamp = new.time; /* structure copy */
523 pold->severity = newSt.severity;
524 pold->stamp = newSt.time; /* structure copy */
525 options = 0;419 options = 0;
526 nRequest = no_elements;
527 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,420 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
528 &nRequest, pfl);421 nRequest, pfl);
529 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
530 }422 }
531 break;423 break;
532 case(oldDBR_TIME_DOUBLE):424 case(oldDBR_TIME_DOUBLE):
@@ -535,21 +427,16 @@
535 struct {427 struct {
536 DBRstatus428 DBRstatus
537 DBRtime429 DBRtime
538 } newSt;430 } new;
539 dbr_double_t *pvalue = &pold->value;
540431
541 options = DBR_STATUS | DBR_TIME;432 options = DBR_STATUS | DBR_TIME;
542 nRequest = 0;433 status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
543 status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,434 pold->status = new.status;
544 pfl);435 pold->severity = new.severity;
545 pold->status = newSt.status;436 pold->stamp = new.time; /* structure copy */
546 pold->severity = newSt.severity;
547 pold->stamp = newSt.time; /* structure copy */
548 options = 0;437 options = 0;
549 nRequest = no_elements;
550 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,438 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
551 &nRequest, pfl);439 nRequest, pfl);
552 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
553 }440 }
554 break;441 break;
555442
@@ -563,28 +450,23 @@
563 DBRunits450 DBRunits
564 DBRgrLong451 DBRgrLong
565 DBRalLong452 DBRalLong
566 } newSt;453 } new;
567 dbr_short_t *pvalue = &pold->value;
568454
569 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;455 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
570 nRequest = 0;456 status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
571 status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,457 pold->status = new.status;
572 pfl);458 pold->severity = new.severity;
573 pold->status = newSt.status;459 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
574 pold->severity = newSt.severity;
575 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
576 pold->units[MAX_UNITS_SIZE-1] = '\0';460 pold->units[MAX_UNITS_SIZE-1] = '\0';
577 pold->upper_disp_limit = newSt.upper_disp_limit;461 pold->upper_disp_limit = new.upper_disp_limit;
578 pold->lower_disp_limit = newSt.lower_disp_limit;462 pold->lower_disp_limit = new.lower_disp_limit;
579 pold->upper_alarm_limit = newSt.upper_alarm_limit;463 pold->upper_alarm_limit = new.upper_alarm_limit;
580 pold->upper_warning_limit = newSt.upper_warning_limit;464 pold->upper_warning_limit = new.upper_warning_limit;
581 pold->lower_warning_limit = newSt.lower_warning_limit;465 pold->lower_warning_limit = new.lower_warning_limit;
582 pold->lower_alarm_limit = newSt.lower_alarm_limit;466 pold->lower_alarm_limit = new.lower_alarm_limit;
583 options = 0;467 options = 0;
584 nRequest = no_elements;
585 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,468 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
586 &nRequest, pfl);469 nRequest, pfl);
587 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
588 }470 }
589 break;471 break;
590 case(oldDBR_GR_FLOAT):472 case(oldDBR_GR_FLOAT):
@@ -596,30 +478,25 @@
596 DBRprecision478 DBRprecision
597 DBRgrDouble479 DBRgrDouble
598 DBRalDouble480 DBRalDouble
599 } newSt;481 } new;
600 dbr_float_t *pvalue = &pold->value;
601482
602 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |483 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
603 DBR_AL_DOUBLE;484 DBR_AL_DOUBLE;
604 nRequest = 0;485 status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
605 status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,486 pold->status = new.status;
606 pfl);487 pold->severity = new.severity;
607 pold->status = newSt.status;488 pold->precision = new.precision.dp;
608 pold->severity = newSt.severity;489 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
609 pold->precision = newSt.precision.dp;
610 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
611 pold->units[MAX_UNITS_SIZE-1] = '\0';490 pold->units[MAX_UNITS_SIZE-1] = '\0';
612 pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);491 pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit);
613 pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);492 pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit);
614 pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);493 pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit);
615 pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);494 pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit);
616 pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);495 pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit);
617 pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);496 pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit);
618 options = 0;497 options = 0;
619 nRequest = no_elements;
620 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,498 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
621 &nRequest, pfl);499 nRequest, pfl);
622 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
623 }500 }
624 break;501 break;
625/* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */502/* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */
@@ -631,28 +508,23 @@
631 DBRunits508 DBRunits
632 DBRgrLong509 DBRgrLong
633 DBRalLong510 DBRalLong
634 } newSt;511 } new;
635 dbr_char_t *pvalue = &pold->value;
636512
637 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;513 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
638 nRequest = 0;514 status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
639 status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,515 pold->status = new.status;
640 pfl);516 pold->severity = new.severity;
641 pold->status = newSt.status;517 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
642 pold->severity = newSt.severity;
643 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
644 pold->units[MAX_UNITS_SIZE-1] = '\0';518 pold->units[MAX_UNITS_SIZE-1] = '\0';
645 pold->upper_disp_limit = newSt.upper_disp_limit;519 pold->upper_disp_limit = new.upper_disp_limit;
646 pold->lower_disp_limit = newSt.lower_disp_limit;520 pold->lower_disp_limit = new.lower_disp_limit;
647 pold->upper_alarm_limit = newSt.upper_alarm_limit;521 pold->upper_alarm_limit = new.upper_alarm_limit;
648 pold->upper_warning_limit = newSt.upper_warning_limit;522 pold->upper_warning_limit = new.upper_warning_limit;
649 pold->lower_warning_limit = newSt.lower_warning_limit;523 pold->lower_warning_limit = new.lower_warning_limit;
650 pold->lower_alarm_limit = newSt.lower_alarm_limit;524 pold->lower_alarm_limit = new.lower_alarm_limit;
651 options = 0;525 options = 0;
652 nRequest = no_elements;
653 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,526 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
654 &nRequest, pfl);527 nRequest, pfl);
655 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
656 }528 }
657 break;529 break;
658 case(oldDBR_GR_LONG):530 case(oldDBR_GR_LONG):
@@ -663,28 +535,23 @@
663 DBRunits535 DBRunits
664 DBRgrLong536 DBRgrLong
665 DBRalLong537 DBRalLong
666 } newSt;538 } new;
667 dbr_long_t *pvalue = &pold->value;
668539
669 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;540 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
670 nRequest = 0;541 status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
671 status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,542 pold->status = new.status;
672 pfl);543 pold->severity = new.severity;
673 pold->status = newSt.status;544 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
674 pold->severity = newSt.severity;
675 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
676 pold->units[MAX_UNITS_SIZE-1] = '\0';545 pold->units[MAX_UNITS_SIZE-1] = '\0';
677 pold->upper_disp_limit = newSt.upper_disp_limit;546 pold->upper_disp_limit = new.upper_disp_limit;
678 pold->lower_disp_limit = newSt.lower_disp_limit;547 pold->lower_disp_limit = new.lower_disp_limit;
679 pold->upper_alarm_limit = newSt.upper_alarm_limit;548 pold->upper_alarm_limit = new.upper_alarm_limit;
680 pold->upper_warning_limit = newSt.upper_warning_limit;549 pold->upper_warning_limit = new.upper_warning_limit;
681 pold->lower_warning_limit = newSt.lower_warning_limit;550 pold->lower_warning_limit = new.lower_warning_limit;
682 pold->lower_alarm_limit = newSt.lower_alarm_limit;551 pold->lower_alarm_limit = new.lower_alarm_limit;
683 options = 0;552 options = 0;
684 nRequest = no_elements;
685 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,553 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
686 &nRequest, pfl);554 nRequest, pfl);
687 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
688 }555 }
689 break;556 break;
690 case(oldDBR_GR_DOUBLE):557 case(oldDBR_GR_DOUBLE):
@@ -696,30 +563,25 @@
696 DBRprecision563 DBRprecision
697 DBRgrDouble564 DBRgrDouble
698 DBRalDouble565 DBRalDouble
699 } newSt;566 } new;
700 dbr_double_t *pvalue = &pold->value;
701567
702 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |568 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
703 DBR_AL_DOUBLE;569 DBR_AL_DOUBLE;
704 nRequest = 0;570 status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
705 status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,571 pold->status = new.status;
706 pfl);572 pold->severity = new.severity;
707 pold->status = newSt.status;573 pold->precision = new.precision.dp;
708 pold->severity = newSt.severity;574 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
709 pold->precision = newSt.precision.dp;
710 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
711 pold->units[MAX_UNITS_SIZE-1] = '\0';575 pold->units[MAX_UNITS_SIZE-1] = '\0';
712 pold->upper_disp_limit = newSt.upper_disp_limit;576 pold->upper_disp_limit = new.upper_disp_limit;
713 pold->lower_disp_limit = newSt.lower_disp_limit;577 pold->lower_disp_limit = new.lower_disp_limit;
714 pold->upper_alarm_limit = newSt.upper_alarm_limit;578 pold->upper_alarm_limit = new.upper_alarm_limit;
715 pold->upper_warning_limit = newSt.upper_warning_limit;579 pold->upper_warning_limit = new.upper_warning_limit;
716 pold->lower_warning_limit = newSt.lower_warning_limit;580 pold->lower_warning_limit = new.lower_warning_limit;
717 pold->lower_alarm_limit = newSt.lower_alarm_limit;581 pold->lower_alarm_limit = new.lower_alarm_limit;
718 options = 0;582 options = 0;
719 nRequest = no_elements;
720 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,583 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
721 &nRequest, pfl);584 nRequest, pfl);
722 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
723 }585 }
724 break;586 break;
725587
@@ -733,31 +595,26 @@
733 DBRgrLong595 DBRgrLong
734 DBRctrlLong596 DBRctrlLong
735 DBRalLong597 DBRalLong
736 } newSt;598 } new;
737 dbr_short_t *pvalue = &pold->value;
738599
739 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |600 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
740 DBR_AL_LONG;601 DBR_AL_LONG;
741 nRequest = 0;602 status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
742 status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,603 pold->status = new.status;
743 pfl);604 pold->severity = new.severity;
744 pold->status = newSt.status;605 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
745 pold->severity = newSt.severity;
746 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
747 pold->units[MAX_UNITS_SIZE-1] = '\0';606 pold->units[MAX_UNITS_SIZE-1] = '\0';
748 pold->upper_disp_limit = newSt.upper_disp_limit;607 pold->upper_disp_limit = new.upper_disp_limit;
749 pold->lower_disp_limit = newSt.lower_disp_limit;608 pold->lower_disp_limit = new.lower_disp_limit;
750 pold->upper_alarm_limit = newSt.upper_alarm_limit;609 pold->upper_alarm_limit = new.upper_alarm_limit;
751 pold->upper_warning_limit = newSt.upper_warning_limit;610 pold->upper_warning_limit = new.upper_warning_limit;
752 pold->lower_warning_limit = newSt.lower_warning_limit;611 pold->lower_warning_limit = new.lower_warning_limit;
753 pold->lower_alarm_limit = newSt.lower_alarm_limit;612 pold->lower_alarm_limit = new.lower_alarm_limit;
754 pold->upper_ctrl_limit = newSt.upper_ctrl_limit;613 pold->upper_ctrl_limit = new.upper_ctrl_limit;
755 pold->lower_ctrl_limit = newSt.lower_ctrl_limit;614 pold->lower_ctrl_limit = new.lower_ctrl_limit;
756 options = 0;615 options = 0;
757 nRequest = no_elements;
758 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,616 status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
759 &nRequest, pfl);617 nRequest, pfl);
760 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
761 }618 }
762 break;619 break;
763 case(oldDBR_CTRL_FLOAT):620 case(oldDBR_CTRL_FLOAT):
@@ -770,32 +627,27 @@
770 DBRgrDouble627 DBRgrDouble
771 DBRctrlDouble628 DBRctrlDouble
772 DBRalDouble629 DBRalDouble
773 } newSt;630 } new;
774 dbr_float_t *pvalue = &pold->value;
775631
776 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |632 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
777 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;633 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
778 nRequest = 0;634 status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
779 status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,635 pold->status = new.status;
780 pfl);636 pold->severity = new.severity;
781 pold->status = newSt.status;637 pold->precision = new.precision.dp;
782 pold->severity = newSt.severity;638 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
783 pold->precision = newSt.precision.dp;
784 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
785 pold->units[MAX_UNITS_SIZE-1] = '\0';639 pold->units[MAX_UNITS_SIZE-1] = '\0';
786 pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);640 pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit);
787 pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);641 pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit);
788 pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);642 pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit);
789 pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);643 pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit);
790 pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);644 pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit);
791 pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);645 pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit);
792 pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit);646 pold->upper_ctrl_limit = epicsConvertDoubleToFloat(new.upper_ctrl_limit);
793 pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit);647 pold->lower_ctrl_limit = epicsConvertDoubleToFloat(new.lower_ctrl_limit);
794 options = 0;648 options = 0;
795 nRequest = no_elements;
796 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,649 status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
797 &nRequest, pfl);650 nRequest, pfl);
798 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
799 }651 }
800 break;652 break;
801 case(oldDBR_GR_ENUM):653 case(oldDBR_GR_ENUM):
@@ -805,29 +657,24 @@
805 struct {657 struct {
806 DBRstatus658 DBRstatus
807 DBRenumStrs659 DBRenumStrs
808 } newSt;660 } new;
809 short no_str;661 short no_str;
810 dbr_enum_t *pvalue = &pold->value;
811662
812 memset(pold, '\0', sizeof(struct dbr_ctrl_enum));663 memset(pold, '\0', sizeof(struct dbr_ctrl_enum));
813 /* first get status and severity */664 /* first get status and severity */
814 options = DBR_STATUS | DBR_ENUM_STRS;665 options = DBR_STATUS | DBR_ENUM_STRS;
815 nRequest = 0;666 status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
816 status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,667 pold->status = new.status;
817 pfl);668 pold->severity = new.severity;
818 pold->status = newSt.status;669 no_str = new.no_str;
819 pold->severity = newSt.severity;
820 no_str = newSt.no_str;
821 if (no_str>16) no_str=16;670 if (no_str>16) no_str=16;
822 pold->no_str = no_str;671 pold->no_str = no_str;
823 for (i = 0; i < no_str; i++)672 for (i = 0; i < no_str; i++)
824 strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i]));673 strncpy(pold->strs[i], new.strs[i], sizeof(pold->strs[i]));
825 /*now get values*/674 /*now get values*/
826 options = 0;675 options = 0;
827 nRequest = no_elements;
828 status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,676 status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
829 &nRequest, pfl);677 nRequest, pfl);
830 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
831 }678 }
832 break;679 break;
833 case(oldDBR_CTRL_CHAR):680 case(oldDBR_CTRL_CHAR):
@@ -839,31 +686,26 @@
839 DBRgrLong686 DBRgrLong
840 DBRctrlLong687 DBRctrlLong
841 DBRalLong688 DBRalLong
842 } newSt;689 } new;
843 dbr_char_t *pvalue = &pold->value;
844690
845 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |691 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
846 DBR_AL_LONG;692 DBR_AL_LONG;
847 nRequest = 0;693 status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
848 status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,694 pold->status = new.status;
849 pfl);695 pold->severity = new.severity;
850 pold->status = newSt.status;696 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
851 pold->severity = newSt.severity;
852 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
853 pold->units[MAX_UNITS_SIZE-1] = '\0';697 pold->units[MAX_UNITS_SIZE-1] = '\0';
854 pold->upper_disp_limit = newSt.upper_disp_limit;698 pold->upper_disp_limit = new.upper_disp_limit;
855 pold->lower_disp_limit = newSt.lower_disp_limit;699 pold->lower_disp_limit = new.lower_disp_limit;
856 pold->upper_alarm_limit = newSt.upper_alarm_limit;700 pold->upper_alarm_limit = new.upper_alarm_limit;
857 pold->upper_warning_limit = newSt.upper_warning_limit;701 pold->upper_warning_limit = new.upper_warning_limit;
858 pold->lower_warning_limit = newSt.lower_warning_limit;702 pold->lower_warning_limit = new.lower_warning_limit;
859 pold->lower_alarm_limit = newSt.lower_alarm_limit;703 pold->lower_alarm_limit = new.lower_alarm_limit;
860 pold->upper_ctrl_limit = newSt.upper_ctrl_limit;704 pold->upper_ctrl_limit = new.upper_ctrl_limit;
861 pold->lower_ctrl_limit = newSt.lower_ctrl_limit;705 pold->lower_ctrl_limit = new.lower_ctrl_limit;
862 options = 0;706 options = 0;
863 nRequest = no_elements;
864 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,707 status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
865 &nRequest, pfl);708 nRequest, pfl);
866 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
867 }709 }
868 break;710 break;
869 case(oldDBR_CTRL_LONG):711 case(oldDBR_CTRL_LONG):
@@ -875,31 +717,26 @@
875 DBRgrLong717 DBRgrLong
876 DBRctrlLong718 DBRctrlLong
877 DBRalLong719 DBRalLong
878 } newSt;720 } new;
879 dbr_long_t *pvalue = &pold->value;
880721
881 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |722 options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
882 DBR_AL_LONG;723 DBR_AL_LONG;
883 nRequest = 0;724 status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
884 status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,725 pold->status = new.status;
885 pfl);726 pold->severity = new.severity;
886 pold->status = newSt.status;727 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
887 pold->severity = newSt.severity;
888 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
889 pold->units[MAX_UNITS_SIZE-1] = '\0';728 pold->units[MAX_UNITS_SIZE-1] = '\0';
890 pold->upper_disp_limit = newSt.upper_disp_limit;729 pold->upper_disp_limit = new.upper_disp_limit;
891 pold->lower_disp_limit = newSt.lower_disp_limit;730 pold->lower_disp_limit = new.lower_disp_limit;
892 pold->upper_alarm_limit = newSt.upper_alarm_limit;731 pold->upper_alarm_limit = new.upper_alarm_limit;
893 pold->upper_warning_limit = newSt.upper_warning_limit;732 pold->upper_warning_limit = new.upper_warning_limit;
894 pold->lower_warning_limit = newSt.lower_warning_limit;733 pold->lower_warning_limit = new.lower_warning_limit;
895 pold->lower_alarm_limit = newSt.lower_alarm_limit;734 pold->lower_alarm_limit = new.lower_alarm_limit;
896 pold->upper_ctrl_limit = newSt.upper_ctrl_limit;735 pold->upper_ctrl_limit = new.upper_ctrl_limit;
897 pold->lower_ctrl_limit = newSt.lower_ctrl_limit;736 pold->lower_ctrl_limit = new.lower_ctrl_limit;
898 options = 0;737 options = 0;
899 nRequest = no_elements;
900 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,738 status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
901 &nRequest, pfl);739 nRequest, pfl);
902 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
903 }740 }
904 break;741 break;
905 case(oldDBR_CTRL_DOUBLE):742 case(oldDBR_CTRL_DOUBLE):
@@ -912,32 +749,27 @@
912 DBRgrDouble749 DBRgrDouble
913 DBRctrlDouble750 DBRctrlDouble
914 DBRalDouble751 DBRalDouble
915 } newSt;752 } new;
916 dbr_double_t *pvalue = &pold->value;
917753
918 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |754 options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
919 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;755 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
920 nRequest = 0;756 status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
921 status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,757 pold->status = new.status;
922 pfl);758 pold->severity = new.severity;
923 pold->status = newSt.status;759 pold->precision = new.precision.dp;
924 pold->severity = newSt.severity;760 strncpy(pold->units, new.units, MAX_UNITS_SIZE);
925 pold->precision = newSt.precision.dp;
926 strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
927 pold->units[MAX_UNITS_SIZE-1] = '\0';761 pold->units[MAX_UNITS_SIZE-1] = '\0';
928 pold->upper_disp_limit = newSt.upper_disp_limit;762 pold->upper_disp_limit = new.upper_disp_limit;
929 pold->lower_disp_limit = newSt.lower_disp_limit;763 pold->lower_disp_limit = new.lower_disp_limit;
930 pold->upper_alarm_limit = newSt.upper_alarm_limit;764 pold->upper_alarm_limit = new.upper_alarm_limit;
931 pold->upper_warning_limit = newSt.upper_warning_limit;765 pold->upper_warning_limit = new.upper_warning_limit;
932 pold->lower_warning_limit = newSt.lower_warning_limit;766 pold->lower_warning_limit = new.lower_warning_limit;
933 pold->lower_alarm_limit = newSt.lower_alarm_limit;767 pold->lower_alarm_limit = new.lower_alarm_limit;
934 pold->upper_ctrl_limit = newSt.upper_ctrl_limit;768 pold->upper_ctrl_limit = new.upper_ctrl_limit;
935 pold->lower_ctrl_limit = newSt.lower_ctrl_limit;769 pold->lower_ctrl_limit = new.lower_ctrl_limit;
936 options = 0;770 options = 0;
937 nRequest = no_elements;
938 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,771 status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
939 &nRequest, pfl);772 nRequest, pfl);
940 for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
941 }773 }
942 break;774 break;
943775
@@ -946,22 +778,17 @@
946 struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer;778 struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer;
947 struct {779 struct {
948 DBRstatus780 DBRstatus
949 } newSt;781 } new;
950 DBSTRING *pvalue = (DBSTRING *)(pold->value);
951782
952 options = DBR_STATUS;783 options = DBR_STATUS;
953 nRequest = 0;784 status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
954 status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,785 pold->status = new.status;
955 pfl);786 pold->severity = new.severity;
956 pold->status = newSt.status;787 pold->ackt = new.ackt;
957 pold->severity = newSt.severity;788 pold->acks = new.acks;
958 pold->ackt = newSt.ackt;
959 pold->acks = newSt.acks;
960 options = 0;789 options = 0;
961 nRequest = no_elements;
962 status = dbGetField(paddr, DBR_STRING, pold->value,790 status = dbGetField(paddr, DBR_STRING, pold->value,
963 &options, &nRequest, pfl);791 &options, nRequest, pfl);
964 for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
965 }792 }
966 break;793 break;
967794
968795
=== modified file 'src/db/db_access_routines.h'
--- src/db/db_access_routines.h 2002-07-12 21:35:43 +0000
+++ src/db/db_access_routines.h 2010-07-05 08:47:25 +0000
@@ -39,6 +39,9 @@
39 DBADDR *paddr, int src_type,const void *psrc, int no_elements);39 DBADDR *paddr, int src_type,const void *psrc, int no_elements);
40epicsShareFunc int epicsShareAPI db_get_field(40epicsShareFunc int epicsShareAPI db_get_field(
41 DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl);41 DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl);
42epicsShareFunc int db_get_field_and_count(
43 struct dbAddr *paddr, int buffer_type,
44 void *pbuffer, long *nRequest, void *pfl);
4245
4346
44#ifdef __cplusplus47#ifdef __cplusplus
4548
=== modified file 'src/rsrv/camessage.c'
--- src/rsrv/camessage.c 2009-07-09 16:37:24 +0000
+++ src/rsrv/camessage.c 2010-07-05 08:47:25 +0000
@@ -530,12 +530,21 @@
530 cid = pciu->cid;530 cid = pciu->cid;
531 }531 }
532532
533 status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size, 533 /* If the client has requested a zero element count we interpret this as a
534 pevext->msg.m_dataType, pevext->msg.m_count, cid, pevext->msg.m_available,534 * request for all avaiable elements. In this case we initialise the
535 * header with the maximum element size specified by the database. */
536 int autosize = pevext->msg.m_count == 0;
537 long item_count =
538 autosize ? paddr->no_elements : pevext->msg.m_count;
539 ca_uint32_t payload_size = dbr_size_n(pevext->msg.m_dataType, item_count);
540 status = cas_copy_in_header(
541 pClient, pevext->msg.m_cmmd, payload_size,
542 pevext->msg.m_dataType, item_count, cid, pevext->msg.m_available,
535 &pPayload );543 &pPayload );
536 if ( status != ECA_NORMAL ) {544 if ( status != ECA_NORMAL ) {
537 send_err ( &pevext->msg, status, pClient, 545 send_err ( &pevext->msg, status, pClient,
538 "server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u",546 "server unable to load read (or subscription update) response "
547 "into protocol buffer PV=\"%s\" max bytes=%u",
539 RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );548 RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );
540 if ( ! eventsRemaining )549 if ( ! eventsRemaining )
541 cas_send_bs_msg ( pClient, FALSE );550 cas_send_bs_msg ( pClient, FALSE );
@@ -554,8 +563,8 @@
554 return;563 return;
555 }564 }
556565
557 status = db_get_field ( paddr, pevext->msg.m_dataType,566 status = db_get_field_and_count(
558 pPayload, pevext->msg.m_count, pfl);567 paddr, pevext->msg.m_dataType, pPayload, &item_count, pfl);
559 if ( status < 0 ) {568 if ( status < 0 ) {
560 /*569 /*
561 * I cant wait to redesign this protocol from scratch!570 * I cant wait to redesign this protocol from scratch!
@@ -569,58 +578,52 @@
569 send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) );578 send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) );
570 }579 }
571 else {580 else {
572 /*581 /* New clients recv the status of the operation directly to the
573 * New clients recv the status of the
574 * operation directly to the
575 * event/put/get callback.582 * event/put/get callback.
576 *583 *
577 * Fetched value is set to zero in case they584 * Fetched value is set to zero in case they use it even when the
578 * use it even when the status indicates 585 * status indicates failure -- unless the client selected autosizing
579 * failure.586 * data, in which case they'd better know what they're doing!
580 *587 *
581 * The m_cid field in the protocol588 * The m_cid field in the protocol header is abused to carry the
582 * header is abused to carry the status589 * status */
583 */590 if (autosize) {
584 memset ( pPayload, 0, pevext->size );591 payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
592 cas_set_header_count(pClient, 0);
593 }
594 memset ( pPayload, 0, payload_size );
585 cas_set_header_cid ( pClient, ECA_GETFAIL );595 cas_set_header_cid ( pClient, ECA_GETFAIL );
586 cas_commit_msg ( pClient, pevext->size );596 cas_commit_msg ( pClient, payload_size );
587 }597 }
588 }598 }
589 else {599 else {
590 ca_uint32_t payloadSize = pevext->size;
591 int cacStatus = caNetConvert ( 600 int cacStatus = caNetConvert (
592 pevext->msg.m_dataType, pPayload, pPayload, 601 pevext->msg.m_dataType, pPayload, pPayload,
593 TRUE /* host -> net format */, pevext->msg.m_count );602 TRUE /* host -> net format */, item_count );
594 if ( cacStatus == ECA_NORMAL ) {603 if ( cacStatus == ECA_NORMAL ) {
595 /*604 ca_uint32_t data_size =
596 * force string message size to be the true size rounded to even605 dbr_size_n(pevext->msg.m_dataType, item_count);
597 * boundary606 if (autosize) {
598 */607 payload_size = data_size;
599 if ( pevext->msg.m_dataType == DBR_STRING 608 cas_set_header_count(pClient, item_count);
600 && pevext->msg.m_count == 1 ) {
601 char * pStr = (char *) pPayload;
602 size_t strcnt = strlen ( pStr );
603 if ( strcnt < payloadSize ) {
604 payloadSize = ( ca_uint32_t ) ( strcnt + 1u );
605 }
606 else {
607 pStr[payloadSize-1] = '\0';
608 errlogPrintf (
609 "caserver: read_reply: detected DBR_STRING w/o nill termination "
610 "in response from db_get_field, pPayload = \"%s\"\n",
611 pStr );
612 }
613 }609 }
610 else if (payload_size > data_size)
611 memset(
612 (char *) pPayload + data_size, 0, payload_size - data_size);
614 }613 }
615 else {614 else {
616 memset ( pPayload, 0, payloadSize );615 if (autosize) {
616 payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
617 cas_set_header_count(pClient, 0);
618 }
619 memset ( pPayload, 0, payload_size );
617 cas_set_header_cid ( pClient, cacStatus );620 cas_set_header_cid ( pClient, cacStatus );
618 }621 }
619 cas_commit_msg ( pClient, payloadSize );622 cas_commit_msg ( pClient, payload_size );
620 }623 }
621624
622 /*625 /*
623 * Ensures timely response for events, but does que 626 * Ensures timely response for events, but does queue
624 * them up like db requests when the OPI does not keep up.627 * them up like db requests when the OPI does not keep up.
625 */628 */
626 if ( ! eventsRemaining )629 if ( ! eventsRemaining )
627630
=== modified file 'src/rsrv/caserverio.c'
--- src/rsrv/caserverio.c 2006-11-20 16:10:02 +0000
+++ src/rsrv/caserverio.c 2010-07-05 08:47:25 +0000
@@ -33,6 +33,10 @@
33#define epicsExportSharedSymbols33#define epicsExportSharedSymbols
34#include "server.h"34#include "server.h"
3535
36/* As an optimisation, any message allocated with a large header is resized to
37 * use a small header if the payload size is below this threshold. */
38#define SMALL_MESSAGE_THRESHOLD 65
39
36/*40/*
37 * cas_send_bs_msg()41 * cas_send_bs_msg()
38 *42 *
@@ -292,32 +296,25 @@
292 }296 }
293 }297 }
294298
295 if ( alignedPayloadSize < 0xffff && nElem < 0xffff ) {299 caHdr *pMsg = (caHdr *) &pclient->send.buf[pclient->send.stk];
296 caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk]; 300 pMsg->m_cmmd = htons(response);
297 pMsg->m_cmmd = htons ( response ); 301 pMsg->m_dataType = htons(dataType);
298 pMsg->m_postsize = htons ( ( ( ca_uint16_t ) alignedPayloadSize ) ); 302 pMsg->m_cid = htonl(cid);
299 pMsg->m_dataType = htons ( dataType ); 303 pMsg->m_available = htonl(responseSpecific);
300 pMsg->m_count = htons ( ( ( ca_uint16_t ) nElem ) ); 304 if (alignedPayloadSize < 0xffff && nElem < 0xffff) {
301 pMsg->m_cid = htonl ( cid ); 305 pMsg->m_postsize = htons(((ca_uint16_t) alignedPayloadSize));
302 pMsg->m_available = htonl ( responseSpecific ); 306 pMsg->m_count = htons(((ca_uint16_t) nElem));
303 if ( ppPayload ) {307 if (ppPayload)
304 *ppPayload = ( void * ) ( pMsg + 1 );308 *ppPayload = (void *) (pMsg + 1);
305 }
306 }309 }
307 else {310 else {
308 caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk];311 ca_uint32_t *pW32 = (ca_uint32_t *) (pMsg + 1);
309 ca_uint32_t *pW32 = ( ca_uint32_t * ) ( pMsg + 1 );312 pMsg->m_postsize = htons(0xffff);
310 pMsg->m_cmmd = htons ( response ); 313 pMsg->m_count = htons(0u);
311 pMsg->m_postsize = htons ( 0xffff ); 314 pW32[0] = htonl(alignedPayloadSize);
312 pMsg->m_dataType = htons ( dataType ); 315 pW32[1] = htonl(nElem);
313 pMsg->m_count = htons ( 0u ); 316 if (ppPayload)
314 pMsg->m_cid = htonl ( cid ); 317 *ppPayload = (void *) (pW32 + 2);
315 pMsg->m_available = htonl ( responseSpecific );
316 pW32[0] = htonl ( alignedPayloadSize );
317 pW32[1] = htonl ( nElem );
318 if ( ppPayload ) {
319 *ppPayload = ( void * ) ( pW32 + 2 );
320 }
321 }318 }
322319
323 /* zero out pad bytes */320 /* zero out pad bytes */
@@ -336,6 +333,20 @@
336 pMsg->m_cid = htonl ( cid );333 pMsg->m_cid = htonl ( cid );
337}334}
338335
336void cas_set_header_count (struct client *pClient, ca_uint32_t count)
337{
338 caHdr *pMsg = (caHdr *) &pClient->send.buf[pClient->send.stk];
339 if (pMsg->m_postsize == htons(0xffff)) {
340 assert(pMsg->m_count == 0);
341 ca_uint32_t *pLW = (ca_uint32_t *) (pMsg + 1);
342 pLW[1] = htonl(count);
343 }
344 else {
345 assert(count < 65536);
346 pMsg->m_count = htons((ca_uint16_t) count);
347 }
348}
349
339void cas_commit_msg ( struct client *pClient, ca_uint32_t size )350void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
340{351{
341 caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];352 caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
@@ -343,8 +354,19 @@
343 if ( pMsg->m_postsize == htons ( 0xffff ) ) {354 if ( pMsg->m_postsize == htons ( 0xffff ) ) {
344 ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 );355 ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 );
345 assert ( size <= ntohl ( *pLW ) );356 assert ( size <= ntohl ( *pLW ) );
346 pLW[0] = htonl ( size );357 if (size < SMALL_MESSAGE_THRESHOLD) {
347 size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );358 /* If the message is sufficiently small it can be worth converting a
359 * large message header into a small header. This saves us all of 8
360 * bytes over the wire, so it's not such a big deal. */
361 pMsg->m_postsize = htons((ca_uint16_t) size);
362 pMsg->m_count = htons((ca_uint16_t) ntohl(pLW[1]));
363 memmove(pLW, pLW + 2, size);
364 size += sizeof(caHdr);
365 }
366 else {
367 pLW[0] = htonl ( size );
368 size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );
369 }
348 }370 }
349 else {371 else {
350 assert ( size <= ntohs ( pMsg->m_postsize ) );372 assert ( size <= ntohs ( pMsg->m_postsize ) );
351373
=== modified file 'src/rsrv/server.h'
--- src/rsrv/server.h 2009-07-09 16:37:24 +0000
+++ src/rsrv/server.h 2010-07-05 08:47:25 +0000
@@ -29,7 +29,7 @@
29#include "asLib.h"29#include "asLib.h"
30#include "dbAddr.h"30#include "dbAddr.h"
31#include "dbNotify.h"31#include "dbNotify.h"
32#define CA_MINOR_PROTOCOL_REVISION 1132#define CA_MINOR_PROTOCOL_REVISION 13
33#include "caProto.h"33#include "caProto.h"
34#include "ellLib.h"34#include "ellLib.h"
35#include "epicsTime.h"35#include "epicsTime.h"
@@ -228,6 +228,7 @@
228 ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, 228 ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
229 ca_uint32_t responseSpecific, void **pPayload );229 ca_uint32_t responseSpecific, void **pPayload );
230void cas_set_header_cid ( struct client *pClient, ca_uint32_t );230void cas_set_header_cid ( struct client *pClient, ca_uint32_t );
231void cas_set_header_count (struct client *pClient, ca_uint32_t count);
231void cas_commit_msg ( struct client *pClient, ca_uint32_t size );232void cas_commit_msg ( struct client *pClient, ca_uint32_t size );
232233
233#endif /*INCLserverh*/234#endif /*INCLserverh*/

Subscribers

People subscribed via source and target branches