Skip to content

Commit fa486f9

Browse files
Merge pull request #108 from Workiva/rt_get
Add get methods.
2 parents a430e78 + e57e14c commit fa486f9

File tree

6 files changed

+114
-0
lines changed

6 files changed

+114
-0
lines changed

mock/rangetree.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,12 @@ func (m *RangeTree) InsertAtDimension(dimension uint64, index,
5050
func (m *RangeTree) Apply(interval rangetree.Interval, fn func(rangetree.Entry) bool) {
5151
m.Called(interval, fn)
5252
}
53+
54+
func (m *RangeTree) Get(entries ...rangetree.Entry) rangetree.Entries {
55+
ifc := m.Called(entries).Get(0)
56+
if ifc == nil {
57+
return nil
58+
}
59+
60+
return ifc.(rangetree.Entries)
61+
}

rangetree/immutable.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,35 @@ func (irt *immutableRangeTree) Query(interval Interval) Entries {
234234
return entries
235235
}
236236

237+
func (irt *immutableRangeTree) get(entry Entry) Entry {
238+
on := irt.top
239+
for i := uint64(1); i <= irt.dimensions; i++ {
240+
n, _ := on.get(entry.ValueAtDimension(i))
241+
if n == nil {
242+
return nil
243+
}
244+
if i == irt.dimensions {
245+
return n.entry
246+
}
247+
on = n.orderedNodes
248+
}
249+
250+
return nil
251+
}
252+
253+
// Get returns any entries that exist at the addresses provided by the
254+
// given entries. Entries are returned in the order in which they are
255+
// received. If an entry cannot be found, a nil is returned in its
256+
// place.
257+
func (irt *immutableRangeTree) Get(entries ...Entry) Entries {
258+
result := make(Entries, 0, len(entries))
259+
for _, entry := range entries {
260+
result = append(result, irt.get(entry))
261+
}
262+
263+
return result
264+
}
265+
237266
// Len returns the number of items in this tree.
238267
func (irt *immutableRangeTree) Len() uint64 {
239268
return irt.number

rangetree/immutable_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,16 @@ func TestImmutableInsertInvalidNumber(t *testing.T) {
514514
assert.Equal(t, tree, tree1)
515515
}
516516

517+
func TestImmutableGet(t *testing.T) {
518+
tree, entries := constructMultiDimensionalImmutableTree(2)
519+
520+
result := tree.Get(entries...)
521+
assert.Equal(t, entries, result)
522+
523+
result = tree.Get(constructMockEntry(10000, 5000, 5000))
524+
assert.Equal(t, Entries{nil}, result)
525+
}
526+
517527
func BenchmarkImmutableInsertFirstDimension(b *testing.B) {
518528
numItems := int64(100000)
519529

rangetree/interface.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ type RangeTree interface {
6767
// cancel iteration. Altering the entry in such a way that its location
6868
// changes will result in undefined behavior.
6969
Apply(interval Interval, fn func(Entry) bool)
70+
// Get returns any entries that exist at the addresses provided by the
71+
// given entries. Entries are returned in the order in which they are
72+
// received. If an entry cannot be found, a nil is returned in its
73+
// place.
74+
Get(entries ...Entry) Entries
7075
// InsertAtDimension will increment items at and above the given index
7176
// by the number provided. Provide a negative number to to decrement.
7277
// Returned are two lists. The first list is a list of entries that

rangetree/orderedtree.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,35 @@ func (ot *orderedTree) delete(entry Entry) *node {
120120
return node
121121
}
122122

123+
func (ot *orderedTree) get(entry Entry) Entry {
124+
on := ot.top
125+
for i := uint64(1); i <= ot.dimensions; i++ {
126+
n, _ := on.get(entry.ValueAtDimension(i))
127+
if n == nil {
128+
return nil
129+
}
130+
if i == ot.dimensions {
131+
return n.entry
132+
}
133+
on = n.orderedNodes
134+
}
135+
136+
return nil
137+
}
138+
139+
// Get returns any entries that exist at the addresses provided by the
140+
// given entries. Entries are returned in the order in which they are
141+
// received. If an entry cannot be found, a nil is returned in its
142+
// place.
143+
func (ot *orderedTree) Get(entries ...Entry) Entries {
144+
result := make(Entries, 0, len(entries))
145+
for _, entry := range entries {
146+
result = append(result, ot.get(entry))
147+
}
148+
149+
return result
150+
}
151+
123152
// Delete will remove the provided entries from the tree.
124153
// Any entries that were deleted will be returned in the order in
125154
// which they were deleted. If an entry does not exist to be deleted,

rangetree/orderedtree_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,16 @@ func TestOverwrites(t *testing.T) {
346346
assert.Equal(t, Entries{entry}, overwritten)
347347
}
348348

349+
func TestGet(t *testing.T) {
350+
tree, entries := constructMultiDimensionalOrderedTree(2)
351+
352+
result := tree.Get(entries...)
353+
assert.Equal(t, entries, result)
354+
355+
result = tree.Get(constructMockEntry(10000, 5000, 5000))
356+
assert.Equal(t, Entries{nil}, result)
357+
}
358+
349359
func TestTreeApply(t *testing.T) {
350360
tree, entries := constructMultiDimensionalOrderedTree(2)
351361

@@ -610,3 +620,25 @@ func BenchmarkDeleteSecondDimension(b *testing.B) {
610620
tree.InsertAtDimension(2, 0, -1)
611621
}
612622
}
623+
624+
func BenchmarkGetMultiDimensions(b *testing.B) {
625+
numItemsX := 10000
626+
numItemsY := 100
627+
628+
tree := newOrderedTree(2)
629+
entries := make(Entries, 0, numItemsY*numItemsX)
630+
631+
for i := 0; i < numItemsX; i++ {
632+
for j := 0; j < numItemsY; j++ {
633+
e := constructMockEntry(uint64(j*numItemsY+i), int64(i), int64(j))
634+
entries = append(entries, e)
635+
}
636+
}
637+
638+
tree.Add(entries...)
639+
b.ResetTimer()
640+
641+
for i := 0; i < b.N; i++ {
642+
tree.Get(entries[i%len(entries)])
643+
}
644+
}

0 commit comments

Comments
 (0)