Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #142 from ipfs/feat/free-space-allocation-metric
`FreeSpace` allocation metric impl
- Loading branch information
Showing
15 changed files
with
411 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Package descendalloc implements an ipfscluster.util.Allocator returns | ||
// allocations based on sorting the metrics in descending order. Thus, peers | ||
// with largest metrics are first in the list. This allocator can be used with a | ||
// number of informers, as long as they provide a numeric metric value. | ||
package descendalloc | ||
|
||
import ( | ||
"github.com/ipfs/ipfs-cluster/allocator/util" | ||
"github.com/ipfs/ipfs-cluster/api" | ||
|
||
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("descendalloc") | ||
|
||
// DescendAllocator extends the SimpleAllocator | ||
type DescendAllocator struct{} | ||
|
||
// NewDescendAllocator returns an initialized DescendAllocator | ||
func NewAllocator() DescendAllocator { | ||
return DescendAllocator{} | ||
} | ||
|
||
// SetClient does nothing in this allocator | ||
func (alloc DescendAllocator) SetClient(c *rpc.Client) {} | ||
|
||
// Shutdown does nothing in this allocator | ||
func (alloc DescendAllocator) Shutdown() error { return nil } | ||
|
||
// Allocate returns where to allocate a pin request based on metrics which | ||
// carry a numeric value such as "used disk". We do not pay attention to | ||
// the metrics of the currently allocated peers and we just sort the | ||
// candidates based on their metric values (largest to smallest). | ||
func (alloc DescendAllocator) Allocate(c *cid.Cid, current, candidates map[peer.ID]api.Metric) ([]peer.ID, error) { | ||
// sort our metrics | ||
return util.SortNumeric(candidates, true), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package descendalloc | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/ipfs/ipfs-cluster/api" | ||
|
||
cid "github.com/ipfs/go-cid" | ||
peer "github.com/libp2p/go-libp2p-peer" | ||
) | ||
|
||
type testcase struct { | ||
candidates map[peer.ID]api.Metric | ||
current map[peer.ID]api.Metric | ||
expected []peer.ID | ||
} | ||
|
||
var ( | ||
peer0 = peer.ID("QmUQ6Nsejt1SuZAu8yL8WgqQZHHAYreLVYYa4VPsLUCed7") | ||
peer1 = peer.ID("QmUZ13osndQ5uL4tPWHXe3iBgBgq9gfewcBMSCAuMBsDJ6") | ||
peer2 = peer.ID("QmPrSBATWGAN56fiiEWEhKX3L1F3mTghEQR7vQwaeo7zHi") | ||
peer3 = peer.ID("QmPGDFvBkgWhvzEK9qaTWrWurSwqXNmhnK3hgELPdZZNPa") | ||
testCid, _ = cid.Decode("QmP63DkAFEnDYNjDYBpyNDfttu1fvUw99x1brscPzpqmmq") | ||
) | ||
|
||
var inAMinute = time.Now().Add(time.Minute).Format(time.RFC3339Nano) | ||
|
||
var testCases = []testcase{ | ||
{ // regular sort | ||
candidates: map[peer.ID]api.Metric{ | ||
peer0: api.Metric{ | ||
Name: "some-metric", | ||
Value: "5", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
peer1: api.Metric{ | ||
Name: "some-metric", | ||
Value: "1", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
peer2: api.Metric{ | ||
Name: "some-metric", | ||
Value: "3", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
peer3: api.Metric{ | ||
Name: "some-metric", | ||
Value: "2", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
}, | ||
current: map[peer.ID]api.Metric{}, | ||
expected: []peer.ID{peer1, peer3, peer2, peer0}, | ||
}, | ||
{ // filter invalid | ||
candidates: map[peer.ID]api.Metric{ | ||
peer0: api.Metric{ | ||
Name: "some-metric", | ||
Value: "1", | ||
Expire: inAMinute, | ||
Valid: false, | ||
}, | ||
peer1: api.Metric{ | ||
Name: "some-metric", | ||
Value: "5", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
}, | ||
current: map[peer.ID]api.Metric{}, | ||
expected: []peer.ID{peer1}, | ||
}, | ||
{ // filter bad value | ||
candidates: map[peer.ID]api.Metric{ | ||
peer0: api.Metric{ | ||
Name: "some-metric", | ||
Value: "abc", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
peer1: api.Metric{ | ||
Name: "some-metric", | ||
Value: "5", | ||
Expire: inAMinute, | ||
Valid: true, | ||
}, | ||
}, | ||
current: map[peer.ID]api.Metric{}, | ||
expected: []peer.ID{peer1}, | ||
}, | ||
} | ||
|
||
func Test(t *testing.T) { | ||
alloc := &DescendAllocator{} | ||
for i, tc := range testCases { | ||
t.Logf("Test case %d", i) | ||
res, err := alloc.Allocate(testCid, tc.current, tc.candidates) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if len(res) == 0 { | ||
t.Fatal("0 allocations") | ||
} | ||
for i, r := range res { | ||
if e := tc.expected[len(res)-i-1]; r != e { | ||
t.Errorf("Expect r[%d]=%s but got %s", i, r, e) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.