37046dc925
License: MIT Signed-off-by: Hector Sanjuan <hector@protocol.ai>
95 lines
2.3 KiB
Go
95 lines
2.3 KiB
Go
// Package numpinalloc implements an ipfscluster.Allocator based on the "numpin"
|
|
// Informer. It is a simple example on how an allocator is implemented.
|
|
package numpinalloc
|
|
|
|
import (
|
|
"sort"
|
|
"strconv"
|
|
|
|
"github.com/ipfs/ipfs-cluster/api"
|
|
"github.com/ipfs/ipfs-cluster/informer/numpin"
|
|
|
|
rpc "github.com/hsanjuan/go-libp2p-gorpc"
|
|
cid "github.com/ipfs/go-cid"
|
|
logging "github.com/ipfs/go-log"
|
|
peer "github.com/libp2p/go-libp2p-peer"
|
|
)
|
|
|
|
var logger = logging.Logger("numpinalloc")
|
|
|
|
// Allocator implements ipfscluster.Allocate.
|
|
type Allocator struct{}
|
|
|
|
// NewAllocator returns an initialized Allocator
|
|
func NewAllocator() *Allocator {
|
|
return &Allocator{}
|
|
}
|
|
|
|
// SetClient does nothing in this allocator
|
|
func (alloc *Allocator) SetClient(c *rpc.Client) {}
|
|
|
|
// Shutdown does nothing in this allocator
|
|
func (alloc *Allocator) Shutdown() error { return nil }
|
|
|
|
// Allocate returns where to allocate a pin request based on "numpin"-Informer
|
|
// metrics. In this simple case, we do not pay attention to the metrics
|
|
// of the current, we just need to sort the candidates by number of pins.
|
|
func (alloc *Allocator) Allocate(c *cid.Cid, current, candidates map[peer.ID]api.Metric) ([]peer.ID, error) {
|
|
// sort our metrics
|
|
numpins := newMetricsSorter(candidates)
|
|
sort.Sort(numpins)
|
|
return numpins.peers, nil
|
|
}
|
|
|
|
// metricsSorter attaches sort.Interface methods to our metrics and sorts
|
|
// a slice of peers in the way that interest us
|
|
type metricsSorter struct {
|
|
peers []peer.ID
|
|
m map[peer.ID]int
|
|
}
|
|
|
|
func newMetricsSorter(m map[peer.ID]api.Metric) *metricsSorter {
|
|
vMap := make(map[peer.ID]int)
|
|
peers := make([]peer.ID, 0, len(m))
|
|
for k, v := range m {
|
|
if v.Name != numpin.MetricName || v.Discard() {
|
|
continue
|
|
}
|
|
val, err := strconv.Atoi(v.Value)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
peers = append(peers, k)
|
|
vMap[k] = val
|
|
}
|
|
|
|
sorter := &metricsSorter{
|
|
m: vMap,
|
|
peers: peers,
|
|
}
|
|
return sorter
|
|
}
|
|
|
|
// Len returns the number of metrics
|
|
func (s metricsSorter) Len() int {
|
|
return len(s.peers)
|
|
}
|
|
|
|
// Less reports if the element in position i is less than the element in j
|
|
func (s metricsSorter) Less(i, j int) bool {
|
|
peeri := s.peers[i]
|
|
peerj := s.peers[j]
|
|
|
|
x := s.m[peeri]
|
|
y := s.m[peerj]
|
|
|
|
return x < y
|
|
}
|
|
|
|
// Swap swaps the elements in positions i and j
|
|
func (s metricsSorter) Swap(i, j int) {
|
|
temp := s.peers[i]
|
|
s.peers[i] = s.peers[j]
|
|
s.peers[j] = temp
|
|
}
|