Exemplo n.º 1
0
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 );
}
Exemplo n.º 2
0
void bhe::beaconAnomalyNotify ( epicsGuard < epicsMutex > & guard )
{
    guard.assertIdenticalMutex ( this->mutex );
    if ( this->pIIU ) {
        this->pIIU->beaconAnomalyNotify ( guard );
    }
}
Exemplo n.º 3
0
void disconnectGovernorTimer::installChan ( 
    epicsGuard < epicsMutex > & guard, nciu & chan )
{
    guard.assertIdenticalMutex ( this->mutex );
    this->chanList.add ( chan );
    chan.channelNode::listMember = channelNode::cs_disconnGov;
}
Exemplo n.º 4
0
void cac::registerSearchDest (
    epicsGuard < epicsMutex > & guard,
    SearchDest & req )
{
    guard.assertIdenticalMutex ( this->mutex );
    this->searchDestList.add ( req );
}
Exemplo n.º 5
0
void dbSubscriptionIO::channelDeleteException ( 
    epicsGuard < epicsMutex > & guard )
{
    guard.assertIdenticalMutex ( this->mutex );
    this->notify.exception ( guard, ECA_CHANDESTROY, 
        this->chan.pName(guard), this->type, this->count );
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
void cac::selfTest ( 
    epicsGuard < epicsMutex > & guard ) const
{
    guard.assertIdenticalMutex ( this->mutex );
    this->chanTable.verify ();
    this->ioTable.verify ();
    this->beaconTable.verify ();
}
Exemplo n.º 9
0
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 );
}
Exemplo n.º 10
0
void cac::initiateConnect ( 
    epicsGuard < epicsMutex > & guard, 
    nciu & chan, netiiu * & piiu )
{
    guard.assertIdenticalMutex ( this->mutex );
    assert ( this->pudpiiu );
    this->pudpiiu->installNewChannel ( guard, chan, piiu );
}
Exemplo n.º 11
0
//
// 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++;
    }
}
Exemplo n.º 12
0
void dbContextReadNotifyCache::show (
    epicsGuard < epicsMutex > & guard, unsigned level ) const
{
    guard.assertIdenticalMutex ( _mutex );

    printf ( "dbContextReadNotifyCache\n" );
    if ( level > 0 ) {
        this->_allocator.show ( level - 1 );
    }
}
Exemplo n.º 13
0
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 );
}
Exemplo n.º 14
0
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 () );
    }
}
Exemplo n.º 15
0
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;
    }
}
Exemplo n.º 16
0
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 );
        }
    }
}
Exemplo n.º 17
0
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 ();
}
Exemplo n.º 18
0
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;
            }
        }
    }
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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 );
}
Exemplo n.º 21
0
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 );
}
Exemplo n.º 22
0
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 );
    }
}
Exemplo n.º 23
0
// 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 () );
    }
}
Exemplo n.º 24
0
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 );
    }
}
Exemplo n.º 25
0
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 );
    }
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
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 ) );
        }
    }
}
Exemplo n.º 28
0
//
// 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 );
                }
            }
        }
    }
}
Exemplo n.º 29
0
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;
}
Exemplo n.º 30
0
void bhe::registerIIU ( 
    epicsGuard < epicsMutex > & guard, tcpiiu & iiu )
{
    guard.assertIdenticalMutex ( this->mutex );
    this->pIIU = & iiu;
}