From cbde3ea9fd1320090e9a4548b718581abec8a53c Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 30 Nov 2012 17:42:47 -0600 Subject: [PATCH] cas: Added propertyEventMask support Allows server tools to send DBE_PROPERTY events to clients. New functionality not tested, but fairly trivial and doesn't break existing server tools. --- src/cas/generic/caServer.cc | 90 +- src/cas/generic/caServerI.cc | 47 +- src/cas/generic/caServerI.h | 65 +- src/cas/generic/casStrmClient.cc | 2033 +++++++++++++++--------------- src/cas/generic/casdef.h | 1 + 5 files changed, 1129 insertions(+), 1107 deletions(-) diff --git a/src/cas/generic/caServer.cc b/src/cas/generic/caServer.cc index fa4401ecd..c4d91558d 100644 --- a/src/cas/generic/caServer.cc +++ b/src/cas/generic/caServer.cc @@ -3,9 +3,8 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * $Revision-Id$ @@ -15,8 +14,8 @@ * 505 665 1831 */ -#include "dbMapper.h" // ait to dbr types -#include "gddAppTable.h" // EPICS application type table +#include "dbMapper.h" // ait to dbr types +#include "gddAppTable.h" // EPICS application type table #include "fdManager.h" #define epicsExportSharedSymbols @@ -37,67 +36,67 @@ caServer::caServer () caServer::~caServer() { - if (this->pCAS) { - delete this->pCAS; + if (this->pCAS) { + delete this->pCAS; this->pCAS = NULL; - } + } } pvExistReturn caServer::pvExistTest ( const casCtx & ctx, - const caNetAddr & /* clientAddress */, const char * pPVAliasName ) + const caNetAddr & /* clientAddress */, const char * pPVAliasName ) { return this->pvExistTest ( ctx, pPVAliasName ); } pvExistReturn caServer::pvExistTest ( const casCtx &, const char * ) { - return pverDoesNotExistHere; + return pverDoesNotExistHere; } pvCreateReturn caServer::createPV ( const casCtx &, const char * ) { - return S_casApp_pvNotFound; + return S_casApp_pvNotFound; } pvAttachReturn caServer::pvAttach ( const casCtx &ctx, const char *pAliasName ) { - // remain backwards compatible (call deprecated routine) - return this->createPV ( ctx, pAliasName ); + // remain backwards compatible (call deprecated routine) + return this->createPV ( ctx, pAliasName ); } -casEventMask caServer::registerEvent (const char *pName) // X aCC 361 +casEventMask caServer::registerEvent (const char *pName) { - if (this->pCAS) { - return this->pCAS->registerEvent(pName); - } - else { - casEventMask emptyMask; - printf("caServer:: no server internals attached\n"); - return emptyMask; - } + if (this->pCAS) { + return this->pCAS->registerEvent(pName); + } + else { + casEventMask emptyMask; + printf("caServer:: no server internals attached\n"); + return emptyMask; + } } void caServer::show(unsigned level) const { - if (this->pCAS) { - this->pCAS->show(level); - } - else { - printf("caServer:: no server internals attached\n"); - } + if (this->pCAS) { + this->pCAS->show(level); + } + else { + printf("caServer:: no server internals attached\n"); + } } void caServer::setDebugLevel (unsigned level) { - if (pCAS) { - this->pCAS->setDebugLevel(level); - } - else { - printf("caServer:: no server internals attached\n"); - } + if (pCAS) { + this->pCAS->setDebugLevel(level); + } + else { + printf("caServer:: no server internals attached\n"); + } } -unsigned caServer::getDebugLevel () const // X aCC 361 +unsigned caServer::getDebugLevel () const { if (pCAS) { return this->pCAS->getDebugLevel(); @@ -108,7 +107,7 @@ unsigned caServer::getDebugLevel () const // X aCC 361 } } -casEventMask caServer::valueEventMask () const // X aCC 361 +casEventMask caServer::valueEventMask () const { if (pCAS) { return this->pCAS->valueEventMask(); @@ -119,7 +118,7 @@ casEventMask caServer::valueEventMask () const // X aCC 361 } } -casEventMask caServer::logEventMask () const // X aCC 361 +casEventMask caServer::logEventMask () const { if (pCAS) { return this->pCAS->logEventMask(); @@ -130,7 +129,7 @@ casEventMask caServer::logEventMask () const // X aCC 361 } } -casEventMask caServer::alarmEventMask () const // X aCC 361 +casEventMask caServer::alarmEventMask () const { if ( pCAS ) { return this->pCAS->alarmEventMask (); @@ -141,12 +140,23 @@ casEventMask caServer::alarmEventMask () const // X aCC 361 } } +casEventMask caServer::propertyEventMask () const +{ + if (pCAS) { + return this->pCAS->propertyEventMask(); + } + else { + printf("caServer:: no server internals attached\n"); + return casEventMask(); + } +} + class epicsTimer & caServer::createTimer () { return fileDescriptorManager.createTimer (); } -unsigned caServer::subscriptionEventsProcessed () const // X aCC 361 +unsigned caServer::subscriptionEventsProcessed () const { if ( pCAS ) { return this->pCAS->subscriptionEventsProcessed (); @@ -156,7 +166,7 @@ unsigned caServer::subscriptionEventsProcessed () const // X aCC 361 } } -unsigned caServer::subscriptionEventsPosted () const // X aCC 361 +unsigned caServer::subscriptionEventsPosted () const { if ( pCAS ) { return this->pCAS->subscriptionEventsPosted (); diff --git a/src/cas/generic/caServerI.cc b/src/cas/generic/caServerI.cc index 320195795..af7ece1eb 100644 --- a/src/cas/generic/caServerI.cc +++ b/src/cas/generic/caServerI.cc @@ -47,22 +47,23 @@ caServerI::caServerI ( caServer & tool ) : nEventsPosted ( 0u ), ioInProgressCount ( 0u ) { - assert ( & adapter != NULL ); + assert ( & adapter != NULL ); // create predefined event types this->valueEvent = registerEvent ( "value" ); - this->logEvent = registerEvent ( "log" ); - this->alarmEvent = registerEvent ( "alarm" ); + this->logEvent = registerEvent ( "log" ); + this->alarmEvent = registerEvent ( "alarm" ); + this->propertyEvent = registerEvent ( "property" ); this->locateInterfaces (); - if (this->intfList.count()==0u) { - errMessage (S_cas_noInterface, + if (this->intfList.count()==0u) { + errMessage (S_cas_noInterface, "- CA server internals init unable to continue"); throw S_cas_noInterface; - } + } - return; + return; } caServerI::~caServerI() @@ -70,22 +71,22 @@ caServerI::~caServerI() delete & this->beaconAnomalyGov; delete & this->beaconTmr; - // delete all clients + // delete all clients while ( casStrmClient * pClient = this->clientList.get() ) { - delete pClient; - } + delete pClient; + } - casIntfOS *pIF; - while ( ( pIF = this->intfList.get() ) ) { - delete pIF; - } + casIntfOS *pIF; + while ( ( pIF = this->intfList.get() ) ) { + delete pIF; + } } void caServerI::destroyClient ( casStrmClient & client ) { { epicsGuard < epicsMutex > locker ( this->mutex ); - this->clientList.remove ( client ); + this->clientList.remove ( client ); } delete & client; } @@ -143,11 +144,11 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn, void caServerI::sendBeacon ( ca_uint32_t beaconNo ) { epicsGuard < epicsMutex > locker ( this->mutex ); - tsDLIter < casIntfOS > iter = this->intfList.firstIter (); - while ( iter.valid () ) { - iter->sendBeacon ( beaconNo ); - iter++; - } + tsDLIter < casIntfOS > iter = this->intfList.firstIter (); + while ( iter.valid () ) { + iter->sendBeacon ( beaconNo ); + iter++; + } } void caServerI::generateBeaconAnomaly () @@ -259,11 +260,11 @@ void caServerI::casMonitorDestroy ( casMonitor & cm ) } // -// caServerI::dumpMsg() +// caServerI::dumpMsg() // -// Debug aid - print the header part of a message. +// Debug aid - print the header part of a message. // -// dp arg allowed to be null +// dp arg allowed to be null // // void caServerI::dumpMsg ( const char * pHostName, const char * pUserName, diff --git a/src/cas/generic/caServerI.h b/src/cas/generic/caServerI.h index 5002bcaa0..6037d8c20 100644 --- a/src/cas/generic/caServerI.h +++ b/src/cas/generic/caServerI.h @@ -44,23 +44,24 @@ caStatus convertContainerMemberToAtomic ( class gdd & dd, aitUint32 appType, aitUint32 elemCount ); class caServerI : - public caServerIO, - public ioBlockedList, - public casEventRegistry { + public caServerIO, + public ioBlockedList, + public casEventRegistry { public: - caServerI ( caServer &tool ); - ~caServerI (); - bool roomForNewChannel() const; - unsigned getDebugLevel() const { return debugLevel; } - inline void setDebugLevel ( unsigned debugLevelIn ); - void show ( unsigned level ) const; + caServerI ( caServer &tool ); + ~caServerI (); + bool roomForNewChannel() const; + unsigned getDebugLevel() const { return debugLevel; } + inline void setDebugLevel ( unsigned debugLevelIn ); + void show ( unsigned level ) const; void destroyMonitor ( casMonitor & ); - caServer * getAdapter (); - caServer * operator -> (); - void connectCB ( casIntfOS & ); - casEventMask valueEventMask () const; // DBE_VALUE registerEvent("value") - casEventMask logEventMask () const; // DBE_LOG registerEvent("log") - casEventMask alarmEventMask () const; // DBE_ALARM registerEvent("alarm") + caServer * getAdapter (); + caServer * operator -> (); + void connectCB ( casIntfOS & ); + casEventMask valueEventMask () const; // DBE_VALUE registerEvent("value") + casEventMask logEventMask () const; // DBE_LOG registerEvent("log") + casEventMask alarmEventMask () const; // DBE_ALARM registerEvent("alarm") + casEventMask propertyEventMask () const; // DBE_PROPERTY registerEvent("property") unsigned subscriptionEventsProcessed () const; void incrEventsProcessedCounter (); unsigned subscriptionEventsPosted () const; @@ -82,29 +83,30 @@ public: private: clientBufMemoryManager clientBufMemMgr; tsFreeList < casMonitor, 1024 > casMonitorFreeList; - tsDLList < casStrmClient > clientList; + tsDLList < casStrmClient > clientList; tsDLList < casIntfOS > intfList; - mutable epicsMutex mutex; - mutable epicsMutex diagnosticCountersMutex; - caServer & adapter; + mutable epicsMutex mutex; + mutable epicsMutex diagnosticCountersMutex; + caServer & adapter; beaconTimer & beaconTmr; beaconAnomalyGovernor & beaconAnomalyGov; - unsigned debugLevel; + unsigned debugLevel; unsigned nEventsProcessed; unsigned nEventsPosted; unsigned ioInProgressCount; casEventMask valueEvent; // DBE_VALUE registerEvent("value") - casEventMask logEvent; // DBE_LOG registerEvent("log") - casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") + casEventMask logEvent; // DBE_LOG registerEvent("log") + casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") + casEventMask propertyEvent; // DBE_PROPERTY registerEvent("property") - caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr, - bool addConfigAddr ); + caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr, + bool addConfigAddr ); void sendBeacon ( ca_uint32_t beaconNo ); - caServerI ( const caServerI & ); - caServerI & operator = ( const caServerI & ); + caServerI ( const caServerI & ); + caServerI & operator = ( const caServerI & ); friend class beaconAnomalyGovernor; friend class beaconTimer; @@ -113,17 +115,17 @@ private: inline caServer * caServerI::getAdapter() { - return & this->adapter; + return & this->adapter; } inline caServer * caServerI::operator -> () { - return this->getAdapter(); + return this->getAdapter(); } inline void caServerI::setDebugLevel(unsigned debugLevelIn) { - this->debugLevel = debugLevelIn; + this->debugLevel = debugLevelIn; } inline casEventMask caServerI::valueEventMask() const @@ -141,6 +143,11 @@ inline casEventMask caServerI::alarmEventMask() const return this->alarmEvent; } +inline casEventMask caServerI::propertyEventMask() const +{ + return this->propertyEvent; +} + inline bool caServerI :: ioIsPending () const { return ( ioInProgressCount > 0u ); diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index 4ecb290b0..51f4d0d7c 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -38,34 +38,34 @@ static const caHdr nill_msg = { 0u, 0u, 0u, 0u, 0u, 0u }; casStrmClient::pCASMsgHandler const casStrmClient::msgHandlers[] = { - & casStrmClient::versionAction, - & casStrmClient::eventAddAction, - & casStrmClient::eventCancelAction, - & casStrmClient::readAction, - & casStrmClient::writeAction, + & casStrmClient::versionAction, + & casStrmClient::eventAddAction, + & casStrmClient::eventCancelAction, + & casStrmClient::readAction, + & casStrmClient::writeAction, & casStrmClient::uknownMessageAction, & casStrmClient::searchAction, & casStrmClient::uknownMessageAction, - & casStrmClient::eventsOffAction, - & casStrmClient::eventsOnAction, - & casStrmClient::readSyncAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::clearChannelAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::readNotifyAction, - & casStrmClient::ignoreMsgAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::claimChannelAction, - & casStrmClient::writeNotifyAction, - & casStrmClient::clientNameAction, - & casStrmClient::hostNameAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::echoAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::uknownMessageAction, - & casStrmClient::uknownMessageAction + & casStrmClient::eventsOffAction, + & casStrmClient::eventsOnAction, + & casStrmClient::readSyncAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::clearChannelAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::readNotifyAction, + & casStrmClient::ignoreMsgAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::claimChannelAction, + & casStrmClient::writeNotifyAction, + & casStrmClient::clientNameAction, + & casStrmClient::hostNameAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::echoAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::uknownMessageAction, + & casStrmClient::uknownMessageAction }; // @@ -107,8 +107,8 @@ casStrmClient::~casStrmClient () this->chanTable.remove ( *pChan ); delete pChan; } - delete [] this->pUserName; - delete [] this->pHostName; + delete [] this->pUserName; + delete [] this->pHostName; } // @@ -117,14 +117,14 @@ casStrmClient::~casStrmClient () caStatus casStrmClient :: processMsg () { epicsGuard < casClientMutex > guard ( this->mutex ); - int status = S_cas_success; - - // protect against service returning s_casApp_success when it - // returned S_casApp_postponeAsyncIO before, but no - // asyn IO completed since the last attempt - if ( this->isBlocked () ) { - return S_casApp_postponeAsyncIO; - } + int status = S_cas_success; + + // protect against service returning s_casApp_success when it + // returned S_casApp_postponeAsyncIO before, but no + // asyn IO completed since the last attempt + if ( this->isBlocked () ) { + return S_casApp_postponeAsyncIO; + } try { @@ -142,20 +142,20 @@ caStatus casStrmClient :: processMsg () } } - // - // process any messages in the in buffer - // - unsigned bytesLeft; - while ( ( bytesLeft = this->in.bytesPresent() ) ) { + // + // process any messages in the in buffer + // + unsigned bytesLeft; + while ( ( bytesLeft = this->in.bytesPresent() ) ) { caHdrLargeArray msgTmp; unsigned msgSize; ca_uint32_t hdrSize; char * rawMP; { - // - // copy as raw bytes in order to avoid - // alignment problems - // + // + // copy as raw bytes in order to avoid + // alignment problems + // caHdr smallHdr; if ( bytesLeft < sizeof ( smallHdr ) ) { status = S_cas_success; @@ -163,7 +163,7 @@ caStatus casStrmClient :: processMsg () } rawMP = this->in.msgPtr (); - memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) ); + memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) ); ca_uint32_t payloadSize = AlignedWireRef < epicsUInt16 > ( smallHdr.m_postsize ); ca_uint32_t nElem = AlignedWireRef < epicsUInt16 > ( smallHdr.m_count ); @@ -226,40 +226,40 @@ caStatus casStrmClient :: processMsg () this->ctx.setMsg ( msgTmp, rawMP + hdrSize ); - if ( this->getCAS().getDebugLevel() > 2u ) { - caServerI::dumpMsg ( this->pHostName, this->pUserName, + if ( this->getCAS().getDebugLevel() > 2u ) { + caServerI::dumpMsg ( this->pHostName, this->pUserName, & msgTmp, rawMP + hdrSize, 0 ); - } + } } - // - // Reset the context to the default - // (guarantees that previous message does not get mixed - // up with the current message) - // - this->ctx.setChannel ( NULL ); - this->ctx.setPV ( NULL ); + // + // Reset the context to the default + // (guarantees that previous message does not get mixed + // up with the current message) + // + this->ctx.setChannel ( NULL ); + this->ctx.setPV ( NULL ); - // - // Call protocol stub - // + // + // Call protocol stub + // casStrmClient::pCASMsgHandler pHandler; - if ( msgTmp.m_cmmd < NELEMENTS ( casStrmClient::msgHandlers ) ) { + if ( msgTmp.m_cmmd < NELEMENTS ( casStrmClient::msgHandlers ) ) { pHandler = this->casStrmClient::msgHandlers[msgTmp.m_cmmd]; - } + } else { pHandler = & casStrmClient::uknownMessageAction; } - status = ( this->*pHandler ) ( guard ); - if ( status ) { - break; - } + status = ( this->*pHandler ) ( guard ); + if ( status ) { + break; + } this->in.removeMsg ( msgSize ); - this->pendingResponseStatus = S_cas_success; + this->pendingResponseStatus = S_cas_success; this->reqPayloadNeedsByteSwap = true; - this->responseIsPending = false; + this->responseIsPending = false; this->pValueRead.set ( 0 ); - } + } } catch ( std::bad_alloc & ) { this->sendErr ( guard, @@ -269,7 +269,7 @@ caStatus casStrmClient :: processMsg () status = S_cas_noMemory; } catch ( std::exception & except ) { - this->sendErr ( guard, + this->sendErr ( guard, this->ctx.getMsg(), invalidResID, ECA_INTERNAL, "C++ exception \"%s\" in server - " "disconnected client", @@ -277,14 +277,14 @@ caStatus casStrmClient :: processMsg () status = S_cas_internal; } catch ( ... ) { - this->sendErr ( guard, + this->sendErr ( guard, this->ctx.getMsg(), invalidResID, ECA_INTERNAL, "unexpected C++ exception in server " "disconnected client" ); status = S_cas_internal; } - return status; + return status; } // @@ -292,27 +292,27 @@ caStatus casStrmClient :: processMsg () // caStatus casStrmClient::uknownMessageAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg(); - caStatus status; + const caHdrLargeArray *mp = this->ctx.getMsg(); + caStatus status; caServerI::dumpMsg ( this->pHostName, this->pUserName, mp, this->ctx.getData(), "bad request code from virtual circuit=%u\n", mp->m_cmmd ); - /* - * most clients dont recover from this - */ - status = this->sendErr ( guard, mp, invalidResID, + /* + * most clients dont recover from this + */ + status = this->sendErr ( guard, mp, invalidResID, ECA_INTERNAL, "Invalid Request Code" ); - if (status) { - return status; - } + if (status) { + return status; + } - /* - * returning S_cas_badProtocol here disconnects - * the client with the bad message - */ - return S_cas_badProtocol; + /* + * returning S_cas_badProtocol here disconnects + * the client with the bad message + */ + return S_cas_badProtocol; } /* @@ -320,7 +320,7 @@ caStatus casStrmClient::uknownMessageAction ( epicsGuard < casClientMutex > & gu */ caStatus casStrmClient::ignoreMsgAction ( epicsGuard < casClientMutex > & ) { - return S_cas_success; + return S_cas_success; } // @@ -329,12 +329,12 @@ caStatus casStrmClient::ignoreMsgAction ( epicsGuard < casClientMutex > & ) caStatus casStrmClient::versionAction ( epicsGuard < casClientMutex > & ) { #if 1 - return S_cas_success; + return S_cas_success; #else // // eventually need to set the priority here // - const caHdrLargeArray * mp = this->ctx.getMsg(); + const caHdrLargeArray * mp = this->ctx.getMsg(); if ( mp->m_dataType > CA_PROTO_PRIORITY_MAX ) { return S_cas_badProtocol; @@ -373,8 +373,8 @@ caStatus casStrmClient::versionAction ( epicsGuard < casClientMutex > & ) // caStatus casStrmClient::echoAction ( epicsGuard < casClientMutex > & ) { - const caHdrLargeArray * mp = this->ctx.getMsg(); - const void * dp = this->ctx.getData(); + const caHdrLargeArray * mp = this->ctx.getMsg(); + const void * dp = this->ctx.getData(); void * pPayloadOut; caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize, @@ -384,7 +384,7 @@ caStatus casStrmClient::echoAction ( epicsGuard < casClientMutex > & ) memcpy ( pPayloadOut, dp, mp->m_postsize ); this->out.commitMsg (); } - return S_cas_success; + return S_cas_success; } // @@ -392,49 +392,49 @@ caStatus casStrmClient::echoAction ( epicsGuard < casClientMutex > & ) // caStatus casStrmClient::verifyRequest ( casChannelI * & pChan ) { - const caHdrLargeArray * mp = this->ctx.getMsg(); + const caHdrLargeArray * mp = this->ctx.getMsg(); - // - // channel exists for this resource id ? - // + // + // channel exists for this resource id ? + // chronIntId tmpId ( mp->m_cid ); - pChan = this->chanTable.lookup ( tmpId ); - if ( ! pChan ) { - return ECA_BADCHID; - } + pChan = this->chanTable.lookup ( tmpId ); + if ( ! pChan ) { + return ECA_BADCHID; + } - // - // data type out of range ? - // - if ( mp->m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) { - return ECA_BADTYPE; - } + // + // data type out of range ? + // + if ( mp->m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) { + return ECA_BADTYPE; + } - // - // element count out of range ? - // - if ( mp->m_count > pChan->getPVI().nativeCount() || mp->m_count == 0u ) { - return ECA_BADCOUNT; - } + // + // element count out of range ? + // + if ( mp->m_count > pChan->getPVI().nativeCount() || mp->m_count == 0u ) { + return ECA_BADCOUNT; + } - this->ctx.setChannel ( pChan ); - this->ctx.setPV ( &pChan->getPVI() ); + this->ctx.setChannel ( pChan ); + this->ctx.setPV ( &pChan->getPVI() ); - return ECA_NORMAL; + return ECA_NORMAL; } void casStrmClient::show ( unsigned level ) const { epicsGuard < epicsMutex > locker ( this->mutex ); - printf ( "casStrmClient at %p\n", + printf ( "casStrmClient at %p\n", static_cast ( this ) ); - if ( level > 1u ) { - printf ("\tuser %s at %s\n", this->pUserName, this->pHostName); - this->casCoreClient::show ( level - 1 ); - this->in.show ( level - 1 ); - this->out.show ( level - 1 ); + if ( level > 1u ) { + printf ("\tuser %s at %s\n", this->pUserName, this->pHostName); + this->casCoreClient::show ( level - 1 ); + this->in.show ( level - 1 ); + this->out.show ( level - 1 ); this->chanTable.show ( level - 1 ); - } + } } /* @@ -442,32 +442,32 @@ void casStrmClient::show ( unsigned level ) const */ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray * mp = this->ctx.getMsg(); - casChannelI * pChan; + const caHdrLargeArray * mp = this->ctx.getMsg(); + casChannelI * pChan; { - caStatus status = this->verifyRequest ( pChan ); - if ( status != ECA_NORMAL ) { + caStatus status = this->verifyRequest ( pChan ); + if ( status != ECA_NORMAL ) { if ( pChan ) { - return this->sendErr ( guard, mp, pChan->getCID(), + return this->sendErr ( guard, mp, pChan->getCID(), status, "get request" ); } else { - return this->sendErr ( guard, mp, invalidResID, + return this->sendErr ( guard, mp, invalidResID, status, "get request" ); } - } + } } - // dont allow a request that completed with the service in the - // past, but was incomplete because no response was sent to be - // executed twice with the service - if ( this->responseIsPending ) { + // dont allow a request that completed with the service in the + // past, but was incomplete because no response was sent to be + // executed twice with the service + if ( this->responseIsPending ) { // dont read twice if we didnt finish in the past // because we were send blocked if ( this->pendingResponseStatus == S_cas_success ) { assert ( pValueRead.valid () ); - return this->readResponse ( guard, pChan, *mp, + return this->readResponse ( guard, pChan, *mp, *pValueRead, S_cas_success ); } else { @@ -476,48 +476,48 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard ) this->pendingResponseStatus, ECA_GETFAIL ); } - } + } - /* - * verify read access - */ - if ( ! pChan->readAccess() ) { - int v41 = CA_V41 ( this->minor_version_number ); + /* + * verify read access + */ + if ( ! pChan->readAccess() ) { + int v41 = CA_V41 ( this->minor_version_number ); int cacStatus; - if ( v41 ) { - cacStatus = ECA_NORDACCESS; - } - else{ - cacStatus = ECA_GETFAIL; - } - return this->sendErr ( guard, mp, pChan->getCID(), + if ( v41 ) { + cacStatus = ECA_NORDACCESS; + } + else{ + cacStatus = ECA_GETFAIL; + } + return this->sendErr ( guard, mp, pChan->getCID(), cacStatus, "read access denied" ); - } - + } + { - caStatus servStat = this->read (); - if ( servStat == S_casApp_success ) { + caStatus servStat = this->read (); + if ( servStat == S_casApp_success ) { assert ( pValueRead.valid () ); - caStatus status = this->readResponse ( guard, pChan, *mp, + caStatus status = this->readResponse ( guard, pChan, *mp, *pValueRead, S_cas_success ); this->responseIsPending = ( status != S_cas_success ); return status; - } - else if ( servStat == S_casApp_asyncCompletion ) { - return S_cas_success; - } - else if ( servStat == S_casApp_postponeAsyncIO ) { + } + else if ( servStat == S_casApp_asyncCompletion ) { + return S_cas_success; + } + else if ( servStat == S_casApp_postponeAsyncIO ) { return S_casApp_postponeAsyncIO; - } - else { - caStatus status = this->sendErrWithEpicsStatus ( guard, mp, + } + else { + caStatus status = this->sendErrWithEpicsStatus ( guard, mp, pChan->getCID(), servStat, ECA_GETFAIL ); if ( status != S_cas_success ) { this->pendingResponseStatus = servStat; - this->responseIsPending = true; - } + this->responseIsPending = true; + } return status; - } + } } } @@ -526,56 +526,56 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard ) // caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard, casChannelI * pChan, const caHdrLargeArray & msg, - const gdd & desc, const caStatus status ) + const gdd & desc, const caStatus status ) { - if ( status != S_casApp_success ) { - return this->sendErrWithEpicsStatus ( guard, & msg, + if ( status != S_casApp_success ) { + return this->sendErrWithEpicsStatus ( guard, & msg, pChan->getCID(), status, ECA_GETFAIL ); - } + } void * pPayload; { - unsigned payloadSize = dbr_size_n ( msg.m_dataType, msg.m_count ); + unsigned payloadSize = dbr_size_n ( msg.m_dataType, msg.m_count ); caStatus localStatus = this->out.copyInHeader ( msg.m_cmmd, payloadSize, msg.m_dataType, msg.m_count, pChan->getCID (), msg.m_available, & pPayload ); - if ( localStatus ) { - if ( localStatus==S_cas_hugeRequest ) { - localStatus = sendErr ( guard, & msg, pChan->getCID(), ECA_TOLARGE, + if ( localStatus ) { + if ( localStatus==S_cas_hugeRequest ) { + localStatus = sendErr ( guard, & msg, pChan->getCID(), ECA_TOLARGE, "unable to fit read response into server's buffer" ); - } - return localStatus; - } + } + return localStatus; + } } - // - // convert gdd to db_access type - // (places the data in network format) - // - int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr( + // + // convert gdd to db_access type + // (places the data in network format) + // + int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr( pPayload, msg.m_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 ); - return this->sendErrWithEpicsStatus ( + 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 ); + return this->sendErrWithEpicsStatus ( guard, & msg, pChan->getCID(), S_cas_badBounds, ECA_GETFAIL ); - } + } int cacStatus = caNetConvert ( msg.m_dataType, pPayload, pPayload, true, msg.m_count ); - if ( cacStatus != ECA_NORMAL ) { - return this->sendErrWithEpicsStatus ( + 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 ) { - unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; - this->out.commitMsg ( reducedPayloadSize ); - } + unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; + this->out.commitMsg ( reducedPayloadSize ); + } else { - this->out.commitMsg (); + this->out.commitMsg (); } - return S_cas_success; + return S_cas_success; } // @@ -583,45 +583,45 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard, // caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray * mp = this->ctx.getMsg(); - casChannelI * pChan; + const caHdrLargeArray * mp = this->ctx.getMsg(); + casChannelI * pChan; { - caStatus status = this->verifyRequest ( pChan ); - if ( status != ECA_NORMAL ) { - return this->readNotifyFailureResponse ( guard, * mp, status ); - } + caStatus status = this->verifyRequest ( pChan ); + if ( status != ECA_NORMAL ) { + return this->readNotifyFailureResponse ( guard, * mp, status ); + } } - // dont allow a request that completed with the service in the - // past, but was incomplete because no response was sent to be - // executed twice with the service - if ( this->responseIsPending ) { + // dont allow a request that completed with the service in the + // past, but was incomplete because no response was sent to be + // executed twice with the service + if ( this->responseIsPending ) { // dont read twice if we didnt finish in the past // because we were send blocked if ( this->pendingResponseStatus == S_cas_success ) { assert ( pValueRead.valid () ); - return this->readNotifyResponse ( guard, pChan, *mp, + return this->readNotifyResponse ( guard, pChan, *mp, *pValueRead, S_cas_success ); } else { return this->readNotifyFailureResponse ( guard, *mp, ECA_GETFAIL ); } - } + } - // - // verify read access - // - if ( ! pChan->readAccess() ) { - return this->readNotifyFailureResponse ( guard, *mp, ECA_NORDACCESS ); - } + // + // verify read access + // + if ( ! pChan->readAccess() ) { + return this->readNotifyFailureResponse ( guard, *mp, ECA_NORDACCESS ); + } { caStatus servStat = this->read (); if ( servStat == S_casApp_success ) { assert ( pValueRead.valid () ); - caStatus status = this->readNotifyResponse ( + caStatus status = this->readNotifyResponse ( guard, pChan, *mp, *pValueRead, servStat ); this->responseIsPending = ( status != S_cas_success ); @@ -652,56 +652,56 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua casChannelI * pChan, const caHdrLargeArray & msg, const gdd & desc, const caStatus completionStatus ) { - if ( completionStatus != S_cas_success ) { + if ( completionStatus != S_cas_success ) { caStatus ecaStatus = this->readNotifyFailureResponse ( guard, msg, ECA_GETFAIL ); return ecaStatus; - } + } void *pPayload; { - unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); + unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); caStatus status = this->out.copyInHeader ( msg.m_cmmd, size, msg.m_dataType, msg.m_count, ECA_NORMAL, msg.m_available, & pPayload ); - if ( status ) { - if ( status == S_cas_hugeRequest ) { - status = sendErr ( guard, & msg, pChan->getCID(), ECA_TOLARGE, + if ( status ) { + if ( status == S_cas_hugeRequest ) { + status = sendErr ( guard, & msg, pChan->getCID(), ECA_TOLARGE, "unable to fit read notify response into server's buffer" ); - } - return status; - } + } + return status; + } } // - // convert gdd to db_access type - // - int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload, + // convert gdd to db_access type + // + int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload, msg.m_count, desc, pChan->enumStringTable() ); - if ( mapDBRStatus < 0 ) { - desc.dump(); - errPrintf ( S_cas_badBounds, __FILE__, __LINE__, + 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, msg.m_count ); return this->readNotifyFailureResponse ( guard, msg, ECA_NOCONVERT ); - } + } int cacStatus = caNetConvert ( msg.m_dataType, pPayload, pPayload, true, msg.m_count ); - if ( cacStatus != ECA_NORMAL ) { - return this->sendErrWithEpicsStatus ( + 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 ) { - unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; - this->out.commitMsg ( reducedPayloadSize ); - } - else { - this->out.commitMsg (); } - return S_cas_success; + if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { + unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; + this->out.commitMsg ( reducedPayloadSize ); + } + else { + this->out.commitMsg (); + } + + return S_cas_success; } // @@ -712,14 +712,14 @@ caStatus casStrmClient::readNotifyFailureResponse ( { assert ( ECA_XXXX != ECA_NORMAL ); void *pPayload; - unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); + unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); caStatus status = this->out.copyInHeader ( msg.m_cmmd, size, msg.m_dataType, msg.m_count, ECA_XXXX, msg.m_available, & pPayload ); - if ( ! status ) { - memset ( pPayload, '\0', size ); - this->out.commitMsg (); - } + if ( ! status ) { + memset ( pPayload, '\0', size ); + this->out.commitMsg (); + } return status; } @@ -734,18 +734,18 @@ caStatus convertContainerMemberToAtomic ( gdd & dd, { gdd * pVal; if ( dd.isContainer() ) { - // All DBR types have a value member + // All DBR types have a value member aitUint32 index; - int gdds = gddApplicationTypeTable::app_table.mapAppToIndex - ( dd.applicationType(), appType, index ); - if ( gdds ) { - return S_cas_badType; - } + int gdds = gddApplicationTypeTable::app_table.mapAppToIndex + ( dd.applicationType(), appType, index ); + if ( gdds ) { + return S_cas_badType; + } - pVal = dd.getDD ( index ); - if ( ! pVal ) { - return S_cas_badType; - } + pVal = dd.getDD ( index ); + if ( ! pVal ) { + return S_cas_badType; + } } else { pVal = & dd; @@ -761,11 +761,11 @@ caStatus convertContainerMemberToAtomic ( gdd & dd, return S_cas_success; } - // convert to atomic - gddBounds bds; - bds.setSize ( elemCount ); - bds.setFirst ( 0u ); - pVal->setDimension ( 1u, & bds ); + // convert to atomic + gddBounds bds; + bds.setSize ( elemCount ); + bds.setFirst ( 0u ); + pVal->setDimension ( 1u, & bds ); return S_cas_success; } @@ -774,37 +774,37 @@ caStatus convertContainerMemberToAtomic ( gdd & dd, // static caStatus createDBRDD ( unsigned dbrType, unsigned elemCount, gdd * & pDD ) -{ - /* - * DBR type has already been checked, but it is possible - * that "gddDbrToAit" will not track with changes in - * the DBR_XXXX type system - */ - if ( dbrType >= NELEMENTS ( gddDbrToAit ) ) { - return S_cas_badType; - } +{ + /* + * DBR type has already been checked, but it is possible + * that "gddDbrToAit" will not track with changes in + * the DBR_XXXX type system + */ + if ( dbrType >= NELEMENTS ( gddDbrToAit ) ) { + return S_cas_badType; + } - if ( gddDbrToAit[dbrType].type == aitEnumInvalid ) { - return S_cas_badType; - } + if ( gddDbrToAit[dbrType].type == aitEnumInvalid ) { + return S_cas_badType; + } - aitUint16 appType = gddDbrToAit[dbrType].app; - - // - // create the descriptor - // - gdd * pDescRet = + aitUint16 appType = gddDbrToAit[dbrType].app; + + // + // create the descriptor + // + gdd * pDescRet = gddApplicationTypeTable::app_table.getDD ( appType ); - if ( ! pDescRet ) { - return S_cas_noMemory; - } + if ( ! pDescRet ) { + return S_cas_noMemory; + } // fix the value element count caStatus status = convertContainerMemberToAtomic ( *pDescRet, gddAppType_value, elemCount ); if ( status != S_cas_success ) { pDescRet->unreference (); - return status; + return status; } // fix the enum string table element count @@ -815,11 +815,11 @@ static caStatus createDBRDD ( unsigned dbrType, *pDescRet, gddAppType_enums, MAX_ENUM_STATES ); if ( status != S_cas_success ) { pDescRet->unreference (); - return status; + return status; } } - pDD = pDescRet; + pDD = pDescRet; return S_cas_success; } @@ -832,14 +832,14 @@ caStatus casStrmClient::monitorFailureResponse ( { assert ( ECA_XXXX != ECA_NORMAL ); void *pPayload; - unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); + unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count ); caStatus status = this->out.copyInHeader ( msg.m_cmmd, size, msg.m_dataType, msg.m_count, ECA_XXXX, msg.m_available, & pPayload ); - if ( ! status ) { - memset ( pPayload, '\0', size ); + if ( ! status ) { + memset ( pPayload, '\0', size ); this->out.commitMsg (); - } + } return status; } @@ -849,31 +849,31 @@ caStatus casStrmClient::monitorFailureResponse ( caStatus casStrmClient::monitorResponse ( epicsGuard < casClientMutex > & guard, casChannelI & chan, const caHdrLargeArray & msg, - const gdd & desc, const caStatus completionStatus ) + const gdd & desc, const caStatus completionStatus ) { 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, msg.m_count ); caStatus status = out.copyInHeader ( msg.m_cmmd, size, msg.m_dataType, msg.m_count, ECA_NORMAL, msg.m_available, & pPayload ); - if ( status ) { - if ( status == S_cas_hugeRequest ) { - status = sendErr ( guard, & msg, chan.getCID(), ECA_TOLARGE, + if ( status ) { + if ( status == S_cas_hugeRequest ) { + status = sendErr ( guard, & msg, chan.getCID(), ECA_TOLARGE, "unable to fit read subscription update response " "into server's buffer" ); - } - return status; - } + } + return status; + } } - if ( ! chan.readAccess () ) { + if ( ! chan.readAccess () ) { return monitorFailureResponse ( guard, msg, ECA_NORDACCESS ); - } + } gdd * pDBRDD = 0; - if ( completionStatus == S_cas_success ) { - caStatus status = createDBRDD ( msg.m_dataType, msg.m_count, pDBRDD ); + if ( completionStatus == S_cas_success ) { + caStatus status = createDBRDD ( msg.m_dataType, msg.m_count, pDBRDD ); if ( status != S_cas_success ) { caStatus ecaStatus; if ( status == S_cas_badType ) { @@ -887,36 +887,36 @@ caStatus casStrmClient::monitorResponse ( } return monitorFailureResponse ( guard, msg, ecaStatus ); } - else { - gddStatus gdds = gddApplicationTypeTable:: - app_table.smartCopy ( pDBRDD, & desc ); - if ( gdds < 0 ) { + else { + gddStatus gdds = gddApplicationTypeTable:: + app_table.smartCopy ( pDBRDD, & desc ); + if ( gdds < 0 ) { pDBRDD->unreference (); - errPrintf ( S_cas_noConvert, __FILE__, __LINE__, + 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, msg.m_count); return monitorFailureResponse ( guard, msg, ECA_NOCONVERT ); } } - } - else { - if ( completionStatus == S_cas_noRead ) { + } + else { + if ( completionStatus == S_cas_noRead ) { return monitorFailureResponse ( guard, msg, ECA_NORDACCESS ); - } - else if ( completionStatus == S_cas_noMemory || + } + else if ( completionStatus == S_cas_noMemory || completionStatus == S_casApp_noMemory ) { return monitorFailureResponse ( guard, msg, ECA_ALLOCMEM ); - } - else if ( completionStatus == S_cas_badType ) { + } + else if ( completionStatus == S_cas_badType ) { return monitorFailureResponse ( guard, msg, ECA_BADTYPE ); - } - else { - errMessage ( completionStatus, "- in monitor response" ); + } + else { + errMessage ( completionStatus, "- in monitor response" ); return monitorFailureResponse ( guard, msg, ECA_GETFAIL ); - } - } + } + } - int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( + int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload, msg.m_count, *pDBRDD, chan.enumStringTable() ); if ( mapDBRStatus < 0 ) { pDBRDD->unreference (); @@ -925,25 +925,25 @@ caStatus casStrmClient::monitorResponse ( int cacStatus = caNetConvert ( msg.m_dataType, pPayload, pPayload, true, msg.m_count ); - if ( cacStatus != ECA_NORMAL ) { - return this->sendErrWithEpicsStatus ( + if ( cacStatus != ECA_NORMAL ) { + return this->sendErrWithEpicsStatus ( guard, & msg, chan.getCID(), S_cas_internal, cacStatus ); - } + } - // - // force string message size to be the true size - // - if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { - ca_uint32_t reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; - this->out.commitMsg ( reducedPayloadSize ); - } + // + // force string message size to be the true size + // + if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { + ca_uint32_t reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; + this->out.commitMsg ( reducedPayloadSize ); + } else { - this->out.commitMsg (); + this->out.commitMsg (); } pDBRDD->unreference (); - return S_cas_success; + return S_cas_success; } /* @@ -952,7 +952,7 @@ caStatus casStrmClient::monitorResponse ( caStatus casStrmClient :: writeActionSendFailureStatus ( epicsGuard < casClientMutex > & guard, const caHdrLargeArray & msg, ca_uint32_t cid, caStatus status ) -{ +{ caStatus ecaStatus; if ( status == S_cas_noMemory ) { ecaStatus = ECA_ALLOCMEM; @@ -966,7 +966,7 @@ caStatus casStrmClient :: else { ecaStatus = ECA_PUTFAIL; } - status = this->sendErrWithEpicsStatus ( guard, & msg, cid, + status = this->sendErrWithEpicsStatus ( guard, & msg, cid, status, ecaStatus ); return status; } @@ -976,58 +976,58 @@ caStatus casStrmClient :: * casStrmClient::writeAction() */ caStatus casStrmClient::writeAction ( epicsGuard < casClientMutex > & guard ) -{ - const caHdrLargeArray *mp = this->ctx.getMsg(); - casChannelI *pChan; +{ + const caHdrLargeArray *mp = this->ctx.getMsg(); + casChannelI *pChan; { - caStatus status = this->verifyRequest ( pChan ); - if (status != ECA_NORMAL) { + caStatus status = this->verifyRequest ( pChan ); + if (status != ECA_NORMAL) { if ( pChan ) { - return this->sendErr ( guard, mp, pChan->getCID(), + return this->sendErr ( guard, mp, pChan->getCID(), status, "get request" ); } else { - return this->sendErr ( guard, mp, invalidResID, + return this->sendErr ( guard, mp, invalidResID, status, "get request" ); } - } + } } - // dont allow a request that completed with the service in the - // past, but was incomplete because no response was sent be - // executed twice with the service - if ( this->responseIsPending ) { + // dont allow a request that completed with the service in the + // past, but was incomplete because no response was sent be + // executed twice with the service + if ( this->responseIsPending ) { caStatus status = this->writeActionSendFailureStatus ( guard, *mp, pChan->getCID(), this->pendingResponseStatus ); - return status; - } + return status; + } - // - // verify write access - // - if ( ! pChan->writeAccess() ) { + // + // verify write access + // + if ( ! pChan->writeAccess() ) { caStatus status; - int v41 = CA_V41 ( this->minor_version_number ); - if (v41) { - status = ECA_NOWTACCESS; - } - else{ - status = ECA_PUTFAIL; - } - return this->sendErr ( guard, mp, pChan->getCID(), + int v41 = CA_V41 ( this->minor_version_number ); + if (v41) { + status = ECA_NOWTACCESS; + } + else{ + status = ECA_PUTFAIL; + } + return this->sendErr ( guard, mp, pChan->getCID(), status, "write access denied"); - } + } - // - // initiate the write operation - // + // + // initiate the write operation + // { caStatus servStat = this->write ( & casChannelI :: write ); if ( servStat == S_casApp_success || servStat == S_casApp_asyncCompletion ) { - return S_cas_success; + return S_cas_success; } else if ( servStat == S_casApp_postponeAsyncIO ) { return S_casApp_postponeAsyncIO; @@ -1038,15 +1038,15 @@ caStatus casStrmClient::writeAction ( epicsGuard < casClientMutex > & guard ) pChan->getCID(), servStat ); if ( status != S_cas_success ) { this->pendingResponseStatus = servStat; - this->responseIsPending = true; + this->responseIsPending = true; } return status; } } - // - // The gdd created above is deleted by the server tool - // + // + // The gdd created above is deleted by the server tool + // } // @@ -1054,20 +1054,20 @@ caStatus casStrmClient::writeAction ( epicsGuard < casClientMutex > & guard ) // caStatus casStrmClient::writeResponse ( epicsGuard < casClientMutex > & guard, casChannelI & chan, - const caHdrLargeArray & msg, const caStatus completionStatus ) + const caHdrLargeArray & msg, const caStatus completionStatus ) { - caStatus status; + caStatus status; - if ( completionStatus ) { - errMessage ( completionStatus, "write failed" ); - status = this->sendErrWithEpicsStatus ( guard, & msg, - chan.getCID(), completionStatus, ECA_PUTFAIL ); - } - else { - status = S_cas_success; - } + if ( completionStatus ) { + errMessage ( completionStatus, "write failed" ); + status = this->sendErrWithEpicsStatus ( guard, & msg, + chan.getCID(), completionStatus, ECA_PUTFAIL ); + } + else { + status = S_cas_success; + } - return status; + return status; } /* @@ -1076,59 +1076,59 @@ caStatus casStrmClient::writeResponse ( caStatus casStrmClient::writeNotifyAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg (); + const caHdrLargeArray *mp = this->ctx.getMsg (); - casChannelI *pChan; + casChannelI *pChan; { - caStatus status = this->verifyRequest ( pChan ); - if ( status != ECA_NORMAL ) { - return casStrmClient::writeNotifyResponseECA_XXX ( guard, *mp, status ); - } + caStatus status = this->verifyRequest ( pChan ); + if ( status != ECA_NORMAL ) { + return casStrmClient::writeNotifyResponseECA_XXX ( guard, *mp, status ); + } + } + + // dont allow a request that completed with the service in the + // past, but was incomplete because no response was sent be + // executed twice with the service + if ( this->responseIsPending ) { + caStatus status = this->writeNotifyResponse ( guard, *pChan, + *mp, this->pendingResponseStatus ); + return status; } - - // dont allow a request that completed with the service in the - // past, but was incomplete because no response was sent be - // executed twice with the service - if ( this->responseIsPending ) { - caStatus status = this->writeNotifyResponse ( guard, *pChan, - *mp, this->pendingResponseStatus ); - return status; - } - // - // verify write access - // - if ( ! pChan->writeAccess() ) { - if ( CA_V41(this->minor_version_number) ) { - return this->casStrmClient::writeNotifyResponseECA_XXX ( - guard, *mp, ECA_NOWTACCESS); - } - else { - return this->casStrmClient::writeNotifyResponse ( - guard, *pChan, *mp, S_cas_noWrite ); - } - } + // + // verify write access + // + if ( ! pChan->writeAccess() ) { + if ( CA_V41(this->minor_version_number) ) { + return this->casStrmClient::writeNotifyResponseECA_XXX ( + guard, *mp, ECA_NOWTACCESS); + } + else { + return this->casStrmClient::writeNotifyResponse ( + guard, *pChan, *mp, S_cas_noWrite ); + } + } - // - // initiate the write operation - // + // + // initiate the write operation + // { - caStatus servStat = this->write ( & casChannelI :: writeNotify ); - if ( servStat == S_casApp_asyncCompletion ) { - return S_cas_success; - } - else if ( servStat == S_casApp_postponeAsyncIO ) { + caStatus servStat = this->write ( & casChannelI :: writeNotify ); + if ( servStat == S_casApp_asyncCompletion ) { + return S_cas_success; + } + else if ( servStat == S_casApp_postponeAsyncIO ) { return S_casApp_postponeAsyncIO; - } - else { - caStatus status = this->writeNotifyResponse ( guard, *pChan, + } + else { + caStatus status = this->writeNotifyResponse ( guard, *pChan, *mp, servStat ); if ( status != S_cas_success ) { this->pendingResponseStatus = servStat; - this->responseIsPending = true; - } + this->responseIsPending = true; + } return status; - } + } } } @@ -1138,60 +1138,60 @@ caStatus casStrmClient::writeNotifyAction ( caStatus casStrmClient::writeNotifyResponse ( epicsGuard < casClientMutex > & guard, casChannelI & chan, const caHdrLargeArray & msg, const caStatus completionStatus ) { - caStatus ecaStatus; + caStatus ecaStatus; - if ( completionStatus == S_cas_success ) { - ecaStatus = ECA_NORMAL; - } - else { - ecaStatus = ECA_PUTFAIL; - } + if ( completionStatus == S_cas_success ) { + ecaStatus = ECA_NORMAL; + } + else { + ecaStatus = ECA_PUTFAIL; + } - ecaStatus = this->casStrmClient::writeNotifyResponseECA_XXX ( + ecaStatus = this->casStrmClient::writeNotifyResponseECA_XXX ( guard, msg, ecaStatus ); - if (ecaStatus) { - return ecaStatus; - } + if (ecaStatus) { + return ecaStatus; + } - // - // send independent warning exception to the client so that they - // will see the error string associated with this error code - // since the error string cant be sent with the put call back - // response (hopefully this is useful information) - // - // order is very important here because it determines that the put - // call back response is always sent, and that this warning exception - // message will be sent at most one time. In rare instances it will - // not be sent, but at least it will not be sent multiple times. - // The message is logged to the console in the rare situations when - // we are unable to send. - // - if ( completionStatus != S_cas_success ) { - ecaStatus = this->sendErrWithEpicsStatus ( guard, & msg, chan.getCID(), + // + // send independent warning exception to the client so that they + // will see the error string associated with this error code + // since the error string cant be sent with the put call back + // response (hopefully this is useful information) + // + // order is very important here because it determines that the put + // call back response is always sent, and that this warning exception + // message will be sent at most one time. In rare instances it will + // not be sent, but at least it will not be sent multiple times. + // The message is logged to the console in the rare situations when + // we are unable to send. + // + if ( completionStatus != S_cas_success ) { + ecaStatus = this->sendErrWithEpicsStatus ( guard, & msg, chan.getCID(), completionStatus, ECA_NOCONVERT ); - if ( ecaStatus ) { - errMessage ( completionStatus, + if ( ecaStatus ) { + errMessage ( completionStatus, "<= put callback failure detail not passed to client" ); - } - } - return S_cas_success; + } + } + return S_cas_success; } /* * casStrmClient::writeNotifyResponseECA_XXX() */ caStatus casStrmClient::writeNotifyResponseECA_XXX ( - epicsGuard < casClientMutex > &, + epicsGuard < casClientMutex > &, const caHdrLargeArray & msg, const caStatus ecaStatus ) { caStatus status = out.copyInHeader ( msg.m_cmmd, 0, msg.m_dataType, msg.m_count, ecaStatus, msg.m_available, 0 ); - if ( ! status ) { - this->out.commitMsg (); - } + if ( ! status ) { + this->out.commitMsg (); + } - return status; + return status; } // @@ -1199,7 +1199,7 @@ caStatus casStrmClient::writeNotifyResponseECA_XXX ( // caStatus casStrmClient :: asyncSearchResponse ( epicsGuard < casClientMutex > & guard, const caNetAddr & /* outAddr */, - const caHdrLargeArray & msg, const pvExistReturn & retVal, + const caHdrLargeArray & msg, const pvExistReturn & retVal, ca_uint16_t /* protocolRevision */, ca_uint32_t /* sequenceNumber */ ) { return this->searchResponse ( guard, msg, retVal ); @@ -1311,21 +1311,21 @@ caStatus casStrmClient :: searchResponse ( // caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg(); + const caHdrLargeArray *mp = this->ctx.getMsg(); const char *pChanName = static_cast ( this->ctx.getData() ); - caStatus status; + caStatus status; // // check the sanity of the message // if ( mp->m_postsize <= 1 ) { - caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(), + caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(), "empty PV name extension in TCP search request?\n" ); return S_cas_success; } if ( pChanName[0] == '\0' ) { - caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(), + caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(), "zero length PV name in UDP search request?\n" ); return S_cas_success; } @@ -1335,56 +1335,56 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard ) // of the client library might not be setting the pad bytes to nill) for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) { if ( i <= 1 ) { - caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(), + caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(), "unterminated PV name in UDP search request?\n" ); return S_cas_success; } } - if ( this->getCAS().getDebugLevel() > 6u ) { - this->hostName ( this->pHostName, sizeof ( pHostName ) ); - printf ( "\"%s\" is searching for \"%s\"\n", + if ( this->getCAS().getDebugLevel() > 6u ) { + this->hostName ( this->pHostName, sizeof ( pHostName ) ); + printf ( "\"%s\" is searching for \"%s\"\n", pHostName, pChanName ); - } + } - // - // verify that we have sufficent memory for a PV and a - // monitor prior to calling PV exist test so that when - // the server runs out of memory we dont reply to - // search requests, and therefore dont thrash through - // caServer::pvExistTest() and casCreatePV::pvAttach() - // + // + // verify that we have sufficent memory for a PV and a + // monitor prior to calling PV exist test so that when + // the server runs out of memory we dont reply to + // search requests, and therefore dont thrash through + // caServer::pvExistTest() and casCreatePV::pvAttach() + // if ( ! osiSufficentSpaceInPool ( 0 ) ) { return S_cas_success; } - // - // ask the server tool if this PV exists - // - this->userStartedAsyncIO = false; - pvExistReturn pver = - this->getCAS()->pvExistTest ( - this->ctx, _clientAddr, pChanName ); + // + // ask the server tool if this PV exists + // + this->userStartedAsyncIO = false; + pvExistReturn pver = + this->getCAS()->pvExistTest ( + this->ctx, _clientAddr, pChanName ); - // - // prevent problems when they initiate - // async IO but dont return status - // indicating so (and vise versa) - // - if ( this->userStartedAsyncIO ) { + // + // prevent problems when they initiate + // async IO but dont return status + // indicating so (and vise versa) + // + if ( this->userStartedAsyncIO ) { if ( pver.getStatus() != pverAsyncCompletion ) { - errMessage ( S_cas_badParameter, - "- assuming asynch IO status from caServer::pvExistTest()"); + errMessage ( S_cas_badParameter, + "- assuming asynch IO status from caServer::pvExistTest()"); } status = S_cas_success; - } - else { - // - // otherwise we assume sync IO operation was initiated - // + } + else { + // + // otherwise we assume sync IO operation was initiated + // switch ( pver.getStatus() ) { case pverExistsHere: - status = this->searchResponse ( guard, *mp, pver ); + status = this->searchResponse ( guard, *mp, pver ); break; case pverDoesNotExistHere: @@ -1392,20 +1392,20 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard ) break; case pverAsyncCompletion: - errMessage ( S_cas_badParameter, - "- unexpected asynch IO status from " - "caServer::pvExistTest() ignored"); + errMessage ( S_cas_badParameter, + "- unexpected asynch IO status from " + "caServer::pvExistTest() ignored"); status = S_cas_success; break; default: - errMessage ( S_cas_badParameter, - "- invalid return from " - "caServer::pvExistTest() ignored"); + errMessage ( S_cas_badParameter, + "- invalid return from " + "caServer::pvExistTest() ignored"); status = S_cas_success; break; - } - } + } + } return status; } @@ -1414,41 +1414,41 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard ) */ caStatus casStrmClient::hostNameAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg(); - char *pName = (char *) this->ctx.getData(); - unsigned size; - char *pMalloc; - caStatus status; + const caHdrLargeArray *mp = this->ctx.getMsg(); + char *pName = (char *) this->ctx.getData(); + unsigned size; + char *pMalloc; + caStatus status; // currently this has to occur prior to // creating channels or its not allowed if ( this->chanList.count () ) { - return this->sendErr ( guard, mp, invalidResID, + return this->sendErr ( guard, mp, invalidResID, ECA_UNAVAILINSERV, pName ); } - size = strlen(pName)+1u; - /* - * user name will not change if there isnt enough memory - */ - pMalloc = new char [size]; - if ( ! pMalloc ){ - status = this->sendErr ( guard, mp, invalidResID, + size = strlen(pName)+1u; + /* + * user name will not change if there isnt enough memory + */ + pMalloc = new char [size]; + if ( ! pMalloc ){ + status = this->sendErr ( guard, mp, invalidResID, ECA_ALLOCMEM, pName ); - if (status) { - return status; - } - return S_cas_internal; - } - strncpy ( pMalloc, pName, size - 1 ); - pMalloc[ size - 1 ]='\0'; + if (status) { + return status; + } + return S_cas_internal; + } + strncpy ( pMalloc, pName, size - 1 ); + pMalloc[ size - 1 ]='\0'; - if ( this->pHostName ) { - delete [] this->pHostName; - } - this->pHostName = pMalloc; + if ( this->pHostName ) { + delete [] this->pHostName; + } + this->pHostName = pMalloc; - return S_cas_success; + return S_cas_success; } /* @@ -1457,42 +1457,42 @@ caStatus casStrmClient::hostNameAction ( epicsGuard < casClientMutex > & guard ) caStatus casStrmClient::clientNameAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg(); - char *pName = (char *) this->ctx.getData(); - unsigned size; - char *pMalloc; - caStatus status; + const caHdrLargeArray *mp = this->ctx.getMsg(); + char *pName = (char *) this->ctx.getData(); + unsigned size; + char *pMalloc; + caStatus status; // currently this has to occur prior to // creating channels or its not allowed if ( this->chanList.count () ) { - return this->sendErr ( guard, mp, invalidResID, + return this->sendErr ( guard, mp, invalidResID, ECA_UNAVAILINSERV, pName ); } - size = strlen(pName)+1; + size = strlen(pName)+1; - /* - * user name will not change if there isnt enough memory - */ - pMalloc = new char [size]; - if(!pMalloc){ - status = this->sendErr ( guard, mp, invalidResID, + /* + * user name will not change if there isnt enough memory + */ + pMalloc = new char [size]; + if(!pMalloc){ + status = this->sendErr ( guard, mp, invalidResID, ECA_ALLOCMEM, pName ); - if (status) { - return status; - } - return S_cas_internal; - } - strncpy ( pMalloc, pName, size - 1 ); - pMalloc[size-1]='\0'; + if (status) { + return status; + } + return S_cas_internal; + } + strncpy ( pMalloc, pName, size - 1 ); + pMalloc[size-1]='\0'; - if ( this->pUserName ) { - delete [] this->pUserName; - } - this->pUserName = pMalloc; + if ( this->pUserName ) { + delete [] this->pUserName; + } + this->pUserName = pMalloc; - return S_cas_success; + return S_cas_success; } /* @@ -1501,82 +1501,82 @@ caStatus casStrmClient::clientNameAction ( caStatus casStrmClient::claimChannelAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray * mp = this->ctx.getMsg(); - char *pName = (char *) this->ctx.getData(); - caServerI & cas = *this->ctx.getServer(); + const caHdrLargeArray * mp = this->ctx.getMsg(); + char *pName = (char *) this->ctx.getData(); + caServerI & cas = *this->ctx.getServer(); /* - * The available field is used (abused) - * here to communicate the miner version number - * starting with CA 4.1. The field was set to zero - * prior to 4.1 - */ + * The available field is used (abused) + * here to communicate the miner version number + * starting with CA 4.1. The field was set to zero + * prior to 4.1 + */ if ( mp->m_available < 0xffff ) { - this->minor_version_number = + this->minor_version_number = static_cast < ca_uint16_t > ( mp->m_available ); } else { - this->minor_version_number = 0; + this->minor_version_number = 0; } - // - // We shouldnt be receiving a connect message from - // an R3.11 client because we will not respond to their - // search requests (if so we disconnect) - // - if ( ! CA_V44 ( this->minor_version_number ) ) { - // - // old connect protocol was dropped when the - // new API was added to the server (they must - // now use clients at EPICS 3.12 or higher) - // - caStatus status = this->sendErr ( guard, mp, mp->m_cid, ECA_DEFUNCT, - "R3.11 connect sequence from old client was ignored"); - if ( status ) { - return status; - } - return S_cas_badProtocol; // disconnect client - } + // + // We shouldnt be receiving a connect message from + // an R3.11 client because we will not respond to their + // search requests (if so we disconnect) + // + if ( ! CA_V44 ( this->minor_version_number ) ) { + // + // old connect protocol was dropped when the + // new API was added to the server (they must + // now use clients at EPICS 3.12 or higher) + // + caStatus status = this->sendErr ( guard, mp, mp->m_cid, ECA_DEFUNCT, + "R3.11 connect sequence from old client was ignored"); + if ( status ) { + return status; + } + return S_cas_badProtocol; // disconnect client + } - if ( mp->m_postsize <= 1u ) { - return S_cas_badProtocol; // disconnect client - } + if ( mp->m_postsize <= 1u ) { + return S_cas_badProtocol; // disconnect client + } pName[mp->m_postsize-1u] = '\0'; - if ( ( mp->m_postsize - 1u ) > unreasonablePVNameSize ) { - return S_cas_badProtocol; // disconnect client - } + if ( ( mp->m_postsize - 1u ) > unreasonablePVNameSize ) { + return S_cas_badProtocol; // disconnect client + } - this->userStartedAsyncIO = false; + this->userStartedAsyncIO = false; - // - // attach to the PV - // - pvAttachReturn pvar = cas->pvAttach ( this->ctx, pName ); + // + // attach to the PV + // + pvAttachReturn pvar = cas->pvAttach ( this->ctx, pName ); - // - // prevent problems when they initiate - // async IO but dont return status - // indicating so (and vise versa) - // - if ( this->userStartedAsyncIO ) { - if ( pvar.getStatus() != S_casApp_asyncCompletion ) { - fprintf ( stderr, + // + // prevent problems when they initiate + // async IO but dont return status + // indicating so (and vise versa) + // + if ( this->userStartedAsyncIO ) { + if ( pvar.getStatus() != S_casApp_asyncCompletion ) { + fprintf ( stderr, "Application returned %d from cas::pvAttach()" " - expected S_casApp_asyncCompletion\n", pvar.getStatus() ); - } - return S_cas_success; - } - else if ( pvar.getStatus() == S_casApp_asyncCompletion ) { - errMessage ( S_cas_badParameter, - "- expected asynch IO creation " + } + return S_cas_success; + } + else if ( pvar.getStatus() == S_casApp_asyncCompletion ) { + errMessage ( S_cas_badParameter, + "- expected asynch IO creation " "from caServer::pvAttach()" ); - return this->createChanResponse ( guard, + return this->createChanResponse ( guard, this->ctx, S_cas_badParameter ); - } - else if ( pvar.getStatus() == S_casApp_postponeAsyncIO ) { + } + else if ( pvar.getStatus() == S_casApp_postponeAsyncIO ) { caServerI & casi ( * this->ctx.getServer() ); if ( casi.ioIsPending () ) { casi.addItemToIOBLockedList ( *this ); @@ -1594,10 +1594,10 @@ caStatus casStrmClient::claimChannelAction ( return this->createChanResponse ( guard, this->ctx, S_cas_posponeWhenNonePending ); } - } - else { - return this->createChanResponse ( guard, this->ctx, pvar ); - } + } + else { + return this->createChanResponse ( guard, this->ctx, pvar ); + } } // @@ -1619,12 +1619,12 @@ caStatus casStrmClient::createChanResponse ( epicsGuard < casClientMutex > & guard, casCtx & ctxIn, const pvAttachReturn & pvar ) { - const caHdrLargeArray & hdr = *ctxIn.getMsg(); + const caHdrLargeArray & hdr = *ctxIn.getMsg(); - if ( pvar.getStatus() != S_cas_success ) { - return this->channelCreateFailedResp ( guard, + if ( pvar.getStatus() != S_cas_success ) { + return this->channelCreateFailedResp ( guard, hdr, pvar.getStatus() ); - } + } if ( ! pvar.getPV()->pPVI ) { // @#$!* Tornado 2 Cygnus GNU compiler bugs @@ -1643,37 +1643,37 @@ caStatus casStrmClient::createChanResponse ( if ( ! pvar.getPV()->pPVI ) { pvar.getPV()->destroyRequest (); - return this->channelCreateFailedResp ( guard, hdr, S_casApp_pvNotFound ); + return this->channelCreateFailedResp ( guard, hdr, S_casApp_pvNotFound ); } } unsigned nativeTypeDBR; - caStatus status = pvar.getPV()->pPVI->bestDBRType ( nativeTypeDBR ); - if ( status ) { - pvar.getPV()->pPVI->deleteSignal(); - errMessage ( status, "best external dbr type fetch failed" ); - return this->channelCreateFailedResp ( guard, hdr, status ); - } + caStatus status = pvar.getPV()->pPVI->bestDBRType ( nativeTypeDBR ); + if ( status ) { + pvar.getPV()->pPVI->deleteSignal(); + errMessage ( status, "best external dbr type fetch failed" ); + return this->channelCreateFailedResp ( guard, hdr, status ); + } // - // attach the PV to this server - // - status = pvar.getPV()->pPVI->attachToServer ( this->getCAS() ); - if ( status ) { - pvar.getPV()->pPVI->deleteSignal(); - return this->channelCreateFailedResp ( guard, hdr, status ); - } + // attach the PV to this server + // + status = pvar.getPV()->pPVI->attachToServer ( this->getCAS() ); + if ( status ) { + pvar.getPV()->pPVI->deleteSignal(); + return this->channelCreateFailedResp ( guard, hdr, status ); + } - // - // create server tool XXX derived from casChannel - // - casChannel * pChan = pvar.getPV()->pPVI->createChannel ( + // + // create server tool XXX derived from casChannel + // + casChannel * pChan = pvar.getPV()->pPVI->createChannel ( ctxIn, this->pUserName, this->pHostName ); - if ( ! pChan ) { - pvar.getPV()->pPVI->deleteSignal(); - return this->channelCreateFailedResp ( + if ( ! pChan ) { + pvar.getPV()->pPVI->deleteSignal(); + return this->channelCreateFailedResp ( guard, hdr, S_cas_noMemory ); - } + } if ( ! pChan->pChanI ) { // @#$!* Tornado 2 Cygnus GNU compiler bugs @@ -1694,8 +1694,8 @@ caStatus casStrmClient::createChanResponse ( if ( ! pChan->pChanI ) { pChan->destroyRequest (); - pChan->getPV()->pPVI->deleteSignal (); - return this->channelCreateFailedResp ( + pChan->getPV()->pPVI->deleteSignal (); + return this->channelCreateFailedResp ( guard, hdr, S_cas_noMemory ); } } @@ -1723,32 +1723,32 @@ caStatus casStrmClient::createChanResponse ( ctxIn.setPV ( pvar.getPV()->pPVI ); this->userStartedAsyncIO = false; status = pvar.getPV()->pPVI->updateEnumStringTable ( ctxIn ); - if ( this->userStartedAsyncIO ) { - if ( status != S_casApp_asyncCompletion ) { - fprintf ( stderr, + if ( this->userStartedAsyncIO ) { + if ( status != S_casApp_asyncCompletion ) { + fprintf ( stderr, "Application returned %d from casChannel::read()" " - expected S_casApp_asyncCompletion\n", status); - } - status = S_cas_success; - } + } + status = S_cas_success; + } else if ( status == S_cas_success ) { status = privateCreateChanResponse ( guard, * pChan->pChanI, hdr, nativeTypeDBR ); } else { if ( status == S_casApp_asyncCompletion ) { - errMessage ( status, - "- enum string tbl cache read returned asynch IO creation, but async IO not started?"); - } + errMessage ( status, + "- enum string tbl cache read returned asynch IO creation, but async IO not started?"); + } else if ( status == S_casApp_postponeAsyncIO ) { errMessage ( status, "- enum string tbl cache read ASYNC IO postponed ?"); - errlogPrintf ( "The server library does not currently support postponment of\n" ); + errlogPrintf ( "The server library does not currently support postponment of\n" ); errlogPrintf ( "string table cache update of casChannel::read().\n" ); - errlogPrintf ( "To postpone this request please postpone the PC attach IO request.\n" ); - errlogPrintf ( "String table cache update did not occur.\n" ); + errlogPrintf ( "To postpone this request please postpone the PC attach IO request.\n" ); + errlogPrintf ( "String table cache update did not occur.\n" ); } else { - errMessage ( status, "- enum string tbl cache read failed ?"); + errMessage ( status, "- enum string tbl cache read failed ?"); } status = privateCreateChanResponse ( guard, * pChan->pChanI, hdr, nativeTypeDBR ); @@ -1799,11 +1799,11 @@ caStatus casStrmClient::privateCreateChanResponse ( casChannelI & chan, const caHdrLargeArray & hdr, unsigned nativeTypeDBR ) { - // - // We are allocating enough space for both the claim - // response and the access rights response so that we know for - // certain that they will both be sent together. - // + // + // We are allocating enough space for both the claim + // response and the access rights response so that we know for + // certain that they will both be sent together. + // // Considering the possibility of large arrays we must allocate // an additional 2 * sizeof(ca_uint32_t) // @@ -1814,37 +1814,37 @@ caStatus casStrmClient::privateCreateChanResponse ( return S_cas_sendBlocked; } - // - // We are certain that the request will complete - // here because we allocated enough space for this - // and the claim response above. - // - caStatus status = this->accessRightsResponse ( guard, & chan ); - if ( status ) { + // + // We are certain that the request will complete + // here because we allocated enough space for this + // and the claim response above. + // + caStatus status = this->accessRightsResponse ( guard, & chan ); + if ( status ) { this->out.popCtx ( outctx ); - errMessage ( status, "incomplete channel create?" ); - status = this->channelCreateFailedResp ( guard, hdr, status ); + errMessage ( status, "incomplete channel create?" ); + status = this->channelCreateFailedResp ( guard, hdr, status ); if ( status != S_cas_sendBlocked ) { this->chanTable.remove ( chan ); this->chanList.remove ( chan ); chan.uninstallFromPV ( this->eventSys ); - delete & chan; + delete & chan; } return status; - } + } - // - // We are allocated enough space for both the claim - // response and the access response so that we know for - // certain that they will both be sent together. - // Nevertheles, some (old) clients do not receive - // an access rights response so we allocate again - // here to be certain that we are at the correct place in - // the protocol buffer. - // - assert ( nativeTypeDBR <= 0xffff ); - aitIndex nativeCount = chan.getPVI().nativeCount(); - assert ( nativeCount <= 0xffffffff ); + // + // We are allocated enough space for both the claim + // response and the access response so that we know for + // certain that they will both be sent together. + // Nevertheles, some (old) clients do not receive + // an access rights response so we allocate again + // here to be certain that we are at the correct place in + // the protocol buffer. + // + assert ( nativeTypeDBR <= 0xffff ); + aitIndex nativeCount = chan.getPVI().nativeCount(); + assert ( nativeCount <= 0xffffffff ); assert ( hdr.m_cid == chan.getCID() ); status = this->out.copyInHeader ( CA_PROTO_CREATE_CHAN, 0, static_cast ( nativeTypeDBR ), @@ -1852,13 +1852,13 @@ caStatus casStrmClient::privateCreateChanResponse ( chan.getCID(), chan.getSID(), 0 ); if ( status != S_cas_success ) { this->out.popCtx ( outctx ); - errMessage ( status, "incomplete channel create?" ); - status = this->channelCreateFailedResp ( guard, hdr, status ); + errMessage ( status, "incomplete channel create?" ); + status = this->channelCreateFailedResp ( guard, hdr, status ); if ( status != S_cas_sendBlocked ) { this->chanTable.remove ( chan ); this->chanList.remove ( chan ); chan.uninstallFromPV ( this->eventSys ); - delete & chan; + delete & chan; } return status; } @@ -1874,7 +1874,7 @@ caStatus casStrmClient::privateCreateChanResponse ( nBytes == 2 * sizeof ( caHdr ) + 2 * sizeof ( ca_uint32_t ) ); this->out.commitRawMsg ( nBytes ); - return status; + return status; } /* @@ -1884,31 +1884,31 @@ caStatus casStrmClient::channelCreateFailedResp ( epicsGuard < casClientMutex > & guard, const caHdrLargeArray & hdr, const caStatus createStatus ) { - if ( createStatus == S_casApp_asyncCompletion ) { - errMessage( S_cas_badParameter, - "- no asynchronous IO create in pvAttach() ?"); - errMessage( S_cas_badParameter, - "- or S_casApp_asyncCompletion was " + if ( createStatus == S_casApp_asyncCompletion ) { + errMessage( S_cas_badParameter, + "- no asynchronous IO create in pvAttach() ?"); + errMessage( S_cas_badParameter, + "- or S_casApp_asyncCompletion was " "async IO competion code ?"); - } - else if ( createStatus != S_casApp_pvNotFound ) { - errMessage ( createStatus, + } + else if ( createStatus != S_casApp_pvNotFound ) { + errMessage ( createStatus, "- Server unable to create a new PV" ); - } + } caStatus status; - if ( CA_V46 ( this->minor_version_number ) ) { + if ( CA_V46 ( this->minor_version_number ) ) { status = this->out.copyInHeader ( CA_PROTO_CREATE_CH_FAIL, 0, 0, 0, hdr.m_cid, 0, 0 ); - if ( status == S_cas_success ) { - this->out.commitMsg (); - } - } - else { - status = this->sendErrWithEpicsStatus ( + if ( status == S_cas_success ) { + this->out.commitMsg (); + } + } + else { + status = this->sendErrWithEpicsStatus ( guard, & hdr, hdr.m_cid, createStatus, ECA_ALLOCMEM ); - } - return status; + } + return status; } // @@ -1917,7 +1917,7 @@ caStatus casStrmClient::channelCreateFailedResp ( caStatus casStrmClient::eventsOnAction ( epicsGuard < casClientMutex > & ) { this->enableEvents (); - return S_cas_success; + return S_cas_success; } // @@ -1926,7 +1926,7 @@ caStatus casStrmClient::eventsOnAction ( epicsGuard < casClientMutex > & ) caStatus casStrmClient::eventsOffAction ( epicsGuard < casClientMutex > & ) { this->disableEvents (); - return S_cas_success; + return S_cas_success; } // @@ -1935,65 +1935,68 @@ caStatus casStrmClient::eventsOffAction ( epicsGuard < casClientMutex > & ) caStatus casStrmClient::eventAddAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray *mp = this->ctx.getMsg(); - struct mon_info *pMonInfo = (struct mon_info *) - this->ctx.getData(); + const caHdrLargeArray *mp = this->ctx.getMsg(); + struct mon_info *pMonInfo = (struct mon_info *) + this->ctx.getData(); - casChannelI *pciu; + casChannelI *pciu; { - caStatus status = casStrmClient::verifyRequest ( pciu ); - if ( status != ECA_NORMAL ) { + caStatus status = casStrmClient::verifyRequest ( pciu ); + if ( status != ECA_NORMAL ) { if ( pciu ) { - return this->sendErr ( guard, mp, + return this->sendErr ( guard, mp, pciu->getCID(), status, NULL); } else { - return this->sendErr ( guard, mp, + return this->sendErr ( guard, mp, invalidResID, status, NULL ); } - } + } } - // dont allow a request that completed with the service in the - // past, but was incomplete because no response was sent to be - // executed twice with the service - if ( this->responseIsPending ) { + // dont allow a request that completed with the service in the + // past, but was incomplete because no response was sent to be + // executed twice with the service + if ( this->responseIsPending ) { // dont read twice if we didnt finish in the past // because we were send blocked if ( this->pendingResponseStatus == S_cas_success ) { assert ( pValueRead.valid () ); - return this->monitorResponse ( guard, *pciu, + return this->monitorResponse ( guard, *pciu, *mp, *pValueRead, S_cas_success ); } else { return this->monitorFailureResponse ( guard, *mp, ECA_GETFAIL ); } - } + } - // - // place monitor mask in correct byte order - // - casEventMask mask; - ca_uint16_t caProtoMask = AlignedWireRef < epicsUInt16 > ( pMonInfo->m_mask ); - if (caProtoMask&DBE_VALUE) { - mask |= this->getCAS().valueEventMask(); - } + // + // place monitor mask in correct byte order + // + casEventMask mask; + ca_uint16_t caProtoMask = AlignedWireRef < epicsUInt16 > ( pMonInfo->m_mask ); + if (caProtoMask&DBE_VALUE) { + mask |= this->getCAS().valueEventMask(); + } - if (caProtoMask&DBE_LOG) { - mask |= this->getCAS().logEventMask(); - } - - if (caProtoMask&DBE_ALARM) { - mask |= this->getCAS().alarmEventMask(); - } + if (caProtoMask&DBE_LOG) { + mask |= this->getCAS().logEventMask(); + } + + if (caProtoMask&DBE_ALARM) { + mask |= this->getCAS().alarmEventMask(); + } + if (caProtoMask&DBE_PROPERTY) { + mask |= this->getCAS().propertyEventMask(); + } - if (mask.noEventsSelected()) { - char errStr[40]; - sprintf ( errStr, "event add req with mask=0X%X\n", caProtoMask ); - return this->sendErr ( guard, mp, pciu->getCID(), + if (mask.noEventsSelected()) { + char errStr[40]; + sprintf ( errStr, "event add req with mask=0X%X\n", caProtoMask ); + return this->sendErr ( guard, mp, pciu->getCID(), ECA_BADMASK, errStr ); - } + } casMonitor & mon = this->monitorFactory ( *pciu, mp->m_available, mp->m_count, @@ -2001,31 +2004,31 @@ caStatus casStrmClient::eventAddAction ( pciu->installMonitor ( mon ); - // - // Attempt to read the first monitored value prior to creating - // the monitor object so that if the server tool chooses - // to postpone asynchronous IO we can safely restart this - // request later. - // + // + // Attempt to read the first monitored value prior to creating + // the monitor object so that if the server tool chooses + // to postpone asynchronous IO we can safely restart this + // request later. + // { - caStatus servStat = this->read (); - // - // always send immediate monitor response at event add - // - if ( servStat == S_cas_success ) { + caStatus servStat = this->read (); + // + // always send immediate monitor response at event add + // + if ( servStat == S_cas_success ) { assert ( pValueRead.valid () ); - caStatus status = this->monitorResponse ( guard, *pciu, + caStatus status = this->monitorResponse ( guard, *pciu, *mp, *pValueRead, servStat ); this->responseIsPending = ( status != S_cas_success ); return status; - } + } else if ( servStat == S_casApp_asyncCompletion ) { - return S_cas_success; - } - else if ( servStat == S_casApp_postponeAsyncIO ) { + return S_cas_success; + } + else if ( servStat == S_casApp_postponeAsyncIO ) { return S_casApp_postponeAsyncIO; - } - else { + } + else { caStatus status = this->monitorFailureResponse ( guard, *mp, ECA_GETFAIL ); if ( status != S_cas_success ) { @@ -2033,7 +2036,7 @@ caStatus casStrmClient::eventAddAction ( this->responseIsPending = true; } return status; - } + } } } @@ -2044,11 +2047,11 @@ caStatus casStrmClient::eventAddAction ( caStatus casStrmClient::clearChannelAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray * mp = this->ctx.getMsg (); - const void * dp = this->ctx.getData (); - int status; + const caHdrLargeArray * mp = this->ctx.getMsg (); + const void * dp = this->ctx.getData (); + int status; - // send delete confirmed message + // send delete confirmed message status = this->out.copyInHeader ( mp->m_cmmd, 0, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 ); @@ -2057,26 +2060,26 @@ caStatus casStrmClient::clearChannelAction ( } this->out.commitMsg (); - // Verify the channel + // Verify the channel chronIntId tmpId ( mp->m_cid ); - casChannelI * pciu = this->chanTable.remove ( tmpId ); - if ( pciu ) { + casChannelI * pciu = this->chanTable.remove ( tmpId ); + if ( pciu ) { this->chanList.remove ( *pciu ); pciu->uninstallFromPV ( this->eventSys ); delete pciu; } else { - /* - * it is possible that the channel delete arrives just - * after the server tool has deleted the PV so we will - * not disconnect the client in this case. Nevertheless, - * we send a warning message in case either the client - * or server has become corrupted - */ - logBadId ( guard, mp, dp, ECA_BADCHID, mp->m_cid ); - } + /* + * it is possible that the channel delete arrives just + * after the server tool has deleted the PV so we will + * not disconnect the client in this case. Nevertheless, + * we send a warning message in case either the client + * or server has become corrupted + */ + logBadId ( guard, mp, dp, ECA_BADCHID, mp->m_cid ); + } - return status; + return status; } // @@ -2105,7 +2108,7 @@ caStatus casStrmClient::channelDestroyEventNotify ( chronIntId tmpId ( sid ); pChanFound = this->chanTable.lookup ( tmpId ); - if ( ! pChanFound ) { + if ( ! pChanFound ) { return S_cas_success; } } @@ -2117,8 +2120,8 @@ caStatus casStrmClient::channelDestroyEventNotify ( if ( status == S_cas_sendBlocked ) { return status; } - this->out.commitMsg (); - } + this->out.commitMsg (); + } else { this->forceDisconnect (); } @@ -2168,18 +2171,18 @@ void casStrmClient::casChannelDestroyFromInterfaceNotify ( caStatus casStrmClient::eventCancelAction ( epicsGuard < casClientMutex > & guard ) { - const caHdrLargeArray * mp = this->ctx.getMsg (); - const void * dp = this->ctx.getData (); + const caHdrLargeArray * mp = this->ctx.getMsg (); + const void * dp = this->ctx.getData (); { chronIntId tmpId ( mp->m_cid ); casChannelI * pChan = this->chanTable.lookup ( tmpId ); - if ( ! pChan ) { - // It is possible that the event delete arrives just - // after the server tool has deleted the PV. Its probably + if ( ! pChan ) { + // It is possible that the event delete arrives just + // after the server tool has deleted the PV. Its probably // best to just diconnect for now since some old clients // may still exist. - logBadId ( guard, mp, dp, ECA_BADCHID, mp->m_cid ); + logBadId ( guard, mp, dp, ECA_BADCHID, mp->m_cid ); return S_cas_badResourceId; } @@ -2197,15 +2200,15 @@ caStatus casStrmClient::eventCancelAction ( this->eventSys.prepareMonitorForDestroy ( *pMon ); } else { - // this indicates client or server library + // this indicates client or server library // corruption so a disconnect is probably // the best option - logBadId ( guard, mp, dp, ECA_BADMONID, mp->m_available ); + logBadId ( guard, mp, dp, ECA_BADMONID, mp->m_available ); return S_cas_badResourceId; } } - return S_cas_success; + return S_cas_success; } #if 0 @@ -2218,48 +2221,48 @@ caStatus casStrmClient::eventCancelAction ( caStatus casStrmClient::noReadAccessEvent ( epicsGuard < casClientMutex > & guard, casClientMon * pMon ) { - caHdr falseReply; - unsigned size; - caHdr * reply; - int status; + caHdr falseReply; + unsigned size; + caHdr * reply; + int status; - size = dbr_size_n ( pMon->getType(), pMon->getCount() ); + size = dbr_size_n ( pMon->getType(), pMon->getCount() ); - falseReply.m_cmmd = CA_PROTO_EVENT_ADD; - falseReply.m_postsize = size; - falseReply.m_dataType = pMon->getType(); - falseReply.m_count = pMon->getCount(); - falseReply.m_cid = pMon->getChannel().getCID(); - falseReply.m_available = pMon->getClientId(); + falseReply.m_cmmd = CA_PROTO_EVENT_ADD; + falseReply.m_postsize = size; + falseReply.m_dataType = pMon->getType(); + falseReply.m_count = pMon->getCount(); + falseReply.m_cid = pMon->getChannel().getCID(); + falseReply.m_available = pMon->getClientId(); - status = this->allocMsg ( size, &reply ); - if ( status ) { - if( status == S_cas_hugeRequest ) { - return this->sendErr ( &falseReply, ECA_TOLARGE, NULL ); - } - return status; - } - else{ - /* - * New clients recv the status of the - * operation directly to the - * event/put/get callback. - * - * Fetched value is zerod in case they - * use it even when the status indicates - * failure. - * - * The m_cid field in the protocol - * header is abused to carry the status - */ - *reply = falseReply; - reply->m_postsize = size; - reply->m_cid = ECA_NORDACCESS; - memset((char *)(reply+1), 0, size); - this->commitMsg (); - } - - return S_cas_success; + status = this->allocMsg ( size, &reply ); + if ( status ) { + if( status == S_cas_hugeRequest ) { + return this->sendErr ( &falseReply, ECA_TOLARGE, NULL ); + } + return status; + } + else{ + /* + * New clients recv the status of the + * operation directly to the + * event/put/get callback. + * + * Fetched value is zerod in case they + * use it even when the status indicates + * failure. + * + * The m_cid field in the protocol + * header is abused to carry the status + */ + *reply = falseReply; + reply->m_postsize = size; + reply->m_cid = ECA_NORDACCESS; + memset((char *)(reply+1), 0, size); + this->commitMsg (); + } + + return S_cas_success; } #endif @@ -2279,16 +2282,16 @@ caStatus casStrmClient::readSyncAction ( epicsGuard < casClientMutex > & ) iter++; } - const caHdrLargeArray * mp = this->ctx.getMsg (); + const caHdrLargeArray * mp = this->ctx.getMsg (); - int status = this->out.copyInHeader ( mp->m_cmmd, 0, + int status = this->out.copyInHeader ( mp->m_cmmd, 0, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 ); - if ( ! status ) { - this->out.commitMsg (); - } + if ( ! status ) { + this->out.commitMsg (); + } - return status; + return status; } // @@ -2339,56 +2342,56 @@ caStatus casStrmClient::accessRightsResponse ( // caStatus casStrmClient :: write ( PWriteMethod pWriteMethod ) { - const caHdrLargeArray *pHdr = this->ctx.getMsg(); + const caHdrLargeArray *pHdr = this->ctx.getMsg(); - // no puts via compound types (for now) - if (dbr_value_offset[pHdr->m_dataType]) { - return S_cas_badType; - } + // no puts via compound types (for now) + if (dbr_value_offset[pHdr->m_dataType]) { + return S_cas_badType; + } // dont byte swap twice if ( this->reqPayloadNeedsByteSwap ) { int cacStatus = caNetConvert ( pHdr->m_dataType, this->ctx.getData(), this->ctx.getData(), false, pHdr->m_count ); - if ( cacStatus != ECA_NORMAL ) { - return S_cas_badType; - } + if ( cacStatus != ECA_NORMAL ) { + return S_cas_badType; + } this->reqPayloadNeedsByteSwap = false; } - // - // clear async IO flag - // - this->userStartedAsyncIO = false; + // + // clear async IO flag + // + this->userStartedAsyncIO = false; - // - // DBR_STRING is stored outside the DD so it - // lumped in with arrays - // + // + // DBR_STRING is stored outside the DD so it + // lumped in with arrays + // { - caStatus servStatus; - if ( pHdr->m_count > 1u ) { - servStatus = this->writeArrayData ( pWriteMethod ); - } - else { - servStatus = this->writeScalarData ( pWriteMethod ); - } + caStatus servStatus; + if ( pHdr->m_count > 1u ) { + servStatus = this->writeArrayData ( pWriteMethod ); + } + else { + servStatus = this->writeScalarData ( pWriteMethod ); + } - // - // prevent problems when they initiate - // async IO but dont return status - // indicating so (and vise versa) - // - if ( this->userStartedAsyncIO ) { - if ( servStatus != S_casApp_asyncCompletion ) { - errlogPrintf ( + // + // prevent problems when they initiate + // async IO but dont return status + // indicating so (and vise versa) + // + if ( this->userStartedAsyncIO ) { + if ( servStatus != S_casApp_asyncCompletion ) { + errlogPrintf ( "Application returned %d from casChannel::write() - " "expected S_casApp_asyncCompletion\n", - servStatus ); - servStatus = S_casApp_asyncCompletion; - } - } + servStatus ); + servStatus = S_casApp_asyncCompletion; + } + } else if ( servStatus == S_casApp_postponeAsyncIO ) { casPVI & pvi ( this->ctx.getChannel()->getPVI() ); if ( pvi.ioIsPending () ) { @@ -2408,13 +2411,13 @@ caStatus casStrmClient :: write ( PWriteMethod pWriteMethod ) } else { if ( servStatus == S_casApp_asyncCompletion ) { - servStatus = S_cas_badParameter; - errMessage ( servStatus, - "- expected asynch IO creation from casChannel::write()" ); + servStatus = S_cas_badParameter; + errMessage ( servStatus, + "- expected asynch IO creation from casChannel::write()" ); } - } + } - return servStatus; + return servStatus; } } @@ -2423,22 +2426,22 @@ caStatus casStrmClient :: write ( PWriteMethod pWriteMethod ) // caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) { - const caHdrLargeArray * pHdr = this->ctx.getMsg (); + const caHdrLargeArray * pHdr = this->ctx.getMsg (); - /* - * DBR type has already been checked, but it is possible - * that "gddDbrToAit" will not track with changes in - * the DBR_XXXX type system - */ - if ( pHdr->m_dataType >= NELEMENTS(gddDbrToAit) ) { - return S_cas_badType; - } + /* + * DBR type has already been checked, but it is possible + * that "gddDbrToAit" will not track with changes in + * the DBR_XXXX type system + */ + if ( pHdr->m_dataType >= NELEMENTS(gddDbrToAit) ) { + return S_cas_badType; + } // a primitive type matching the atomic DBR_XXX type - aitEnum type = gddDbrToAit[pHdr->m_dataType].type; - if ( type == aitEnumInvalid ) { - return S_cas_badType; - } + aitEnum type = gddDbrToAit[pHdr->m_dataType].type; + if ( type == aitEnumInvalid ) { + return S_cas_badType; + } // the application type best maching this DBR_XXX type aitUint16 app = gddDbrToAit[pHdr->m_dataType].app; @@ -2451,9 +2454,9 @@ caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) type; gdd * pDD = new gddScalar ( app, bestWritePrimType ); - if ( ! pDD ) { - return S_cas_noMemory; - } + if ( ! pDD ) { + return S_cas_noMemory; + } // // copy in, and convert to native type, the incoming data @@ -2461,13 +2464,13 @@ caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) gddStatus gddStat = aitConvert ( pDD->primitiveType(), pDD->dataVoid(), type, this->ctx.getData(), 1, &this->ctx.getPV()->enumStringTable() ); - caStatus status = S_cas_noConvert; + caStatus status = S_cas_noConvert; if ( gddStat >= 0 ) { // // set the status and severity to normal // - pDD->setStat ( epicsAlarmNone ); - pDD->setSevr ( epicsSevNone ); + pDD->setStat ( epicsAlarmNone ); + pDD->setSevr ( epicsSevNone ); // // set the time stamp to the last time that @@ -2476,20 +2479,20 @@ caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) aitTimeStamp gddts = this->lastRecvTS; pDD->setTimeStamp ( & gddts ); - // - // call the server tool's virtual function - // - status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); + // + // call the server tool's virtual function + // + status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); } - // - // reference count is managed by smart pointer class - // from here down - // - gddStat = pDD->unreference(); - assert ( ! gddStat ); + // + // reference count is managed by smart pointer class + // from here down + // + gddStat = pDD->unreference(); + assert ( ! gddStat ); - return status; + return status; } // @@ -2497,22 +2500,22 @@ caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) // caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) { - const caHdrLargeArray *pHdr = this->ctx.getMsg (); + const caHdrLargeArray *pHdr = this->ctx.getMsg (); - /* - * DBR type has already been checked, but it is possible - * that "gddDbrToAit" will not track with changes in - * the DBR_XXXX type system - */ - if ( pHdr->m_dataType >= NELEMENTS(gddDbrToAit) ) { - return S_cas_badType; - } - aitEnum type = gddDbrToAit[pHdr->m_dataType].type; - if ( type == aitEnumInvalid ) { - return S_cas_badType; - } + /* + * DBR type has already been checked, but it is possible + * that "gddDbrToAit" will not track with changes in + * the DBR_XXXX type system + */ + if ( pHdr->m_dataType >= NELEMENTS(gddDbrToAit) ) { + return S_cas_badType; + } + aitEnum type = gddDbrToAit[pHdr->m_dataType].type; + if ( type == aitEnumInvalid ) { + return S_cas_badType; + } - aitEnum bestExternalType = this->ctx.getPV()->bestExternalType (); + aitEnum bestExternalType = this->ctx.getPV()->bestExternalType (); // the application type best maching this DBR_XXX type aitUint16 app = gddDbrToAit[pHdr->m_dataType].app; @@ -2524,39 +2527,39 @@ caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) this->ctx.getPV()->bestExternalType () : type; - gdd * pDD = new gddAtomic( app, bestWritePrimType, 1, pHdr->m_count); - if ( ! pDD ) { - return S_cas_noMemory; - } + gdd * pDD = new gddAtomic( app, bestWritePrimType, 1, pHdr->m_count); + if ( ! pDD ) { + return S_cas_noMemory; + } size_t size = aitSize[bestExternalType] * pHdr->m_count; - char * pData = new char [size]; - if ( ! pData ) { + char * pData = new char [size]; + if ( ! pData ) { pDD->unreference(); - return S_cas_noMemory; - } + return S_cas_noMemory; + } - // - // ok to use the default gddDestructor here because - // an array of characters was allocated above - // - gddDestructor * pDestructor = new gddDestructor; - if ( ! pDestructor ) { + // + // ok to use the default gddDestructor here because + // an array of characters was allocated above + // + gddDestructor * pDestructor = new gddDestructor; + if ( ! pDestructor ) { pDD->unreference(); - delete [] pData; - return S_cas_noMemory; - } + delete [] pData; + return S_cas_noMemory; + } - // - // install allocated area into the DD - // - pDD->putRef ( pData, bestWritePrimType, pDestructor ); + // + // install allocated area into the DD + // + pDD->putRef ( pData, bestWritePrimType, pDestructor ); - // - // convert the data from the protocol buffer - // to the allocated area so that they - // will be allowed to ref the DD - // + // + // convert the data from the protocol buffer + // to the allocated area so that they + // will be allowed to ref the DD + // caStatus status = S_cas_noConvert; gddStatus gddStat = aitConvert ( bestWritePrimType, pData, type, this->ctx.getData(), @@ -2566,7 +2569,7 @@ caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) // set the status and severity to normal // pDD->setStat ( epicsAlarmNone ); - pDD->setSevr ( epicsSevNone ); + pDD->setSevr ( epicsSevNone ); // // set the time stamp to the last time that @@ -2575,19 +2578,19 @@ caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) aitTimeStamp gddts = this->lastRecvTS; pDD->setTimeStamp ( & gddts ); - // - // call the server tool's virtual function - // - status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); + // + // call the server tool's virtual function + // + status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); } else { status = S_cas_noConvert; } gddStat = pDD->unreference (); - assert ( ! gddStat ); + assert ( ! gddStat ); - return status; + return status; } // @@ -2595,57 +2598,57 @@ caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) // caStatus casStrmClient::read () { - const caHdrLargeArray * pHdr = this->ctx.getMsg(); + const caHdrLargeArray * pHdr = this->ctx.getMsg(); { gdd * pDD = 0; caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count, pDD ); - if ( status != S_cas_success ) { - return status; - } + if ( status != S_cas_success ) { + return status; + } pValueRead.set ( pDD ); pDD->unreference (); } - // - // clear the async IO flag - // - this->userStartedAsyncIO = false; + // + // clear the async IO flag + // + this->userStartedAsyncIO = false; { - // - // call the server tool's virtual function - // - caStatus servStat = this->ctx.getChannel()-> + // + // call the server tool's virtual function + // + caStatus servStat = this->ctx.getChannel()-> read ( this->ctx, *pValueRead ); - // - // prevent problems when they initiate - // async IO but dont return status - // indicating so (and vise versa) - // - if ( this->userStartedAsyncIO ) { - if ( servStat != S_casApp_asyncCompletion ) { - errlogPrintf ( + // + // prevent problems when they initiate + // async IO but dont return status + // indicating so (and vise versa) + // + if ( this->userStartedAsyncIO ) { + if ( servStat != S_casApp_asyncCompletion ) { + errlogPrintf ( "Application returned %d from casChannel::read() - " "expected S_casApp_asyncCompletion\n", - servStat ); - servStat = S_casApp_asyncCompletion; - } + servStat ); + servStat = S_casApp_asyncCompletion; + } pValueRead.set ( 0 ); - } - else if ( servStat == S_casApp_asyncCompletion ) { - servStat = S_cas_badParameter; - errMessage ( servStat, - "- expected asynch IO creation from casChannel::read()"); - } + } + else if ( servStat == S_casApp_asyncCompletion ) { + servStat = S_cas_badParameter; + errMessage ( servStat, + "- expected asynch IO creation from casChannel::read()"); + } else if ( servStat != S_casApp_success ) { pValueRead.set ( 0 ); if ( servStat == S_casApp_postponeAsyncIO ) { casPVI & pvi ( this->ctx.getChannel()->getPVI() ); if ( pvi.ioIsPending () ) { - pvi.addItemToIOBLockedList ( *this ); + pvi.addItemToIOBLockedList ( *this ); } else { // Its not ok to postpone IO when there isnt at @@ -2681,7 +2684,7 @@ void casStrmClient::userName ( char * pBuf, unsigned bufSize ) const // inline bool caServerI::roomForNewChannel() const { - return true; + return true; } // @@ -2699,13 +2702,13 @@ outBufClient::flushCondition casStrmClient :: inBufClient::fillCondition casStrmClient::xRecv ( char * pBufIn, bufSizeT nBytesToRecv, inBufClient::fillParameter, bufSizeT & nActualBytes ) { - inBufClient::fillCondition stat = + inBufClient::fillCondition stat = this->osdRecv ( pBufIn, nBytesToRecv, nActualBytes ); // // this is used to set the time stamp for write GDD's // this->lastRecvTS = epicsTime::getCurrent (); - return stat; + return stat; } // @@ -2713,7 +2716,7 @@ inBufClient::fillCondition casStrmClient::xRecv ( char * pBufIn, bufSizeT nBytes // unsigned casStrmClient::getDebugLevel () const { - return this->getCAS().getDebugLevel (); + return this->getCAS().getDebugLevel (); } // @@ -2727,30 +2730,30 @@ caStatus casStrmClient::casMonitorCallBack ( } // -// casStrmClient::sendErr() +// casStrmClient::sendErr() // caStatus casStrmClient::sendErr ( epicsGuard &, const caHdrLargeArray * curp, ca_uint32_t cid, const int reportedStatus, const char *pformat, ... ) { - unsigned stringSize; - char msgBuf[1024]; /* allocate plenty of space for the message string */ - if ( pformat ) { - va_list args; - va_start ( args, pformat ); - int status = vsprintf (msgBuf, pformat, args); - if ( status < 0 ) { - errPrintf (S_cas_internal, __FILE__, __LINE__, - "bad sendErr(%s)", pformat); - stringSize = 0u; - } - else { - stringSize = 1u + (unsigned) status; - } - } - else { - stringSize = 0u; - } + unsigned stringSize; + char msgBuf[1024]; /* allocate plenty of space for the message string */ + if ( pformat ) { + va_list args; + va_start ( args, pformat ); + int status = vsprintf (msgBuf, pformat, args); + if ( status < 0 ) { + errPrintf (S_cas_internal, __FILE__, __LINE__, + "bad sendErr(%s)", pformat); + stringSize = 0u; + } + else { + stringSize = 1u + (unsigned) status; + } + } + else { + stringSize = 0u; + } unsigned hdrSize = sizeof ( caHdr ); if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) && @@ -2800,7 +2803,7 @@ caStatus casStrmClient::sendErr ( epicsGuard &, this->out.commitMsg (); } - return S_cas_success; + return S_cas_success; } // send minor protocol revision to the client @@ -2854,22 +2857,22 @@ caStatus casStrmClient::logBadIdWithFileAndLineno ( const int cacStatus, const char * pFileName, const unsigned lineno, const unsigned idIn ) { - if ( pFileName ) { + if ( pFileName ) { caServerI::dumpMsg ( this->pHostName, this->pUserName, mp, dp, "bad resource id in \"%s\" at line %d\n", - pFileName, lineno ); - } + pFileName, lineno ); + } else { - caServerI::dumpMsg ( this->pHostName, this->pUserName, mp, dp, + caServerI::dumpMsg ( this->pHostName, this->pUserName, mp, dp, "bad resource id\n" ); } - int status = this->sendErr ( guard, - mp, invalidResID, cacStatus, + int status = this->sendErr ( guard, + mp, invalidResID, cacStatus, "Bad Resource ID=%u detected at %s.%d", - idIn, pFileName, lineno ); + idIn, pFileName, lineno ); - return status; + return status; } /* @@ -2880,10 +2883,10 @@ caStatus casStrmClient::logBadIdWithFileAndLineno ( */ caStatus casStrmClient::sendErrWithEpicsStatus ( epicsGuard < casClientMutex > & guard, const caHdrLargeArray * pMsg, - ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus ) + ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus ) { - char buf[0x1ff]; - errSymLookup ( epicsStatus, buf, sizeof(buf) ); - return this->sendErr ( guard, pMsg, cid, clientStatus, buf ); + char buf[0x1ff]; + errSymLookup ( epicsStatus, buf, sizeof(buf) ); + return this->sendErr ( guard, pMsg, cid, clientStatus, buf ); } diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index 72f0cb365..507a63f68 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -245,6 +245,7 @@ public: epicsShareFunc casEventMask valueEventMask () const; // DBE_VALUE epicsShareFunc casEventMask logEventMask () const; // DBE_LOG epicsShareFunc casEventMask alarmEventMask () const; // DBE_ALARM + epicsShareFunc casEventMask propertyEventMask () const; // DBE_PROPERTY epicsShareFunc void setDebugLevel ( unsigned level ); epicsShareFunc unsigned getDebugLevel () const;