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:
James Shubin
2018-05-05 17:35:08 -04:00
parent fb275d9537
commit a5842a41b2
56 changed files with 5459 additions and 2654 deletions

View File

@@ -86,7 +86,7 @@ func TestEasyAckOnce2(t *testing.T) {
}
}
func ExampleSubscribeSync() {
func ExampleSubscribedSignal() {
fmt.Println("hello")
x := &SubscribedSignal{}

View File

@@ -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.

View File

@@ -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"}