24 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" 32 static const unsigned initialTriesPerFrame = 1u;
33 static const unsigned maxTriesPerFrame = 64u;
40 epicsTimerQueue & queueIn,
41 const unsigned indexIn,
43 bool boostPossibleIn ) :
44 timeAtLastSend ( epicsTime::getCurrent () ),
45 timer ( queueIn.createTimer () ),
48 framesPerTry ( initialTriesPerFrame ),
49 framesPerTryCongestThresh ( DBL_MAX ),
51 searchAttempts ( 0u ),
52 searchResponses ( 0u ),
54 dgSeqNoAtTimerExpireBegin ( 0u ),
55 dgSeqNoAtTimerExpireEnd ( 0u ),
56 boostPossible ( boostPossibleIn ),
64 this->
timer.
start ( *
this, this->period ( guard ) );
87 while (
nciu * pChan = this->chanListReqPending.
get () ) {
88 pChan->channelNode::listMember =
90 pChan->serviceShutdownNotify ( cbGuard, guard );
92 while (
nciu * pChan = this->chanListRespPending.
get () ) {
93 pChan->channelNode::listMember =
95 pChan->serviceShutdownNotify ( cbGuard, guard );
102 this->chanListReqPending.
add ( chan );
103 chan.channelNode::setReqPendingState ( guard, this->index );
109 while (
nciu * pChan = this->chanListRespPending.
get () ) {
110 if ( this->searchAttempts > 0 ) {
111 this->searchAttempts--;
115 while (
nciu * pChan = this->chanListReqPending.
get () ) {
123 epicsTimerNotify::expireStatus searchTimer::expire (
128 while (
nciu * pChan = this->chanListRespPending.
get () ) {
129 pChan->channelNode::listMember =
130 channelNode::cs_none;
132 guard, *pChan, this->index );
135 this->timeAtLastSend = currentTime;
139 if ( this->searchResponses && this->boostPossible ) {
140 while (
nciu * pChan = this->chanListReqPending.
get () ) {
141 pChan->channelNode::listMember =
142 channelNode::cs_none;
147 if ( this->searchAttempts ) {
172 if ( this->searchResponses >
173 ( this->searchAttempts - (this->searchAttempts/16u) ) ) {
175 if ( this->framesPerTry < maxTriesPerFrame ) {
177 if ( this->framesPerTry < this->framesPerTryCongestThresh ) {
178 this->framesPerTry += this->framesPerTry;
181 this->framesPerTry += (this->framesPerTry/8) + 1;
183 debugPrintf ( (
"Increasing frame count to %u t=%u r=%u\n",
184 this->framesPerTry, this->searchAttempts, this->searchResponses) );
189 else if ( this->searchResponses <
190 ( this->searchAttempts - (this->searchAttempts/8u) ) ) {
191 if ( this->framesPerTry > 1 ) {
192 this->framesPerTry--;
194 this->framesPerTryCongestThresh = this->framesPerTry/2 + 1;
195 debugPrintf ( (
"Congestion detected - set frames per try to %f t=%u r=%u\n",
196 this->framesPerTry, this->searchAttempts, this->searchResponses) );
199 if ( this->searchResponses == this->searchAttempts ) {
201 if ( this->framesPerTry < maxTriesPerFrame ) {
203 if ( this->framesPerTry < this->framesPerTryCongestThresh ) {
204 double doubled = 2 * this->framesPerTry;
205 if ( doubled > this->framesPerTryCongestThresh ) {
206 this->framesPerTry = this->framesPerTryCongestThresh;
209 this->framesPerTry = doubled;
213 this->framesPerTry += 1.0 / this->framesPerTry;
215 debugPrintf ( (
"Increasing frame count to %g t=%u r=%u\n",
216 this->framesPerTry, this->searchAttempts, this->searchResponses) );
220 this->framesPerTryCongestThresh = this->framesPerTry / 2.0;
221 this->framesPerTry = 1u;
222 debugPrintf ( (
"Congestion detected - set frames per try to %g t=%u r=%u\n",
223 this->framesPerTry, this->searchAttempts, this->searchResponses) );
228 this->dgSeqNoAtTimerExpireBegin =
231 this->searchAttempts = 0;
232 this->searchResponses = 0;
234 unsigned nFrameSent = 0u;
236 nciu * pChan = this->chanListReqPending.
get ();
241 pChan->channelNode::listMember =
242 channelNode::cs_none;
244 bool success = pChan->
searchMsg ( guard );
248 if ( nFrameSent < this->framesPerTry ) {
253 this->chanListReqPending.
push ( *pChan );
254 pChan->channelNode::setReqPendingState (
255 guard, this->index );
260 this->chanListRespPending.
add ( *pChan );
261 pChan->channelNode::setRespPendingState (
262 guard, this->index );
264 if ( this->searchAttempts < UINT_MAX ) {
265 this->searchAttempts++;
274 this->dgSeqNoAtTimerExpireEnd =
278 if ( this->searchAttempts ) {
280 currentTime.strftime ( buf,
sizeof(buf),
"%M:%S.%09f");
282 nFrameSent, this->period(), buf ) );
286 return expireStatus ( restart, this->period ( guard ) );
292 ::printf (
"searchTimer with period %f\n", this->period ( guard ) );
294 ::printf (
"channels with search request pending = %u\n",
295 this->chanListReqPending.
count () );
299 while ( pChan.
valid () ) {
300 pChan->
show ( level - 2u );
304 ::printf (
"channels with search response pending = %u\n",
305 this->chanListRespPending.
count () );
309 while ( pChan.
valid () ) {
310 pChan->
show ( level - 2u );
324 ca_uint32_t respDatagramSeqNo,
bool seqNumberIsValid,
330 if ( this->stopped ) {
334 bool validResponse =
true;
335 if ( seqNumberIsValid ) {
337 this->dgSeqNoAtTimerExpireBegin <= respDatagramSeqNo &&
338 this->dgSeqNoAtTimerExpireEnd >= respDatagramSeqNo;
343 if ( validResponse ) {
344 double measured = currentTime - this->timeAtLastSend;
347 if ( this->searchResponses < UINT_MAX ) {
348 this->searchResponses++;
349 if ( this->searchResponses == this->searchAttempts ) {
350 if ( this->chanListReqPending.
count () ) {
355 debugPrintf ( (
"All requests succesful, set timer delay to zero\n" ) );
368 static_cast <
unsigned> ( chan.channelNode::listMember );
370 static_cast <
unsigned> ( channelNode::cs_searchReqPending0 );
371 if ( ulistmem == this->index + uReqBase ) {
372 this->chanListReqPending.
remove ( chan );
376 static_cast <
unsigned > (
377 channelNode::cs_searchRespPending0 );
378 if ( ulistmem == this->index + uRespBase ) {
379 this->chanListRespPending.
remove ( chan );
382 throw std::runtime_error (
383 "uninstalling channel search timer, but channel " 387 chan.channelNode::listMember = channelNode::cs_none;
390 double searchTimer::period (
394 return (1 << this->index ) * this->iiu.
getRTTE ( guard );
bool searchMsg(epicsGuard< epicsMutex > &)
#define assert(exp)
Declare that a condition should be true.
virtual ca_uint32_t datagramSeqNumber(epicsGuard< epicsMutex > &) const =0
void shutdown(epicsGuard< epicsMutex > &cbGuard, epicsGuard< epicsMutex > &guard)
Routines to get and set EPICS environment parameters.
tsDLIterConst< T > firstIter() const
virtual bool datagramFlush(epicsGuard< epicsMutex > &, const epicsTime ¤tTime)=0
void assertIdenticalMutex(const T &) const
void uninstallChanDueToSuccessfulSearchResponse(epicsGuard< epicsMutex > &, nciu &, ca_uint32_t respDatagramSeqNo, bool seqNumberIsValid, const epicsTime ¤tTime)
virtual ~searchTimerNotify()=0
void show(unsigned level) const
virtual void boostChannel(epicsGuard< epicsMutex > &, nciu &)=0
void installChannel(epicsGuard< epicsMutex > &, nciu &)
void uninstallChan(epicsGuard< epicsMutex > &, nciu &)
virtual void noSearchRespNotify(epicsGuard< epicsMutex > &, nciu &, unsigned)=0
void moveChannels(epicsGuard< epicsMutex > &, searchTimer &dest)
void show(unsigned level) const
#define debugPrintf(argsInParen)
searchTimer(class searchTimerNotify &, epicsTimerQueue &, const unsigned index, epicsMutex &, bool boostPossible)
void start(class epicsTimerNotify &, const epicsTime &)
virtual double getRTTE(epicsGuard< epicsMutex > &) const =0
virtual void updateRTTE(epicsGuard< epicsMutex > &, double rtte)=0
void start(epicsGuard< epicsMutex > &)