Skip to content

Commit

Permalink
bugfix: slimtrie: getStep should use int32 id instead of uint16 id. fix
Browse files Browse the repository at this point in the history
#104; thanks to @aaaton
  • Loading branch information
drmingdrmer committed May 28, 2019
1 parent 4430458 commit 4d4ced5
Show file tree
Hide file tree
Showing 3 changed files with 50,037 additions and 5 deletions.
10 changes: 5 additions & 5 deletions trie/slimtrie.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func (st *SlimTrie) searchID(key string) (lID, eqID, rID int32) {
break
}

i += int(st.getStep(uint16(eqID)))
i += int(st.getStep(eqID))

if lenWords < i {
rID = eqID
Expand Down Expand Up @@ -382,7 +382,7 @@ func (st *SlimTrie) Get(key string) (eqVal interface{}, found bool) {
break
}

idx += int(st.getStep(uint16(eqID)))
idx += int(st.getStep(eqID))
if lenWords < idx {
eqID = -1
break
Expand All @@ -397,7 +397,7 @@ func (st *SlimTrie) Get(key string) (eqVal interface{}, found bool) {
shift := 4 - (idx&1)*4
word = ((key[idx>>1] >> uint(shift)) & 0x0f)

if (bm >> word & 1) == 1 {
if ((bm >> word) & 1) == 1 {
chNum := bits.OnesCount16(bm & ((uint16(1) << word) - 1))
eqID = of + int32(chNum)
} else {
Expand All @@ -421,8 +421,8 @@ func (st *SlimTrie) getChild(idx int32) (bitmap uint16, offset int32, found bool
return 0, 0, false
}

func (st *SlimTrie) getStep(idx uint16) uint16 {
step, found := st.Steps.Get(int32(idx))
func (st *SlimTrie) getStep(idx int32) uint16 {
step, found := st.Steps.Get(idx)
if found {
return step
}
Expand Down
27 changes: 27 additions & 0 deletions trie/slimtrie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,33 @@ func TestSlimTrie_RangeGet_rangeindex_bug_2019_05_21(t *testing.T) {
}
}

func TestSlimTrie_u16step_bug_2019_05_29(t *testing.T) {

// Reported by @aaaton
// 2019 May 29
//
// When number of keys becomes greater than 50000,
// SlimTrie.Get() returns negaitve for some existent keys.
// Caused by SlimTrie.step has been using uint16 id, it should be int32.

ta := require.New(t)
keys := keys50k
n := len(keys)
values := make([]int32, n)
for i := 0; i < n; i++ {
values[i] = int32(i)
}
st, err := NewSlimTrie(encode.I32{}, keys, values)
ta.Nil(err)

for i, c := range keys {
rst, found := st.Get(c)
ta.Equal(values[i], rst, "%d-th: Get: %+v", i+1, c)
ta.Equal(true, found, "%d-th: Get: %+v", i+1, c)
}

}

func TestNewSlimTrie(t *testing.T) {

st, err := NewSlimTrie(encode.Int{}, []string{"ab", "cd"}, []int{1, 2})
Expand Down
Loading

0 comments on commit 4d4ced5

Please sign in to comment.