Skip to content

Commit

Permalink
Merged the pcas-vararray-3.14 branch, with fixes and notes
Browse files Browse the repository at this point in the history
  • Loading branch information
anjohnson committed Oct 20, 2016
2 parents 994cf0f + ac6b8bf commit 0743417
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 180 deletions.
11 changes: 8 additions & 3 deletions documentation/RELEASE_NOTES.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ <h3>Add dynamic (variable length) array support to PCAS</h3>
<p>Dynamic array sizing support was added to the IOC server (RSRV) in the
Base-3.14.12 release, but has not until now been supported in the <q>Portable
Channel Access Server</q> (PCAS). Channel Access server applications using the
PCAS will have to be modified slightly to provide full support for variable
length arrays, but unmodified applications will continue to build and work as
before against this release.</p>
PCAS may not need to be modified at all; if they already push monitors with
different gdd array lengths, those variable sizes will be forwarded to any CA
clients who have requested variable length updates. The example CAS server
application has been modified to demonstrate this feature.</p>

<p>In implementing the above, the gdd method <tt>gdd::put(const gdd *)</tt> now
copies the full-sized array from the source gdd if the destination gdd is of
type array, has no allocated memory and a boundary size of 0.</p>

<h3>Additional epicsTime conversion</h3>

Expand Down
9 changes: 7 additions & 2 deletions src/cas/generic/caServerI.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ class casIntfOS;
class casMonitor;
class casChannelI;

caStatus convertContainerMemberToAtomic ( class gdd & dd,
aitUint32 appType, aitUint32 elemCount );
caStatus convertContainerMemberToAtomic (class gdd & dd,
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount);

// Keep the old signature for backward compatibility
inline caStatus convertContainerMemberToAtomic (class gdd & dd,
aitUint32 appType, aitUint32 elemCount)
{ return convertContainerMemberToAtomic(dd, appType, elemCount, elemCount); }

class caServerI :
public caServerIO,
Expand Down
90 changes: 47 additions & 43 deletions src/cas/generic/casStrmClient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -409,17 +409,8 @@ caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
//
// element count out of range ?
//
if ( allowdyn && ctx.msg.m_count==0 &&
CA_V413 ( this->minor_version_number ) ) {
// Hack
// Since GDD interface doesn't support variable sized arrays
// we present dynamic requests as max size.
// This allows PCAS to claim support for dynamic arrays w/o
// going to the trouble of fixing GDD.
ctx.msg.m_count = pChan->getPVI().nativeCount();
}
else if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
ctx.msg.m_count == 0u ) {
if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
return ECA_BADCOUNT;
}

Expand Down Expand Up @@ -452,7 +443,7 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard )
casChannelI * pChan;

{
caStatus status = this->verifyRequest ( pChan, true );
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
if ( pChan ) {
return this->sendErr ( guard, mp, pChan->getCID(),
Expand Down Expand Up @@ -539,11 +530,15 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
pChan->getCID(), status, ECA_GETFAIL );
}

ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;

void * pPayload;
{
unsigned payloadSize = dbr_size_n ( msg.m_dataType, msg.m_count );
unsigned payloadSize = dbr_size_n ( msg.m_dataType, count );
caStatus localStatus = this->out.copyInHeader ( msg.m_cmmd, payloadSize,
msg.m_dataType, msg.m_count, pChan->getCID (),
msg.m_dataType, count, pChan->getCID (),
msg.m_available, & pPayload );
if ( localStatus ) {
if ( localStatus==S_cas_hugeRequest ) {
Expand All @@ -559,21 +554,21 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
// (places the data in network format)
//
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr(
pPayload, msg.m_count, desc, pChan->enumStringTable() );
pPayload, count, desc, pChan->enumStringTable() );
if ( mapDBRStatus < 0 ) {
desc.dump ();
errPrintf ( S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u",
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
pChan->getPVI().getName(), msg.m_dataType, count );
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_badBounds, ECA_GETFAIL );
}
int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
}
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
Expand All @@ -593,7 +588,7 @@ caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard
casChannelI * pChan;

{
caStatus status = this->verifyRequest ( pChan, true );
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
return this->readNotifyFailureResponse ( guard, * mp, status );
}
Expand Down Expand Up @@ -664,11 +659,15 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
return ecaStatus;
}

ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;

void *pPayload;
{
unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count );
unsigned size = dbr_size_n ( msg.m_dataType, count );
caStatus status = this->out.copyInHeader ( msg.m_cmmd, size,
msg.m_dataType, msg.m_count, ECA_NORMAL,
msg.m_dataType, count, ECA_NORMAL,
msg.m_available, & pPayload );
if ( status ) {
if ( status == S_cas_hugeRequest ) {
Expand All @@ -683,23 +682,23 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
// convert gdd to db_access type
//
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload,
msg.m_count, desc, pChan->enumStringTable() );
count, desc, pChan->enumStringTable() );
if ( mapDBRStatus < 0 ) {
desc.dump();
errPrintf ( S_cas_badBounds, __FILE__, __LINE__,
"- get notify with PV=%s type=%u count=%u",
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
pChan->getPVI().getName(), msg.m_dataType, count );
return this->readNotifyFailureResponse ( guard, msg, ECA_NOCONVERT );
}

int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
return this->sendErrWithEpicsStatus (
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
}

if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
Expand Down Expand Up @@ -735,8 +734,8 @@ caStatus casStrmClient::readNotifyFailureResponse (
// to be more efficent if it discovers that the source has less data
// than the destination)
//
caStatus convertContainerMemberToAtomic ( gdd & dd,
aitUint32 appType, aitUint32 elemCount )
caStatus convertContainerMemberToAtomic ( gdd & dd,
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount )
{
gdd * pVal;
if ( dd.isContainer() ) {
Expand All @@ -763,13 +762,13 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
return S_cas_badType;
}

if ( elemCount <= 1 ) {
if ( nativeCount <= 1 ) {
return S_cas_success;
}

// convert to atomic
gddBounds bds;
bds.setSize ( elemCount );
bds.setSize ( requestedCount );
bds.setFirst ( 0u );
pVal->setDimension ( 1u, & bds );
return S_cas_success;
Expand All @@ -778,9 +777,9 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
//
// createDBRDD ()
//
static caStatus createDBRDD ( unsigned dbrType,
unsigned elemCount, gdd * & pDD )
{
static caStatus createDBRDD ( unsigned dbrType,
unsigned requestedCount, unsigned nativeCount, gdd * & pDD )
{
/*
* DBR type has already been checked, but it is possible
* that "gddDbrToAit" will not track with changes in
Expand All @@ -807,7 +806,7 @@ static caStatus createDBRDD ( unsigned dbrType,

// fix the value element count
caStatus status = convertContainerMemberToAtomic (
*pDescRet, gddAppType_value, elemCount );
*pDescRet, gddAppType_value, requestedCount, nativeCount );
if ( status != S_cas_success ) {
pDescRet->unreference ();
return status;
Expand Down Expand Up @@ -857,11 +856,15 @@ caStatus casStrmClient::monitorResponse (
casChannelI & chan, const caHdrLargeArray & msg,
const gdd & desc, const caStatus completionStatus )
{
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
msg.m_count;

void * pPayload = 0;
{
ca_uint32_t size = dbr_size_n ( msg.m_dataType, msg.m_count );
ca_uint32_t size = dbr_size_n ( msg.m_dataType, count );
caStatus status = out.copyInHeader ( msg.m_cmmd, size,
msg.m_dataType, msg.m_count, ECA_NORMAL,
msg.m_dataType, count, ECA_NORMAL,
msg.m_available, & pPayload );
if ( status ) {
if ( status == S_cas_hugeRequest ) {
Expand All @@ -879,7 +882,8 @@ caStatus casStrmClient::monitorResponse (

gdd * pDBRDD = 0;
if ( completionStatus == S_cas_success ) {
caStatus status = createDBRDD ( msg.m_dataType, msg.m_count, pDBRDD );
caStatus status = createDBRDD ( msg.m_dataType, count,
chan.getPVI().nativeCount(), pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
Expand All @@ -900,7 +904,7 @@ caStatus casStrmClient::monitorResponse (
pDBRDD->unreference ();
errPrintf ( S_cas_noConvert, __FILE__, __LINE__,
"no conversion between event app type=%d and DBR type=%d Element count=%d",
desc.applicationType (), msg.m_dataType, msg.m_count);
desc.applicationType (), msg.m_dataType, count);
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
}
}
Expand All @@ -923,14 +927,14 @@ caStatus casStrmClient::monitorResponse (
}

int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr (
pPayload, msg.m_count, *pDBRDD, chan.enumStringTable() );
pPayload, count, *pDBRDD, chan.enumStringTable() );
if ( mapDBRStatus < 0 ) {
pDBRDD->unreference ();
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
}

int cacStatus = caNetConvert (
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
msg.m_dataType, pPayload, pPayload, true, count );
if ( cacStatus != ECA_NORMAL ) {
pDBRDD->unreference ();
return this->sendErrWithEpicsStatus (
Expand All @@ -940,7 +944,7 @@ caStatus casStrmClient::monitorResponse (
//
// force string message size to be the true size
//
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
ca_uint32_t reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
this->out.commitMsg ( reducedPayloadSize );
}
Expand Down Expand Up @@ -1948,7 +1952,7 @@ caStatus casStrmClient::eventAddAction (

casChannelI *pciu;
{
caStatus status = casStrmClient::verifyRequest ( pciu, true );
caStatus status = casStrmClient::verifyRequest ( pciu, CA_V413 ( this->minor_version_number ) );
if ( status != ECA_NORMAL ) {
if ( pciu ) {
return this->sendErr ( guard, mp,
Expand Down Expand Up @@ -2609,8 +2613,8 @@ caStatus casStrmClient::read ()

{
gdd * pDD = 0;
caStatus status = createDBRDD ( pHdr->m_dataType,
pHdr->m_count, pDD );
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
this->ctx.getChannel()->getPVI().nativeCount(), pDD );
if ( status != S_cas_success ) {
return status;
}
Expand Down
5 changes: 3 additions & 2 deletions src/gdd/gdd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1355,8 +1355,9 @@ gddStatus gdd::put ( const gdd * dd )
}

aitUint32 srcAvailSize = srcElemCount - unusedSrcBelow;
if ( srcAvailSize > this->getBounds()->size() ) {
srcCopySize = this->getBounds()->size();
aitUint32 destSize = this->getBounds()->size();
if ( destSize > 0 && srcAvailSize > destSize ) {
srcCopySize = destSize;
}
else {
srcCopySize = srcAvailSize;
Expand Down

0 comments on commit 0743417

Please sign in to comment.