github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/routing/dht/providers.go (about) 1 package dht 2 3 import ( 4 "time" 5 6 peer "github.com/jbenet/go-ipfs/peer" 7 u "github.com/jbenet/go-ipfs/util" 8 ctxc "github.com/jbenet/go-ipfs/util/ctxcloser" 9 10 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" 11 ) 12 13 type ProviderManager struct { 14 providers map[u.Key][]*providerInfo 15 local map[u.Key]struct{} 16 lpeer peer.ID 17 getlocal chan chan []u.Key 18 newprovs chan *addProv 19 getprovs chan *getProv 20 period time.Duration 21 ctxc.ContextCloser 22 } 23 24 type addProv struct { 25 k u.Key 26 val peer.Peer 27 } 28 29 type getProv struct { 30 k u.Key 31 resp chan []peer.Peer 32 } 33 34 func NewProviderManager(ctx context.Context, local peer.ID) *ProviderManager { 35 pm := new(ProviderManager) 36 pm.getprovs = make(chan *getProv) 37 pm.newprovs = make(chan *addProv) 38 pm.providers = make(map[u.Key][]*providerInfo) 39 pm.getlocal = make(chan chan []u.Key) 40 pm.local = make(map[u.Key]struct{}) 41 pm.ContextCloser = ctxc.NewContextCloser(ctx, nil) 42 43 pm.Children().Add(1) 44 go pm.run() 45 46 return pm 47 } 48 49 func (pm *ProviderManager) run() { 50 defer pm.Children().Done() 51 52 tick := time.NewTicker(time.Hour) 53 for { 54 select { 55 case np := <-pm.newprovs: 56 if np.val.ID().Equal(pm.lpeer) { 57 pm.local[np.k] = struct{}{} 58 } 59 pi := new(providerInfo) 60 pi.Creation = time.Now() 61 pi.Value = np.val 62 arr := pm.providers[np.k] 63 pm.providers[np.k] = append(arr, pi) 64 65 case gp := <-pm.getprovs: 66 var parr []peer.Peer 67 provs := pm.providers[gp.k] 68 for _, p := range provs { 69 parr = append(parr, p.Value) 70 } 71 gp.resp <- parr 72 73 case lc := <-pm.getlocal: 74 var keys []u.Key 75 for k, _ := range pm.local { 76 keys = append(keys, k) 77 } 78 lc <- keys 79 80 case <-tick.C: 81 for k, provs := range pm.providers { 82 var filtered []*providerInfo 83 for _, p := range provs { 84 if time.Now().Sub(p.Creation) < time.Hour*24 { 85 filtered = append(filtered, p) 86 } 87 } 88 pm.providers[k] = filtered 89 } 90 91 case <-pm.Closing(): 92 return 93 } 94 } 95 } 96 97 func (pm *ProviderManager) AddProvider(k u.Key, val peer.Peer) { 98 pm.newprovs <- &addProv{ 99 k: k, 100 val: val, 101 } 102 } 103 104 func (pm *ProviderManager) GetProviders(k u.Key) []peer.Peer { 105 gp := new(getProv) 106 gp.k = k 107 gp.resp = make(chan []peer.Peer) 108 pm.getprovs <- gp 109 return <-gp.resp 110 } 111 112 func (pm *ProviderManager) GetLocal() []u.Key { 113 resp := make(chan []u.Key) 114 pm.getlocal <- resp 115 return <-resp 116 }