providers.go 2.15 KB
Newer Older
1 2 3 4 5 6
package dht

import (
	"time"

	peer "github.com/jbenet/go-ipfs/peer"
7
	u "github.com/jbenet/go-ipfs/util"
8 9 10 11
)

type ProviderManager struct {
	providers map[u.Key][]*providerInfo
12 13 14
	local     map[u.Key]struct{}
	lpeer     peer.ID
	getlocal  chan chan []u.Key
15 16 17
	newprovs  chan *addProv
	getprovs  chan *getProv
	halt      chan struct{}
18
	period    time.Duration
19 20 21
}

type addProv struct {
22
	k   u.Key
23 24 25 26
	val *peer.Peer
}

type getProv struct {
27
	k    u.Key
28 29 30
	resp chan []*peer.Peer
}

31
func NewProviderManager(local peer.ID) *ProviderManager {
32 33 34 35
	pm := new(ProviderManager)
	pm.getprovs = make(chan *getProv)
	pm.newprovs = make(chan *addProv)
	pm.providers = make(map[u.Key][]*providerInfo)
36 37
	pm.getlocal = make(chan chan []u.Key)
	pm.local = make(map[u.Key]struct{})
38 39 40 41 42 43 44 45 46 47
	pm.halt = make(chan struct{})
	go pm.run()
	return pm
}

func (pm *ProviderManager) run() {
	tick := time.NewTicker(time.Hour)
	for {
		select {
		case np := <-pm.newprovs:
48 49 50
			if np.val.ID.Equal(pm.lpeer) {
				pm.local[np.k] = struct{}{}
			}
51 52 53 54 55 56 57 58 59 60 61 62
			pi := new(providerInfo)
			pi.Creation = time.Now()
			pi.Value = np.val
			arr := pm.providers[np.k]
			pm.providers[np.k] = append(arr, pi)
		case gp := <-pm.getprovs:
			var parr []*peer.Peer
			provs := pm.providers[gp.k]
			for _, p := range provs {
				parr = append(parr, p.Value)
			}
			gp.resp <- parr
63 64 65 66 67 68
		case lc := <-pm.getlocal:
			var keys []u.Key
			for k, _ := range pm.local {
				keys = append(keys, k)
			}
			lc <- keys
69 70 71 72
		case <-tick.C:
			for k, provs := range pm.providers {
				var filtered []*providerInfo
				for _, p := range provs {
73
					if time.Now().Sub(p.Creation) < time.Hour*24 {
74 75 76 77 78 79 80 81 82 83 84 85 86
						filtered = append(filtered, p)
					}
				}
				pm.providers[k] = filtered
			}
		case <-pm.halt:
			return
		}
	}
}

func (pm *ProviderManager) AddProvider(k u.Key, val *peer.Peer) {
	pm.newprovs <- &addProv{
87
		k:   k,
88 89 90 91 92 93 94 95 96 97 98
		val: val,
	}
}

func (pm *ProviderManager) GetProviders(k u.Key) []*peer.Peer {
	gp := new(getProv)
	gp.k = k
	gp.resp = make(chan []*peer.Peer)
	pm.getprovs <- gp
	return <-gp.resp
}
99

100 101 102 103 104 105
func (pm *ProviderManager) GetLocal() []u.Key {
	resp := make(chan []u.Key)
	pm.getlocal <- resp
	return <-resp
}

106 107 108
func (pm *ProviderManager) Halt() {
	pm.halt <- struct{}{}
}