func (sw *sessionWants) HasLiveWants() bool {
	return len(sw.liveWants) > 0
}
Has live wants indicates if there are any live wants
package session
import (
	"fmt"
	"math/rand"
	"time"
	cid "github.com/ipfs/go-cid"
)
const liveWantsOrderGCLimit = 32
type sessionWants struct {
	toFetch *cidQueue
	liveWants map[cid.Cid]time.Time
	liveWantsOrder []cid.Cid
	broadcastLimit int
}
func newSessionWants(broadcastLimit int) sessionWants {
	return sessionWants{
		toFetch:        newCidQueue(),
		liveWants:      make(map[cid.Cid]time.Time),
		broadcastLimit: broadcastLimit,
	}
}
func (sw *sessionWants) String() string {
	return fmt.Sprintf("%d pending / %d live", sw.toFetch.Len(), len(sw.liveWants))
}
func (sw *sessionWants) BlocksRequested(newWants []cid.Cid) {
	for _, k := range newWants {
		sw.toFetch.Push(k)
	}
}
func (sw *sessionWants) GetNextWants() []cid.Cid {
	now := time.Now()
	currentLiveCount := len(sw.liveWants)
	toAdd := sw.broadcastLimit - currentLiveCount
	var live []cid.Cid
	for ; toAdd > 0 && sw.toFetch.Len() > 0; toAdd-- {
		c := sw.toFetch.Pop()
		live = append(live, c)
		sw.liveWantsOrder = append(sw.liveWantsOrder, c)
		sw.liveWants[c] = now
	}
	return live
}
func (sw *sessionWants) WantsSent(ks []cid.Cid) {
	now := time.Now()
	for _, c := range ks {
		if _, ok := sw.liveWants[c]; !ok && sw.toFetch.Has(c) {
			sw.toFetch.Remove(c)
			sw.liveWantsOrder = append(sw.liveWantsOrder, c)
			sw.liveWants[c] = now
		}
	}
}
func (sw *sessionWants) BlocksReceived(ks []cid.Cid) ([]cid.Cid, time.Duration) {
	wanted := make([]cid.Cid, 0, len(ks))
	totalLatency := time.Duration(0)
	if len(ks) == 0 {
		return wanted, totalLatency
	}
	now := time.Now()
	for _, c := range ks {
		if sw.isWanted(c) {
			wanted = append(wanted, c)
			sentAt, ok := sw.liveWants[c]
			if ok && !sentAt.IsZero() {
				totalLatency += now.Sub(sentAt)
			}
			delete(sw.liveWants, c)
			sw.toFetch.Remove(c)
		}
	}
	if len(sw.liveWantsOrder)-len(sw.liveWants) > liveWantsOrderGCLimit {
		cleaned := sw.liveWantsOrder[:0]
		for _, c := range sw.liveWantsOrder {
			if _, ok := sw.liveWants[c]; ok {
				cleaned = append(cleaned, c)
			}
		}
		sw.liveWantsOrder = cleaned
	}
	return wanted, totalLatency
}
func (sw *sessionWants) PrepareBroadcast() []cid.Cid {
	now := time.Now()
	live := make([]cid.Cid, 0, len(sw.liveWants))
	for _, c := range sw.liveWantsOrder {
		if _, ok := sw.liveWants[c]; ok {
			sw.liveWants[c] = now
			live = append(live, c)
			if len(live) == sw.broadcastLimit {
				break
			}
		}
	}
	return live
}
func (sw *sessionWants) CancelPending(keys []cid.Cid) {
	for _, k := range keys {
		sw.toFetch.Remove(k)
	}
}
func (sw *sessionWants) LiveWants() []cid.Cid {
	live := make([]cid.Cid, 0, len(sw.liveWants))
	for c := range sw.liveWants {
		live = append(live, c)
	}
	return live
}
func (sw *sessionWants) RandomLiveWant() cid.Cid {
	if len(sw.liveWants) == 0 {
		return cid.Cid{}
	}
	i := rand.Intn(len(sw.liveWants))
	for k := range sw.liveWants {
		if i == 0 {
			return k
		}
		i--
	}
	return cid.Cid{}
}