From e3a61ce4e402e0d88925f5b876bd454f53666a58 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Mon, 3 Aug 2009 22:09:52 +0000 Subject: [PATCH] fix for mantis 358 --- src/cas/generic/casChannel.cc | 5 +++++ src/cas/generic/casChannelI.cc | 11 +++++++++++ src/cas/generic/casChannelI.h | 1 + src/cas/generic/casPV.cc | 12 ++++++++++++ src/cas/generic/casPVI.cc | 17 +++++++++++++++++ src/cas/generic/casPVI.h | 1 + src/cas/generic/casStrmClient.cc | 18 +++++++++--------- src/cas/generic/casStrmClient.h | 11 ++++++----- src/cas/generic/casdef.h | 27 +++++++++++++++++++++++++-- 9 files changed, 87 insertions(+), 16 deletions(-) diff --git a/src/cas/generic/casChannel.cc b/src/cas/generic/casChannel.cc index 3e16e243d..cc6cc8a74 100644 --- a/src/cas/generic/casChannel.cc +++ b/src/cas/generic/casChannel.cc @@ -90,6 +90,11 @@ caStatus casChannel::write ( const casCtx & ctx, const gdd & value ) return ctx.getPV()->write ( ctx, value ); } +caStatus casChannel::writeNotify ( const casCtx & ctx, const gdd & value ) +{ + return ctx.getPV()->writeNotify ( ctx, value ); +} + void casChannel::show ( unsigned level ) const { if ( level > 2u ) { diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index f29786bce..dc9f85867 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -101,6 +101,17 @@ caStatus casChannelI::write ( const casCtx & ctx, const gdd & value ) return status; } +caStatus casChannelI::writeNotify ( const casCtx & ctx, const gdd & value ) +{ + caStatus status = this->chan.beginTransaction (); + if ( status != S_casApp_success ) { + return status; + } + status = this->chan.writeNotify ( ctx, value ); + this->chan.endTransaction (); + return status; +} + void casChannelI::postDestroyEvent () { if ( ! this->serverDeletePending ) { diff --git a/src/cas/generic/casChannelI.h b/src/cas/generic/casChannelI.h index eda94cea6..d14cfc5c7 100644 --- a/src/cas/generic/casChannelI.h +++ b/src/cas/generic/casChannelI.h @@ -54,6 +54,7 @@ public: bool confirmationRequested () const; caStatus read ( const casCtx & ctx, gdd & prototype ); caStatus write ( const casCtx & ctx, const gdd & value ); + caStatus writeNotify ( const casCtx & ctx, const gdd & value ); void show ( unsigned level ) const; private: chanIntfForPV privateForPV; diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index c5fe52865..15838567b 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -111,6 +111,18 @@ caStatus casPV::write (const casCtx &, const gdd &) return S_casApp_noSupport; } +// +// casPV::writeNotify() +// +caStatus casPV :: writeNotify ( + const casCtx & ctx, const gdd & val ) +{ + // plumbed this way to preserve backwards + // compatibility with the old interface which + // did not include a writeNotify interface + return this->write ( ctx, val ); +} + // // casPV::bestExternalType() // diff --git a/src/cas/generic/casPVI.cc b/src/cas/generic/casPVI.cc index ff5ddf96f..dc69f7296 100644 --- a/src/cas/generic/casPVI.cc +++ b/src/cas/generic/casPVI.cc @@ -464,6 +464,23 @@ caStatus casPVI::write ( const casCtx & ctx, const gdd & value ) } } +caStatus casPVI::writeNotify ( const casCtx & ctx, const gdd & value ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( this->pPV ) { + caStatus status = this->pPV->beginTransaction (); + if ( status != S_casApp_success ) { + return status; + } + status = this->pPV->writeNotify ( ctx, value ); + this->pPV->endTransaction (); + return status; + } + else { + return S_cas_disconnect; + } +} + casChannel * casPVI::createChannel ( const casCtx & ctx, const char * const pUserName, const char * const pHostName ) { diff --git a/src/cas/generic/casPVI.h b/src/cas/generic/casPVI.h index 0b8ab985b..4ea22c463 100644 --- a/src/cas/generic/casPVI.h +++ b/src/cas/generic/casPVI.h @@ -77,6 +77,7 @@ public: void show ( unsigned level ) const; caStatus read ( const casCtx & ctx, gdd & prototype ); caStatus write ( const casCtx & ctx, const gdd & value ); + caStatus writeNotify ( const casCtx & ctx, const gdd & value ); casChannel * createChannel ( const casCtx & ctx, const char * const pUserName, const char * const pHostName ); aitEnum bestExternalType () const; diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index a7c213ab7..009d75ab7 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -973,7 +973,7 @@ caStatus casStrmClient::writeAction ( epicsGuard < casClientMutex > & guard ) // // initiate the write operation // - status = this->write (); + status = this->write ( & casChannelI :: write ); if ( status == S_casApp_success || status == S_casApp_asyncCompletion ) { status = S_cas_success; } @@ -1061,7 +1061,7 @@ caStatus casStrmClient::writeNotifyAction ( // // initiate the write operation // - status = this->write(); + status = this->write ( & casChannelI :: writeNotify ); if (status == S_casApp_asyncCompletion) { status = S_cas_success; } @@ -2023,7 +2023,7 @@ caStatus casStrmClient::accessRightsResponse ( // // casStrmClient::write() // -caStatus casStrmClient::write() +caStatus casStrmClient :: write ( PWriteMethod pWriteMethod ) { const caHdrLargeArray *pHdr = this->ctx.getMsg(); caStatus status; @@ -2054,10 +2054,10 @@ caStatus casStrmClient::write() // lumped in with arrays // if ( pHdr->m_count > 1u ) { - status = this->writeArrayData (); + status = this->writeArrayData ( pWriteMethod ); } else { - status = this->writeScalarData (); + status = this->writeScalarData ( pWriteMethod ); } // @@ -2089,7 +2089,7 @@ caStatus casStrmClient::write() // // casStrmClient::writeScalarData() // -caStatus casStrmClient::writeScalarData () +caStatus casStrmClient :: writeScalarData ( PWriteMethod pWriteMethod ) { const caHdrLargeArray * pHdr = this->ctx.getMsg (); @@ -2147,7 +2147,7 @@ caStatus casStrmClient::writeScalarData () // // call the server tool's virtual function // - status = this->ctx.getChannel()->write ( this->ctx, *pDD ); + status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); } // @@ -2163,7 +2163,7 @@ caStatus casStrmClient::writeScalarData () // // casStrmClient::writeArrayData() // -caStatus casStrmClient::writeArrayData() +caStatus casStrmClient :: writeArrayData ( PWriteMethod pWriteMethod ) { const caHdrLargeArray *pHdr = this->ctx.getMsg (); @@ -2246,7 +2246,7 @@ caStatus casStrmClient::writeArrayData() // // call the server tool's virtual function // - status = this->ctx.getChannel()->write ( this->ctx, *pDD ); + status = ( this->ctx.getChannel()->*pWriteMethod ) ( this->ctx, *pDD ); } else { status = S_cas_noConvert; diff --git a/src/cas/generic/casStrmClient.h b/src/cas/generic/casStrmClient.h index 2089273f7..06a01d015 100644 --- a/src/cas/generic/casStrmClient.h +++ b/src/cas/generic/casStrmClient.h @@ -142,12 +142,13 @@ private: caStatus accessRightsResponse ( epicsGuard < casClientMutex > &, casChannelI * pciu ); - caStatus read ( const gdd * & pDesc ); - caStatus write (); - caStatus writeArrayData(); - caStatus writeScalarData(); - caStatus writeString(); + typedef caStatus ( casChannelI :: * PWriteMethod ) ( + const casCtx &, const gdd & ); + caStatus read ( const gdd * & pDesc ); + caStatus write ( PWriteMethod ); + caStatus writeArrayData( PWriteMethod ); + caStatus writeScalarData( PWriteMethod ); outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesToSend, bufSizeT & nBytesSent ); diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index 8481a1fa7..2f826d0ef 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -392,16 +392,31 @@ public: // asynchronous IO operation (read or write) completes // against the PV. // - // NOTE: + // NOTES: // o The incoming GDD with application type "value" is always // converted to the PV.bestExternalType() primitive type. // o The time stamp in the incoming GDD is set to the time that // the last message was received from the client. // o Currently, no container type GDD's are passed here and // the application type is always "value". This may change. + // o The write interface is called when the server receives + // ca_put request and the writeNotify interface is called + // when the server receives ca_put_callback request. + // o A writeNotify request is considered complete and therefore + // ready for asynchronous completion notification when any + // action that it initiates, and any cascaded actions, complete. + // o In an IOC context intermediate write requets can be discarded + // as long as the final writeRequest is always executed. In an + // IOC context intermediate writeNotify requests are never discarded. + // o If the service does not implement writeNotify then + // the base implementation of casPV :: writeNotify calls + // casPV :: write thereby preserving backwards compatibility + // with the original interface which included a virtual write + // method but not a virtual writeNotify method. // epicsShareFunc virtual caStatus write (const casCtx &ctx, const gdd &value); - + epicsShareFunc virtual caStatus writeNotify (const casCtx &ctx, const gdd &value); + // // chCreate() is called each time that a PV is attached to // by a client. The server tool may choose not to @@ -600,6 +615,14 @@ public: // epicsShareFunc virtual caStatus write (const casCtx &ctx, const gdd &value); + // + // writeNotify + // + // If this function is not provided in the derived class then casPV::writeNotify() + // is called - see casPV::writeNotify() for additional comments. + // + epicsShareFunc virtual caStatus writeNotify (const casCtx &ctx, const gdd &value); + // // This is called for each channel in the server if // caServer::show() is called and the level is high