Skip to content

Commit

Permalink
Hold on to the lower-case version of a hostname, rather than re-compu…
Browse files Browse the repository at this point in the history
…ting it every time
  • Loading branch information
bboreham committed Nov 2, 2015
1 parent 963b6c5 commit 609d458
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
22 changes: 16 additions & 6 deletions nameserver/entry.go
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -126,7 +127,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)
})
Expand Down Expand Up @@ -204,14 +206,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]
Expand All @@ -228,6 +230,13 @@ func (es *Entries) first(f func(*Entry) bool) (*Entry, error) {
return nil, fmt.Errorf("Not found")
}

func (es *Entries) addLowercase() {
for i, e := range *es {
e.lHostname = strings.ToLower(e.Hostname)
(*es)[i] = e
}
}

type GossipData struct {
Timestamp int64
Entries
Expand All @@ -246,6 +255,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
}
Expand Down
37 changes: 19 additions & 18 deletions nameserver/entry_test.go
Expand Up @@ -2,6 +2,7 @@ package nameserver

import (
"testing"
"unicode"

"github.com/stretchr/testify/require"

Expand All @@ -17,27 +18,27 @@ func TestAdd(t *testing.T) {
entries := Entries{}
entries.add("A", "", router.UnknownPeerName, address.Address(0))
expected := Entries{
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0)},
Entry{Hostname: "A", lHostname: "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{
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 1, Tombstone: 1234},
Entry{Hostname: "A", lHostname: "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{
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 2},
Entry{Hostname: "A", lHostname: "a", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 2},
}
require.Equal(t, entries, expected)
}

func makeEntries(values string) Entries {
entries := make(Entries, len(values))
for i, c := range values {
entries[i] = Entry{Hostname: string(c)}
entries[i] = Entry{Hostname: string(c), lHostname: string(unicode.ToLower(c))}
}
return entries
}
Expand All @@ -56,14 +57,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 := Entries{Entry{Hostname: "A", lHostname: "a", Version: 0}}
diff := e1.merge(Entries{Entry{Hostname: "A", lHostname: "a", Version: 1}})
require.Equal(t, Entries{Entry{Hostname: "A", lHostname: "a", Version: 1}}, diff)
require.Equal(t, Entries{Entry{Hostname: "A", lHostname: "a", Version: 1}}, e1)

diff = e1.merge(Entries{Entry{Hostname: "A", Version: 0}})
diff = e1.merge(Entries{Entry{Hostname: "A", lHostname: "a", Version: 0}})
require.Equal(t, Entries{}, diff)
require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, e1)
require.Equal(t, Entries{Entry{Hostname: "A", lHostname: "a", Version: 1}}, e1)
}

func TestTombstone(t *testing.T) {
Expand All @@ -77,8 +78,8 @@ func TestTombstone(t *testing.T) {
return e.Hostname == "B"
})
expected := Entries{
Entry{Hostname: "A"},
Entry{Hostname: "B", Version: 1, Tombstone: 1234},
Entry{Hostname: "A", lHostname: "a"},
Entry{Hostname: "B", lHostname: "b", Version: 1, Tombstone: 1234},
}
require.Equal(t, expected, es)
}
Expand All @@ -94,16 +95,16 @@ func TestDelete(t *testing.T) {

func TestLookup(t *testing.T) {
es := Entries{
Entry{Hostname: "A"},
Entry{Hostname: "B", ContainerID: "bar"},
Entry{Hostname: "B", ContainerID: "foo"},
Entry{Hostname: "C"},
Entry{Hostname: "A", lHostname: "a"},
Entry{Hostname: "B", lHostname: "b", ContainerID: "bar"},
Entry{Hostname: "B", lHostname: "b", ContainerID: "foo"},
Entry{Hostname: "C", lHostname: "c"},
}

have := es.lookup("B")
want := Entries{
Entry{Hostname: "B", ContainerID: "bar"},
Entry{Hostname: "B", ContainerID: "foo"},
Entry{Hostname: "B", lHostname: "b", ContainerID: "bar"},
Entry{Hostname: "B", lHostname: "b", ContainerID: "foo"},
}
require.Equal(t, have, want)
}
Expand Down
1 change: 1 addition & 0 deletions nameserver/nameserver_test.go
Expand Up @@ -265,6 +265,7 @@ func TestTombstoneDeletion(t *testing.T) {
Origin: peername,
Addr: address.Address(0),
Hostname: "hostname",
lHostname: "hostname",
Version: 1,
Tombstone: 1234,
}}, nameserver.entries)
Expand Down

0 comments on commit 609d458

Please sign in to comment.