Merge lp:~michael-abbott/epics-base/dynamic-array into lp:~epics-core/epics-base/3.14
- dynamic-array
- Merge into 3.14
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
Review via email: mp+26796@code.launchpad.net |
Commit message
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...
Michael Abbott (michael-abbott) wrote : | # |
Michael Abbott (michael-abbott) wrote : | # |
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_
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/
src/ca/tcpiiu.cpp | 11 +-
src/catools/
src/catools/
src/catools/
src/catools/
src/db/db_access.c | 345 +++++++
src/db/
src/rsrv/
src/rsrv/
src/rsrv/server.h | 3 +-
16 files changed, 214 insertions(+...
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/
-epicsShareExtern const unsigned short dbr_size[
+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_
+epicsShareExtern const unsigned short dbr_value_size[];
Changes to rssrv/camessage.c
I am a bit concerned that if for whatever reason db_get_
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.
Michael Abbott (michael-abbott) wrote : | # |
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/
> -epicsShareExtern const unsigned short dbr_size[
> +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_
> +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_
> 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...
- 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.
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.
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
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
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2009-12-23 21:06:44 +0000 |
3 | +++ .bzrignore 2010-07-05 08:47:25 +0000 |
4 | @@ -1,3 +1,5 @@ |
5 | +./.git |
6 | +./.gitignore |
7 | ./bin |
8 | ./lib |
9 | ./db |
10 | |
11 | === modified file 'src/ca/caProto.h' |
12 | --- src/ca/caProto.h 2004-10-04 18:55:40 +0000 |
13 | +++ src/ca/caProto.h 2010-07-05 08:47:25 +0000 |
14 | @@ -40,6 +40,7 @@ |
15 | # define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */ |
16 | # define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */ |
17 | # define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */ |
18 | +# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */ |
19 | #elif CA_MAJOR_PROTOCOL_REVISION > 4u |
20 | # define CA_V41(MINOR) ( 1u ) |
21 | # define CA_V42(MINOR) ( 1u ) |
22 | @@ -52,6 +53,7 @@ |
23 | # define CA_V49(MINOR) ( 1u ) |
24 | # define CA_V410(MINOR) ( 1u ) |
25 | # define CA_V411(MINOR) ( 1u ) |
26 | +# define CA_V413(MINOR) ( 1u ) |
27 | #else |
28 | # define CA_V41(MINOR) ( 0u ) |
29 | # define CA_V42(MINOR) ( 0u ) |
30 | @@ -64,6 +66,7 @@ |
31 | # define CA_V49(MINOR) ( 0u ) |
32 | # define CA_V410(MINOR) ( 0u ) |
33 | # define CA_V411(MINOR) ( 0u ) |
34 | +# define CA_V413(MINOR) ( 0u ) |
35 | #endif |
36 | |
37 | /* |
38 | |
39 | === modified file 'src/ca/db_access.h' |
40 | --- src/ca/db_access.h 2009-08-14 00:29:56 +0000 |
41 | +++ src/ca/db_access.h 2010-07-05 08:47:25 +0000 |
42 | @@ -524,16 +524,16 @@ |
43 | dbr_double_t value; /* current value */ |
44 | }; |
45 | |
46 | -#ifndef db_accessHFORdb_accessC |
47 | #define dbr_size_n(TYPE,COUNT)\ |
48 | ((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE])) |
49 | |
50 | /* size for each type - array indexed by the DBR_ type code */ |
51 | -epicsShareExtern const unsigned short dbr_size[LAST_BUFFER_TYPE+1]; |
52 | +epicsShareExtern const unsigned short dbr_size[]; |
53 | |
54 | /* size for each type's value - array indexed by the DBR_ type code */ |
55 | -epicsShareExtern const unsigned short dbr_value_size[LAST_BUFFER_TYPE+1]; |
56 | +epicsShareExtern const unsigned short dbr_value_size[]; |
57 | |
58 | +#ifndef db_accessHFORdb_accessC |
59 | /* class for each type's value */ |
60 | enum dbr_value_class { |
61 | dbr_class_int, |
62 | |
63 | === modified file 'src/ca/nciu.cpp' |
64 | --- src/ca/nciu.cpp 2009-08-24 17:03:17 +0000 |
65 | +++ src/ca/nciu.cpp 2010-07-05 08:47:25 +0000 |
66 | @@ -291,9 +291,6 @@ |
67 | if ( countIn > this->count ) { |
68 | throw cacChannel::outOfBounds (); |
69 | } |
70 | - if ( countIn == 0 ) { |
71 | - countIn = this->count; |
72 | - } |
73 | |
74 | // |
75 | // fail out if their arguments are invalid |
76 | |
77 | === modified file 'src/ca/nciu.h' |
78 | --- src/ca/nciu.h 2008-07-28 16:19:50 +0000 |
79 | +++ src/ca/nciu.h 2010-07-05 08:47:25 +0000 |
80 | @@ -41,7 +41,7 @@ |
81 | # include "shareLib.h" |
82 | #endif |
83 | |
84 | -#define CA_MINOR_PROTOCOL_REVISION 11 |
85 | +#define CA_MINOR_PROTOCOL_REVISION 13 |
86 | #include "caProto.h" |
87 | |
88 | #include "cacIO.h" |
89 | @@ -205,6 +205,7 @@ |
90 | void disconnectAllIO ( |
91 | epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & ); |
92 | bool connected ( epicsGuard < epicsMutex > & ) const; |
93 | + unsigned getcount() const { return count; } |
94 | |
95 | private: |
96 | tsDLList < class baseNMIU > eventq; |
97 | |
98 | === modified file 'src/ca/netIO.h' |
99 | --- src/ca/netIO.h 2004-10-04 18:55:40 +0000 |
100 | +++ src/ca/netIO.h 2010-07-05 08:47:25 +0000 |
101 | @@ -83,7 +83,7 @@ |
102 | void show ( |
103 | epicsGuard < epicsMutex > &, unsigned level ) const; |
104 | arrayElementCount getCount ( |
105 | - epicsGuard < epicsMutex > & ) const; |
106 | + epicsGuard < epicsMutex > &, bool allow_zero ) const; |
107 | unsigned getType ( |
108 | epicsGuard < epicsMutex > & ) const; |
109 | unsigned getMask ( |
110 | @@ -242,11 +242,11 @@ |
111 | } |
112 | |
113 | inline arrayElementCount netSubscription::getCount ( |
114 | - epicsGuard < epicsMutex > & guard ) const // X aCC 361 |
115 | + epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361 |
116 | { |
117 | //guard.assertIdenticalMutex ( this->mutex ); |
118 | arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard ); |
119 | - if ( this->count == 0u || this->count > nativeCount ) { |
120 | + if ( (this->count == 0u && !allow_zero) || this->count > nativeCount ) { |
121 | return nativeCount; |
122 | } |
123 | else { |
124 | |
125 | === modified file 'src/ca/oldChannelNotify.cpp' |
126 | --- src/ca/oldChannelNotify.cpp 2007-01-11 21:45:58 +0000 |
127 | +++ src/ca/oldChannelNotify.cpp 2010-07-05 08:47:25 +0000 |
128 | @@ -280,6 +280,9 @@ |
129 | if ( type < 0 ) { |
130 | return ECA_BADTYPE; |
131 | } |
132 | + if ( count == 0 ) |
133 | + return ECA_BADCOUNT; |
134 | + |
135 | unsigned tmpType = static_cast < unsigned > ( type ); |
136 | epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () ); |
137 | pChan->eliminateExcessiveSendBacklog ( guard ); |
138 | |
139 | === modified file 'src/ca/tcpiiu.cpp' |
140 | --- src/ca/tcpiiu.cpp 2009-09-11 00:49:02 +0000 |
141 | +++ src/ca/tcpiiu.cpp 2010-07-05 08:47:25 +0000 |
142 | @@ -1443,6 +1443,8 @@ |
143 | if ( nElem > maxElem ) { |
144 | throw cacChannel::msgBodyCacheTooSmall (); |
145 | } |
146 | + if (nElem == 0 && !CA_V413(this->minorProtocolVersion)) |
147 | + nElem = chan.getcount(); |
148 | comQueSendMsgMinder minder ( this->sendQue, guard ); |
149 | this->sendQue.insertRequestHeader ( |
150 | CA_PROTO_READ_NOTIFY, 0u, |
151 | @@ -1538,7 +1540,8 @@ |
152 | if ( mask > 0xffff ) { |
153 | throw cacChannel::badEventSelection (); |
154 | } |
155 | - arrayElementCount nElem = subscr.getCount ( guard ); |
156 | + arrayElementCount nElem = subscr.getCount ( |
157 | + guard, CA_V413(this->minorProtocolVersion) ); |
158 | arrayElementCount maxBytes; |
159 | if ( CA_V49 ( this->minorProtocolVersion ) ) { |
160 | maxBytes = this->cacRef.largeBufferSizeTCP (); |
161 | @@ -1584,7 +1587,8 @@ |
162 | if ( this->state != iiucs_connected ) { |
163 | return; |
164 | } |
165 | - arrayElementCount nElem = subscr.getCount ( guard ); |
166 | + arrayElementCount nElem = subscr.getCount ( |
167 | + guard, CA_V413(this->minorProtocolVersion) ); |
168 | arrayElementCount maxBytes; |
169 | if ( CA_V49 ( this->minorProtocolVersion ) ) { |
170 | maxBytes = this->cacRef.largeBufferSizeTCP (); |
171 | @@ -1622,7 +1626,8 @@ |
172 | this->sendQue.insertRequestHeader ( |
173 | CA_PROTO_EVENT_CANCEL, 0u, |
174 | static_cast < ca_uint16_t > ( subscr.getType ( guard ) ), |
175 | - static_cast < ca_uint16_t > ( subscr.getCount ( guard ) ), |
176 | + static_cast < ca_uint16_t > ( subscr.getCount ( |
177 | + guard, CA_V413(this->minorProtocolVersion) ) ), |
178 | chan.getSID(guard), subscr.getId(), |
179 | CA_V49 ( this->minorProtocolVersion ) ); |
180 | minder.commit (); |
181 | |
182 | === modified file 'src/catools/caget.c' |
183 | --- src/catools/caget.c 2009-12-15 22:05:55 +0000 |
184 | +++ src/catools/caget.c 2010-07-05 08:47:25 +0000 |
185 | @@ -127,6 +127,7 @@ |
186 | ppv->value = calloc(1, dbr_size_n(args.type, args.count)); |
187 | memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count)); |
188 | ppv->onceConnected = 1; |
189 | + ppv->nElems = args.count; |
190 | nRead++; |
191 | } |
192 | } |
193 | @@ -183,11 +184,9 @@ |
194 | } |
195 | } |
196 | /* Adjust array count */ |
197 | - if (reqElems == 0 || pvs[n].nElems < reqElems){ |
198 | - pvs[n].reqElems = pvs[n].nElems; /* Use full number of points */ |
199 | - } else { |
200 | - pvs[n].reqElems = reqElems; /* Limit to specified number */ |
201 | - } |
202 | + if (reqElems > pvs[n].nElems) |
203 | + reqElems = pvs[n].nElems; |
204 | + pvs[n].reqElems = reqElems; |
205 | |
206 | /* Issue CA request */ |
207 | /* ---------------- */ |
208 | @@ -205,13 +204,13 @@ |
209 | (void*)&pvs[n]); |
210 | } else { |
211 | /* Allocate value structure */ |
212 | - pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems)); |
213 | + pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems)); |
214 | if(!pvs[n].value) { |
215 | fprintf(stderr,"Allocation failed\n"); |
216 | return 1; |
217 | } |
218 | result = ca_array_get(pvs[n].dbrType, |
219 | - pvs[n].reqElems, |
220 | + pvs[n].nElems, |
221 | pvs[n].chid, |
222 | pvs[n].value); |
223 | } |
224 | @@ -253,10 +252,13 @@ |
225 | /* -------------- */ |
226 | |
227 | for (n = 0; n < nPvs; n++) { |
228 | + /* Truncate the data printed to what was requested. */ |
229 | + if (pvs[n].reqElems != 0 && pvs[n].nElems > pvs[n].reqElems) |
230 | + pvs[n].nElems = pvs[n].reqElems; |
231 | |
232 | switch (format) { |
233 | case plain: /* Emulate old caget behaviour */ |
234 | - if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name); |
235 | + if (pvs[n].nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name); |
236 | else printf("%s", pvs[n].name); |
237 | printf("%c", fieldSeparator); |
238 | case terse: |
239 | @@ -270,7 +272,7 @@ |
240 | printf("*** no data available (timeout)\n"); |
241 | else |
242 | { |
243 | - if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) { |
244 | + if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) { |
245 | dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType); |
246 | int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s)); |
247 | char *d = calloc(dlen+1, sizeof(char)); |
248 | @@ -282,8 +284,8 @@ |
249 | fprintf(stderr,"Failed to allocate space for escaped string\n"); |
250 | } |
251 | } else { |
252 | - if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator); |
253 | - for (i=0; i<pvs[n].reqElems; ++i) { |
254 | + if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].nElems, fieldSeparator); |
255 | + for (i=0; i<pvs[n].nElems; ++i) { |
256 | if (i) printf ("%c", fieldSeparator); |
257 | printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i)); |
258 | } |
259 | @@ -315,8 +317,8 @@ |
260 | else { |
261 | printf(" Element count: %lu\n" |
262 | " Value: ", |
263 | - pvs[n].reqElems); |
264 | - if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) { |
265 | + pvs[n].nElems); |
266 | + if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].nElems > 1)) { |
267 | dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType); |
268 | int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s)); |
269 | char *d = calloc(dlen+1, sizeof(char)); |
270 | @@ -328,7 +330,7 @@ |
271 | fprintf(stderr,"Failed to allocate space for escaped string\n"); |
272 | } |
273 | } else { |
274 | - for (i=0; i<pvs[n].reqElems; ++i) { |
275 | + for (i=0; i<pvs[n].nElems; ++i) { |
276 | if (i) printf ("%c", fieldSeparator); |
277 | printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i)); |
278 | } |
279 | |
280 | === modified file 'src/catools/camonitor.c' |
281 | --- src/catools/camonitor.c 2009-12-15 22:05:55 +0000 |
282 | +++ src/catools/camonitor.c 2010-07-05 08:47:25 +0000 |
283 | @@ -107,6 +107,7 @@ |
284 | if (args.status == ECA_NORMAL) |
285 | { |
286 | pv->dbrType = args.type; |
287 | + pv->nElems = args.count; |
288 | memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count)); |
289 | |
290 | print_time_val_sts(pv, reqElems); |
291 | @@ -150,11 +151,9 @@ |
292 | ppv->dbrType = DBR_TIME_STRING; |
293 | } |
294 | /* Adjust array count */ |
295 | - if (reqElems == 0 || ppv->nElems < reqElems){ |
296 | - ppv->reqElems = ppv->nElems; /* Use full number of points */ |
297 | - } else { |
298 | - ppv->reqElems = reqElems; /* Limit to specified number */ |
299 | - } |
300 | + if (reqElems > ppv->nElems) |
301 | + reqElems = ppv->nElems; |
302 | + ppv->reqElems = reqElems; |
303 | |
304 | ppv->onceConnected = 1; |
305 | nConn++; |
306 | @@ -163,7 +162,7 @@ |
307 | /* install monitor once with first connect */ |
308 | if ( ! ppv->value ) { |
309 | /* Allocate value structure */ |
310 | - ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->reqElems)); |
311 | + ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->nElems)); |
312 | if ( ppv->value ) { |
313 | ppv->status = ca_create_subscription(ppv->dbrType, |
314 | ppv->reqElems, |
315 | |
316 | === modified file 'src/catools/tool_lib.c' |
317 | --- src/catools/tool_lib.c 2009-12-15 22:05:55 +0000 |
318 | +++ src/catools/tool_lib.c 2010-07-05 08:47:25 +0000 |
319 | @@ -455,8 +455,8 @@ |
320 | printf("Failed to allocate for print_time_val_sts\n"); \ |
321 | } \ |
322 | } else { \ |
323 | - if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->reqElems); \ |
324 | - for (i=0; i<pv->reqElems; ++i) { \ |
325 | + if (reqElems || pv->nElems > 1) printf("%c%lu", fieldSeparator, pv->nElems); \ |
326 | + for (i=0; i<pv->nElems; ++i) { \ |
327 | printf("%c%s", fieldSeparator, val2str(value, TYPE_ENUM, i)); \ |
328 | } \ |
329 | } \ |
330 | @@ -492,7 +492,7 @@ |
331 | tsInitS = 1; |
332 | } |
333 | |
334 | - if (pv->reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name); |
335 | + if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name); |
336 | else printf("%s", pv->name); |
337 | printf("%c", fieldSeparator); |
338 | if (!pv->onceConnected) |
339 | |
340 | === modified file 'src/catools/tool_lib.h' |
341 | --- src/catools/tool_lib.h 2009-12-15 22:05:55 +0000 |
342 | +++ src/catools/tool_lib.h 2010-07-05 08:47:25 +0000 |
343 | @@ -64,8 +64,8 @@ |
344 | chid chid; |
345 | long dbfType; |
346 | long dbrType; |
347 | - unsigned long nElems; |
348 | - unsigned long reqElems; |
349 | + unsigned long nElems; // True length of data in value |
350 | + unsigned long reqElems; // Requested length of data |
351 | int status; |
352 | void* value; |
353 | epicsTimeStamp tsPreviousC; |
354 | |
355 | === modified file 'src/db/db_access.c' |
356 | --- src/db/db_access.c 2010-06-16 19:58:00 +0000 |
357 | +++ src/db/db_access.c 2010-07-05 08:47:25 +0000 |
358 | @@ -149,10 +149,29 @@ |
359 | int epicsShareAPI db_get_field(struct dbAddr *paddr, |
360 | int buffer_type, void *pbuffer, int no_elements, void *pfl) |
361 | { |
362 | + long nRequest = no_elements; |
363 | + int result = db_get_field_and_count( |
364 | + paddr, buffer_type, pbuffer, &nRequest, pfl); |
365 | + if (nRequest < no_elements) |
366 | + /* If the database request returned fewer elements than requested then |
367 | + * fill out the remainder of the array with zeros. */ |
368 | + memset( |
369 | + (char *)pbuffer + dbr_size_n(buffer_type, nRequest), 0, |
370 | + (no_elements - nRequest) * dbr_value_size[buffer_type]); |
371 | + return result; |
372 | +} |
373 | + |
374 | +/* Performs the work of the public db_get_field API, but also returns the number |
375 | + * of elements actually copied to the buffer. The caller is responsible for |
376 | + * zeroing the remaining part of the buffer. */ |
377 | +int epicsShareAPI db_get_field_and_count( |
378 | + struct dbAddr *paddr, int buffer_type, |
379 | + void *pbuffer, long *nRequest, void *pfl) |
380 | +{ |
381 | long status; |
382 | long options; |
383 | - long nRequest; |
384 | long i; |
385 | + long zero = 0; |
386 | |
387 | /* The order of the DBR* elements in the "new" structures below is |
388 | * very important and must correspond to the order of processing |
389 | @@ -161,82 +180,26 @@ |
390 | |
391 | switch(buffer_type) { |
392 | case(oldDBR_STRING): |
393 | - { |
394 | - DBSTRING *pvalue = (DBSTRING *)pbuffer; |
395 | - |
396 | - options = 0; |
397 | - nRequest = no_elements; |
398 | - status = dbGetField(paddr, DBR_STRING, pbuffer, &options, &nRequest, |
399 | - pfl); |
400 | - for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0; |
401 | - } |
402 | + status = dbGetField(paddr, DBR_STRING, pbuffer, &zero, nRequest, pfl); |
403 | break; |
404 | /* case(oldDBR_INT): */ |
405 | case(oldDBR_SHORT): |
406 | - { |
407 | - dbr_short_t *pvalue = (dbr_short_t *)pbuffer; |
408 | - |
409 | - options = 0; |
410 | - nRequest = no_elements; |
411 | - status = dbGetField(paddr, DBR_SHORT, pbuffer, &options, &nRequest, |
412 | - pfl); |
413 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
414 | - } |
415 | + status = dbGetField(paddr, DBR_SHORT, pbuffer, &zero, nRequest, pfl); |
416 | break; |
417 | case(oldDBR_FLOAT): |
418 | - { |
419 | - dbr_float_t *pvalue = (dbr_float_t *)pbuffer; |
420 | - |
421 | - options = 0; |
422 | - nRequest = no_elements; |
423 | - status = dbGetField(paddr, DBR_FLOAT, pbuffer, &options, &nRequest, |
424 | - pfl); |
425 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
426 | - } |
427 | + status = dbGetField(paddr, DBR_FLOAT, pbuffer, &zero, nRequest, pfl); |
428 | break; |
429 | case(oldDBR_ENUM): |
430 | - { |
431 | - dbr_enum_t *pvalue = (dbr_enum_t *)pbuffer; |
432 | - |
433 | - options = 0; |
434 | - nRequest = no_elements; |
435 | - status = dbGetField(paddr, DBR_ENUM, pbuffer, &options, &nRequest, |
436 | - pfl); |
437 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
438 | - } |
439 | + status = dbGetField(paddr, DBR_ENUM, pbuffer, &zero, nRequest, pfl); |
440 | break; |
441 | case(oldDBR_CHAR): |
442 | - { |
443 | - dbr_char_t *pvalue = (dbr_char_t *)pbuffer; |
444 | - |
445 | - options = 0; |
446 | - nRequest = no_elements; |
447 | - status = dbGetField(paddr, DBR_CHAR, pbuffer, &options, &nRequest, |
448 | - pfl); |
449 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
450 | - } |
451 | + status = dbGetField(paddr, DBR_CHAR, pbuffer, &zero, nRequest, pfl); |
452 | break; |
453 | case(oldDBR_LONG): |
454 | - { |
455 | - dbr_long_t *pvalue = (dbr_long_t *)pbuffer; |
456 | - |
457 | - options = 0; |
458 | - nRequest = no_elements; |
459 | - status = dbGetField(paddr, DBR_LONG, pbuffer, &options, &nRequest, |
460 | - pfl); |
461 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
462 | - } |
463 | + status = dbGetField(paddr, DBR_LONG, pbuffer, &zero, nRequest, pfl); |
464 | break; |
465 | case(oldDBR_DOUBLE): |
466 | - { |
467 | - dbr_double_t *pvalue = (dbr_double_t *)pbuffer; |
468 | - |
469 | - options = 0; |
470 | - nRequest = no_elements; |
471 | - status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &options, &nRequest, |
472 | - pfl); |
473 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
474 | - } |
475 | + status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl); |
476 | break; |
477 | |
478 | case(oldDBR_STS_STRING): |
479 | @@ -246,20 +209,14 @@ |
480 | struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer; |
481 | struct { |
482 | DBRstatus |
483 | - } newSt; |
484 | - DBSTRING *pvalue = (DBSTRING *)pold->value; |
485 | + } new; |
486 | |
487 | options = DBR_STATUS; |
488 | - nRequest = 0; |
489 | - status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest, |
490 | - pfl); |
491 | - pold->status = newSt.status; |
492 | - pold->severity = newSt.severity; |
493 | - options = 0; |
494 | - nRequest = no_elements; |
495 | - status = dbGetField(paddr, DBR_STRING, pold->value, &options, |
496 | - &nRequest, pfl); |
497 | - for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0; |
498 | + status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl); |
499 | + pold->status = new.status; |
500 | + pold->severity = new.severity; |
501 | + status = dbGetField(paddr, DBR_STRING, pold->value, &zero, |
502 | + nRequest, pfl); |
503 | } |
504 | break; |
505 | /* case(oldDBR_STS_INT): */ |
506 | @@ -268,20 +225,14 @@ |
507 | struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer; |
508 | struct { |
509 | DBRstatus |
510 | - } newSt; |
511 | - dbr_short_t *pvalue = &pold->value; |
512 | + } new; |
513 | |
514 | options = DBR_STATUS; |
515 | - nRequest = 0; |
516 | - status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest, |
517 | - pfl); |
518 | - pold->status = newSt.status; |
519 | - pold->severity = newSt.severity; |
520 | - options = 0; |
521 | - nRequest = no_elements; |
522 | - status = dbGetField(paddr, DBR_SHORT, &pold->value, &options, |
523 | - &nRequest, pfl); |
524 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
525 | + status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl); |
526 | + pold->status = new.status; |
527 | + pold->severity = new.severity; |
528 | + status = dbGetField(paddr, DBR_SHORT, &pold->value, &zero, |
529 | + nRequest, pfl); |
530 | } |
531 | break; |
532 | case(oldDBR_STS_FLOAT): |
533 | @@ -289,20 +240,14 @@ |
534 | struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer; |
535 | struct { |
536 | DBRstatus |
537 | - } newSt; |
538 | - dbr_float_t *pvalue = &pold->value; |
539 | + } new; |
540 | |
541 | options = DBR_STATUS; |
542 | - nRequest = 0; |
543 | - status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest, |
544 | - pfl); |
545 | - pold->status = newSt.status; |
546 | - pold->severity = newSt.severity; |
547 | - options = 0; |
548 | - nRequest = no_elements; |
549 | - status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options, |
550 | - &nRequest, pfl); |
551 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
552 | + status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl); |
553 | + pold->status = new.status; |
554 | + pold->severity = new.severity; |
555 | + status = dbGetField(paddr, DBR_FLOAT, &pold->value, &zero, |
556 | + nRequest, pfl); |
557 | } |
558 | break; |
559 | case(oldDBR_STS_ENUM): |
560 | @@ -310,20 +255,14 @@ |
561 | struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer; |
562 | struct { |
563 | DBRstatus |
564 | - } newSt; |
565 | - dbr_enum_t *pvalue = &pold->value; |
566 | + } new; |
567 | |
568 | options = DBR_STATUS; |
569 | - nRequest = 0; |
570 | - status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest, |
571 | - pfl); |
572 | - pold->status = newSt.status; |
573 | - pold->severity = newSt.severity; |
574 | - options = 0; |
575 | - nRequest = no_elements; |
576 | - status = dbGetField(paddr, DBR_ENUM, &pold->value, &options, |
577 | - &nRequest, pfl); |
578 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
579 | + status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl); |
580 | + pold->status = new.status; |
581 | + pold->severity = new.severity; |
582 | + status = dbGetField(paddr, DBR_ENUM, &pold->value, &zero, |
583 | + nRequest, pfl); |
584 | } |
585 | break; |
586 | case(oldDBR_STS_CHAR): |
587 | @@ -331,20 +270,14 @@ |
588 | struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer; |
589 | struct { |
590 | DBRstatus |
591 | - } newSt; |
592 | - dbr_char_t *pvalue = &pold->value; |
593 | + } new; |
594 | |
595 | options = DBR_STATUS; |
596 | - nRequest = 0; |
597 | - status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest, |
598 | - pfl); |
599 | - pold->status = newSt.status; |
600 | - pold->severity = newSt.severity; |
601 | - options = 0; |
602 | - nRequest = no_elements; |
603 | - status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options, |
604 | - &nRequest, pfl); |
605 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
606 | + status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl); |
607 | + pold->status = new.status; |
608 | + pold->severity = new.severity; |
609 | + status = dbGetField(paddr, DBR_UCHAR, &pold->value, &zero, |
610 | + nRequest, pfl); |
611 | } |
612 | break; |
613 | case(oldDBR_STS_LONG): |
614 | @@ -352,20 +285,14 @@ |
615 | struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer; |
616 | struct { |
617 | DBRstatus |
618 | - } newSt; |
619 | - dbr_long_t *pvalue = &pold->value; |
620 | + } new; |
621 | |
622 | options = DBR_STATUS; |
623 | - nRequest = 0; |
624 | - status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest, |
625 | - pfl); |
626 | - pold->status = newSt.status; |
627 | - pold->severity = newSt.severity; |
628 | - options = 0; |
629 | - nRequest = no_elements; |
630 | - status = dbGetField(paddr, DBR_LONG, &pold->value, &options, |
631 | - &nRequest, pfl); |
632 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
633 | + status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl); |
634 | + pold->status = new.status; |
635 | + pold->severity = new.severity; |
636 | + status = dbGetField(paddr, DBR_LONG, &pold->value, &zero, |
637 | + nRequest, pfl); |
638 | } |
639 | break; |
640 | case(oldDBR_STS_DOUBLE): |
641 | @@ -373,20 +300,15 @@ |
642 | struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer; |
643 | struct { |
644 | DBRstatus |
645 | - } newSt; |
646 | - dbr_double_t *pvalue = &pold->value; |
647 | + } new; |
648 | |
649 | options = DBR_STATUS; |
650 | - nRequest = 0; |
651 | - status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest, |
652 | - pfl); |
653 | - pold->status = newSt.status; |
654 | - pold->severity = newSt.severity; |
655 | + status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl); |
656 | + pold->status = new.status; |
657 | + pold->severity = new.severity; |
658 | options = 0; |
659 | - nRequest = no_elements; |
660 | status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options, |
661 | - &nRequest, pfl); |
662 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
663 | + nRequest, pfl); |
664 | } |
665 | break; |
666 | |
667 | @@ -396,21 +318,16 @@ |
668 | struct { |
669 | DBRstatus |
670 | DBRtime |
671 | - } newSt; |
672 | - DBSTRING *pvalue = (DBSTRING *)(pold->value); |
673 | + } new; |
674 | |
675 | options = DBR_STATUS | DBR_TIME; |
676 | - nRequest = 0; |
677 | - status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest, |
678 | - pfl); |
679 | - pold->status = newSt.status; |
680 | - pold->severity = newSt.severity; |
681 | - pold->stamp = newSt.time; /* structure copy */ |
682 | + status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl); |
683 | + pold->status = new.status; |
684 | + pold->severity = new.severity; |
685 | + pold->stamp = new.time; /* structure copy */ |
686 | options = 0; |
687 | - nRequest = no_elements; |
688 | - status = dbGetField(paddr, DBR_STRING, pold->value, &options, |
689 | - &nRequest, pfl); |
690 | - for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0; |
691 | + status = dbGetField(paddr, DBR_STRING, pold->value, &options, |
692 | + nRequest, pfl); |
693 | } |
694 | break; |
695 | /* case(oldDBR_TIME_INT): */ |
696 | @@ -420,21 +337,16 @@ |
697 | struct { |
698 | DBRstatus |
699 | DBRtime |
700 | - } newSt; |
701 | - dbr_short_t *pvalue = &pold->value; |
702 | + } new; |
703 | |
704 | options = DBR_STATUS | DBR_TIME; |
705 | - nRequest = 0; |
706 | - status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest, |
707 | - pfl); |
708 | - pold->status = newSt.status; |
709 | - pold->severity = newSt.severity; |
710 | - pold->stamp = newSt.time; /* structure copy */ |
711 | + status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl); |
712 | + pold->status = new.status; |
713 | + pold->severity = new.severity; |
714 | + pold->stamp = new.time; /* structure copy */ |
715 | options = 0; |
716 | - nRequest = no_elements; |
717 | status = dbGetField(paddr, DBR_SHORT, &pold->value, &options, |
718 | - &nRequest, pfl); |
719 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
720 | + nRequest, pfl); |
721 | } |
722 | break; |
723 | case(oldDBR_TIME_FLOAT): |
724 | @@ -443,21 +355,16 @@ |
725 | struct { |
726 | DBRstatus |
727 | DBRtime |
728 | - } newSt; |
729 | - dbr_float_t *pvalue = &pold->value; |
730 | + } new; |
731 | |
732 | options = DBR_STATUS | DBR_TIME; |
733 | - nRequest = 0; |
734 | - status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest, |
735 | - pfl); |
736 | - pold->status = newSt.status; |
737 | - pold->severity = newSt.severity; |
738 | - pold->stamp = newSt.time; /* structure copy */ |
739 | + status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl); |
740 | + pold->status = new.status; |
741 | + pold->severity = new.severity; |
742 | + pold->stamp = new.time; /* structure copy */ |
743 | options = 0; |
744 | - nRequest = no_elements; |
745 | status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options, |
746 | - &nRequest, pfl); |
747 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
748 | + nRequest, pfl); |
749 | } |
750 | break; |
751 | case(oldDBR_TIME_ENUM): |
752 | @@ -466,21 +373,16 @@ |
753 | struct { |
754 | DBRstatus |
755 | DBRtime |
756 | - } newSt; |
757 | - dbr_enum_t *pvalue = &pold->value; |
758 | + } new; |
759 | |
760 | options = DBR_STATUS | DBR_TIME; |
761 | - nRequest = 0; |
762 | - status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest, |
763 | - pfl); |
764 | - pold->status = newSt.status; |
765 | - pold->severity = newSt.severity; |
766 | - pold->stamp = newSt.time; /* structure copy */ |
767 | + status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl); |
768 | + pold->status = new.status; |
769 | + pold->severity = new.severity; |
770 | + pold->stamp = new.time; /* structure copy */ |
771 | options = 0; |
772 | - nRequest = no_elements; |
773 | status = dbGetField(paddr, DBR_ENUM, &pold->value, &options, |
774 | - &nRequest, pfl); |
775 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
776 | + nRequest, pfl); |
777 | } |
778 | break; |
779 | case(oldDBR_TIME_CHAR): |
780 | @@ -489,21 +391,16 @@ |
781 | struct { |
782 | DBRstatus |
783 | DBRtime |
784 | - } newSt; |
785 | - dbr_char_t *pvalue = &pold->value; |
786 | + } new; |
787 | |
788 | options = DBR_STATUS | DBR_TIME; |
789 | - nRequest = 0; |
790 | - status = dbGetField(paddr, DBR_CHAR, &newSt, &options, &nRequest, |
791 | - pfl); |
792 | - pold->status = newSt.status; |
793 | - pold->severity = newSt.severity; |
794 | - pold->stamp = newSt.time; /* structure copy */ |
795 | + status = dbGetField(paddr, DBR_CHAR, &new, &options, &zero, pfl); |
796 | + pold->status = new.status; |
797 | + pold->severity = new.severity; |
798 | + pold->stamp = new.time; /* structure copy */ |
799 | options = 0; |
800 | - nRequest = no_elements; |
801 | status = dbGetField(paddr, DBR_CHAR, &pold->value, &options, |
802 | - &nRequest, pfl); |
803 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
804 | + nRequest, pfl); |
805 | } |
806 | break; |
807 | case(oldDBR_TIME_LONG): |
808 | @@ -512,21 +409,16 @@ |
809 | struct { |
810 | DBRstatus |
811 | DBRtime |
812 | - } newSt; |
813 | - dbr_long_t *pvalue = &pold->value; |
814 | + } new; |
815 | |
816 | options = DBR_STATUS | DBR_TIME; |
817 | - nRequest = 0; |
818 | - status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest, |
819 | - pfl); |
820 | - pold->status = newSt.status; |
821 | - pold->severity = newSt.severity; |
822 | - pold->stamp = newSt.time; /* structure copy */ |
823 | + status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl); |
824 | + pold->status = new.status; |
825 | + pold->severity = new.severity; |
826 | + pold->stamp = new.time; /* structure copy */ |
827 | options = 0; |
828 | - nRequest = no_elements; |
829 | status = dbGetField(paddr, DBR_LONG, &pold->value, &options, |
830 | - &nRequest, pfl); |
831 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
832 | + nRequest, pfl); |
833 | } |
834 | break; |
835 | case(oldDBR_TIME_DOUBLE): |
836 | @@ -535,21 +427,16 @@ |
837 | struct { |
838 | DBRstatus |
839 | DBRtime |
840 | - } newSt; |
841 | - dbr_double_t *pvalue = &pold->value; |
842 | + } new; |
843 | |
844 | options = DBR_STATUS | DBR_TIME; |
845 | - nRequest = 0; |
846 | - status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest, |
847 | - pfl); |
848 | - pold->status = newSt.status; |
849 | - pold->severity = newSt.severity; |
850 | - pold->stamp = newSt.time; /* structure copy */ |
851 | + status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl); |
852 | + pold->status = new.status; |
853 | + pold->severity = new.severity; |
854 | + pold->stamp = new.time; /* structure copy */ |
855 | options = 0; |
856 | - nRequest = no_elements; |
857 | status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options, |
858 | - &nRequest, pfl); |
859 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
860 | + nRequest, pfl); |
861 | } |
862 | break; |
863 | |
864 | @@ -563,28 +450,23 @@ |
865 | DBRunits |
866 | DBRgrLong |
867 | DBRalLong |
868 | - } newSt; |
869 | - dbr_short_t *pvalue = &pold->value; |
870 | + } new; |
871 | |
872 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; |
873 | - nRequest = 0; |
874 | - status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest, |
875 | - pfl); |
876 | - pold->status = newSt.status; |
877 | - pold->severity = newSt.severity; |
878 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
879 | + status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl); |
880 | + pold->status = new.status; |
881 | + pold->severity = new.severity; |
882 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
883 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
884 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
885 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
886 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
887 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
888 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
889 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
890 | + pold->upper_disp_limit = new.upper_disp_limit; |
891 | + pold->lower_disp_limit = new.lower_disp_limit; |
892 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
893 | + pold->upper_warning_limit = new.upper_warning_limit; |
894 | + pold->lower_warning_limit = new.lower_warning_limit; |
895 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
896 | options = 0; |
897 | - nRequest = no_elements; |
898 | status = dbGetField(paddr, DBR_SHORT, &pold->value, &options, |
899 | - &nRequest, pfl); |
900 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
901 | + nRequest, pfl); |
902 | } |
903 | break; |
904 | case(oldDBR_GR_FLOAT): |
905 | @@ -596,30 +478,25 @@ |
906 | DBRprecision |
907 | DBRgrDouble |
908 | DBRalDouble |
909 | - } newSt; |
910 | - dbr_float_t *pvalue = &pold->value; |
911 | + } new; |
912 | |
913 | options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | |
914 | DBR_AL_DOUBLE; |
915 | - nRequest = 0; |
916 | - status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest, |
917 | - pfl); |
918 | - pold->status = newSt.status; |
919 | - pold->severity = newSt.severity; |
920 | - pold->precision = newSt.precision.dp; |
921 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
922 | + status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl); |
923 | + pold->status = new.status; |
924 | + pold->severity = new.severity; |
925 | + pold->precision = new.precision.dp; |
926 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
927 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
928 | - pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit); |
929 | - pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit); |
930 | - pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit); |
931 | - pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit); |
932 | - pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit); |
933 | - pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit); |
934 | + pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit); |
935 | + pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit); |
936 | + pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit); |
937 | + pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit); |
938 | + pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit); |
939 | + pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit); |
940 | options = 0; |
941 | - nRequest = no_elements; |
942 | status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options, |
943 | - &nRequest, pfl); |
944 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
945 | + nRequest, pfl); |
946 | } |
947 | break; |
948 | /* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */ |
949 | @@ -631,28 +508,23 @@ |
950 | DBRunits |
951 | DBRgrLong |
952 | DBRalLong |
953 | - } newSt; |
954 | - dbr_char_t *pvalue = &pold->value; |
955 | + } new; |
956 | |
957 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; |
958 | - nRequest = 0; |
959 | - status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest, |
960 | - pfl); |
961 | - pold->status = newSt.status; |
962 | - pold->severity = newSt.severity; |
963 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
964 | + status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl); |
965 | + pold->status = new.status; |
966 | + pold->severity = new.severity; |
967 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
968 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
969 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
970 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
971 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
972 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
973 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
974 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
975 | + pold->upper_disp_limit = new.upper_disp_limit; |
976 | + pold->lower_disp_limit = new.lower_disp_limit; |
977 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
978 | + pold->upper_warning_limit = new.upper_warning_limit; |
979 | + pold->lower_warning_limit = new.lower_warning_limit; |
980 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
981 | options = 0; |
982 | - nRequest = no_elements; |
983 | status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options, |
984 | - &nRequest, pfl); |
985 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
986 | + nRequest, pfl); |
987 | } |
988 | break; |
989 | case(oldDBR_GR_LONG): |
990 | @@ -663,28 +535,23 @@ |
991 | DBRunits |
992 | DBRgrLong |
993 | DBRalLong |
994 | - } newSt; |
995 | - dbr_long_t *pvalue = &pold->value; |
996 | + } new; |
997 | |
998 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; |
999 | - nRequest = 0; |
1000 | - status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest, |
1001 | - pfl); |
1002 | - pold->status = newSt.status; |
1003 | - pold->severity = newSt.severity; |
1004 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1005 | + status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl); |
1006 | + pold->status = new.status; |
1007 | + pold->severity = new.severity; |
1008 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1009 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1010 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1011 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1012 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1013 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1014 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1015 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1016 | + pold->upper_disp_limit = new.upper_disp_limit; |
1017 | + pold->lower_disp_limit = new.lower_disp_limit; |
1018 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1019 | + pold->upper_warning_limit = new.upper_warning_limit; |
1020 | + pold->lower_warning_limit = new.lower_warning_limit; |
1021 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1022 | options = 0; |
1023 | - nRequest = no_elements; |
1024 | status = dbGetField(paddr, DBR_LONG, &pold->value, &options, |
1025 | - &nRequest, pfl); |
1026 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1027 | + nRequest, pfl); |
1028 | } |
1029 | break; |
1030 | case(oldDBR_GR_DOUBLE): |
1031 | @@ -696,30 +563,25 @@ |
1032 | DBRprecision |
1033 | DBRgrDouble |
1034 | DBRalDouble |
1035 | - } newSt; |
1036 | - dbr_double_t *pvalue = &pold->value; |
1037 | + } new; |
1038 | |
1039 | options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | |
1040 | DBR_AL_DOUBLE; |
1041 | - nRequest = 0; |
1042 | - status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest, |
1043 | - pfl); |
1044 | - pold->status = newSt.status; |
1045 | - pold->severity = newSt.severity; |
1046 | - pold->precision = newSt.precision.dp; |
1047 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1048 | + status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl); |
1049 | + pold->status = new.status; |
1050 | + pold->severity = new.severity; |
1051 | + pold->precision = new.precision.dp; |
1052 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1053 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1054 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1055 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1056 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1057 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1058 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1059 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1060 | + pold->upper_disp_limit = new.upper_disp_limit; |
1061 | + pold->lower_disp_limit = new.lower_disp_limit; |
1062 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1063 | + pold->upper_warning_limit = new.upper_warning_limit; |
1064 | + pold->lower_warning_limit = new.lower_warning_limit; |
1065 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1066 | options = 0; |
1067 | - nRequest = no_elements; |
1068 | status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options, |
1069 | - &nRequest, pfl); |
1070 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1071 | + nRequest, pfl); |
1072 | } |
1073 | break; |
1074 | |
1075 | @@ -733,31 +595,26 @@ |
1076 | DBRgrLong |
1077 | DBRctrlLong |
1078 | DBRalLong |
1079 | - } newSt; |
1080 | - dbr_short_t *pvalue = &pold->value; |
1081 | + } new; |
1082 | |
1083 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | |
1084 | DBR_AL_LONG; |
1085 | - nRequest = 0; |
1086 | - status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest, |
1087 | - pfl); |
1088 | - pold->status = newSt.status; |
1089 | - pold->severity = newSt.severity; |
1090 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1091 | + status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl); |
1092 | + pold->status = new.status; |
1093 | + pold->severity = new.severity; |
1094 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1095 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1096 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1097 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1098 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1099 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1100 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1101 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1102 | - pold->upper_ctrl_limit = newSt.upper_ctrl_limit; |
1103 | - pold->lower_ctrl_limit = newSt.lower_ctrl_limit; |
1104 | + pold->upper_disp_limit = new.upper_disp_limit; |
1105 | + pold->lower_disp_limit = new.lower_disp_limit; |
1106 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1107 | + pold->upper_warning_limit = new.upper_warning_limit; |
1108 | + pold->lower_warning_limit = new.lower_warning_limit; |
1109 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1110 | + pold->upper_ctrl_limit = new.upper_ctrl_limit; |
1111 | + pold->lower_ctrl_limit = new.lower_ctrl_limit; |
1112 | options = 0; |
1113 | - nRequest = no_elements; |
1114 | status = dbGetField(paddr, DBR_SHORT, &pold->value, &options, |
1115 | - &nRequest, pfl); |
1116 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1117 | + nRequest, pfl); |
1118 | } |
1119 | break; |
1120 | case(oldDBR_CTRL_FLOAT): |
1121 | @@ -770,32 +627,27 @@ |
1122 | DBRgrDouble |
1123 | DBRctrlDouble |
1124 | DBRalDouble |
1125 | - } newSt; |
1126 | - dbr_float_t *pvalue = &pold->value; |
1127 | + } new; |
1128 | |
1129 | options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | |
1130 | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE; |
1131 | - nRequest = 0; |
1132 | - status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest, |
1133 | - pfl); |
1134 | - pold->status = newSt.status; |
1135 | - pold->severity = newSt.severity; |
1136 | - pold->precision = newSt.precision.dp; |
1137 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1138 | + status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl); |
1139 | + pold->status = new.status; |
1140 | + pold->severity = new.severity; |
1141 | + pold->precision = new.precision.dp; |
1142 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1143 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1144 | - pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit); |
1145 | - pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit); |
1146 | - pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit); |
1147 | - pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit); |
1148 | - pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit); |
1149 | - pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit); |
1150 | - pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit); |
1151 | - pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit); |
1152 | + pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit); |
1153 | + pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit); |
1154 | + pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit); |
1155 | + pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit); |
1156 | + pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit); |
1157 | + pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit); |
1158 | + pold->upper_ctrl_limit = epicsConvertDoubleToFloat(new.upper_ctrl_limit); |
1159 | + pold->lower_ctrl_limit = epicsConvertDoubleToFloat(new.lower_ctrl_limit); |
1160 | options = 0; |
1161 | - nRequest = no_elements; |
1162 | status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options, |
1163 | - &nRequest, pfl); |
1164 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1165 | + nRequest, pfl); |
1166 | } |
1167 | break; |
1168 | case(oldDBR_GR_ENUM): |
1169 | @@ -805,29 +657,24 @@ |
1170 | struct { |
1171 | DBRstatus |
1172 | DBRenumStrs |
1173 | - } newSt; |
1174 | + } new; |
1175 | short no_str; |
1176 | - dbr_enum_t *pvalue = &pold->value; |
1177 | |
1178 | memset(pold, '\0', sizeof(struct dbr_ctrl_enum)); |
1179 | /* first get status and severity */ |
1180 | options = DBR_STATUS | DBR_ENUM_STRS; |
1181 | - nRequest = 0; |
1182 | - status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest, |
1183 | - pfl); |
1184 | - pold->status = newSt.status; |
1185 | - pold->severity = newSt.severity; |
1186 | - no_str = newSt.no_str; |
1187 | + status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl); |
1188 | + pold->status = new.status; |
1189 | + pold->severity = new.severity; |
1190 | + no_str = new.no_str; |
1191 | if (no_str>16) no_str=16; |
1192 | pold->no_str = no_str; |
1193 | for (i = 0; i < no_str; i++) |
1194 | - strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i])); |
1195 | + strncpy(pold->strs[i], new.strs[i], sizeof(pold->strs[i])); |
1196 | /*now get values*/ |
1197 | options = 0; |
1198 | - nRequest = no_elements; |
1199 | status = dbGetField(paddr, DBR_ENUM, &pold->value, &options, |
1200 | - &nRequest, pfl); |
1201 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1202 | + nRequest, pfl); |
1203 | } |
1204 | break; |
1205 | case(oldDBR_CTRL_CHAR): |
1206 | @@ -839,31 +686,26 @@ |
1207 | DBRgrLong |
1208 | DBRctrlLong |
1209 | DBRalLong |
1210 | - } newSt; |
1211 | - dbr_char_t *pvalue = &pold->value; |
1212 | + } new; |
1213 | |
1214 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | |
1215 | DBR_AL_LONG; |
1216 | - nRequest = 0; |
1217 | - status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest, |
1218 | - pfl); |
1219 | - pold->status = newSt.status; |
1220 | - pold->severity = newSt.severity; |
1221 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1222 | + status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl); |
1223 | + pold->status = new.status; |
1224 | + pold->severity = new.severity; |
1225 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1226 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1227 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1228 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1229 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1230 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1231 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1232 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1233 | - pold->upper_ctrl_limit = newSt.upper_ctrl_limit; |
1234 | - pold->lower_ctrl_limit = newSt.lower_ctrl_limit; |
1235 | + pold->upper_disp_limit = new.upper_disp_limit; |
1236 | + pold->lower_disp_limit = new.lower_disp_limit; |
1237 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1238 | + pold->upper_warning_limit = new.upper_warning_limit; |
1239 | + pold->lower_warning_limit = new.lower_warning_limit; |
1240 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1241 | + pold->upper_ctrl_limit = new.upper_ctrl_limit; |
1242 | + pold->lower_ctrl_limit = new.lower_ctrl_limit; |
1243 | options = 0; |
1244 | - nRequest = no_elements; |
1245 | status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options, |
1246 | - &nRequest, pfl); |
1247 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1248 | + nRequest, pfl); |
1249 | } |
1250 | break; |
1251 | case(oldDBR_CTRL_LONG): |
1252 | @@ -875,31 +717,26 @@ |
1253 | DBRgrLong |
1254 | DBRctrlLong |
1255 | DBRalLong |
1256 | - } newSt; |
1257 | - dbr_long_t *pvalue = &pold->value; |
1258 | + } new; |
1259 | |
1260 | options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | |
1261 | DBR_AL_LONG; |
1262 | - nRequest = 0; |
1263 | - status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest, |
1264 | - pfl); |
1265 | - pold->status = newSt.status; |
1266 | - pold->severity = newSt.severity; |
1267 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1268 | + status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl); |
1269 | + pold->status = new.status; |
1270 | + pold->severity = new.severity; |
1271 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1272 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1273 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1274 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1275 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1276 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1277 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1278 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1279 | - pold->upper_ctrl_limit = newSt.upper_ctrl_limit; |
1280 | - pold->lower_ctrl_limit = newSt.lower_ctrl_limit; |
1281 | + pold->upper_disp_limit = new.upper_disp_limit; |
1282 | + pold->lower_disp_limit = new.lower_disp_limit; |
1283 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1284 | + pold->upper_warning_limit = new.upper_warning_limit; |
1285 | + pold->lower_warning_limit = new.lower_warning_limit; |
1286 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1287 | + pold->upper_ctrl_limit = new.upper_ctrl_limit; |
1288 | + pold->lower_ctrl_limit = new.lower_ctrl_limit; |
1289 | options = 0; |
1290 | - nRequest = no_elements; |
1291 | status = dbGetField(paddr, DBR_LONG, &pold->value, &options, |
1292 | - &nRequest, pfl); |
1293 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1294 | + nRequest, pfl); |
1295 | } |
1296 | break; |
1297 | case(oldDBR_CTRL_DOUBLE): |
1298 | @@ -912,32 +749,27 @@ |
1299 | DBRgrDouble |
1300 | DBRctrlDouble |
1301 | DBRalDouble |
1302 | - } newSt; |
1303 | - dbr_double_t *pvalue = &pold->value; |
1304 | + } new; |
1305 | |
1306 | options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | |
1307 | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE; |
1308 | - nRequest = 0; |
1309 | - status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest, |
1310 | - pfl); |
1311 | - pold->status = newSt.status; |
1312 | - pold->severity = newSt.severity; |
1313 | - pold->precision = newSt.precision.dp; |
1314 | - strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); |
1315 | + status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl); |
1316 | + pold->status = new.status; |
1317 | + pold->severity = new.severity; |
1318 | + pold->precision = new.precision.dp; |
1319 | + strncpy(pold->units, new.units, MAX_UNITS_SIZE); |
1320 | pold->units[MAX_UNITS_SIZE-1] = '\0'; |
1321 | - pold->upper_disp_limit = newSt.upper_disp_limit; |
1322 | - pold->lower_disp_limit = newSt.lower_disp_limit; |
1323 | - pold->upper_alarm_limit = newSt.upper_alarm_limit; |
1324 | - pold->upper_warning_limit = newSt.upper_warning_limit; |
1325 | - pold->lower_warning_limit = newSt.lower_warning_limit; |
1326 | - pold->lower_alarm_limit = newSt.lower_alarm_limit; |
1327 | - pold->upper_ctrl_limit = newSt.upper_ctrl_limit; |
1328 | - pold->lower_ctrl_limit = newSt.lower_ctrl_limit; |
1329 | + pold->upper_disp_limit = new.upper_disp_limit; |
1330 | + pold->lower_disp_limit = new.lower_disp_limit; |
1331 | + pold->upper_alarm_limit = new.upper_alarm_limit; |
1332 | + pold->upper_warning_limit = new.upper_warning_limit; |
1333 | + pold->lower_warning_limit = new.lower_warning_limit; |
1334 | + pold->lower_alarm_limit = new.lower_alarm_limit; |
1335 | + pold->upper_ctrl_limit = new.upper_ctrl_limit; |
1336 | + pold->lower_ctrl_limit = new.lower_ctrl_limit; |
1337 | options = 0; |
1338 | - nRequest = no_elements; |
1339 | status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options, |
1340 | - &nRequest, pfl); |
1341 | - for (i = nRequest; i < no_elements; i++) pvalue[i] = 0; |
1342 | + nRequest, pfl); |
1343 | } |
1344 | break; |
1345 | |
1346 | @@ -946,22 +778,17 @@ |
1347 | struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer; |
1348 | struct { |
1349 | DBRstatus |
1350 | - } newSt; |
1351 | - DBSTRING *pvalue = (DBSTRING *)(pold->value); |
1352 | + } new; |
1353 | |
1354 | options = DBR_STATUS; |
1355 | - nRequest = 0; |
1356 | - status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest, |
1357 | - pfl); |
1358 | - pold->status = newSt.status; |
1359 | - pold->severity = newSt.severity; |
1360 | - pold->ackt = newSt.ackt; |
1361 | - pold->acks = newSt.acks; |
1362 | + status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl); |
1363 | + pold->status = new.status; |
1364 | + pold->severity = new.severity; |
1365 | + pold->ackt = new.ackt; |
1366 | + pold->acks = new.acks; |
1367 | options = 0; |
1368 | - nRequest = no_elements; |
1369 | status = dbGetField(paddr, DBR_STRING, pold->value, |
1370 | - &options, &nRequest, pfl); |
1371 | - for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0; |
1372 | + &options, nRequest, pfl); |
1373 | } |
1374 | break; |
1375 | |
1376 | |
1377 | === modified file 'src/db/db_access_routines.h' |
1378 | --- src/db/db_access_routines.h 2002-07-12 21:35:43 +0000 |
1379 | +++ src/db/db_access_routines.h 2010-07-05 08:47:25 +0000 |
1380 | @@ -39,6 +39,9 @@ |
1381 | DBADDR *paddr, int src_type,const void *psrc, int no_elements); |
1382 | epicsShareFunc int epicsShareAPI db_get_field( |
1383 | DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl); |
1384 | +epicsShareFunc int db_get_field_and_count( |
1385 | + struct dbAddr *paddr, int buffer_type, |
1386 | + void *pbuffer, long *nRequest, void *pfl); |
1387 | |
1388 | |
1389 | #ifdef __cplusplus |
1390 | |
1391 | === modified file 'src/rsrv/camessage.c' |
1392 | --- src/rsrv/camessage.c 2009-07-09 16:37:24 +0000 |
1393 | +++ src/rsrv/camessage.c 2010-07-05 08:47:25 +0000 |
1394 | @@ -530,12 +530,21 @@ |
1395 | cid = pciu->cid; |
1396 | } |
1397 | |
1398 | - status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size, |
1399 | - pevext->msg.m_dataType, pevext->msg.m_count, cid, pevext->msg.m_available, |
1400 | + /* If the client has requested a zero element count we interpret this as a |
1401 | + * request for all avaiable elements. In this case we initialise the |
1402 | + * header with the maximum element size specified by the database. */ |
1403 | + int autosize = pevext->msg.m_count == 0; |
1404 | + long item_count = |
1405 | + autosize ? paddr->no_elements : pevext->msg.m_count; |
1406 | + ca_uint32_t payload_size = dbr_size_n(pevext->msg.m_dataType, item_count); |
1407 | + status = cas_copy_in_header( |
1408 | + pClient, pevext->msg.m_cmmd, payload_size, |
1409 | + pevext->msg.m_dataType, item_count, cid, pevext->msg.m_available, |
1410 | &pPayload ); |
1411 | if ( status != ECA_NORMAL ) { |
1412 | send_err ( &pevext->msg, status, pClient, |
1413 | - "server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u", |
1414 | + "server unable to load read (or subscription update) response " |
1415 | + "into protocol buffer PV=\"%s\" max bytes=%u", |
1416 | RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP ); |
1417 | if ( ! eventsRemaining ) |
1418 | cas_send_bs_msg ( pClient, FALSE ); |
1419 | @@ -554,8 +563,8 @@ |
1420 | return; |
1421 | } |
1422 | |
1423 | - status = db_get_field ( paddr, pevext->msg.m_dataType, |
1424 | - pPayload, pevext->msg.m_count, pfl); |
1425 | + status = db_get_field_and_count( |
1426 | + paddr, pevext->msg.m_dataType, pPayload, &item_count, pfl); |
1427 | if ( status < 0 ) { |
1428 | /* |
1429 | * I cant wait to redesign this protocol from scratch! |
1430 | @@ -569,58 +578,52 @@ |
1431 | send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) ); |
1432 | } |
1433 | else { |
1434 | - /* |
1435 | - * New clients recv the status of the |
1436 | - * operation directly to the |
1437 | + /* New clients recv the status of the operation directly to the |
1438 | * event/put/get callback. |
1439 | * |
1440 | - * Fetched value is set to zero in case they |
1441 | - * use it even when the status indicates |
1442 | - * failure. |
1443 | + * Fetched value is set to zero in case they use it even when the |
1444 | + * status indicates failure -- unless the client selected autosizing |
1445 | + * data, in which case they'd better know what they're doing! |
1446 | * |
1447 | - * The m_cid field in the protocol |
1448 | - * header is abused to carry the status |
1449 | - */ |
1450 | - memset ( pPayload, 0, pevext->size ); |
1451 | + * The m_cid field in the protocol header is abused to carry the |
1452 | + * status */ |
1453 | + if (autosize) { |
1454 | + payload_size = dbr_size_n(pevext->msg.m_dataType, 0); |
1455 | + cas_set_header_count(pClient, 0); |
1456 | + } |
1457 | + memset ( pPayload, 0, payload_size ); |
1458 | cas_set_header_cid ( pClient, ECA_GETFAIL ); |
1459 | - cas_commit_msg ( pClient, pevext->size ); |
1460 | + cas_commit_msg ( pClient, payload_size ); |
1461 | } |
1462 | } |
1463 | else { |
1464 | - ca_uint32_t payloadSize = pevext->size; |
1465 | int cacStatus = caNetConvert ( |
1466 | pevext->msg.m_dataType, pPayload, pPayload, |
1467 | - TRUE /* host -> net format */, pevext->msg.m_count ); |
1468 | - if ( cacStatus == ECA_NORMAL ) { |
1469 | - /* |
1470 | - * force string message size to be the true size rounded to even |
1471 | - * boundary |
1472 | - */ |
1473 | - if ( pevext->msg.m_dataType == DBR_STRING |
1474 | - && pevext->msg.m_count == 1 ) { |
1475 | - char * pStr = (char *) pPayload; |
1476 | - size_t strcnt = strlen ( pStr ); |
1477 | - if ( strcnt < payloadSize ) { |
1478 | - payloadSize = ( ca_uint32_t ) ( strcnt + 1u ); |
1479 | - } |
1480 | - else { |
1481 | - pStr[payloadSize-1] = '\0'; |
1482 | - errlogPrintf ( |
1483 | - "caserver: read_reply: detected DBR_STRING w/o nill termination " |
1484 | - "in response from db_get_field, pPayload = \"%s\"\n", |
1485 | - pStr ); |
1486 | - } |
1487 | + TRUE /* host -> net format */, item_count ); |
1488 | + if ( cacStatus == ECA_NORMAL ) { |
1489 | + ca_uint32_t data_size = |
1490 | + dbr_size_n(pevext->msg.m_dataType, item_count); |
1491 | + if (autosize) { |
1492 | + payload_size = data_size; |
1493 | + cas_set_header_count(pClient, item_count); |
1494 | } |
1495 | + else if (payload_size > data_size) |
1496 | + memset( |
1497 | + (char *) pPayload + data_size, 0, payload_size - data_size); |
1498 | } |
1499 | else { |
1500 | - memset ( pPayload, 0, payloadSize ); |
1501 | + if (autosize) { |
1502 | + payload_size = dbr_size_n(pevext->msg.m_dataType, 0); |
1503 | + cas_set_header_count(pClient, 0); |
1504 | + } |
1505 | + memset ( pPayload, 0, payload_size ); |
1506 | cas_set_header_cid ( pClient, cacStatus ); |
1507 | - } |
1508 | - cas_commit_msg ( pClient, payloadSize ); |
1509 | + } |
1510 | + cas_commit_msg ( pClient, payload_size ); |
1511 | } |
1512 | |
1513 | /* |
1514 | - * Ensures timely response for events, but does que |
1515 | + * Ensures timely response for events, but does queue |
1516 | * them up like db requests when the OPI does not keep up. |
1517 | */ |
1518 | if ( ! eventsRemaining ) |
1519 | |
1520 | === modified file 'src/rsrv/caserverio.c' |
1521 | --- src/rsrv/caserverio.c 2006-11-20 16:10:02 +0000 |
1522 | +++ src/rsrv/caserverio.c 2010-07-05 08:47:25 +0000 |
1523 | @@ -33,6 +33,10 @@ |
1524 | #define epicsExportSharedSymbols |
1525 | #include "server.h" |
1526 | |
1527 | +/* As an optimisation, any message allocated with a large header is resized to |
1528 | + * use a small header if the payload size is below this threshold. */ |
1529 | +#define SMALL_MESSAGE_THRESHOLD 65 |
1530 | + |
1531 | /* |
1532 | * cas_send_bs_msg() |
1533 | * |
1534 | @@ -292,32 +296,25 @@ |
1535 | } |
1536 | } |
1537 | |
1538 | - if ( alignedPayloadSize < 0xffff && nElem < 0xffff ) { |
1539 | - caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk]; |
1540 | - pMsg->m_cmmd = htons ( response ); |
1541 | - pMsg->m_postsize = htons ( ( ( ca_uint16_t ) alignedPayloadSize ) ); |
1542 | - pMsg->m_dataType = htons ( dataType ); |
1543 | - pMsg->m_count = htons ( ( ( ca_uint16_t ) nElem ) ); |
1544 | - pMsg->m_cid = htonl ( cid ); |
1545 | - pMsg->m_available = htonl ( responseSpecific ); |
1546 | - if ( ppPayload ) { |
1547 | - *ppPayload = ( void * ) ( pMsg + 1 ); |
1548 | - } |
1549 | + caHdr *pMsg = (caHdr *) &pclient->send.buf[pclient->send.stk]; |
1550 | + pMsg->m_cmmd = htons(response); |
1551 | + pMsg->m_dataType = htons(dataType); |
1552 | + pMsg->m_cid = htonl(cid); |
1553 | + pMsg->m_available = htonl(responseSpecific); |
1554 | + if (alignedPayloadSize < 0xffff && nElem < 0xffff) { |
1555 | + pMsg->m_postsize = htons(((ca_uint16_t) alignedPayloadSize)); |
1556 | + pMsg->m_count = htons(((ca_uint16_t) nElem)); |
1557 | + if (ppPayload) |
1558 | + *ppPayload = (void *) (pMsg + 1); |
1559 | } |
1560 | else { |
1561 | - caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk]; |
1562 | - ca_uint32_t *pW32 = ( ca_uint32_t * ) ( pMsg + 1 ); |
1563 | - pMsg->m_cmmd = htons ( response ); |
1564 | - pMsg->m_postsize = htons ( 0xffff ); |
1565 | - pMsg->m_dataType = htons ( dataType ); |
1566 | - pMsg->m_count = htons ( 0u ); |
1567 | - pMsg->m_cid = htonl ( cid ); |
1568 | - pMsg->m_available = htonl ( responseSpecific ); |
1569 | - pW32[0] = htonl ( alignedPayloadSize ); |
1570 | - pW32[1] = htonl ( nElem ); |
1571 | - if ( ppPayload ) { |
1572 | - *ppPayload = ( void * ) ( pW32 + 2 ); |
1573 | - } |
1574 | + ca_uint32_t *pW32 = (ca_uint32_t *) (pMsg + 1); |
1575 | + pMsg->m_postsize = htons(0xffff); |
1576 | + pMsg->m_count = htons(0u); |
1577 | + pW32[0] = htonl(alignedPayloadSize); |
1578 | + pW32[1] = htonl(nElem); |
1579 | + if (ppPayload) |
1580 | + *ppPayload = (void *) (pW32 + 2); |
1581 | } |
1582 | |
1583 | /* zero out pad bytes */ |
1584 | @@ -336,6 +333,20 @@ |
1585 | pMsg->m_cid = htonl ( cid ); |
1586 | } |
1587 | |
1588 | +void cas_set_header_count (struct client *pClient, ca_uint32_t count) |
1589 | +{ |
1590 | + caHdr *pMsg = (caHdr *) &pClient->send.buf[pClient->send.stk]; |
1591 | + if (pMsg->m_postsize == htons(0xffff)) { |
1592 | + assert(pMsg->m_count == 0); |
1593 | + ca_uint32_t *pLW = (ca_uint32_t *) (pMsg + 1); |
1594 | + pLW[1] = htonl(count); |
1595 | + } |
1596 | + else { |
1597 | + assert(count < 65536); |
1598 | + pMsg->m_count = htons((ca_uint16_t) count); |
1599 | + } |
1600 | +} |
1601 | + |
1602 | void cas_commit_msg ( struct client *pClient, ca_uint32_t size ) |
1603 | { |
1604 | caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk]; |
1605 | @@ -343,8 +354,19 @@ |
1606 | if ( pMsg->m_postsize == htons ( 0xffff ) ) { |
1607 | ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 ); |
1608 | assert ( size <= ntohl ( *pLW ) ); |
1609 | - pLW[0] = htonl ( size ); |
1610 | - size += sizeof ( caHdr ) + 2 * sizeof ( *pLW ); |
1611 | + if (size < SMALL_MESSAGE_THRESHOLD) { |
1612 | + /* If the message is sufficiently small it can be worth converting a |
1613 | + * large message header into a small header. This saves us all of 8 |
1614 | + * bytes over the wire, so it's not such a big deal. */ |
1615 | + pMsg->m_postsize = htons((ca_uint16_t) size); |
1616 | + pMsg->m_count = htons((ca_uint16_t) ntohl(pLW[1])); |
1617 | + memmove(pLW, pLW + 2, size); |
1618 | + size += sizeof(caHdr); |
1619 | + } |
1620 | + else { |
1621 | + pLW[0] = htonl ( size ); |
1622 | + size += sizeof ( caHdr ) + 2 * sizeof ( *pLW ); |
1623 | + } |
1624 | } |
1625 | else { |
1626 | assert ( size <= ntohs ( pMsg->m_postsize ) ); |
1627 | |
1628 | === modified file 'src/rsrv/server.h' |
1629 | --- src/rsrv/server.h 2009-07-09 16:37:24 +0000 |
1630 | +++ src/rsrv/server.h 2010-07-05 08:47:25 +0000 |
1631 | @@ -29,7 +29,7 @@ |
1632 | #include "asLib.h" |
1633 | #include "dbAddr.h" |
1634 | #include "dbNotify.h" |
1635 | -#define CA_MINOR_PROTOCOL_REVISION 11 |
1636 | +#define CA_MINOR_PROTOCOL_REVISION 13 |
1637 | #include "caProto.h" |
1638 | #include "ellLib.h" |
1639 | #include "epicsTime.h" |
1640 | @@ -228,6 +228,7 @@ |
1641 | ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, |
1642 | ca_uint32_t responseSpecific, void **pPayload ); |
1643 | void cas_set_header_cid ( struct client *pClient, ca_uint32_t ); |
1644 | +void cas_set_header_count (struct client *pClient, ca_uint32_t count); |
1645 | void cas_commit_msg ( struct client *pClient, ca_uint32_t size ); |
1646 | |
1647 | #endif /*INCLserverh*/ |
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.