sessioninterestmanager.go 2.95 KB
Newer Older
dirkmc's avatar
dirkmc committed
1 2 3
package sessioninterestmanager

import (
4 5
	"sync"

6
	bsswl "github.com/ipfs/go-bitswap/internal/sessionwantlist"
dirkmc's avatar
dirkmc committed
7 8 9 10 11
	blocks "github.com/ipfs/go-block-format"

	cid "github.com/ipfs/go-cid"
)

12
// SessionInterestManager records the CIDs that each session is interested in.
dirkmc's avatar
dirkmc committed
13
type SessionInterestManager struct {
14
	lk         sync.RWMutex
dirkmc's avatar
dirkmc committed
15 16 17 18 19 20 21 22 23 24 25 26
	interested *bsswl.SessionWantlist
	wanted     *bsswl.SessionWantlist
}

// New initializes a new SessionInterestManager.
func New() *SessionInterestManager {
	return &SessionInterestManager{
		interested: bsswl.NewSessionWantlist(),
		wanted:     bsswl.NewSessionWantlist(),
	}
}

27 28
// When the client asks the session for blocks, the session calls
// RecordSessionInterest() with those cids.
dirkmc's avatar
dirkmc committed
29
func (sim *SessionInterestManager) RecordSessionInterest(ses uint64, ks []cid.Cid) {
30 31 32
	sim.lk.Lock()
	defer sim.lk.Unlock()

dirkmc's avatar
dirkmc committed
33 34 35 36
	sim.interested.Add(ks, ses)
	sim.wanted.Add(ks, ses)
}

37
// When the session shuts down it calls RemoveSessionInterest().
dirkmc's avatar
dirkmc committed
38
func (sim *SessionInterestManager) RemoveSessionInterest(ses uint64) []cid.Cid {
39 40 41
	sim.lk.Lock()
	defer sim.lk.Unlock()

dirkmc's avatar
dirkmc committed
42 43 44 45
	sim.wanted.RemoveSession(ses)
	return sim.interested.RemoveSession(ses)
}

46
// When the session receives blocks, it calls RemoveSessionWants().
dirkmc's avatar
dirkmc committed
47
func (sim *SessionInterestManager) RemoveSessionWants(ses uint64, wants []cid.Cid) {
48 49 50
	sim.lk.Lock()
	defer sim.lk.Unlock()

dirkmc's avatar
dirkmc committed
51 52 53
	sim.wanted.RemoveSessionKeys(ses, wants)
}

54 55
// The session calls FilterSessionInterested() to filter the sets of keys for
// those that the session is interested in
dirkmc's avatar
dirkmc committed
56
func (sim *SessionInterestManager) FilterSessionInterested(ses uint64, ksets ...[]cid.Cid) [][]cid.Cid {
57 58 59
	sim.lk.RLock()
	defer sim.lk.RUnlock()

dirkmc's avatar
dirkmc committed
60 61 62 63 64 65 66
	kres := make([][]cid.Cid, len(ksets))
	for i, ks := range ksets {
		kres[i] = sim.interested.SessionHas(ses, ks).Keys()
	}
	return kres
}

67 68
// When bitswap receives blocks it calls SplitWantedUnwanted() to discard
// unwanted blocks
dirkmc's avatar
dirkmc committed
69
func (sim *SessionInterestManager) SplitWantedUnwanted(blks []blocks.Block) ([]blocks.Block, []blocks.Block) {
70 71 72
	sim.lk.RLock()
	defer sim.lk.RUnlock()

dirkmc's avatar
dirkmc committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
	// Get the wanted block keys
	ks := make([]cid.Cid, len(blks))
	for _, b := range blks {
		ks = append(ks, b.Cid())
	}
	wantedKs := sim.wanted.Has(ks)

	// Separate the blocks into wanted and unwanted
	wantedBlks := make([]blocks.Block, 0, len(blks))
	notWantedBlks := make([]blocks.Block, 0)
	for _, b := range blks {
		if wantedKs.Has(b.Cid()) {
			wantedBlks = append(wantedBlks, b)
		} else {
			notWantedBlks = append(notWantedBlks, b)
		}
	}
	return wantedBlks, notWantedBlks
}

93 94
// When the WantManager receives a message is calls InterestedSessions() to
// find out which sessions are interested in the message.
dirkmc's avatar
dirkmc committed
95
func (sim *SessionInterestManager) InterestedSessions(blks []cid.Cid, haves []cid.Cid, dontHaves []cid.Cid) []uint64 {
96 97 98
	sim.lk.RLock()
	defer sim.lk.RUnlock()

dirkmc's avatar
dirkmc committed
99 100 101 102 103 104 105
	ks := make([]cid.Cid, 0, len(blks)+len(haves)+len(dontHaves))
	ks = append(ks, blks...)
	ks = append(ks, haves...)
	ks = append(ks, dontHaves...)

	return sim.interested.SessionsFor(ks)
}