@@ -54,6 +54,7 @@ class ConnectDescription {
54
54
class ConnStrategy {
55
55
constructor ( ) {
56
56
this . nextOptToTry = 0 ;
57
+ this . reorderDescriptionList = 0 ;
57
58
this . retryCount = 0 ;
58
59
this . lastRetryCounter = 0 ;
59
60
this . lastRetryConnectDescription = 0 ;
@@ -95,6 +96,10 @@ class ConnStrategy {
95
96
this . retryCount = config . retryCount ;
96
97
}
97
98
}
99
+ if ( ! this . reorderDescriptionList ) {
100
+ this . descriptionList = SOLE_INST_DHCACHE . reorderDescriptionList ( this . descriptionList ) ;
101
+ this . reorderDescriptionList = true ;
102
+ }
98
103
/* We try the address list at least once and upto (1 + retryCount) times */
99
104
for ( let d = this . lastRetryConnectDescription ; d < this . descriptionList . length ; d ++ ) {
100
105
const desc = this . descriptionList [ d ] ;
@@ -108,6 +113,11 @@ class ConnStrategy {
108
113
}
109
114
}
110
115
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
+ }
111
121
while ( this . nextOptToTry < cOpts . length ) {
112
122
const copt = cOpts [ this . nextOptToTry ] ;
113
123
this . lastRetryCounter = i ;
@@ -174,4 +184,117 @@ async function createNode(str) {
174
184
await navobj . navigate ( cs ) ;
175
185
return cs ;
176
186
}
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