forked from External/ergo
bump buntdb to v1.2.3
Potentially fixes the database corruption seen on #1603
This commit is contained in:
parent
b022c34a23
commit
fd3cbab6ee
36 changed files with 912 additions and 324 deletions
278
vendor/github.com/tidwall/rtred/rtree.go
generated
vendored
Normal file
278
vendor/github.com/tidwall/rtred/rtree.go
generated
vendored
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
package rtred
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"github.com/tidwall/rtred/base"
|
||||
)
|
||||
|
||||
type Iterator func(item Item) bool
|
||||
type Item interface {
|
||||
Rect(ctx interface{}) (min []float64, max []float64)
|
||||
}
|
||||
|
||||
type RTree struct {
|
||||
dims int
|
||||
maxEntries int
|
||||
ctx interface{}
|
||||
trs []*base.RTree
|
||||
used int
|
||||
}
|
||||
|
||||
func New(ctx interface{}) *RTree {
|
||||
tr := &RTree{
|
||||
ctx: ctx,
|
||||
dims: 20,
|
||||
maxEntries: 13,
|
||||
}
|
||||
tr.trs = make([]*base.RTree, 20)
|
||||
return tr
|
||||
}
|
||||
|
||||
func (tr *RTree) Insert(item Item) {
|
||||
if item == nil {
|
||||
panic("nil item")
|
||||
}
|
||||
min, max := item.Rect(tr.ctx)
|
||||
if len(min) != len(max) {
|
||||
return // just return
|
||||
panic("invalid item rectangle")
|
||||
}
|
||||
if len(min) < 1 || len(min) > len(tr.trs) {
|
||||
return // just return
|
||||
panic("invalid dimension")
|
||||
}
|
||||
btr := tr.trs[len(min)-1]
|
||||
if btr == nil {
|
||||
btr = base.New(len(min), tr.maxEntries)
|
||||
tr.trs[len(min)-1] = btr
|
||||
tr.used++
|
||||
}
|
||||
amin := make([]float64, len(min))
|
||||
amax := make([]float64, len(max))
|
||||
for i := 0; i < len(min); i++ {
|
||||
amin[i], amax[i] = min[i], max[i]
|
||||
}
|
||||
btr.Insert(amin, amax, item)
|
||||
}
|
||||
|
||||
func (tr *RTree) Remove(item Item) {
|
||||
if item == nil {
|
||||
panic("nil item")
|
||||
}
|
||||
min, max := item.Rect(tr.ctx)
|
||||
if len(min) != len(max) {
|
||||
return // just return
|
||||
panic("invalid item rectangle")
|
||||
}
|
||||
if len(min) < 1 || len(min) > len(tr.trs) {
|
||||
return // just return
|
||||
panic("invalid dimension")
|
||||
}
|
||||
btr := tr.trs[len(min)-1]
|
||||
if btr == nil {
|
||||
return
|
||||
}
|
||||
amin := make([]float64, len(min))
|
||||
amax := make([]float64, len(max))
|
||||
for i := 0; i < len(min); i++ {
|
||||
amin[i], amax[i] = min[i], max[i]
|
||||
}
|
||||
btr.Remove(amin, amax, item)
|
||||
if btr.IsEmpty() {
|
||||
tr.trs[len(min)-1] = nil
|
||||
tr.used--
|
||||
}
|
||||
}
|
||||
func (tr *RTree) Reset() {
|
||||
for i := 0; i < len(tr.trs); i++ {
|
||||
tr.trs[i] = nil
|
||||
}
|
||||
tr.used = 0
|
||||
}
|
||||
func (tr *RTree) Count() int {
|
||||
var count int
|
||||
for _, btr := range tr.trs {
|
||||
if btr != nil {
|
||||
count += btr.Count()
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (tr *RTree) Search(bounds Item, iter Iterator) {
|
||||
if bounds == nil {
|
||||
panic("nil bounds being used for search")
|
||||
}
|
||||
min, max := bounds.Rect(tr.ctx)
|
||||
if len(min) != len(max) {
|
||||
return // just return
|
||||
panic("invalid item rectangle")
|
||||
}
|
||||
if len(min) < 1 || len(min) > len(tr.trs) {
|
||||
return // just return
|
||||
panic("invalid dimension")
|
||||
}
|
||||
used := tr.used
|
||||
for i, btr := range tr.trs {
|
||||
if used == 0 {
|
||||
break
|
||||
}
|
||||
if btr != nil {
|
||||
if !search(btr, min, max, i+1, iter) {
|
||||
return
|
||||
}
|
||||
used--
|
||||
}
|
||||
}
|
||||
}
|
||||
func search(btr *base.RTree, min, max []float64, dims int, iter Iterator) bool {
|
||||
amin := make([]float64, dims)
|
||||
amax := make([]float64, dims)
|
||||
for i := 0; i < dims; i++ {
|
||||
if i < len(min) {
|
||||
amin[i] = min[i]
|
||||
amax[i] = max[i]
|
||||
} else {
|
||||
amin[i] = math.Inf(-1)
|
||||
amax[i] = math.Inf(+1)
|
||||
}
|
||||
}
|
||||
var ended bool
|
||||
btr.Search(amin, amax, func(item interface{}) bool {
|
||||
if !iter(item.(Item)) {
|
||||
ended = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return !ended
|
||||
}
|
||||
|
||||
func (tr *RTree) KNN(bounds Item, center bool, iter func(item Item, dist float64) bool) {
|
||||
if bounds == nil {
|
||||
panic("nil bounds being used for search")
|
||||
}
|
||||
min, max := bounds.Rect(tr.ctx)
|
||||
if len(min) != len(max) {
|
||||
return // just return
|
||||
panic("invalid item rectangle")
|
||||
}
|
||||
if len(min) < 1 || len(min) > len(tr.trs) {
|
||||
return // just return
|
||||
panic("invalid dimension")
|
||||
}
|
||||
|
||||
if tr.used == 0 {
|
||||
return
|
||||
}
|
||||
if tr.used == 1 {
|
||||
for i, btr := range tr.trs {
|
||||
if btr != nil {
|
||||
knn(btr, min, max, center, i+1, func(item interface{}, dist float64) bool {
|
||||
return iter(item.(Item), dist)
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type queueT struct {
|
||||
done bool
|
||||
step int
|
||||
item Item
|
||||
dist float64
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
var ended bool
|
||||
queues := make(map[int][]queueT)
|
||||
cond := sync.NewCond(&mu)
|
||||
for i, btr := range tr.trs {
|
||||
if btr != nil {
|
||||
dims := i + 1
|
||||
mu.Lock()
|
||||
queues[dims] = []queueT{}
|
||||
cond.Signal()
|
||||
mu.Unlock()
|
||||
go func(dims int, btr *base.RTree) {
|
||||
knn(btr, min, max, center, dims, func(item interface{}, dist float64) bool {
|
||||
mu.Lock()
|
||||
if ended {
|
||||
mu.Unlock()
|
||||
return false
|
||||
}
|
||||
queues[dims] = append(queues[dims], queueT{item: item.(Item), dist: dist})
|
||||
cond.Signal()
|
||||
mu.Unlock()
|
||||
return true
|
||||
})
|
||||
mu.Lock()
|
||||
queues[dims] = append(queues[dims], queueT{done: true})
|
||||
cond.Signal()
|
||||
mu.Unlock()
|
||||
}(dims, btr)
|
||||
}
|
||||
}
|
||||
mu.Lock()
|
||||
for {
|
||||
ready := true
|
||||
for i := range queues {
|
||||
if len(queues[i]) == 0 {
|
||||
ready = false
|
||||
break
|
||||
}
|
||||
if queues[i][0].done {
|
||||
delete(queues, i)
|
||||
}
|
||||
}
|
||||
if len(queues) == 0 {
|
||||
break
|
||||
}
|
||||
if ready {
|
||||
var j int
|
||||
var minDist float64
|
||||
var minItem Item
|
||||
var minQueue int
|
||||
for i := range queues {
|
||||
if j == 0 || queues[i][0].dist < minDist {
|
||||
minDist = queues[i][0].dist
|
||||
minItem = queues[i][0].item
|
||||
minQueue = i
|
||||
}
|
||||
}
|
||||
queues[minQueue] = queues[minQueue][1:]
|
||||
if !iter(minItem, minDist) {
|
||||
ended = true
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
cond.Wait()
|
||||
}
|
||||
mu.Unlock()
|
||||
}
|
||||
func knn(btr *base.RTree, min, max []float64, center bool, dims int, iter func(item interface{}, dist float64) bool) bool {
|
||||
amin := make([]float64, dims)
|
||||
amax := make([]float64, dims)
|
||||
for i := 0; i < dims; i++ {
|
||||
if i < len(min) {
|
||||
amin[i] = min[i]
|
||||
amax[i] = max[i]
|
||||
} else {
|
||||
amin[i] = math.Inf(-1)
|
||||
amax[i] = math.Inf(+1)
|
||||
}
|
||||
}
|
||||
var ended bool
|
||||
btr.KNN(amin, amax, center, func(item interface{}, dist float64) bool {
|
||||
if !iter(item.(Item), dist) {
|
||||
ended = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return !ended
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue