etcd: Rewrite embed etcd implementation
This is a giant cleanup of the etcd code. The earlier version was written when I was less experienced with golang. This is still not perfect, and does contain some races, but at least it's a decent base to start from. The automatic elastic clustering should be considered an experimental feature. If you need a more battle-tested cluster, then you should manage etcd manually and point mgmt at your existing cluster.
This commit is contained in:
@@ -86,7 +86,7 @@ func TestEasyAckOnce2(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleSubscribeSync() {
|
||||
func ExampleSubscribedSignal() {
|
||||
fmt.Println("hello")
|
||||
|
||||
x := &SubscribedSignal{}
|
||||
|
||||
35
util/util.go
35
util/util.go
@@ -430,6 +430,21 @@ func TimeAfterOrBlockCtx(ctx context.Context, t int) <-chan struct{} {
|
||||
return ch
|
||||
}
|
||||
|
||||
// CloseAfter takes a duration, similarly to `time.After`, and returns a channel
|
||||
// that closes when either the context is done, or the duration expires.
|
||||
func CloseAfter(ctx context.Context, d time.Duration) <-chan struct{} {
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
defer close(ch)
|
||||
select {
|
||||
case <-time.After(d):
|
||||
// done
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// SystemBusPrivateUsable makes using the private bus usable.
|
||||
// TODO: should be upstream: https://github.com/godbus/dbus/issues/15
|
||||
func SystemBusPrivateUsable() (conn *dbus.Conn, err error) {
|
||||
@@ -468,6 +483,26 @@ func SessionBusPrivateUsable() (conn *dbus.Conn, err error) {
|
||||
return conn, nil // success
|
||||
}
|
||||
|
||||
// PriorityStrSliceSort filters any elements matching fn to the end of the list.
|
||||
// You can reverse the match result with a not to filter to the front instead!
|
||||
// A copy of the list is returned, the original is not modified.
|
||||
func PriorityStrSliceSort(input []string, fn func(string) bool) []string {
|
||||
output := []string{}
|
||||
found := []string{}
|
||||
for _, x := range input {
|
||||
if fn(x) { // if we find the key, don't include it just yet
|
||||
found = append(found, x) // save for later
|
||||
continue
|
||||
}
|
||||
output = append(output, x)
|
||||
}
|
||||
|
||||
// include the keys at the end (if found)
|
||||
output = append(output, found...)
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
// SortedStrSliceCompare takes two lists of strings and returns whether or not
|
||||
// they are equivalent. It will return nil if both sets contain the same
|
||||
// elements, regardless of order, and an error if they do not.
|
||||
|
||||
@@ -22,6 +22,7 @@ package util
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -1014,6 +1015,76 @@ func TestRemovePathPrefix0(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityStrSliceSort0(t *testing.T) {
|
||||
in := []string{"foo", "bar", "baz"}
|
||||
ex := []string{"bar", "baz", "foo"}
|
||||
|
||||
fn := func(x string) bool {
|
||||
return x == "foo"
|
||||
}
|
||||
out := PriorityStrSliceSort(in, fn)
|
||||
|
||||
if !reflect.DeepEqual(ex, out) {
|
||||
t.Errorf("PriorityStrSliceSort expected: %v; got: %v.", ex, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityStrSliceSort1(t *testing.T) {
|
||||
in := []string{"foo", "bar", "baz"}
|
||||
ex := []string{"bar", "foo", "baz"}
|
||||
|
||||
fn := func(x string) bool {
|
||||
return x != "bar" // != brings this key to the front
|
||||
}
|
||||
out := PriorityStrSliceSort(in, fn)
|
||||
|
||||
if !reflect.DeepEqual(ex, out) {
|
||||
t.Errorf("PriorityStrSliceSort expected: %v; got: %v.", ex, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityStrSliceSort2(t *testing.T) {
|
||||
in := []string{"bar", "foo", "bar", "bar", "baz"}
|
||||
ex := []string{"foo", "baz", "bar", "bar", "bar"}
|
||||
|
||||
fn := func(x string) bool {
|
||||
return x == "bar"
|
||||
}
|
||||
out := PriorityStrSliceSort(in, fn)
|
||||
|
||||
if !reflect.DeepEqual(ex, out) {
|
||||
t.Errorf("PriorityStrSliceSort expected: %v; got: %v.", ex, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityStrSliceSort3(t *testing.T) {
|
||||
in := []string{"foo", "bar1", "bar2", "bar3", "baz"}
|
||||
ex := []string{"bar1", "bar2", "bar3", "foo", "baz"}
|
||||
|
||||
fn := func(x string) bool {
|
||||
return !strings.HasPrefix(x, "bar")
|
||||
}
|
||||
out := PriorityStrSliceSort(in, fn)
|
||||
|
||||
if !reflect.DeepEqual(ex, out) {
|
||||
t.Errorf("PriorityStrSliceSort expected: %v; got: %v.", ex, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityStrSliceSort4(t *testing.T) {
|
||||
in := []string{"foo", "bar1", "bar2", "bar3", "baz"}
|
||||
ex := []string{"foo", "baz", "bar1", "bar2", "bar3"}
|
||||
|
||||
fn := func(x string) bool {
|
||||
return strings.HasPrefix(x, "bar")
|
||||
}
|
||||
out := PriorityStrSliceSort(in, fn)
|
||||
|
||||
if !reflect.DeepEqual(ex, out) {
|
||||
t.Errorf("PriorityStrSliceSort expected: %v; got: %v.", ex, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortedStrSliceCompare0(t *testing.T) {
|
||||
slice0 := []string{"foo", "bar", "baz"}
|
||||
slice1 := []string{"bar", "foo", "baz"}
|
||||
|
||||
Reference in New Issue
Block a user