further bullet proof the server tool initiated PV destroy

This commit is contained in:
Jeff Hill
2003-03-13 00:16:39 +00:00
parent 18cac266cd
commit 38aad33d78
7 changed files with 76 additions and 48 deletions

View File

@@ -122,11 +122,10 @@ caStatus casCoreClient::channelCreateFailedResp (
{
return S_casApp_noSupport;
}
caStatus casCoreClient::channelDestroyNotify (
caStatus casCoreClient::channelDestroyEvent (
epicsGuard < casClientMutex > &,
casChannelI &, bool )
casChannelI * const, ca_uint32_t )
{
assert ( 0 );
return S_casApp_noSupport;
}

View File

@@ -85,10 +85,10 @@ public:
virtual caStatus channelCreateFailedResp (
epicsGuard < casClientMutex > &,
const caHdrLargeArray &, const caStatus createStatus );
virtual caStatus channelDestroyNotify (
epicsGuard < casClientMutex > &,
casChannelI &, bool uninstallNeeded );
virtual void casChannelDestroyNotify (
virtual caStatus channelDestroyEvent (
epicsGuard < casClientMutex > & guard,
casChannelI * const pChan, ca_uint32_t sid );
virtual void casChannelDestroyNotify (
casChannelI & chan, bool immediateDestroyNeeded );
virtual ca_uint16_t protocolRevision () const = 0;

View File

@@ -68,6 +68,7 @@ casPVI::~casPVI ()
void casPVI::casPVDestroyNotify ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->pPV = 0;
if ( ! this->deletePending ) {
tsDLIter < chanIntfForPV > iter = this->chanList.firstIter ();
while ( iter.valid() ) {

View File

@@ -1629,6 +1629,61 @@ caStatus casStrmClient::clearChannelAction (
return status;
}
//
// If the channel pointer is nill this indicates that
// the existence of the channel isnt certain because
// it is still installed and the client or the server
// tool might have destroyed it. Therefore, we must
// locate it using the supplied server id.
//
// If the channel pointer isnt nill this indicates
// that the channel has already been uninstalled.
//
// In both situations we need to send a channel
// disconnect message to the client and destroy the
// channel.
//
caStatus casStrmClient::channelDestroyEvent (
epicsGuard < casClientMutex > & guard,
casChannelI * const pChan, ca_uint32_t sid )
{
casChannelI * pChanFound;
if ( pChan ) {
pChanFound = pChan;
}
else {
chronIntId tmpId ( sid );
pChanFound =
this->chanTable.lookup ( tmpId );
if ( ! pChanFound ) {
return S_cas_success;
}
}
if ( CA_V47 ( this->minor_version_number ) ) {
caStatus status = this->out.copyInHeader (
CA_PROTO_SERVER_DISCONN, 0,
0, 0, pChanFound->getCID(), 0, 0 );
if ( status == S_cas_sendBlocked ) {
return status;
}
this->out.commitMsg ();
}
else {
this->forceDisconnect ();
}
if ( ! pChan ) {
this->chanTable.remove ( * pChanFound );
this->chanList.remove ( * pChanFound );
pChanFound->uninstallFromPV ( this->eventSys );
}
delete pChanFound;
return S_cas_success;
}
// casStrmClient::casChannelDestroyNotify()
// immediateUninstallNeeded is false when we must avoid
// taking the lock insituations where we would compromise
@@ -1644,9 +1699,10 @@ void casStrmClient::casChannelDestroyNotify (
chan.uninstallFromPV ( this->eventSys );
}
channelDestroyEvent * pEvent =
new ( std::nothrow ) channelDestroyEvent (
chan, !immediateUninstallNeeded );
class channelDestroyEvent * pEvent =
new ( std::nothrow ) class channelDestroyEvent (
immediateUninstallNeeded ? & chan : 0,
chan.getSID() );
if ( pEvent ) {
this->eventSys.addToEventQueue ( *pEvent );
}
@@ -1658,34 +1714,6 @@ void casStrmClient::casChannelDestroyNotify (
}
}
// casStrmClient::channelDestroyNotify()
caStatus casStrmClient::channelDestroyNotify (
epicsGuard < casClientMutex > & guard,
casChannelI & chan, bool uninstallNeeded )
{
caStatus status = S_cas_success;
if ( CA_V47 ( this->minor_version_number ) ) {
caStatus status = this->out.copyInHeader (
CA_PROTO_SERVER_DISCONN, 0,
0, 0, chan.getCID(), 0, 0 );
if ( status == S_cas_success ) {
this->out.commitMsg ();
}
}
else {
this->forceDisconnect ();
}
if ( status != S_cas_sendBlocked ) {
if ( uninstallNeeded ) {
this->chanTable.remove ( chan );
this->chanList.remove ( chan );
chan.uninstallFromPV ( this->eventSys );
}
delete & chan;
}
return status;
}
// casStrmClient::eventCancelAction()
caStatus casStrmClient::eventCancelAction (
epicsGuard < casClientMutex > & guard )

View File

@@ -127,10 +127,9 @@ private:
casChannelI & chan, const caHdrLargeArray & hdr, unsigned dbrType );
caStatus channelCreateFailedResp ( epicsGuard < casClientMutex > &,
const caHdrLargeArray &, const caStatus createStatus );
caStatus channelDestroyNotify (
caStatus channelDestroyEvent (
epicsGuard < casClientMutex > & guard,
casChannelI &, bool uninstallNeeded );
casChannelI * const pChan, ca_uint32_t sid );
caStatus accessRightsResponse (
casChannelI * pciu );
caStatus accessRightsResponse (

View File

@@ -25,8 +25,8 @@ caStatus channelDestroyEvent::cbFunc (
epicsGuard < casClientMutex > & clientGuard,
epicsGuard < evSysMutex > & )
{
caStatus status = client.channelDestroyNotify (
clientGuard, this->chan, this->uninstallNeeded );
caStatus status = client.channelDestroyEvent (
clientGuard, this->pChan, this->sid );
if ( status != S_cas_sendBlocked ) {
delete this;
}

View File

@@ -37,10 +37,11 @@ class casChannelI;
class channelDestroyEvent : public casEvent {
public:
channelDestroyEvent ( casChannelI &, bool uninstallNeeded );
channelDestroyEvent (
casChannelI * pChan, ca_uint32_t sid );
private:
casChannelI & chan;
bool uninstallNeeded;
casChannelI * pChan;
ca_uint32_t sid;
caStatus cbFunc (
casCoreClient &,
epicsGuard < casClientMutex > &,
@@ -48,8 +49,8 @@ private:
};
inline channelDestroyEvent::channelDestroyEvent (
casChannelI & chanIn, bool uninstallNeededIn ) :
chan ( chanIn ), uninstallNeeded ( uninstallNeededIn )
casChannelI * pChanIn, ca_uint32_t sidIn ) :
pChan ( pChanIn ), sid ( sidIn )
{
}