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

View File

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

View File

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

View File

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