/* * 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 ); } }
/* * 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); } } } }