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  }