@cryptotaxi247 / kubo / commits / ad3033358

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 +}