14
14
// You should have received a copy of the GNU Lesser General Public License
15
15
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
16
17
- // resultcache implements a structure for maintaining fetchResults, tracking their
18
- // download-progress and delivering (finished) results
19
-
20
17
package downloader
21
18
22
19
import (
@@ -27,9 +24,10 @@ import (
27
24
"github.com/ethereum/go-ethereum/core/types"
28
25
)
29
26
27
+ // resultStore implements a structure for maintaining fetchResults, tracking their
28
+ // download-progress and delivering (finished) results.
30
29
type resultStore struct {
31
30
items []* fetchResult // Downloaded but not yet delivered fetch results
32
- lock * sync.RWMutex // lock protect internals
33
31
resultOffset uint64 // Offset of the first cached fetch result in the block chain
34
32
35
33
// Internal index of first non-completed entry, updated atomically when needed.
@@ -43,20 +41,24 @@ type resultStore struct {
43
41
// 8192 possible places. The queue will, at certain times, recalibrate
44
42
// this index.
45
43
throttleThreshold uint64
44
+
45
+ lock sync.RWMutex
46
46
}
47
47
48
48
func newResultStore (size int ) * resultStore {
49
49
return & resultStore {
50
50
resultOffset : 0 ,
51
51
items : make ([]* fetchResult , size ),
52
- lock : new (sync.RWMutex ),
53
52
throttleThreshold : 3 * uint64 (size ) / 4 , // 75%
54
53
}
55
54
}
56
55
56
+ // SetThrottleThreshold updates the throttling threshold based on the requested
57
+ // limit and the total queue capacity.
57
58
func (r * resultStore ) SetThrottleThreshold (threshold uint64 ) {
58
59
r .lock .Lock ()
59
60
defer r .lock .Unlock ()
61
+
60
62
limit := uint64 (len (r .items )) * 3 / 4
61
63
if threshold >= limit {
62
64
threshold = limit
@@ -66,15 +68,16 @@ func (r *resultStore) SetThrottleThreshold(threshold uint64) {
66
68
67
69
// AddFetch adds a header for body/receipt fetching. This is used when the queue
68
70
// wants to reserve headers for fetching.
71
+ //
69
72
// It returns the following:
70
- // stale -- if true, this item is already passed, and should not be requested again.
71
- // throttled -- if true, the resultcache is at capacity, and this particular header is not
72
- // prio right now
73
- // fetchResult -- the result to store data into
74
- // err -- any error that occurred
73
+ // stale - if true, this item is already passed, and should not be requested again
74
+ // throttled - if true, the store is at capacity, this particular header is not prio now
75
+ // item - the result to store data into
76
+ // err - any error that occurred
75
77
func (r * resultStore ) AddFetch (header * types.Header , fastSync bool ) (stale , throttled bool , item * fetchResult , err error ) {
76
78
r .lock .Lock ()
77
79
defer r .lock .Unlock ()
80
+
78
81
var index int
79
82
item , index , stale , throttled , err = r .getFetchResult (header .Number .Uint64 ())
80
83
if err != nil || stale || throttled {
@@ -88,20 +91,20 @@ func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, thro
88
91
}
89
92
90
93
// GetDeliverySlot returns the fetchResult for the given header. If the 'stale' flag
91
- // is true, that means the header has already been delivered 'upstream'.
92
- // This method does not bubble up the 'throttle' flag, since it's moot at the
93
- // point in time when the item is downloaded and ready for delivery
94
+ // is true, that means the header has already been delivered 'upstream'. This method
95
+ // does not bubble up the 'throttle' flag, since it's moot at the point in time when
96
+ // the item is downloaded and ready for delivery
94
97
func (r * resultStore ) GetDeliverySlot (headerNumber uint64 ) (* fetchResult , bool , error ) {
95
98
r .lock .RLock ()
96
99
defer r .lock .RUnlock ()
100
+
97
101
res , _ , stale , _ , err := r .getFetchResult (headerNumber )
98
102
return res , stale , err
99
103
}
100
104
101
- // getFetchResult returns the fetchResult corresponding to the given item, and the index where
102
- // the result is stored.
105
+ // getFetchResult returns the fetchResult corresponding to the given item, and
106
+ // the index where the result is stored.
103
107
func (r * resultStore ) getFetchResult (headerNumber uint64 ) (item * fetchResult , index int , stale , throttle bool , err error ) {
104
-
105
108
index = int (int64 (headerNumber ) - int64 (r .resultOffset ))
106
109
throttle = index >= int (r .throttleThreshold )
107
110
stale = index < 0
@@ -124,6 +127,7 @@ func (r *resultStore) getFetchResult(headerNumber uint64) (item *fetchResult, in
124
127
func (r * resultStore ) HasCompletedItems () bool {
125
128
r .lock .RLock ()
126
129
defer r .lock .RUnlock ()
130
+
127
131
if len (r .items ) == 0 {
128
132
return false
129
133
}
@@ -135,7 +139,8 @@ func (r *resultStore) HasCompletedItems() bool {
135
139
136
140
// countCompleted returns the number of items ready for delivery, stopping at
137
141
// the first non-complete item.
138
- // It assumes (at least) rlock is held
142
+ //
143
+ // The mthod assumes (at least) rlock is held.
139
144
func (r * resultStore ) countCompleted () int {
140
145
// We iterate from the already known complete point, and see
141
146
// if any more has completed since last count
@@ -170,18 +175,19 @@ func (r *resultStore) GetCompleted(limit int) []*fetchResult {
170
175
for i := len (r .items ) - limit ; i < len (r .items ); i ++ {
171
176
r .items [i ] = nil
172
177
}
173
- // Advance the expected block number of the first cache entry.
178
+ // Advance the expected block number of the first cache entry
174
179
r .resultOffset += uint64 (limit )
175
- // And subtract the number of items from our index
176
180
atomic .AddInt32 (& r .indexIncomplete , int32 (- limit ))
181
+
177
182
return results
178
183
}
179
184
180
185
// Prepare initialises the offset with the given block number
181
186
func (r * resultStore ) Prepare (offset uint64 ) {
182
187
r .lock .Lock ()
188
+ defer r .lock .Unlock ()
189
+
183
190
if r .resultOffset < offset {
184
191
r .resultOffset = offset
185
192
}
186
- r .lock .Unlock ()
187
193
}
0 commit comments