diff --git a/nameserver/entry.go b/nameserver/entry.go index 312bcd4e..a3310423 100644 --- a/nameserver/entry.go +++ b/nameserver/entry.go @@ -18,7 +18,8 @@ type Entry struct { ContainerID string Origin router.PeerName Addr address.Address - Hostname string + Hostname string // as supplied + lHostname string // lowercased (not exported, so not encoded by gob) Version int Tombstone int64 // timestamp of when it was deleted } @@ -69,7 +70,7 @@ func (e1 *Entry) less(e2 *Entry) bool { func (e1 *Entry) insensitiveLess(e2 *Entry) bool { // Entries are kept sorted by Hostname, Origin, ContainerID then address - e1Hostname, e2Hostname := strings.ToLower(e1.Hostname), strings.ToLower(e2.Hostname) + e1Hostname, e2Hostname := e1.lHostname, e2.lHostname switch { case e1Hostname != e2Hostname: return e1Hostname < e2Hostname @@ -100,6 +101,10 @@ func (e1 *Entry) String() string { return fmt.Sprintf("%s -> %s", e1.Hostname, e1.Addr.String()) } +func (e1 *Entry) addLowercase() { + e1.lHostname = strings.ToLower(e1.Hostname) +} + func check(es SortableEntries) error { if !sort.IsSorted(es) { return fmt.Errorf("Not sorted!") @@ -126,7 +131,8 @@ func (es *Entries) checkAndPanic() *Entries { func (es *Entries) add(hostname, containerid string, origin router.PeerName, addr address.Address) Entry { defer es.checkAndPanic().checkAndPanic() - entry := Entry{Hostname: hostname, Origin: origin, ContainerID: containerid, Addr: addr} + entry := Entry{Hostname: hostname, lHostname: strings.ToLower(hostname), + Origin: origin, ContainerID: containerid, Addr: addr} i := sort.Search(len(*es), func(i int) bool { return !(*es)[i].insensitiveLess(&entry) }) @@ -204,14 +210,14 @@ func (es Entries) lookup(hostname string) Entries { lowerHostname := strings.ToLower(hostname) i := sort.Search(len(es), func(i int) bool { - return strings.ToLower(es[i].Hostname) >= lowerHostname + return es[i].lHostname >= lowerHostname }) - if i >= len(es) || strings.ToLower(es[i].Hostname) != lowerHostname { + if i >= len(es) || es[i].lHostname != lowerHostname { return Entries{} } j := sort.Search(len(es)-i, func(j int) bool { - return strings.ToLower(es[i+j].Hostname) > lowerHostname + return es[i+j].lHostname > lowerHostname }) return es[i : i+j] @@ -228,6 +234,12 @@ func (es Entries) first(f func(*Entry) bool) (*Entry, error) { return nil, fmt.Errorf("Not found") } +func (es Entries) addLowercase() { + for i := range es { + es[i].addLowercase() + } +} + type GossipData struct { Timestamp int64 Entries @@ -246,6 +258,7 @@ func (g *GossipData) Decode(msg []byte) error { return err } + g.Entries.addLowercase() // lowercase strings not sent on the wire sort.Sort(CaseInsensitive(g.Entries)) return nil } diff --git a/nameserver/entry_test.go b/nameserver/entry_test.go index e0640c1f..1e350e64 100644 --- a/nameserver/entry_test.go +++ b/nameserver/entry_test.go @@ -9,12 +9,17 @@ import ( "github.com/weaveworks/weave/router" ) +func l(es Entries) Entries { + es.addLowercase() + return es +} + func makeEntries(values string) Entries { entries := make(Entries, len(values)) for i, c := range values { entries[i] = Entry{Hostname: string(c)} } - return entries + return l(entries) } func TestAdd(t *testing.T) { @@ -24,21 +29,21 @@ func TestAdd(t *testing.T) { entries := Entries{} entries.add("A", "", router.UnknownPeerName, address.Address(0)) - expected := Entries{ + expected := l(Entries{ Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0)}, - } + }) require.Equal(t, entries, expected) entries.tombstone(router.UnknownPeerName, func(e *Entry) bool { return e.Hostname == "A" }) - expected = Entries{ + expected = l(Entries{ Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 1, Tombstone: 1234}, - } + }) require.Equal(t, entries, expected) entries.add("A", "", router.UnknownPeerName, address.Address(0)) - expected = Entries{ + expected = l(Entries{ Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 2}, - } + }) require.Equal(t, entries, expected) } @@ -56,14 +61,14 @@ func TestMerge(t *testing.T) { } func TestOldMerge(t *testing.T) { - e1 := Entries{Entry{Hostname: "A", Version: 0}} - diff := e1.merge(Entries{Entry{Hostname: "A", Version: 1}}) - require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, diff) - require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, e1) + e1 := l(Entries{Entry{Hostname: "A", Version: 0}}) + diff := e1.merge(l(Entries{Entry{Hostname: "A", Version: 1}})) + require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), diff) + require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), e1) - diff = e1.merge(Entries{Entry{Hostname: "A", Version: 0}}) + diff = e1.merge(l(Entries{Entry{Hostname: "A", Version: 0}})) require.Equal(t, Entries{}, diff) - require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, e1) + require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), e1) } func TestTombstone(t *testing.T) { @@ -76,10 +81,10 @@ func TestTombstone(t *testing.T) { es.tombstone(router.UnknownPeerName, func(e *Entry) bool { return e.Hostname == "B" }) - expected := Entries{ + expected := l(Entries{ Entry{Hostname: "A"}, Entry{Hostname: "B", Version: 1, Tombstone: 1234}, - } + }) require.Equal(t, expected, es) } @@ -93,18 +98,18 @@ func TestDelete(t *testing.T) { } func TestLookup(t *testing.T) { - es := Entries{ + es := l(Entries{ Entry{Hostname: "A"}, Entry{Hostname: "B", ContainerID: "bar"}, Entry{Hostname: "B", ContainerID: "foo"}, Entry{Hostname: "C"}, - } + }) have := es.lookup("B") - want := Entries{ + want := l(Entries{ Entry{Hostname: "B", ContainerID: "bar"}, Entry{Hostname: "B", ContainerID: "foo"}, - } + }) require.Equal(t, have, want) } diff --git a/nameserver/nameserver_test.go b/nameserver/nameserver_test.go index 5b518ad8..77b39b84 100644 --- a/nameserver/nameserver_test.go +++ b/nameserver/nameserver_test.go @@ -260,14 +260,14 @@ func TestTombstoneDeletion(t *testing.T) { err = nameserver.Delete("hostname", "containerid", "", address.Address(0)) require.Nil(t, err) require.Equal(t, []address.Address{}, nameserver.Lookup("hostname")) - require.Equal(t, Entries{{ + require.Equal(t, l(Entries{Entry{ ContainerID: "containerid", Origin: peername, Addr: address.Address(0), Hostname: "hostname", Version: 1, Tombstone: 1234, - }}, nameserver.entries) + }}), nameserver.entries) now = func() int64 { return 1234 + int64(tombstoneTimeout/time.Second) + 1 } nameserver.deleteTombstones()