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
<2010>
2011
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
<2010>
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|