From 40c8b04181014e8c1aad1bf2a698ad0656a3f3fa Mon Sep 17 00:00:00 2001 From: Oliver Tonnhofer Date: Mon, 6 May 2013 13:42:58 +0200 Subject: [PATCH] keep ref ids in RefIndex sorted --- cache/diff.go | 17 +++++++++++++++-- cache/diff_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 cache/diff_test.go diff --git a/cache/diff.go b/cache/diff.go index 3437c69..3680b6a 100644 --- a/cache/diff.go +++ b/cache/diff.go @@ -3,6 +3,7 @@ package cache import ( "code.google.com/p/goprotobuf/proto" bin "encoding/binary" + "sort" "sync" ) @@ -39,8 +40,7 @@ func (index *RefIndex) Add(id, ref int64) error { refs.Ids = make([]int64, 0, 1) } // TODO change to delta encoding - // TODO check for duplicates - refs.Ids = append(refs.Ids, ref) + refs.insertId(ref) data, err = proto.Marshal(refs) if err != nil { @@ -50,6 +50,19 @@ func (index *RefIndex) Add(id, ref int64) error { return err } +func (r *Refs) insertId(ref int64) { + i := sort.Search(len(r.Ids), func(i int) bool { + return r.Ids[i] >= ref + }) + if i < len(r.Ids) && r.Ids[i] >= ref { + r.Ids = append(r.Ids, 0) + copy(r.Ids[i+1:], r.Ids[i:]) + r.Ids[i] = ref + } else { + r.Ids = append(r.Ids, ref) + } +} + func (index *RefIndex) Get(id int64) []int64 { keyBuf := make([]byte, 8) bin.PutVarint(keyBuf, id) diff --git a/cache/diff_test.go b/cache/diff_test.go new file mode 100644 index 0000000..caba52c --- /dev/null +++ b/cache/diff_test.go @@ -0,0 +1,46 @@ +package cache + +import ( + "testing" +) + +func TestInsertId(t *testing.T) { + + refs := Refs{} + refs.Ids = make([]int64, 0, 1) + + refs.insertId(1) + if refs.Ids[0] != 1 { + t.Fatal(refs) + } + + refs.insertId(10) + if refs.Ids[0] != 1 && refs.Ids[1] != 10 { + t.Fatal(refs) + } + + // insert twice + refs.insertId(10) + if refs.Ids[0] != 1 && refs.Ids[1] != 10 { + t.Fatal(refs) + } + + // insert before + refs.insertId(0) + if refs.Ids[0] != 0 && refs.Ids[1] != 1 && refs.Ids[2] != 10 { + t.Fatal(refs) + } + + // insert after + refs.insertId(12) + if refs.Ids[0] != 0 && refs.Ids[1] != 1 && refs.Ids[2] != 10 && refs.Ids[3] != 12 { + t.Fatal(refs) + } + + // insert between + refs.insertId(11) + if refs.Ids[0] != 0 && refs.Ids[1] != 1 && refs.Ids[2] != 10 && refs.Ids[3] != 11 && refs.Ids[4] != 12 { + t.Fatal(refs) + } + +}