fix(bitswap:ledger) race conditions
https://github.com/jbenet/go-ipfs/issues/39
Brian Tiger Chow committed
Sep 11, 2014 at 01:02 UTC
ad30333581e9050f70c64b81cff0047671949ce4
2 files changed
+46
bitswap/ledger.go
+23
@@ -1,6 +1,7 @@
1
package bitswap
2
3
import (
4
+ "sync"
5
"time"
6
7
peer "github.com/jbenet/go-ipfs/peer"
@@ -9,6 +10,7 @@ import (
10
11
// Ledger stores the data exchange relationship between two peers.
12
type Ledger struct {
13
+ lock sync.RWMutex
14
15
// Partner is the remote Peer.
16
Partner *peer.Peer
@@ -35,16 +37,25 @@ type Ledger struct {
37
type LedgerMap map[u.Key]*Ledger
38
39
func (l *Ledger) ShouldSend() bool {
40
+ l.lock.Lock()
41
+ defer l.lock.Unlock()
42
+
43
return l.Strategy(l)
44
}
45
46
func (l *Ledger) SentBytes(n int) {
47
+ l.lock.Lock()
48
+ defer l.lock.Unlock()
49
+
50
l.exchangeCount++
51
l.lastExchange = time.Now()
52
l.Accounting.BytesSent += uint64(n)
53
}
54
55
func (l *Ledger) ReceivedBytes(n int) {
56
+ l.lock.Lock()
57
+ defer l.lock.Unlock()
58
+
59
l.exchangeCount++
60
l.lastExchange = time.Now()
61
l.Accounting.BytesRecv += uint64(n)
@@ -52,10 +63,22 @@ func (l *Ledger) ReceivedBytes(n int) {
63
64
// TODO: this needs to be different. We need timeouts.
65
func (l *Ledger) Wants(k u.Key) {
66
+ l.lock.Lock()
67
+ defer l.lock.Unlock()
68
+
69
l.wantList[k] = struct{}{}
70
}
71
72
func (l *Ledger) WantListContains(k u.Key) bool {
73
+ l.lock.RLock()
74
+ defer l.lock.RUnlock()
75
+
76
_, ok := l.wantList[k]
77
return ok
78
}
79
+
80
+func (l *Ledger) ExchangeCount() uint64 {
81
+ l.lock.RLock()
82
+ defer l.lock.RUnlock()
83
+ return l.exchangeCount
84
+}
bitswap/ledger_test.go
new
+23
@@ -0,0 +1,23 @@
1
+package bitswap
2
+
3
+import (
4
+ "sync"
5
+ "testing"
6
+)
7
+
8
+func TestRaceConditions(t *testing.T) {
9
+ const numberOfExpectedExchanges = 10000
10
+ l := new(Ledger)
11
+ var wg sync.WaitGroup
12
+ for i := 0; i < numberOfExpectedExchanges; i++ {
13
+ wg.Add(1)
14
+ go func() {
15
+ defer wg.Done()
16
+ l.ReceivedBytes(1)
17
+ }()
18
+ }
19
+ wg.Wait()
20
+ if l.ExchangeCount() != numberOfExpectedExchanges {
21
+ t.Fail()
22
+ }
23
+}