Exemple #1
0
/*
 * register_new_client()
 */
static void register_new_client ( osiSockAddr & from, 
            tsFreeList < repeaterClient, 0x20 > & freeList )
{
    bool newClient = false;
    int status;

    if ( from.sa.sa_family != AF_INET ) {
        return;
    }

    /*
     * the repeater and its clients must be on the same host
     */
    if ( INADDR_LOOPBACK != ntohl ( from.ia.sin_addr.s_addr ) ) {
        static SOCKET testSock = INVALID_SOCKET;
        static bool init = false;

        if ( ! init ) {
            SOCKET sock;
            if ( ! makeSocket ( PORT_ANY, true, & sock ) ) {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                fprintf ( stderr, "%s: Unable to create repeater bind test socket because \"%s\"\n",
                    __FILE__, sockErrBuf );
            }
            else {
                testSock = sock;
            }
            init = true;
        }

        /*
         * Unfortunately on 3.13 beta 11 and before the
         * repeater would not always allow the loopback address
         * as a local client address so current clients alternate
         * between the address of the first non-loopback interface
         * found and the loopback addresss when subscribing with 
         * the CA repeater until all CA repeaters have been updated
         * to current code.
         */
        if ( testSock != INVALID_SOCKET ) {
            osiSockAddr addr;

            addr = from;
            addr.ia.sin_port = PORT_ANY;

            /* we can only bind to a local address */
            status = bind ( testSock, &addr.sa, sizeof ( addr ) );
            if ( status ) {
                return;
            }
        }
        else {
            return;
        }
    }

    tsDLIter < repeaterClient > pclient = client_list.firstIter ();
    while ( pclient.valid () ) {
        if ( pclient->identicalPort ( from ) ) {
            break;
        }
        pclient++;
    }      
    
    repeaterClient *pNewClient;
    if ( pclient.valid () ) {
        pNewClient = pclient.pointer ();
    }
    else {
        pNewClient = new ( freeList ) repeaterClient ( from );
        if ( ! pNewClient ) {
            fprintf ( stderr, "%s: no memory for new client\n", __FILE__ );
            return;
        }
        if ( ! pNewClient->connect () ) {
            pNewClient->~repeaterClient ();
            freeList.release ( pNewClient );
            return;
        }
        client_list.add ( *pNewClient ); 
        newClient = true;
    }

    if ( ! pNewClient->sendConfirm () ) {
        client_list.remove ( *pNewClient );
        pNewClient->~repeaterClient ();
        freeList.release ( pNewClient );
#       ifdef DEBUG
            epicsUInt16 port = ntohs ( from.ia.sin_port );
            debugPrintf ( ( "Deleted repeater client=%u (error while sending ack)\n",
                        port ) );
#       endif
    }

    /*
     * send a noop message to all other clients so that we dont 
     * accumulate sockets when there are no beacons
     */
    caHdr noop;
    memset ( (char *) &noop, '\0', sizeof ( noop ) );
    AlignedWireRef < epicsUInt16 > ( noop.m_cmmd ) = CA_PROTO_VERSION;
    fanOut ( from, &noop, sizeof ( noop ), freeList );

    if ( newClient ) {
        /*
         * For HPUX and Solaris we need to verify that the clients
         * have not gone away - because an ICMP error return does not
         * get through to send(), which returns no error code.
         *
         * This is done each time that a new client is created.
         * See also the note in the file header.
         *
         * This is done here in order to avoid deleting a client
         * prior to sending its confirm message.
         */
        verifyClients ( freeList );
    }
}
Exemple #2
0
/*
 *  ca_repeater ()
 */
void ca_repeater () 
{
    tsFreeList < repeaterClient, 0x20 > freeList;
    int size;
    SOCKET sock;
    osiSockAddr from;
    unsigned short port;
    char * pBuf; 

    pBuf = new char [MAX_UDP_RECV];

    {
        bool success = osiSockAttach();
        assert ( success );
    }

    port = envGetInetPortConfigParam ( & EPICS_CA_REPEATER_PORT,
                                       static_cast <unsigned short> (CA_REPEATER_PORT) );
    if ( ! makeSocket ( port, true, & sock ) ) {
        /*
         * test for server was already started
         */
        if ( SOCKERRNO == SOCK_EADDRINUSE ) {
            osiSockRelease ();
            debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
            return;
        }
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf ( stderr, "%s: Unable to create repeater socket because \"%s\" - fatal\n",
            __FILE__, sockErrBuf );
        osiSockRelease ();
        delete [] pBuf;
        return;
    }

    debugPrintf ( ( "CA Repeater: Attached and initialized\n" ) );

    while ( true ) {
        osiSocklen_t from_size = sizeof ( from );
        size = recvfrom ( sock, pBuf, MAX_UDP_RECV, 0,
                    &from.sa, &from_size );
        if ( size < 0 ) {
            int errnoCpy = SOCKERRNO;
            // Avoid spurious ECONNREFUSED bug in linux
            if ( errnoCpy == SOCK_ECONNREFUSED ) {
                continue;
            }
            // Avoid ECONNRESET from connected socket in windows
            if ( errnoCpy == SOCK_ECONNRESET ) {
                continue;
            }
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            fprintf ( stderr, "CA Repeater: unexpected UDP recv err: %s\n",
                sockErrBuf );
            continue;
        }

        caHdr * pMsg = ( caHdr * ) pBuf;

        /*
         * both zero length message and a registration message
         * will register a new client
         */
        if ( ( (size_t) size) >= sizeof (*pMsg) ) {
            if ( AlignedWireRef < epicsUInt16 > ( pMsg->m_cmmd ) == REPEATER_REGISTER ) {
                register_new_client ( from, freeList );

                /*
                 * strip register client message
                 */
                pMsg++;
                size -= sizeof ( *pMsg );
                if ( size==0 ) {
                    continue;
                }
            }
            else if ( AlignedWireRef < epicsUInt16 > ( pMsg->m_cmmd ) == CA_PROTO_RSRV_IS_UP ) {
                if ( pMsg->m_available == 0u ) {
                    pMsg->m_available = from.ia.sin_addr.s_addr;
                }
            }
        }
        else if ( size == 0 ) {
            register_new_client ( from, freeList );
            continue;
        }

        fanOut ( from, pMsg, size, freeList ); 
    }
}
void CompressionSafeScheduler::assignTimestamps(const MinimalState & s,
                                                         list<FFEvent> & header,
                                                         list<FFEvent> & now)
{

    if (!safeToUseThis) {
        std::cerr << "Fatal internal error - attempting to use the simple compression-safe scheduler on a problem that needs at least the STP solver\n";
        assert(safeToUseThis);
        exit(1);
    }
    
    const int planSize = header.size() + now.size();
    
    vector<FFEvent*> planAsAVector(planSize);
    vector<int> fanIn(planSize, 0);
    vector<list<int> > fanOut(planSize);
    list<int> visit;
    
    {
        int i = 0;
        const map<int,bool> * stepsBefore;
        for (int pass = 0; pass < 2; ++pass) {
            list<FFEvent> & currList = (pass ? now : header);
            list<FFEvent>::iterator clItr = currList.begin();
            const list<FFEvent>::iterator clEnd = currList.end();
            
            for (; clItr != clEnd; ++clItr, ++i) {
                planAsAVector[i] = &(*clItr);
                stepsBefore = s.temporalConstraints->stepsBefore(i);
                fanIn[i] = (stepsBefore ? stepsBefore->size() : 0);
                if (!fanIn[i]) {
                    visit.push_back(i);                
                } else {
                    map<int,bool>::const_iterator sbItr = stepsBefore->begin();
                    const map<int,bool>::const_iterator sbEnd = stepsBefore->end();
                    
                    for (; sbItr != sbEnd; ++sbItr) {
                        fanOut[sbItr->first].push_back(i);
                    }
                }
            }
        }
    }
    
    int i;
    const map<int,bool> * stepsBefore;
    while (!visit.empty()) {
        i = visit.front();
        visit.pop_front();
        
        double & currTS = planAsAVector[i]->lpTimestamp;
        
        stepsBefore = s.temporalConstraints->stepsBefore(i);
        
        if (stepsBefore) {
            map<int,bool>::const_iterator sbItr = stepsBefore->begin();
            const map<int,bool>::const_iterator sbEnd = stepsBefore->end();
            
            for (double prevTS; sbItr != sbEnd; ++sbItr) {
                prevTS = planAsAVector[sbItr->first]->lpTimestamp;
                if (sbItr->second) {
                    prevTS += 0.001;
                }
                if (prevTS > currTS) {
                    currTS = prevTS;
                }
            }
            
            if (planAsAVector[i]->time_spec == Planner::E_AT_END) {
                const int & pairedWith = planAsAVector[i]->pairWithStep;
                const double minDurationSinceStart = planAsAVector[pairedWith]->lpTimestamp + planAsAVector[pairedWith]->minDuration;
                if (minDurationSinceStart > currTS) {
                    currTS = minDurationSinceStart;
                }
            }
            
        } else {
            currTS = 0.0;
        }
        
        planAsAVector[i]->lpMinTimestamp = currTS;
        planAsAVector[i]->lpMaxTimestamp = DBL_MAX;
        
        list<int>::const_iterator foItr = fanOut[i].begin();
        const list<int>::const_iterator foEnd = fanOut[i].end();
        
        for (; foItr != foEnd; ++foItr) {
            if (!(--fanIn[*foItr])) {
                visit.push_back(*foItr);
            }
        }
        
    }
    
}