mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-05 08:10:50 +00:00
This commit refactors the pilosa codebase. It makes several major changes: * Removes bitmap handles * Removes dispatch/hold/transport * Removes etcd dependency * Adds consistent hash ring for slice placement * Refactors parser/lexer * Adds strong typing to PQL AST * Flattens package hierarchy
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
package pilosa_test
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"reflect"
|
|
"testing"
|
|
"testing/quick"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/umbel/pilosa"
|
|
)
|
|
|
|
// Ensure the cluster can fairly distribute partitions across the nodes.
|
|
func TestCluster_Owners(t *testing.T) {
|
|
c := pilosa.Cluster{
|
|
Nodes: []*pilosa.Node{
|
|
{Host: "serverA:1000"},
|
|
{Host: "serverB:1000"},
|
|
{Host: "serverC:1000"},
|
|
},
|
|
Hasher: NewModHasher(),
|
|
ReplicaN: 2,
|
|
}
|
|
|
|
// Verify nodes are distributed.
|
|
if a := c.PartitionNodes(0); !reflect.DeepEqual(a, []*pilosa.Node{c.Nodes[0], c.Nodes[1]}) {
|
|
t.Fatalf("unexpected owners: %s", spew.Sdump(a))
|
|
}
|
|
|
|
// Verify nodes go around the ring.
|
|
if a := c.PartitionNodes(2); !reflect.DeepEqual(a, []*pilosa.Node{c.Nodes[2], c.Nodes[0]}) {
|
|
t.Fatalf("unexpected owners: %s", spew.Sdump(a))
|
|
}
|
|
}
|
|
|
|
// Ensure the partitioner can assign a fragment to a partition.
|
|
func TestCluster_Partition(t *testing.T) {
|
|
if err := quick.Check(func(slice uint64, partitionN int) bool {
|
|
c := pilosa.NewCluster()
|
|
c.PartitionN = partitionN
|
|
|
|
partitionID := c.Partition(slice)
|
|
if partitionID < 0 || partitionID > partitionN {
|
|
t.Errorf("partition out of range: slice=%d, p=%d, n=%d", slice, partitionID, partitionN)
|
|
}
|
|
|
|
return true
|
|
}, &quick.Config{
|
|
Values: func(values []reflect.Value, rand *rand.Rand) {
|
|
values[0] = reflect.ValueOf(uint64(rand.Uint32()))
|
|
values[1] = reflect.ValueOf(rand.Intn(1000) + 1)
|
|
},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// NewCluster returns a cluster with n nodes and uses a mod-based hasher.
|
|
func NewCluster(n int) *pilosa.Cluster {
|
|
c := pilosa.NewCluster()
|
|
c.ReplicaN = 1
|
|
c.Hasher = NewModHasher()
|
|
|
|
for i := 0; i < n; i++ {
|
|
c.Nodes = append(c.Nodes, &pilosa.Node{
|
|
Host: fmt.Sprintf("host%d", i),
|
|
})
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
// ModHasher represents a simple, mod-based hashing.
|
|
type ModHasher struct{}
|
|
|
|
// NewModHasher returns a new instance of ModHasher with n buckets.
|
|
func NewModHasher() *ModHasher { return &ModHasher{} }
|
|
|
|
func (*ModHasher) Hash(key uint64, n int) int { return int(key) % n }
|
|
|
|
// ConstHasher represents hash that always returns the same index.
|
|
type ConstHasher struct {
|
|
i int
|
|
}
|
|
|
|
// NewConstHasher returns a new instance of ConstHasher that always returns i.
|
|
func NewConstHasher(i int) *ConstHasher { return &ConstHasher{i: i} }
|
|
|
|
func (h *ConstHasher) Hash(key uint64, n int) int { return h.i }
|