EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: [PATCH 2/4] Update rsrv to support V4.12 protocol extension.
From: Michael Abbott <[email protected]>
To: undisclosed-recipients:;
Date: Wed, 2 Jun 2010 10:04:38 +0100
The rsrv server is updated in this commit to deliver variable sized
waveforms in response to a zero length request, implementing an
extension to the v4 EPICS protocol tied to minor version 12.

The core of the changes are in read_reply, rsrv/camessage.c, which first
reserves packet space for the largest possible response, but then resizes
the packet according to how much data is actually returned from the
database.

Signed-off-by: Michael Abbott <[email protected]>
---
 src/ca/db_access.h          |    6 +-
 src/db/db_access.c          |  345 +++++++++++--------------------------------
 src/db/db_access_routines.h |    3 +
 src/rsrv/camessage.c        |   85 ++++++-----
 src/rsrv/caserverio.c       |   14 ++
 src/rsrv/server.h           |    3 +-
 6 files changed, 152 insertions(+), 304 deletions(-)

diff --git a/src/ca/db_access.h b/src/ca/db_access.h
index e88a929..92aa5d0 100644
--- a/src/ca/db_access.h
+++ b/src/ca/db_access.h
@@ -524,16 +524,16 @@ struct dbr_ctrl_double{
 	dbr_double_t	value;			/* current value */
 };
 
-#ifndef db_accessHFORdb_accessC
 #define dbr_size_n(TYPE,COUNT)\
 ((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))
 
 /* size for each type - array indexed by the DBR_ type code */
-epicsShareExtern const unsigned short dbr_size[LAST_BUFFER_TYPE+1];
+epicsShareExtern const unsigned short dbr_size[];
 
 /* size for each type's value - array indexed by the DBR_ type code */
-epicsShareExtern const unsigned short dbr_value_size[LAST_BUFFER_TYPE+1];
+epicsShareExtern const unsigned short dbr_value_size[];
 
+#ifndef db_accessHFORdb_accessC
 /* class for each type's value */
 enum dbr_value_class { 
 		dbr_class_int, 
diff --git a/src/db/db_access.c b/src/db/db_access.c
index 55f4155..6ba381f 100644
--- a/src/db/db_access.c
+++ b/src/db/db_access.c
@@ -149,10 +149,29 @@ int epicsShareAPI db_name_to_addr(const char *pname, struct dbAddr *paddr)
 int epicsShareAPI db_get_field(struct dbAddr *paddr,
     int buffer_type, void *pbuffer, int no_elements, void *pfl)
 {
+    long nRequest = no_elements;
+    int result = db_get_field_and_count(
+        paddr, buffer_type, pbuffer, &nRequest, pfl);
+    if (nRequest < no_elements)
+        /* If the database request returned fewer elements than requested then
+         * fill out the remainder of the array with zeros. */
+        memset(
+            (char *)pbuffer + dbr_size_n(buffer_type, nRequest), 0,
+            (no_elements - nRequest) * dbr_value_size[buffer_type]);
+    return result;
+}
+
+/* Performs the work of the public db_get_field API, but also returns the number
+ * of elements actually copied to the buffer.  The caller is responsible for
+ * zeroing the remaining part of the buffer. */
+int epicsShareAPI db_get_field_and_count(
+    struct dbAddr *paddr, int buffer_type,
+    void *pbuffer, long *nRequest, void *pfl)
+{
     long status;
     long options;
-    long nRequest;
     long i;
+    long zero = 0;
 
    /* The order of the DBR* elements in the "new" structures below is
     * very important and must correspond to the order of processing
@@ -161,82 +180,26 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
 
     switch(buffer_type) {
     case(oldDBR_STRING):
-        {
-            DBSTRING *pvalue = (DBSTRING *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_STRING, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
-        }
+        status = dbGetField(paddr, DBR_STRING, pbuffer, &zero, nRequest, pfl);
         break;
 /*  case(oldDBR_INT): */
     case(oldDBR_SHORT):
-        {
-            dbr_short_t *pvalue = (dbr_short_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_SHORT, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
         break;
     case(oldDBR_FLOAT):
-        {
-            dbr_float_t *pvalue = (dbr_float_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_FLOAT, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
         break;
     case(oldDBR_ENUM):
-        {
-            dbr_enum_t *pvalue = (dbr_enum_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_ENUM, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
         break;
     case(oldDBR_CHAR):
-        {
-            dbr_char_t *pvalue = (dbr_char_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_CHAR, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
         break;
     case(oldDBR_LONG):
-        {
-            dbr_long_t *pvalue = (dbr_long_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_LONG, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_LONG, pbuffer, &zero, nRequest, pfl);
         break;
     case(oldDBR_DOUBLE):
-        {
-            dbr_double_t *pvalue = (dbr_double_t *)pbuffer;
-
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &options, &nRequest,
-                pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
-        }
+        status = dbGetField(paddr, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
         break;
 
     case(oldDBR_STS_STRING):
@@ -247,19 +210,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            DBSTRING *pvalue = (DBSTRING *)pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_STRING, pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
+            status = dbGetField(paddr, DBR_STRING, pold->value, &zero,
+                nRequest, pfl);
         }
         break;
 /*  case(oldDBR_STS_INT): */
@@ -269,19 +226,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_short_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+            status = dbGetField(paddr, DBR_SHORT, &pold->value, &zero,
+                nRequest, pfl);
         }
         break;
     case(oldDBR_STS_FLOAT):
@@ -290,19 +241,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_float_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+            status = dbGetField(paddr, DBR_FLOAT, &pold->value, &zero,
+                nRequest, pfl);
         }
         break;
     case(oldDBR_STS_ENUM):
@@ -311,19 +256,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_enum_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
-                    pfl);
+            status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+            status = dbGetField(paddr, DBR_ENUM, &pold->value, &zero,
+                nRequest, pfl);
         }
         break;
     case(oldDBR_STS_CHAR):
@@ -332,19 +271,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_char_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+            status = dbGetField(paddr, DBR_UCHAR, &pold->value, &zero,
+                nRequest, pfl);
         }
         break;
     case(oldDBR_STS_LONG):
@@ -353,19 +286,13 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_long_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
-            options = 0;
-            nRequest = no_elements;
-            status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+            status = dbGetField(paddr, DBR_LONG, &pold->value, &zero,
+                nRequest, pfl);
         }
         break;
     case(oldDBR_STS_DOUBLE):
@@ -374,19 +301,14 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            dbr_double_t *pvalue = &pold->value;
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
 
@@ -397,20 +319,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            DBSTRING *pvalue = (DBSTRING *)(pold->value);
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
-                    pfl);
+            status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
-                status = dbGetField(paddr, DBR_STRING, pold->value, &options,
-                        &nRequest, pfl);
-                for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
+            status = dbGetField(paddr, DBR_STRING, pold->value, &options,
+                    nRequest, pfl);
         }
         break;
 /*  case(oldDBR_TIME_INT): */
@@ -421,20 +338,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_short_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_TIME_FLOAT):
@@ -444,20 +356,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_float_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_TIME_ENUM):
@@ -467,20 +374,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_enum_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_TIME_CHAR):
@@ -490,20 +392,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_char_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_CHAR, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_CHAR, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_CHAR, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_TIME_LONG):
@@ -513,20 +410,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_long_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_TIME_DOUBLE):
@@ -536,20 +428,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRstatus
                 DBRtime
             } new;
-            dbr_double_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_TIME;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->stamp = new.time;         /* structure copy */
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
 
@@ -564,12 +451,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRgrLong
                 DBRalLong
             } new;
-            dbr_short_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -581,10 +465,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->lower_warning_limit = new.lower_warning_limit;
             pold->lower_alarm_limit = new.lower_alarm_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_GR_FLOAT):
@@ -597,13 +479,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRgrDouble
                 DBRalDouble
             } new;
-            dbr_float_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
                 DBR_AL_DOUBLE;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->precision = new.precision.dp;
@@ -616,10 +495,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit);
             pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit);
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
 /*  case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */
@@ -632,12 +509,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRgrLong
                 DBRalLong
             } new;
-            dbr_char_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -649,10 +523,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->lower_warning_limit = new.lower_warning_limit;
             pold->lower_alarm_limit = new.lower_alarm_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_GR_LONG):
@@ -664,12 +536,9 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRgrLong
                 DBRalLong
             } new;
-            dbr_long_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -681,10 +550,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->lower_warning_limit = new.lower_warning_limit;
             pold->lower_alarm_limit = new.lower_alarm_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_GR_DOUBLE):
@@ -697,13 +564,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRgrDouble
                 DBRalDouble
             } new;
-            dbr_double_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
                 DBR_AL_DOUBLE;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->precision = new.precision.dp;
@@ -716,10 +580,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->lower_warning_limit = new.lower_warning_limit;
             pold->lower_alarm_limit = new.lower_alarm_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
 
@@ -734,13 +596,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRctrlLong
                 DBRalLong
             } new;
-            dbr_short_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
                 DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_SHORT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -754,10 +613,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_ctrl_limit = new.upper_ctrl_limit;
             pold->lower_ctrl_limit = new.lower_ctrl_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_CTRL_FLOAT):
@@ -771,13 +628,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRctrlDouble
                 DBRalDouble
             } new;
-            dbr_float_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
                 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_FLOAT, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->precision = new.precision.dp;
@@ -792,10 +646,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_ctrl_limit = epicsConvertDoubleToFloat(new.upper_ctrl_limit);
             pold->lower_ctrl_limit = epicsConvertDoubleToFloat(new.lower_ctrl_limit);
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_GR_ENUM):
@@ -807,14 +659,11 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRenumStrs
             } new;
             short no_str;
-            dbr_enum_t *pvalue = &pold->value;
 
             memset(pold, '\0', sizeof(struct dbr_ctrl_enum));
             /* first get status and severity */
             options = DBR_STATUS | DBR_ENUM_STRS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_ENUM, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             no_str = new.no_str;
@@ -824,10 +673,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 strncpy(pold->strs[i], new.strs[i], sizeof(pold->strs[i]));
             /*now get values*/
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_CTRL_CHAR):
@@ -840,13 +687,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRctrlLong
                 DBRalLong
             } new;
-            dbr_char_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
                 DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_UCHAR, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -860,10 +704,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_ctrl_limit = new.upper_ctrl_limit;
             pold->lower_ctrl_limit = new.lower_ctrl_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_CTRL_LONG):
@@ -876,13 +718,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRctrlLong
                 DBRalLong
             } new;
-            dbr_long_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
                 DBR_AL_LONG;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_LONG, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             strncpy(pold->units, new.units, MAX_UNITS_SIZE);
@@ -896,10 +735,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_ctrl_limit = new.upper_ctrl_limit;
             pold->lower_ctrl_limit = new.lower_ctrl_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
     case(oldDBR_CTRL_DOUBLE):
@@ -913,13 +750,10 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
                 DBRctrlDouble
                 DBRalDouble
             } new;
-            dbr_double_t *pvalue = &pold->value;
 
             options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
                 DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->precision = new.precision.dp;
@@ -934,10 +768,8 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             pold->upper_ctrl_limit = new.upper_ctrl_limit;
             pold->lower_ctrl_limit = new.lower_ctrl_limit;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
-                &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i] = 0;
+                nRequest, pfl);
         }
         break;
 
@@ -947,21 +779,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
             struct {
                 DBRstatus
             } new;
-            DBSTRING *pvalue = (DBSTRING *)(pold->value);
 
             options = DBR_STATUS;
-            nRequest = 0;
-            status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
-                pfl);
+            status = dbGetField(paddr, DBR_STRING, &new, &options, &zero, pfl);
             pold->status = new.status;
             pold->severity = new.severity;
             pold->ackt = new.ackt;
             pold->acks = new.acks;
             options = 0;
-            nRequest = no_elements;
             status = dbGetField(paddr, DBR_STRING, pold->value,
-                &options, &nRequest, pfl);
-            for (i = nRequest; i < no_elements; i++) pvalue[i][0] = 0;
+                &options, nRequest, pfl);
         }
         break;
 
diff --git a/src/db/db_access_routines.h b/src/db/db_access_routines.h
index 4dde58f..a45c24e 100644
--- a/src/db/db_access_routines.h
+++ b/src/db/db_access_routines.h
@@ -39,6 +39,9 @@ epicsShareFunc int epicsShareAPI db_put_field(
     DBADDR *paddr, int src_type,const void *psrc, int no_elements);
 epicsShareFunc int epicsShareAPI db_get_field(
     DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl);
+epicsShareFunc int db_get_field_and_count(
+    struct dbAddr *paddr, int buffer_type,
+    void *pbuffer, long *nRequest, void *pfl);
 
 
 #ifdef __cplusplus
diff --git a/src/rsrv/camessage.c b/src/rsrv/camessage.c
index e59681f..77bdc52 100644
--- a/src/rsrv/camessage.c
+++ b/src/rsrv/camessage.c
@@ -530,12 +530,21 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
         cid = pciu->cid;
     }
 
-    status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size, 
-        pevext->msg.m_dataType, pevext->msg.m_count, cid, pevext->msg.m_available,
+    /* If the client has requested a zero element count we interpret this as a
+     * request for all avaiable elements.  In this case we initialise the
+     * header with the maximum element size specified by the database. */
+    int autosize = pevext->msg.m_count == 0;
+    long item_count =
+        autosize ? paddr->no_elements : pevext->msg.m_count;
+    ca_uint32_t payload_size = dbr_size_n(pevext->msg.m_dataType, item_count);
+    status = cas_copy_in_header(
+        pClient, pevext->msg.m_cmmd, payload_size,
+        pevext->msg.m_dataType, item_count, cid, pevext->msg.m_available,
         &pPayload );
     if ( status != ECA_NORMAL ) {
         send_err ( &pevext->msg, status, pClient, 
-            "server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u",
+            "server unable to load read (or subscription update) response "
+            "into protocol buffer PV=\"%s\" max bytes=%u",
             RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );
         if ( ! eventsRemaining )
             cas_send_bs_msg ( pClient, FALSE );
@@ -554,8 +563,8 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
         return;
     }
 
-    status = db_get_field ( paddr, pevext->msg.m_dataType,
-                  pPayload, pevext->msg.m_count, pfl);
+    status = db_get_field_and_count(
+        paddr, pevext->msg.m_dataType, pPayload, &item_count, pfl);
     if ( status < 0 ) {
         /*
          * I cant wait to redesign this protocol from scratch!
@@ -569,58 +578,52 @@ static void read_reply ( void *pArg, struct dbAddr *paddr,
             send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) );
         }
         else {
-            /*
-             * New clients recv the status of the
-             * operation directly to the
+            /* New clients recv the status of the operation directly to the
              * event/put/get callback.
              *
-             * Fetched value is set to zero in case they
-             * use it even when the status indicates 
-             * failure.
+             * Fetched value is set to zero in case they use it even when the
+             * status indicates failure -- unless the client selected autosizing
+             * data, in which case they'd better know what they're doing!
              *
-             * The m_cid field in the protocol
-             * header is abused to carry the status
-             */
-            memset ( pPayload, 0, pevext->size );
+             * The m_cid field in the protocol header is abused to carry the
+             * status */
+            if (autosize) {
+                payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
+                cas_set_header_count(pClient, 0);
+            }
+            memset ( pPayload, 0, payload_size );
             cas_set_header_cid ( pClient, ECA_GETFAIL );
-            cas_commit_msg ( pClient, pevext->size );
+            cas_commit_msg ( pClient, payload_size );
         }
     }
     else {
-        ca_uint32_t payloadSize = pevext->size;
         int cacStatus = caNetConvert ( 
             pevext->msg.m_dataType, pPayload, pPayload, 
-            TRUE /* host -> net format */, pevext->msg.m_count );
-	    if ( cacStatus == ECA_NORMAL ) {
-            /*
-            * force string message size to be the true size rounded to even
-            * boundary
-            */
-            if ( pevext->msg.m_dataType == DBR_STRING 
-                && pevext->msg.m_count == 1 ) {
-                char * pStr = (char *) pPayload;
-                size_t strcnt = strlen ( pStr );
-                if ( strcnt < payloadSize ) {
-                    payloadSize = ( ca_uint32_t ) ( strcnt + 1u );
-                }
-                else {
-                    pStr[payloadSize-1] = '\0';
-                    errlogPrintf ( 
-                        "caserver: read_reply: detected DBR_STRING w/o nill termination "
-                        "in response from db_get_field, pPayload = \"%s\"\n",
-                        pStr );
-                }
+            TRUE /* host -> net format */, item_count );
+        if ( cacStatus == ECA_NORMAL ) {
+            ca_uint32_t data_size =
+                dbr_size_n(pevext->msg.m_dataType, item_count);
+            if (autosize) {
+                payload_size = data_size;
+                cas_set_header_count(pClient, item_count);
             }
+            else
+                memset(
+                    (char *) pPayload + data_size, 0, payload_size - data_size);
         }
         else {
-            memset ( pPayload, 0, payloadSize );
+            if (autosize) {
+                payload_size = dbr_size_n(pevext->msg.m_dataType, 0);
+                cas_set_header_count(pClient, 0);
+            }
+            memset ( pPayload, 0, payload_size );
             cas_set_header_cid ( pClient, cacStatus );
-	    }
-        cas_commit_msg ( pClient, payloadSize );
+        }
+        cas_commit_msg ( pClient, payload_size );
     }
 
     /*
-     * Ensures timely response for events, but does que 
+     * Ensures timely response for events, but does queue 
      * them up like db requests when the OPI does not keep up.
      */
     if ( ! eventsRemaining )
diff --git a/src/rsrv/caserverio.c b/src/rsrv/caserverio.c
index 34ead95..4d8b773 100644
--- a/src/rsrv/caserverio.c
+++ b/src/rsrv/caserverio.c
@@ -336,6 +336,20 @@ void cas_set_header_cid ( struct client *pClient, ca_uint32_t cid )
     pMsg->m_cid = htonl ( cid );
 }
 
+void cas_set_header_count (struct client *pClient, ca_uint32_t count)
+{
+    caHdr *pMsg = (caHdr *) &pClient->send.buf[pClient->send.stk];
+    if (pMsg->m_postsize == htons(0xffff)) {
+        assert(pMsg->m_count == 0);
+        ca_uint32_t *pLW = (ca_uint32_t *) (pMsg + 1);
+        pLW[1] = htonl(count);
+    }
+    else {
+        assert(count < 65536);
+        pMsg->m_count = htons((ca_uint16_t) count);
+    }
+}
+
 void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
 {
     caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
diff --git a/src/rsrv/server.h b/src/rsrv/server.h
index 443c068..82042af 100644
--- a/src/rsrv/server.h
+++ b/src/rsrv/server.h
@@ -29,7 +29,7 @@
 #include "asLib.h"
 #include "dbAddr.h"
 #include "dbNotify.h"
-#define CA_MINOR_PROTOCOL_REVISION 11
+#define CA_MINOR_PROTOCOL_REVISION 12
 #include "caProto.h"
 #include "ellLib.h"
 #include "epicsTime.h"
@@ -228,6 +228,7 @@ int cas_copy_in_header (
     ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, 
     ca_uint32_t responseSpecific, void **pPayload );
 void cas_set_header_cid ( struct client *pClient, ca_uint32_t );
+void cas_set_header_count (struct client *pClient, ca_uint32_t count);
 void cas_commit_msg ( struct client *pClient, ca_uint32_t size );
 
 #endif /*INCLserverh*/
-- 
1.6.6.1


References:
[PATCH 0/4] Adding dynamic arrays to EPICS Channel Access Michael Abbott

Navigate by Date:
Prev: [PATCH 1/4] Client side support for automatic resizing arrays. Michael Abbott
Next: [PATCH 4/4] Drive-by refactoring in caserverio.c Michael Abbott
Index: 2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: [PATCH 1/4] Client side support for automatic resizing arrays. Michael Abbott
Next: [PATCH 4/4] Drive-by refactoring in caserverio.c Michael Abbott
Index: 2002  2003  2004  2005  2006  2007  2008  2009  <20102011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·