-
Notifications
You must be signed in to change notification settings - Fork 202
/
requiredDataPool.go
74 lines (65 loc) · 2.05 KB
/
requiredDataPool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package process
import (
"bytes"
"math/bits"
"sync"
)
// RequiredDataPool represents a structure that can hold a list of required data.
// Any time one of the expected hash value is received, the associated bit
// in the receivedBitmap property is set to 1. All of the data is
// considered received when the ones count of the received bitmap
// is equal to the expected data length
type RequiredDataPool struct {
dataLock sync.RWMutex
expectedData [][]byte
receivedBitmap []byte
}
// ExpectedData returns the RequiredDataPool's expected data
func (rh *RequiredDataPool) ExpectedData() [][]byte {
return rh.expectedData
}
// SetHashes sets the expected data to the passed hashes parameter. The bitmap is also
// reset and adapted to the length of the new expected data
func (rh *RequiredDataPool) SetHashes(hashes [][]byte) {
hashLength := len(hashes)
if hashLength < 1 {
rh.reset()
return
}
rh.dataLock.Lock()
rh.expectedData = hashes
rh.receivedBitmap = make([]byte, hashLength/8+1)
rh.dataLock.Unlock()
}
// SetReceivedHash finds the hash in the expected values and sets the appropriate
// bit to 1. Nothing will happen if the hash is not actually expected
func (rh *RequiredDataPool) SetReceivedHash(hash []byte) {
rh.dataLock.Lock()
hashLength := len(rh.expectedData)
for i := 0; i < hashLength; i++ {
if bytes.Equal(rh.expectedData[i], hash) {
rh.receivedBitmap[i/8] |= 1 << (uint16(i) % 8)
}
}
rh.dataLock.Unlock()
}
// ReceivedAll will return true if the count of ones in the bitmap is greater
// or equal to the expected data length
func (rh *RequiredDataPool) ReceivedAll() bool {
flags := 0
rh.dataLock.Lock()
bitmapLength := len(rh.receivedBitmap)
dataLength := len(rh.expectedData)
for i := 0; i < bitmapLength; i++ {
flags += bits.OnesCount8(rh.receivedBitmap[i])
}
rh.dataLock.Unlock()
return flags >= dataLength
}
// reset unsets the expectedData and bitmap fields and set them to nil values
func (rh *RequiredDataPool) reset() {
rh.dataLock.Lock()
rh.expectedData = nil
rh.receivedBitmap = nil
rh.dataLock.Unlock()
}