dbCa: dbCaGet/PutLink dynamic size
dbCaGetLink return actual number of elements w/o zero padding. dbCaPutLink write only requested number of elements, w/o padding
This commit is contained in:
@@ -346,19 +346,16 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
assert(pca->pgetNative);
|
||||
status = fConvert(pca->pgetNative, pdest, 0);
|
||||
} else {
|
||||
unsigned long ntoreport = *nelements, ntoget;
|
||||
unsigned long ntoget = *nelements;
|
||||
struct dbAddr dbAddr;
|
||||
long (*aConvert)(struct dbAddr *paddr, void *to, long nreq, long nto, long off);
|
||||
|
||||
aConvert = dbGetConvertRoutine[newType][dbrType];
|
||||
assert(pca->pgetNative);
|
||||
|
||||
if (ntoreport > pca->nelements)
|
||||
ntoreport = pca->nelements;
|
||||
ntoget = ntoreport;
|
||||
if (ntoget > pca->usedelements)
|
||||
ntoget = pca->usedelements;
|
||||
*nelements = ntoreport;
|
||||
*nelements = ntoget;
|
||||
|
||||
memset((void *)&dbAddr, 0, sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
@@ -366,12 +363,6 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
/*Ignore error return*/
|
||||
aConvert(&dbAddr, pdest, ntoget, ntoget, 0);
|
||||
if(ntoget<ntoreport) {
|
||||
/* zero out remainder of buffer */
|
||||
memset(ntoget*pca->elementSize+(char*)pca->pgetNative,
|
||||
0,
|
||||
(ntoreport-ntoget)*pca->elementSize);
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (pstat) *pstat = pca->stat;
|
||||
@@ -418,6 +409,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
|
||||
if (!pca->pputNative) {
|
||||
pca->pputNative = dbCalloc(pca->nelements,
|
||||
dbr_value_size[ca_field_type(pca->chid)]);
|
||||
pca->putnelements = 0;
|
||||
/* Fixed and disabled by ANJ, see comment above.
|
||||
plink->value.pv_link.pvlMask |= pvlOptOutNative;
|
||||
*/
|
||||
@@ -439,10 +431,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
|
||||
if(nRequest>pca->nelements)
|
||||
nRequest = pca->nelements;
|
||||
status = aConvert(&dbAddr, pbuffer, nRequest, pca->nelements, 0);
|
||||
if(nRequest<pca->nelements) {
|
||||
long elemsize = dbr_value_size[ca_field_type(pca->chid)];
|
||||
memset(nRequest*elemsize+(char*)pca->pputNative, 0, (pca->nelements-nRequest)*elemsize);
|
||||
}
|
||||
pca->putnelements = nRequest;
|
||||
}
|
||||
link_action |= CA_WRITE_NATIVE;
|
||||
pca->gotOutNative = TRUE;
|
||||
@@ -767,6 +756,7 @@ static void eventCallback(struct event_handler_args arg)
|
||||
goto done;
|
||||
}
|
||||
assert(arg.dbr);
|
||||
assert(arg.count<=pca->nelements);
|
||||
size = arg.count * dbr_value_size[arg.type];
|
||||
if (arg.type == DBR_TIME_STRING &&
|
||||
ca_field_type(pca->chid) == DBR_ENUM) {
|
||||
@@ -988,11 +978,11 @@ static void dbCaTask(void *arg)
|
||||
assert(pca->pputNative);
|
||||
if (pca->putType == CA_PUT) {
|
||||
status = ca_array_put(
|
||||
pca->dbrType, pca->nelements,
|
||||
pca->dbrType, pca->putnelements,
|
||||
pca->chid, pca->pputNative);
|
||||
} else if (pca->putType==CA_PUT_CALLBACK) {
|
||||
status = ca_array_put_callback(
|
||||
pca->dbrType, pca->nelements,
|
||||
pca->dbrType, pca->putnelements,
|
||||
pca->chid, pca->pputNative,
|
||||
putComplete, pca);
|
||||
} else {
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef struct caLink
|
||||
size_t elementSize; /* size of one element in pgetNative */
|
||||
unsigned long nelements; /* PVs max array size */
|
||||
unsigned long usedelements; /* currently used in pgetNative */
|
||||
unsigned long putnelements; /* currently used in pputNative */
|
||||
char hasReadAccess;
|
||||
char hasWriteAccess;
|
||||
char isConnected;
|
||||
|
||||
@@ -294,45 +294,35 @@ static void fillArrayDouble(double *buf, unsigned count, double first)
|
||||
|
||||
static void checkArray(const char *msg,
|
||||
epicsInt32 *buf, epicsInt32 first,
|
||||
unsigned used, unsigned total)
|
||||
unsigned used)
|
||||
{
|
||||
int match = 1;
|
||||
unsigned i;
|
||||
epicsInt32 x, *b;
|
||||
for(b=buf,x=first,i=0;i<used;i++,x++,b++)
|
||||
match &= (*b)==x;
|
||||
for(;i<total;i++,x++,b++)
|
||||
match &= (*b)==0;
|
||||
testOk(match, "%s", msg);
|
||||
if(!match) {
|
||||
for(b=buf,x=first,i=0;i<used;i++,x++,b++)
|
||||
if((*b)!=x)
|
||||
testDiag("%u %u != %u", i, (unsigned)*b, (unsigned)x);
|
||||
for(;i<total;i++,x++,b++)
|
||||
if((*b)!=0)
|
||||
testDiag("%u %u != %u", i, (unsigned)*b, (unsigned)x);
|
||||
}
|
||||
}
|
||||
|
||||
static void checkArrayDouble(const char *msg,
|
||||
double *buf, double first,
|
||||
unsigned used, unsigned total)
|
||||
unsigned used)
|
||||
{
|
||||
int match = 1;
|
||||
unsigned i;
|
||||
double x, *b;
|
||||
for(b=buf,x=first,i=0;i<used;i++,x++,b++)
|
||||
match &= (*b)==x;
|
||||
for(;i<total;i++,x++,b++)
|
||||
match &= (*b)==0;
|
||||
testOk(match, "%s", msg);
|
||||
if(!match) {
|
||||
for(b=buf,x=first,i=0;i<used;i++,x++,b++)
|
||||
if((*b)!=x)
|
||||
testDiag("%u %u != %u", i, (unsigned)*b, (unsigned)x);
|
||||
for(;i<total;i++,x++,b++)
|
||||
if((*b)!=0)
|
||||
testDiag("%u %u != %u", i, (unsigned)*b, (unsigned)x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,7 +393,7 @@ static void testArrayLink(unsigned nsrc, unsigned ntarg)
|
||||
if(dbGetLink(psrclnk, DBR_LONG, bufsrc, NULL, &nReq)==0) {
|
||||
testPass("dbGetLink");
|
||||
testOp("%ld",nReq,==,(long)num);
|
||||
checkArray("array update", bufsrc, 1, nReq, psrc->nelm);
|
||||
checkArray("array update", bufsrc, 1, nReq);
|
||||
} else {
|
||||
testFail("dbGetLink");
|
||||
testSkip(2, "dbGetLink fails");
|
||||
@@ -415,12 +405,8 @@ static void testArrayLink(unsigned nsrc, unsigned ntarg)
|
||||
putLink(psrclnk, DBR_LONG, bufsrc, psrc->nelm);
|
||||
|
||||
dbScanLock((dbCommon*)ptarg);
|
||||
/* CA links always write the full target array length */
|
||||
testOp("%ld",(long)ptarg->nord,==,(long)ptarg->nelm);
|
||||
/* However, if the source length is less, then the target
|
||||
* is zero filled
|
||||
*/
|
||||
checkArray("array update", buftarg, 2, num, ptarg->nelm);
|
||||
testOp("%ld",(long)ptarg->nord,==,(long)num);
|
||||
|
||||
dbScanUnlock((dbCommon*)ptarg);
|
||||
|
||||
/* write again to ensure that buffer is completely updated */
|
||||
@@ -429,8 +415,8 @@ static void testArrayLink(unsigned nsrc, unsigned ntarg)
|
||||
putLink(psrclnk, DBR_LONG, bufsrc, psrc->nelm);
|
||||
|
||||
dbScanLock((dbCommon*)ptarg);
|
||||
testOp("%ld",(long)ptarg->nord,==,(long)ptarg->nelm);
|
||||
checkArray("array update", buftarg, 3, num, ptarg->nelm);
|
||||
testOp("%ld",(long)ptarg->nord,==,(long)num);
|
||||
checkArray("array update", buftarg, 3, num);
|
||||
dbScanUnlock((dbCommon*)ptarg);
|
||||
|
||||
testIocShutdownOk();
|
||||
@@ -513,7 +499,7 @@ static void testreTargetTypeChange(void)
|
||||
|
||||
dbScanLock((dbCommon*)psrc);
|
||||
testOp("%ld",(long)psrc->nord,==,(long)5);
|
||||
checkArrayDouble("array update", bufsrc, 1, 5, psrc->nelm);
|
||||
checkArrayDouble("array update", bufsrc, 1, 5);
|
||||
dbScanUnlock((dbCommon*)psrc);
|
||||
|
||||
testDiag("Retarget");
|
||||
@@ -523,7 +509,7 @@ static void testreTargetTypeChange(void)
|
||||
|
||||
dbScanLock((dbCommon*)psrc);
|
||||
testOp("%ld",(long)psrc->nord,==,(long)5);
|
||||
checkArrayDouble("array update", bufsrc, 2, 5, psrc->nelm);
|
||||
checkArrayDouble("array update", bufsrc, 2, 5);
|
||||
dbScanUnlock((dbCommon*)psrc);
|
||||
|
||||
testIocShutdownOk();
|
||||
@@ -583,7 +569,7 @@ static void testCAC(void)
|
||||
|
||||
MAIN(dbCaLinkTest)
|
||||
{
|
||||
testPlan(91);
|
||||
testPlan(87);
|
||||
testNativeLink();
|
||||
testStringLink();
|
||||
testCP();
|
||||
|
||||
Reference in New Issue
Block a user