@@ -102,12 +102,13 @@ class BlockRequest extends Attachable {
102
102
}
103
103
104
104
class RangeRequest extends Attachable {
105
- constructor ( ranges , start , end , linear , blocks ) {
105
+ constructor ( ranges , start , end , linear , ifAvailable , blocks ) {
106
106
super ( )
107
107
108
108
this . start = start
109
109
this . end = end
110
110
this . linear = linear
111
+ this . ifAvailable = ifAvailable
111
112
this . blocks = blocks
112
113
this . ranges = ranges
113
114
@@ -172,6 +173,10 @@ class InflightTracker {
172
173
this . _free = [ ]
173
174
}
174
175
176
+ get idle ( ) {
177
+ return this . _requests . length === this . _free . length
178
+ }
179
+
175
180
* [ Symbol . iterator ] ( ) {
176
181
for ( const req of this . _requests ) {
177
182
if ( req !== null ) yield req
@@ -260,6 +265,7 @@ class Peer {
260
265
261
266
this . inflight = 0
262
267
this . maxInflight = DEFAULT_MAX_INFLIGHT
268
+ this . dataProcessing = 0
263
269
264
270
this . canUpgrade = true
265
271
@@ -515,6 +521,8 @@ class Peer {
515
521
516
522
if ( reorg === true ) return this . replicator . _onreorgdata ( this , req , data )
517
523
524
+ this . dataProcessing ++
525
+
518
526
try {
519
527
if ( ! matchingRequest ( req , data ) || ! ( await this . core . verify ( data , this ) ) ) {
520
528
this . replicator . _onnodata ( this , req )
@@ -523,6 +531,8 @@ class Peer {
523
531
} catch ( err ) {
524
532
this . replicator . _onnodata ( this , req )
525
533
throw err
534
+ } finally {
535
+ this . dataProcessing --
526
536
}
527
537
528
538
this . replicator . _ondata ( this , req , data )
@@ -909,13 +919,21 @@ module.exports = class Replicator {
909
919
return ref
910
920
}
911
921
912
- addRange ( session , { start = 0 , end = - 1 , length = toLength ( start , end ) , blocks = null , linear = false } = { } ) {
922
+ addRange ( session , { start = 0 , end = - 1 , length = toLength ( start , end ) , blocks = null , linear = false , ifAvailable = false } = { } ) {
913
923
if ( blocks !== null ) { // if using blocks, start, end just acts as frames around the blocks array
914
924
start = 0
915
925
end = length = blocks . length
916
926
}
917
927
918
- const r = new RangeRequest ( this . _ranges , start , length === - 1 ? - 1 : start + length , linear , blocks )
928
+ const r = new RangeRequest (
929
+ this . _ranges ,
930
+ start ,
931
+ length === - 1 ? - 1 : start + length ,
932
+ linear ,
933
+ ifAvailable ,
934
+ blocks
935
+ )
936
+
919
937
const ref = r . attach ( session )
920
938
921
939
this . _ranges . push ( r )
@@ -1115,6 +1133,14 @@ module.exports = class Replicator {
1115
1133
return true
1116
1134
}
1117
1135
1136
+ _resolveRangeRequest ( req , index ) {
1137
+ const head = this . _ranges . pop ( )
1138
+
1139
+ if ( index < this . _ranges . length ) this . _ranges [ index ] = head
1140
+
1141
+ req . resolve ( true )
1142
+ }
1143
+
1118
1144
_clearInflightBlock ( tracker , req ) {
1119
1145
const isBlock = tracker === this . _blocks
1120
1146
const index = isBlock === true ? req . block . index : req . hash . index / 2
@@ -1168,14 +1194,9 @@ module.exports = class Replicator {
1168
1194
while ( r . start < r . end && this . core . bitfield . get ( mapIndex ( r . blocks , r . start ) ) === true ) r . start ++
1169
1195
while ( r . start < r . end && this . core . bitfield . get ( mapIndex ( r . blocks , r . end - 1 ) ) === true ) r . end --
1170
1196
1171
- if ( r . end === - 1 || r . start < r . end ) continue
1172
-
1173
- if ( i < this . _ranges . length - 1 ) this . _ranges [ i ] = this . _ranges . pop ( )
1174
- else this . _ranges . pop ( )
1175
-
1176
- i --
1177
-
1178
- r . resolve ( true )
1197
+ if ( r . end !== - 1 && r . start >= r . end ) {
1198
+ this . _resolveRangeRequest ( r , i -- )
1199
+ }
1179
1200
}
1180
1201
1181
1202
for ( let i = 0 ; i < this . _seeks . length ; i ++ ) {
@@ -1201,7 +1222,7 @@ module.exports = class Replicator {
1201
1222
else s . resolve ( res )
1202
1223
}
1203
1224
1204
- this . updateAll ( )
1225
+ if ( this . _inflight . idle ) this . updateAll ( )
1205
1226
1206
1227
// No additional updates scheduled - return
1207
1228
if ( -- this . _updatesPending === 0 ) return
@@ -1210,6 +1231,22 @@ module.exports = class Replicator {
1210
1231
}
1211
1232
}
1212
1233
1234
+ _maybeResolveIfAvailableRanges ( ) {
1235
+ if ( this . _ifAvailable > 0 || ! this . _inflight . idle || ! this . _ranges . length ) return
1236
+
1237
+ for ( let i = 0 ; i < this . peers . length ; i ++ ) {
1238
+ if ( this . peers [ i ] . dataProcessing > 0 ) return
1239
+ }
1240
+
1241
+ for ( let i = 0 ; i < this . _ranges . length ; i ++ ) {
1242
+ const r = this . _ranges [ i ]
1243
+
1244
+ if ( r . ifAvailable ) {
1245
+ this . _resolveRangeRequest ( r , i -- )
1246
+ }
1247
+ }
1248
+ }
1249
+
1213
1250
_clearRequest ( peer , req ) {
1214
1251
if ( req . block !== null ) {
1215
1252
this . _clearInflightBlock ( this . _blocks , req )
@@ -1407,6 +1444,7 @@ module.exports = class Replicator {
1407
1444
while ( this . _updatePeerNonPrimary ( peer ) === true ) ;
1408
1445
1409
1446
this . _checkUpgradeIfAvailable ( )
1447
+ this . _maybeResolveIfAvailableRanges ( )
1410
1448
}
1411
1449
1412
1450
updateAll ( ) {
@@ -1434,6 +1472,7 @@ module.exports = class Replicator {
1434
1472
}
1435
1473
1436
1474
this . _checkUpgradeIfAvailable ( )
1475
+ this . _maybeResolveIfAvailableRanges ( )
1437
1476
}
1438
1477
1439
1478
attachTo ( protomux ) {
0 commit comments