@@ -54,6 +54,7 @@ class ConnectDescription {
5454class ConnStrategy {
5555 constructor ( ) {
5656 this . nextOptToTry = 0 ;
57+ this . reorderDescriptionList = 0 ;
5758 this . retryCount = 0 ;
5859 this . lastRetryCounter = 0 ;
5960 this . lastRetryConnectDescription = 0 ;
@@ -95,6 +96,10 @@ class ConnStrategy {
9596 this . retryCount = config . retryCount ;
9697 }
9798 }
99+ if ( ! this . reorderDescriptionList ) {
100+ this . descriptionList = SOLE_INST_DHCACHE . reorderDescriptionList ( this . descriptionList ) ;
101+ this . reorderDescriptionList = true ;
102+ }
98103 /* We try the address list at least once and upto (1 + retryCount) times */
99104 for ( let d = this . lastRetryConnectDescription ; d < this . descriptionList . length ; d ++ ) {
100105 const desc = this . descriptionList [ d ] ;
@@ -108,6 +113,11 @@ class ConnStrategy {
108113 }
109114 }
110115 for ( let i = this . lastRetryCounter ; i <= this . retryCount ; ++ i ) {
116+ //Conn options must be reordered only when all options are tried
117+ // i.e for retry and before the first try.
118+ if ( this . nextOptToTry == 0 ) {
119+ cOpts = SOLE_INST_DHCACHE . reorderAddresses ( cOpts ) ;
120+ }
111121 while ( this . nextOptToTry < cOpts . length ) {
112122 const copt = cOpts [ this . nextOptToTry ] ;
113123 this . lastRetryCounter = i ;
@@ -174,4 +184,117 @@ async function createNode(str) {
174184 await navobj . navigate ( cs ) ;
175185 return cs ;
176186}
177- module . exports = { createNode } ;
187+
188+
189+ class DownHostsCache {
190+
191+ constructor ( ) {
192+ // Timeout for each item in the cache
193+ this . DOWN_HOSTS_TIMEOUT = 600 ;
194+ // Minimum amount of time between each refresh
195+ this . MIN_TIME_BETWEEN_REFRESH = 60 ;
196+ // DownHostsCache Map
197+ this . downHostsCacheMap = new Map ( ) ;
198+ // Last Refresh Time
199+ this . lastRefreshTime = 0 ;
200+ }
201+
202+ /**
203+ * Add an address to the cache
204+ *
205+ * @param connOption
206+ * address to be cached
207+ * @return Map with address as key and time of insertion as value
208+ */
209+ markDownHost ( addr ) {
210+ return this . downHostsCacheMap . set ( addr , Date . now ( ) ) ;
211+ }
212+
213+ // Remove elements older than DownHostsTimeout
214+ refreshCache ( ) {
215+ if ( Date . now ( ) - this . MIN_TIME_BETWEEN_REFRESH * 1000 > this . lastRefreshTime ) {
216+ this . downHostsCacheMap . forEach ( ( value , key ) => {
217+ const entryTime = value ;
218+ if ( entryTime != null && ( ( Date . now ( ) - this . DOWN_HOSTS_TIMEOUT * 1000 ) > entryTime ) ) {
219+ this . downHostsCacheMap . delete ( key ) ;
220+ }
221+ } ) ;
222+ this . lastRefreshTime = Date . now ( ) ;
223+ }
224+ }
225+
226+ /**
227+ * Reorder addresses such that cached elements
228+ * occur at the end of the array.
229+ */
230+ reorderAddresses ( cOpts ) {
231+ this . refreshCache ( ) ;
232+
233+ let topIdx = 0 , btmIdx = cOpts . length - 1 ;
234+
235+ while ( topIdx < btmIdx ) {
236+
237+ // increment topIdx if the address is not cached
238+ while ( topIdx <= btmIdx
239+ && ! this . isDownHostsCached ( cOpts [ topIdx ] ) )
240+ topIdx ++ ;
241+
242+ // decrement btmIdx if address is cached
243+ while ( btmIdx >= topIdx
244+ && this . isDownHostsCached ( cOpts [ btmIdx ] ) )
245+ btmIdx -- ;
246+
247+ // swap cached with uncached
248+ if ( topIdx < btmIdx )
249+ [ cOpts [ topIdx ] , cOpts [ btmIdx ] ] = [ cOpts [ btmIdx ] , cOpts [ topIdx ] ] ;
250+
251+ }
252+ return cOpts ;
253+ }
254+
255+ isDownDescCached ( desc ) {
256+ //const desc = this.descriptionList[d];
257+ //let cOpts = new Array();
258+ const cOpts = desc . getConnectOptions ( ) ;
259+ for ( let i = 0 ; i < cOpts . length ; i ++ ) {
260+ if ( ! this . isDownHostsCached ( cOpts [ i ] ) )
261+ return false ;
262+ }
263+ return true ;
264+ }
265+ /**
266+ * Reorder description list such that description with all connection options in downcache
267+ * is pushed to the end of the description list
268+ */
269+ reorderDescriptionList ( descs ) {
270+ this . refreshCache ( ) ;
271+
272+ let topIdx = 0 , btmIdx = descs . length - 1 ;
273+
274+ while ( topIdx < btmIdx ) {
275+
276+ // increment topIdx if the address is not cached
277+ while ( topIdx <= btmIdx
278+ && ! this . isDownDescCached ( descs [ topIdx ] ) )
279+ topIdx ++ ;
280+
281+ // decrement btmIdx if address is cached
282+ while ( btmIdx >= topIdx
283+ && this . isDownDescCached ( descs [ btmIdx ] ) )
284+ btmIdx -- ;
285+
286+ // swap cached with uncached
287+ if ( topIdx < btmIdx ) {
288+ [ descs [ topIdx ] , descs [ btmIdx ] ] = [ descs [ btmIdx ] , descs [ topIdx ] ] ;
289+ }
290+ }
291+ return descs ;
292+ }
293+ // Return if a host is cached
294+ isDownHostsCached ( copt ) {
295+ return this . downHostsCacheMap . has ( copt . host ) ;
296+ }
297+ }
298+ // Single instance
299+ const SOLE_INST_DHCACHE = new DownHostsCache ( ) ;
300+ module . exports = { createNode, SOLE_INST_DHCACHE } ;
0 commit comments