void cac::exception ( epicsGuard < epicsMutex > & cbGuard, epicsGuard < epicsMutex > & guard, int status, const char * pContext, const char * pFileName, unsigned lineNo ) { cbGuard.assertIdenticalMutex ( this->cbMutex ); guard.assertIdenticalMutex ( this->mutex ); this->notify.exception ( guard, status, pContext, pFileName, lineNo ); }
void bhe::beaconAnomalyNotify ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); if ( this->pIIU ) { this->pIIU->beaconAnomalyNotify ( guard ); } }
void disconnectGovernorTimer::installChan ( epicsGuard < epicsMutex > & guard, nciu & chan ) { guard.assertIdenticalMutex ( this->mutex ); this->chanList.add ( chan ); chan.channelNode::listMember = channelNode::cs_disconnGov; }
void cac::registerSearchDest ( epicsGuard < epicsMutex > & guard, SearchDest & req ) { guard.assertIdenticalMutex ( this->mutex ); this->searchDestList.add ( req ); }
void dbSubscriptionIO::channelDeleteException ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); this->notify.exception ( guard, ECA_CHANDESTROY, this->chan.pName(guard), this->type, this->count ); }
void searchTimer::uninstallChan ( epicsGuard < epicsMutex > & cacGuard, nciu & chan ) { cacGuard.assertIdenticalMutex ( this->mutex ); unsigned ulistmem = static_cast <unsigned> ( chan.channelNode::listMember ); unsigned uReqBase = static_cast <unsigned> ( channelNode::cs_searchReqPending0 ); if ( ulistmem == this->index + uReqBase ) { this->chanListReqPending.remove ( chan ); } else { unsigned uRespBase = static_cast <unsigned > ( channelNode::cs_searchRespPending0 ); if ( ulistmem == this->index + uRespBase ) { this->chanListRespPending.remove ( chan ); } else { throw std::runtime_error ( "uninstalling channel search timer, but channel " "state is wrong" ); } } chan.channelNode::listMember = channelNode::cs_none; }
bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard, const caHdr & msg, const void * pExt, ca_uint16_t extsize ) { guard.assertIdenticalMutex ( this->cacMutex ); ca_uint16_t alignedExtSize = static_cast <ca_uint16_t> (CA_MESSAGE_ALIGN ( extsize )); arrayElementCount msgsize = sizeof ( caHdr ) + alignedExtSize; /* fail out if max message size exceeded */ if ( msgsize >= sizeof ( this->xmitBuf ) - 7 ) { return false; } if ( msgsize + this->nBytesInXmitBuf > sizeof ( this->xmitBuf ) ) { return false; } caHdr * pbufmsg = ( caHdr * ) &this->xmitBuf[this->nBytesInXmitBuf]; *pbufmsg = msg; if ( extsize ) { memcpy ( pbufmsg + 1, pExt, extsize ); if ( extsize != alignedExtSize ) { char *pDest = (char *) ( pbufmsg + 1 ); memset ( pDest + extsize, '\0', alignedExtSize - extsize ); } } AlignedWireRef < epicsUInt16 > ( pbufmsg->m_postsize ) = alignedExtSize; this->nBytesInXmitBuf += msgsize; return true; }
void cac::selfTest ( epicsGuard < epicsMutex > & guard ) const { guard.assertIdenticalMutex ( this->mutex ); this->chanTable.verify (); this->ioTable.verify (); this->beaconTable.verify (); }
void udpiiu :: SearchDestUDP :: show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( _udpiiu.cacMutex ); char buf[64]; sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) ); :: printf ( "UDP Search destination \"%s\"\n", buf ); }
void cac::initiateConnect ( epicsGuard < epicsMutex > & guard, nciu & chan, netiiu * & piiu ) { guard.assertIdenticalMutex ( this->mutex ); assert ( this->pudpiiu ); this->pudpiiu->installNewChannel ( guard, chan, piiu ); }
// // set the push pending flag on all virtual circuits // void cac::flush ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); tsDLIter < tcpiiu > iter = this->circuitList.firstIter (); while ( iter.valid () ) { iter->flushRequest ( guard ); iter++; } }
void dbContextReadNotifyCache::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( _mutex ); printf ( "dbContextReadNotifyCache\n" ); if ( level > 0 ) { this->_allocator.show ( level - 1 ); } }
void cac::disconnectChannel ( epicsGuard < epicsMutex > & cbGuard, epicsGuard < epicsMutex > & guard, nciu & chan ) { guard.assertIdenticalMutex ( this->mutex ); assert ( this->pudpiiu ); chan.disconnectAllIO ( cbGuard, guard ); chan.getPIIU(guard)->uninstallChan ( guard, chan ); this->pudpiiu->installDisconnectedChannel ( guard, chan ); chan.unresponsiveCircuitNotify ( cbGuard, guard ); }
void bhe::unregisterIIU ( epicsGuard < epicsMutex > & guard, tcpiiu & iiu ) { guard.assertIdenticalMutex ( this->mutex ); if ( this->pIIU == & iiu ) { this->pIIU = 0; this->timeStamp = epicsTime(); this->averagePeriod = - DBL_MAX; logBeacon ( "ui", this->averagePeriod, epicsTime::getCurrent () ); } }
void cac::disconnectAllIO ( epicsGuard < epicsMutex > & cbGuard, epicsGuard < epicsMutex > & guard, nciu & chan, tsDLList < baseNMIU > & ioList ) { cbGuard.assertIdenticalMutex ( this->cbMutex ); guard.assertIdenticalMutex ( this->mutex ); char buf[128]; chan.getHostName ( guard, buf, sizeof ( buf ) ); tsDLIter < baseNMIU > pNetIO = ioList.firstIter(); while ( pNetIO.valid () ) { tsDLIter < baseNMIU > pNext = pNetIO; pNext++; if ( ! pNetIO->isSubscription() ) { this->ioTable.remove ( pNetIO->getId () ); } pNetIO->exception ( guard, *this, ECA_DISCONN, buf ); pNetIO = pNext; } }
void dbSubscriptionIO::unsubscribe ( CallbackGuard & cbGuard, epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); if ( this->es ) { dbEventSubscription tmp = this->es; this->es = 0; { epicsGuardRelease < epicsMutex > unguard ( guard ); db_cancel_event ( tmp ); } } }
void oldChannelNotify::destructor ( CallbackGuard & cbGuard, epicsGuard < epicsMutex > & mutexGuard ) { mutexGuard.assertIdenticalMutex ( this->cacCtx.mutexRef () ); this->io.destroy ( cbGuard, mutexGuard ); // no need to worry about a connect preempting here because // the io (the nciu) has been destroyed above if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) { this->cacCtx.decrementOutstandingIO ( mutexGuard, this->ioSeqNo ); } this->~oldChannelNotify (); }
void udpiiu :: SearchDestUDP :: searchRequest ( epicsGuard < epicsMutex > & guard, const char * pBuf, size_t bufSize ) { guard.assertIdenticalMutex ( _udpiiu.cacMutex ); assert ( bufSize <= INT_MAX ); int bufSizeAsInt = static_cast < int > ( bufSize ); while ( true ) { // This const_cast is needed for vxWorks: int status = sendto ( _udpiiu.sock, const_cast<char *>(pBuf), bufSizeAsInt, 0, & _destAddr.sa, sizeof ( _destAddr.sa ) ); if ( status == bufSizeAsInt ) { break; } if ( status >= 0 ) { errlogPrintf ( "CAC: UDP sendto () call returned strange xmit count?\n" ); break; } else { int localErrno = SOCKERRNO; if ( localErrno == SOCK_EINTR ) { if ( _udpiiu.shutdownCmd ) { break; } else { continue; } } else if ( localErrno == SOCK_SHUTDOWN ) { break; } else if ( localErrno == SOCK_ENOTSOCK ) { break; } else if ( localErrno == SOCK_EBADF ) { break; } else { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); char buf[64]; sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) ); errlogPrintf ( "CAC: error = \"%s\" sending UDP msg to %s\n", sockErrBuf, buf); break; } } } }
bool cac::findOrCreateVirtCircuit ( epicsGuard < epicsMutex > & guard, const osiSockAddr & addr, unsigned priority, tcpiiu *& piiu, unsigned minorVersionNumber, SearchDestTCP * pSearchDest ) { guard.assertIdenticalMutex ( this->mutex ); bool newIIU = false; if ( piiu ) { if ( ! piiu->alive ( guard ) ) { return newIIU; } } else { try { autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu ( this->freeListVirtualCircuit, new ( this->freeListVirtualCircuit ) tcpiiu ( *this, this->mutex, this->cbMutex, this->notify, this->connTMO, this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber, this->ipToAEngine, priority, pSearchDest ) ); bhe * pBHE = this->beaconTable.lookup ( addr.ia ); if ( ! pBHE ) { pBHE = new ( this->bheFreeList ) bhe ( this->mutex, epicsTime (), 0u, addr.ia ); if ( this->beaconTable.add ( *pBHE ) < 0 ) { return newIIU; } } this->serverTable.add ( *pnewiiu ); this->circuitList.add ( *pnewiiu ); this->iiuExistenceCount++; pBHE->registerIIU ( guard, *pnewiiu ); piiu = pnewiiu.release (); newIIU = true; } catch ( std :: exception & except ) { errlogPrintf ( "CAC: exception during virtual circuit creation \"%s\"\n", except.what () ); return newIIU; } catch ( ... ) { errlogPrintf ( "CAC: Nonstandard exception during virtual circuit creation\n" ); return newIIU; } } return newIIU; }
void cac::destroyChannel ( epicsGuard < epicsMutex > & guard, nciu & chan ) { guard.assertIdenticalMutex ( this->mutex ); // uninstall channel so that recv threads // will not start a new callback for this channel's IO. if ( this->chanTable.remove ( chan ) != & chan ) { throw std::logic_error ( "Invalid channel identifier" ); } chan.~nciu (); this->channelFreeList.release ( & chan ); }
void udpiiu::updateRTTE ( epicsGuard < epicsMutex > & guard, double measured ) { guard.assertIdenticalMutex ( this->cacMutex ); if ( measured > maxRoundTripEstimate ) { measured = maxRoundTripEstimate; } if ( measured < minRoundTripEstimate ) { measured = minRoundTripEstimate; } double error = measured - this->rtteMean; this->rtteMean += 0.125 * error; if ( error < 0.0 ) { error = - error; } this->rtteMeanDev = this->rtteMeanDev + .25 * ( error - this->rtteMeanDev ); }
oldChannelNotify::oldChannelNotify ( epicsGuard < epicsMutex > & guard, ca_client_context & cacIn, const char *pName, caCh * pConnCallBackIn, void * pPrivateIn, capri priority ) : cacCtx ( cacIn ), io ( cacIn.createChannel ( guard, pName, *this, priority ) ), pConnCallBack ( pConnCallBackIn ), pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler ), ioSeqNo ( 0 ), currentlyConnected ( false ), prevConnected ( false ) { guard.assertIdenticalMutex ( cacIn.mutexRef () ); this->ioSeqNo = cacIn.sequenceNumberOfOutstandingIO ( guard ); if ( pConnCallBackIn == 0 ) { cacIn.incrementOutstandingIO ( guard, this->ioSeqNo ); } }
// extra effort taken here to not hold the lock when calling the callback void dbContextReadNotifyCache::callReadNotify ( epicsGuard < epicsMutex > & guard, struct dbChannel * dbch, unsigned type, unsigned long count, cacReadNotify & notify ) { guard.assertIdenticalMutex ( _mutex ); if ( type > INT_MAX ) { notify.exception ( guard, ECA_BADTYPE, "type code out of range (high side)", type, count ); return; } if ( dbChannelElements(dbch) < 0 ) { notify.exception ( guard, ECA_BADCOUNT, "database has negetive element count", type, count); return; } if ( count > static_cast < unsigned long > ( dbChannelElements(dbch) ) ) { notify.exception ( guard, ECA_BADCOUNT, "element count out of range (high side)", type, count); return; } unsigned long size = dbr_size_n ( type, count ); privateAutoDestroyPtr ptr ( _allocator, size ); int status; { epicsGuardRelease < epicsMutex > unguard ( guard ); status = dbChannel_get ( dbch, static_cast <int> ( type ), ptr.get (), static_cast <long> ( count ), 0 ); } if ( status ) { notify.exception ( guard, ECA_GETFAIL, "db_get_field() completed unsuccessfuly", type, count ); } else { notify.completion ( guard, type, count, ptr.get () ); } }
void cac::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); ::printf ( "Channel Access Client Context at %p for user %s\n", static_cast <const void *> ( this ), this->pUserName ); // this also supresses the "defined, but not used" // warning message ::printf ( "\trevision \"%s\"\n", pVersionCAC ); if ( level > 0u ) { this->serverTable.show ( level - 1u ); ::printf ( "\tconnection time out watchdog period %f\n", this->connTMO ); } if ( level > 1u ) { if ( this->pudpiiu ) { this->pudpiiu->show ( level - 2u ); } } if ( level > 2u ) { ::printf ( "Program begin time:\n"); this->programBeginTime.show ( level - 3u ); ::printf ( "Channel identifier hash table:\n" ); this->chanTable.show ( level - 3u ); ::printf ( "IO identifier hash table:\n" ); this->ioTable.show ( level - 3u ); ::printf ( "Beacon source identifier hash table:\n" ); this->beaconTable.show ( level - 3u ); ::printf ( "Timer queue:\n" ); this->timerQueue.show ( level - 3u ); ::printf ( "IP address to name conversion engine:\n" ); this->ipToAEngine.show ( level - 3u ); } if ( level > 3u ) { ::printf ( "Default mutex:\n"); this->mutex.show ( level - 4u ); ::printf ( "mutex:\n" ); this->mutex.show ( level - 4u ); } }
dbSubscriptionIO::dbSubscriptionIO ( epicsGuard < epicsMutex > & guard, epicsMutex & mutexIn, dbContext &, dbChannelIO & chanIO, dbChannel * dbch, cacStateNotify & notifyIn, unsigned typeIn, unsigned long countIn, unsigned maskIn, dbEventCtx ctx ) : mutex ( mutexIn ), count ( countIn ), notify ( notifyIn ), chan ( chanIO ), es ( 0 ), type ( typeIn ), id ( 0u ) { guard.assertIdenticalMutex ( this->mutex ); { epicsGuardRelease < epicsMutex > unguard ( guard ); this->es = db_add_event ( ctx, dbch, dbSubscriptionEventCallback, (void *) this, maskIn ); if ( this->es == 0 ) { throw std::bad_alloc(); } db_post_single_event ( this->es ); db_event_enable ( this->es ); } }
bool cac::destroyIO ( epicsGuard < epicsMutex > & guard, const cacChannel::ioid & idIn, nciu & chan ) { guard.assertIdenticalMutex ( this->mutex ); baseNMIU * pIO = this->ioTable.remove ( idIn ); if ( pIO ) { class netSubscription * pSubscr = pIO->isSubscription (); if ( pSubscr ) { pSubscr->unsubscribeIfRequired ( guard, chan ); } // this uninstalls from the list and destroys the IO pIO->exception ( guard, *this, ECA_CHANDESTROY, chan.pName ( guard ) ); return true; } return false; }
void dbSubscriptionIO::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); printf ( "Data base subscription IO at %p\n", static_cast <const void *> ( this ) ); if ( level > 0u ) { short tmpType; if ( this->type < SHRT_MAX ) { tmpType = static_cast < short > ( this->type ); printf ( "\ttype %s, count %lu, channel at %p\n", dbf_type_to_text ( tmpType ), this->count, static_cast <void *> ( &this->chan ) ); } else { printf ( "strange type !, count %lu, channel at %p\n", this->count, static_cast <void *> ( &this->chan ) ); } } }
// // Reset the delay to the next search request if we get // at least one response. However, dont reset this delay if we // get a delayed response to an old search request. // void searchTimer::uninstallChanDueToSuccessfulSearchResponse ( epicsGuard < epicsMutex > & guard, nciu & chan, ca_uint32_t respDatagramSeqNo, bool seqNumberIsValid, const epicsTime & currentTime ) { guard.assertIdenticalMutex ( this->mutex ); this->uninstallChan ( guard, chan ); if ( this->stopped ) { return; } bool validResponse = true; if ( seqNumberIsValid ) { validResponse = this->dgSeqNoAtTimerExpireBegin <= respDatagramSeqNo && this->dgSeqNoAtTimerExpireEnd >= respDatagramSeqNo; } // if we receive a successful response then reset to a // reasonable timer period if ( validResponse ) { double measured = currentTime - this->timeAtLastSend; this->iiu.updateRTTE ( guard, measured ); if ( this->searchResponses < UINT_MAX ) { this->searchResponses++; if ( this->searchResponses == this->searchAttempts ) { if ( this->chanListReqPending.count () ) { // // when we get 100% success immediately // send another search request // debugPrintf ( ( "All requests succesful, set timer delay to zero\n" ) ); this->timer.start ( *this, currentTime ); } } } } }
bool udpiiu :: datagramFlush ( epicsGuard < epicsMutex > & guard, const epicsTime & currentTime ) { guard.assertIdenticalMutex ( cacMutex ); // dont send the version header by itself if ( this->nBytesInXmitBuf <= sizeof ( caHdr ) ) { return false; } tsDLIter < SearchDest > iter ( _searchDestList.firstIter () ); while ( iter.valid () ) { iter->searchRequest ( guard, this->xmitBuf, this->nBytesInXmitBuf ); iter++; } this->nBytesInXmitBuf = 0u; this->pushVersionMsg (); return true; }
void bhe::registerIIU ( epicsGuard < epicsMutex > & guard, tcpiiu & iiu ) { guard.assertIdenticalMutex ( this->mutex ); this->pIIU = & iiu; }