Change btree implementation for collections

This commit is contained in:
tidwall 2018-10-18 07:12:24 -07:00
parent 3e41a2ecce
commit d64aad9be0
4 changed files with 28 additions and 41 deletions

View File

@ -16,12 +16,12 @@ import (
"sync"
"time"
"github.com/tidwall/btree"
"github.com/tidwall/buntdb"
"github.com/tidwall/geojson"
"github.com/tidwall/resp"
"github.com/tidwall/tile38/core"
"github.com/tidwall/tile38/internal/collection"
"github.com/tidwall/tile38/internal/ds"
"github.com/tidwall/tile38/internal/endpoint"
"github.com/tidwall/tile38/internal/expire"
"github.com/tidwall/tile38/internal/log"
@ -34,11 +34,6 @@ const goingLive = "going live"
const hookLogPrefix = "hook:log:"
type collectionT struct {
Key string
Collection *collection.Collection
}
type commandDetailsT struct {
command string
key, id string
@ -57,10 +52,6 @@ type commandDetailsT struct {
children []*commandDetailsT // for multi actions such as "PDEL"
}
func (col *collectionT) Less(item btree.Item, ctx interface{}) bool {
return col.Key < item.(*collectionT).Key
}
// Controller is a tile38 controller
type Controller struct {
// static values
@ -95,7 +86,7 @@ type Controller struct {
aofsz int // active size of the aof file
qdb *buntdb.DB // hook queue log
qidx uint64 // hook queue log last idx
cols *btree.BTree // data collections
cols ds.BTree // data collections
expires map[string]map[string]time.Time // synced with cols
follows map[*bytes.Buffer]bool
@ -136,7 +127,6 @@ func ListenAndServeEx(host string, port int, dir string, ln *net.Listener, http
host: host,
port: port,
dir: dir,
cols: btree.New(16, 0),
follows: make(map[*bytes.Buffer]bool),
fcond: sync.NewCond(&sync.Mutex{}),
lives: make(map[*liveBuffer]bool),
@ -353,30 +343,29 @@ func (c *Controller) watchLuaStatePool() {
}
func (c *Controller) setCol(key string, col *collection.Collection) {
c.cols.ReplaceOrInsert(&collectionT{Key: key, Collection: col})
c.cols.Set(key, col)
}
func (c *Controller) getCol(key string) *collection.Collection {
item := c.cols.Get(&collectionT{Key: key})
if item == nil {
return nil
if value, ok := c.cols.Get(key); ok {
return value.(*collection.Collection)
}
return item.(*collectionT).Collection
return nil
}
func (c *Controller) scanGreaterOrEqual(key string, iterator func(key string, col *collection.Collection) bool) {
c.cols.AscendGreaterOrEqual(&collectionT{Key: key}, func(item btree.Item) bool {
col := item.(*collectionT)
return iterator(col.Key, col.Collection)
func (c *Controller) scanGreaterOrEqual(
key string, iterator func(key string, col *collection.Collection) bool,
) {
c.cols.Ascend(key, func(ikey string, ivalue interface{}) bool {
return iterator(ikey, ivalue.(*collection.Collection))
})
}
func (c *Controller) deleteCol(key string) *collection.Collection {
i := c.cols.Delete(&collectionT{Key: key})
if i == nil {
return nil
if prev, ok := c.cols.Delete(key); ok {
return prev.(*collection.Collection)
}
return i.(*collectionT).Collection
return nil
}
func isReservedFieldName(field string) bool {
@ -625,7 +614,7 @@ func randomKey(n int) string {
func (c *Controller) reset() {
c.aofsz = 0
c.cols = btree.New(16, 0)
c.cols = ds.BTree{}
c.exlistmu.Lock()
c.exlist = nil
c.exlistmu.Unlock()

View File

@ -8,11 +8,11 @@ import (
"time"
"github.com/mmcloughlin/geohash"
"github.com/tidwall/btree"
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
"github.com/tidwall/resp"
"github.com/tidwall/tile38/internal/collection"
"github.com/tidwall/tile38/internal/ds"
"github.com/tidwall/tile38/internal/glob"
"github.com/tidwall/tile38/internal/server"
)
@ -461,7 +461,7 @@ func (c *Controller) cmdFlushDB(msg *server.Message) (res resp.Value, d commandD
err = errInvalidNumberOfArguments
return
}
c.cols = btree.New(16, 0)
c.cols = ds.BTree{}
c.exlistmu.Lock()
c.exlist = nil
c.exlistmu.Unlock()

View File

@ -5,7 +5,6 @@ import (
"strings"
"time"
"github.com/tidwall/btree"
"github.com/tidwall/resp"
"github.com/tidwall/tile38/internal/glob"
"github.com/tidwall/tile38/internal/server"
@ -34,8 +33,7 @@ func (c *Controller) cmdKeys(msg *server.Message) (res resp.Value, err error) {
var greaterPivot string
var vals []resp.Value
iterator := func(item btree.Item) bool {
key := item.(*collectionT).Key
iterator := func(key string, value interface{}) bool {
var match bool
if everything {
match = true
@ -66,24 +64,24 @@ func (c *Controller) cmdKeys(msg *server.Message) (res resp.Value, err error) {
}
if pattern == "*" {
everything = true
c.cols.Ascend(iterator)
c.cols.Scan(iterator)
} else {
if strings.HasSuffix(pattern, "*") {
greaterPivot = pattern[:len(pattern)-1]
if glob.IsGlob(greaterPivot) {
greater = false
c.cols.Ascend(iterator)
c.cols.Scan(iterator)
} else {
greater = true
c.cols.AscendGreaterOrEqual(&collectionT{Key: greaterPivot}, iterator)
c.cols.Ascend(greaterPivot, iterator)
}
} else if glob.IsGlob(pattern) {
greater = false
c.cols.Ascend(iterator)
c.cols.Scan(iterator)
} else {
greater = true
greaterPivot = pattern
c.cols.AscendGreaterOrEqual(&collectionT{Key: greaterPivot}, iterator)
c.cols.Ascend(greaterPivot, iterator)
}
}
if msg.OutputType == server.JSON {

View File

@ -10,9 +10,9 @@ import (
"strings"
"time"
"github.com/tidwall/btree"
"github.com/tidwall/resp"
"github.com/tidwall/tile38/core"
"github.com/tidwall/tile38/internal/collection"
"github.com/tidwall/tile38/internal/server"
)
@ -86,8 +86,8 @@ func (c *Controller) cmdServer(msg *server.Message) (res resp.Value, err error)
m["num_collections"] = c.cols.Len()
m["num_hooks"] = len(c.hooks)
sz := 0
c.cols.Ascend(func(item btree.Item) bool {
col := item.(*collectionT).Collection
c.cols.Scan(func(key string, value interface{}) bool {
col := value.(*collection.Collection)
sz += col.TotalWeight()
return true
})
@ -95,8 +95,8 @@ func (c *Controller) cmdServer(msg *server.Message) (res resp.Value, err error)
points := 0
objects := 0
strings := 0
c.cols.Ascend(func(item btree.Item) bool {
col := item.(*collectionT).Collection
c.cols.Scan(func(key string, value interface{}) bool {
col := value.(*collection.Collection)
points += col.PointCount()
objects += col.Count()
strings += col.StringCount()