syncthing/vendor/github.com/cznic/ql/mem.go

1278 lines
23 KiB
Go
Raw Normal View History

2016-05-31 20:35:35 +00:00
// Copyright (c) 2014 ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Plain memory storage back end.
package ql
import (
"bytes"
"fmt"
"io"
"math/big"
"time"
)
var (
_ btreeIndex = (*memIndex)(nil)
_ btreeIterator = (*memBTreeIterator)(nil)
_ indexIterator = (*xenumerator2)(nil)
_ storage = (*mem)(nil)
_ temp = (*memTemp)(nil)
)
type memIndex struct {
m *mem
t *xtree
unique bool
}
func newMemIndex(m *mem, unique bool) *memIndex {
r := &memIndex{t: xtreeNew(), unique: unique, m: m}
//dbg("newMemIndex %p, %p", r, m)
return r
}
func (x *memIndex) Clear() error {
//dbg("memIndex(%p, %p).Clear", x, x.m)
x.m.newUndo(undoClearX, 0, []interface{}{x, x.t})
x.t = xtreeNew()
return nil
}
func (x *memIndex) Create(indexedValues []interface{}, h int64) error {
//dbg("memIndex(%p, %p).Create %v, %v", x, x.m, indexedValues, h)
t := x.t
switch {
case !x.unique:
k := indexKey{indexedValues, h}
x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved?
t.Set(k, 0)
case isIndexNull(indexedValues): // unique, NULL
k := indexKey{nil, h}
x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved?
t.Set(k, 0)
default: // unique, non NULL
k := indexKey{indexedValues, 0}
if _, ok := t.Get(k); ok { //LATER need .Put
return fmt.Errorf("cannot insert into unique index: duplicate value(s): %v", indexedValues)
}
x.m.newUndo(undoCreateX, 0, []interface{}{x, k}) //TODO why is old value, if any, not saved?
t.Set(k, int(h))
}
return nil
}
func (x *memIndex) Delete(indexedValues []interface{}, h int64) error {
//dbg("memIndex(%p, %p).Delete %v, %v", x, x.m, indexedValues, h)
t := x.t
var k indexKey
var v interface{}
var ok, okv bool
switch {
case !x.unique:
k = indexKey{indexedValues, h}
v, okv = t.Get(k)
ok = t.delete(k)
case isIndexNull(indexedValues): // unique, NULL
k = indexKey{nil, h}
v, okv = t.Get(k)
ok = t.delete(k)
default: // unique, non NULL
k = indexKey{indexedValues, 0}
v, okv = t.Get(k)
ok = t.delete(k)
}
if ok {
if okv {
x.m.newUndo(undoDeleteX, int64(v.(int)), []interface{}{x, k})
}
return nil
}
return fmt.Errorf("internal error 047")
}
func (x *memIndex) Drop() error {
x.m.newUndo(undoDropX, 0, []interface{}{x, *x})
*x = memIndex{}
return nil
}
func (x *memIndex) Seek(indexedValues []interface{}) (indexIterator, bool, error) {
it, hit := x.t.Seek(indexKey{indexedValues, 0})
return &xenumerator2{*it, x.unique}, hit, nil
}
func (x *memIndex) SeekFirst() (iter indexIterator, err error) {
it, err := x.t.SeekFirst()
if err != nil {
return nil, err
}
return &xenumerator2{*it, x.unique}, nil
}
func (x *memIndex) SeekLast() (iter indexIterator, err error) {
it, err := x.t.SeekLast()
if err != nil {
return nil, err
}
return &xenumerator2{*it, x.unique}, nil
}
type xenumerator2 struct {
it xenumerator
unique bool
}
func (it *xenumerator2) Next() ([]interface{}, int64, error) {
k, h, err := it.it.Next()
if err != nil {
return nil, -1, err
}
switch it.unique {
case true:
if k.value == nil {
return nil, k.h, nil
}
return k.value, h, nil
default:
return k.value, k.h, nil
}
}
func (it *xenumerator2) Prev() ([]interface{}, int64, error) {
k, h, err := it.it.Prev()
if err != nil {
return nil, -1, err
}
switch it.unique {
case true:
if k.value == nil {
return nil, k.h, nil
}
return k.value, h, nil
default:
return k.value, k.h, nil
}
}
type memBTreeIterator enumerator
func (it *memBTreeIterator) Next() (k, v []interface{}, err error) {
return (*enumerator)(it).Next()
}
type memTemp struct {
tree *tree
store *mem
}
func (t *memTemp) BeginTransaction() (err error) {
return nil
}
func (t *memTemp) Get(k []interface{}) (v []interface{}, err error) {
v, _ = t.tree.Get(k)
return
}
func (t *memTemp) Create(data ...interface{}) (h int64, err error) {
s := t.store
switch n := len(s.recycler); {
case n != 0:
h = int64(s.recycler[n-1])
s.recycler = s.recycler[:n-1]
s.data[h] = s.clone(data...)
default:
h = int64(len(s.data))
s.data = append(s.data, s.clone(data...))
}
return
}
func (t *memTemp) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) {
return t.store.Read(dst, h, cols...)
}
func (*memTemp) Drop() (err error) { return }
func (t *memTemp) Set(k, v []interface{}) (err error) {
t.tree.Set(append([]interface{}(nil), k...), t.store.clone(v...))
return
}
func (t *memTemp) SeekFirst() (e btreeIterator, err error) {
en, err := t.tree.SeekFirst()
if err != nil {
return
}
return (*memBTreeIterator)(en), nil
}
const (
undoCreateNewHandle = iota
undoCreateRecycledHandle
undoUpdate
undoDelete
undoClearX // {0: *memIndex, 1: *xtree}
undoCreateX // {0: *memIndex, 1: indexKey}
undoDeleteX // {0: *memIndex, 1: indexKey}
undoDropX // {0: *memIndex, 1: memIndex}
)
type undo struct {
tag int
h int64
data []interface{}
}
type undos struct {
list []undo
parent *undos
}
type mem struct {
data [][]interface{}
id int64
recycler []int
tnl int
rollback *undos
}
func newMemStorage() (s *mem, err error) {
s = &mem{data: [][]interface{}{nil}}
if err = s.BeginTransaction(); err != nil {
return nil, err
}
h, err := s.Create()
if h != 1 {
panic("internal error 048")
}
if err = s.Commit(); err != nil {
return nil, err
}
return
}
func (s *mem) OpenIndex(unique bool, handle int64) (btreeIndex, error) { // Never called on the memory backend.
panic("internal error 049")
}
func (s *mem) newUndo(tag int, h int64, data []interface{}) {
s.rollback.list = append(s.rollback.list, undo{tag, h, data})
}
func (s *mem) Acid() bool { return false }
func (s *mem) Close() (err error) {
if s.tnl != 0 {
return fmt.Errorf("cannot close DB while open transaction exist")
}
*s = mem{}
return
}
func (s *mem) CreateIndex(unique bool) ( /* handle */ int64, btreeIndex, error) {
return -1, newMemIndex(s, unique), nil // handle of memIndex should never be used
}
func (s *mem) Name() string { return fmt.Sprintf("/proc/self/mem/%p", s) } // fake, non existing name
// OpenMem returns a new, empty DB backed by the process' memory. The back end
// has no limits on field/record/table/DB size other than memory available to
// the process.
func OpenMem() (db *DB, err error) {
s, err := newMemStorage()
if err != nil {
return
}
if db, err = newDB(s); err != nil {
return nil, err
}
db.isMem = true
return db, nil
}
func (s *mem) Verify() (allocs int64, err error) {
for _, v := range s.recycler {
if s.data[v] != nil {
return 0, fmt.Errorf("corrupted: non nil free handle %d", s.data[v])
}
}
for _, v := range s.data {
if v != nil {
allocs++
}
}
if allocs != int64(len(s.data))-1-int64(len(s.recycler)) {
return 0, fmt.Errorf("corrupted: len(data) %d, len(recycler) %d, allocs %d", len(s.data), len(s.recycler), allocs)
}
return
}
func (s *mem) String() string {
var b bytes.Buffer
for i, v := range s.data {
b.WriteString(fmt.Sprintf("s.data[%d] %#v\n", i, v))
}
for i, v := range s.recycler {
b.WriteString(fmt.Sprintf("s.recycler[%d] %v\n", i, v))
}
return b.String()
}
func (s *mem) CreateTemp(asc bool) (_ temp, err error) {
st, err := newMemStorage()
if err != nil {
return
}
return &memTemp{
tree: treeNew(collators[asc]),
store: st,
}, nil
}
func (s *mem) ResetID() (err error) {
s.id = 0
return
}
func (s *mem) ID() (id int64, err error) {
s.id++
return s.id, nil
}
func (s *mem) clone(data ...interface{}) []interface{} {
r := make([]interface{}, len(data))
for i, v := range data {
switch x := v.(type) {
case nil:
// nop
case idealComplex:
r[i] = complex128(x)
case idealFloat:
r[i] = float64(x)
case idealInt:
r[i] = int64(x)
case idealRune:
r[i] = int32(x)
case idealUint:
r[i] = uint64(x)
case bool:
r[i] = x
case complex64:
r[i] = x
case complex128:
r[i] = x
case float32:
r[i] = x
case float64:
r[i] = x
case int:
r[i] = int64(x)
case int8:
r[i] = x
case int16:
r[i] = x
case int32:
r[i] = x
case int64:
r[i] = x
case string:
r[i] = x
case uint:
r[i] = uint64(x)
case uint8:
r[i] = x
case uint16:
r[i] = x
case uint32:
r[i] = x
case uint64:
r[i] = x
case []byte:
r[i] = append([]byte(nil), x...)
case *big.Int:
r[i] = big.NewInt(0).Set(x)
case *big.Rat:
r[i] = big.NewRat(1, 2).Set(x)
case time.Time:
t := x
r[i] = t
case time.Duration:
r[i] = x
case map[string]interface{}: // map of ids of a cross join
r[i] = x
default:
panic("internal error 050")
}
}
return r
}
func (s *mem) Create(data ...interface{}) (h int64, err error) {
switch n := len(s.recycler); {
case n != 0:
h = int64(s.recycler[n-1])
s.recycler = s.recycler[:n-1]
s.data[h] = s.clone(data...)
r := s.rollback
r.list = append(r.list, undo{
tag: undoCreateRecycledHandle,
h: h,
})
default:
h = int64(len(s.data))
s.data = append(s.data, s.clone(data...))
r := s.rollback
r.list = append(r.list, undo{
tag: undoCreateNewHandle,
h: h,
})
}
return
}
func (s *mem) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) {
if i := int(h); i != 0 && i < len(s.data) {
d := s.clone(s.data[h]...)
if cols == nil {
return d, nil
}
for n, dn := len(cols)+2, len(d); dn < n; dn++ {
d = append(d, nil)
}
return d, nil
}
return nil, errNoDataForHandle
}
func (s *mem) UpdateRow(h int64, _ []*col, data ...interface{}) (err error) {
return s.Update(h, data...)
}
func (s *mem) Update(h int64, data ...interface{}) (err error) {
r := s.rollback
r.list = append(r.list, undo{
tag: undoUpdate,
h: h,
data: s.data[h],
})
s.data[h] = s.clone(data...)
return
}
func (s *mem) Delete(h int64, _ ...*col) (err error) {
r := s.rollback
r.list = append(r.list, undo{
tag: undoDelete,
h: h,
data: s.data[h],
})
s.recycler = append(s.recycler, int(h))
s.data[h] = nil
return
}
func (s *mem) BeginTransaction() (err error) {
s.rollback = &undos{parent: s.rollback}
s.tnl++
return nil
}
func (s *mem) Rollback() (err error) {
if s.tnl == 0 {
return errRollbackNotInTransaction
}
list := s.rollback.list
for i := len(list) - 1; i >= 0; i-- {
undo := list[i]
switch h, data := int(undo.h), undo.data; undo.tag {
case undoCreateNewHandle:
d := s.data
s.data = d[:len(d)-1]
case undoCreateRecycledHandle:
s.data[h] = nil
r := s.recycler
s.recycler = append(r, h)
case undoUpdate:
s.data[h] = data
case undoDelete:
s.data[h] = data
s.recycler = s.recycler[:len(s.recycler)-1]
case undoClearX:
x, t := data[0].(*memIndex), data[1].(*xtree)
x.t = t
case undoCreateX:
x, k := data[0].(*memIndex), data[1].(indexKey)
x.t.delete(k)
case undoDeleteX:
x, k := data[0].(*memIndex), data[1].(indexKey)
x.t.Set(k, h)
case undoDropX:
x, v := data[0].(*memIndex), data[1].(memIndex)
*x = v
default:
panic("internal error 051")
}
}
s.tnl--
s.rollback = s.rollback.parent
return nil
}
func (s *mem) Commit() (err error) {
if s.tnl == 0 {
return errCommitNotInTransaction
}
s.tnl--
s.rollback = s.rollback.parent
return nil
}
// Transaction index B+Tree
//LATER make it just a wrapper of the implementation in btree.go.
type (
xd struct { // data page
c int
xd [2*kd + 1]xde
n *xd
p *xd
}
xde struct { // xd element
k indexKey
v int
}
// xenumerator captures the state of enumerating a tree. It is returned
// from the Seek* methods. The enumerator is aware of any mutations
// made to the tree in the process of enumerating it and automatically
// resumes the enumeration at the proper key, if possible.
//
// However, once an xenumerator returns io.EOF to signal "no more
// items", it does no more attempt to "resync" on tree mutation(s). In
// other words, io.EOF from an Enumaretor is "sticky" (idempotent).
xenumerator struct {
err error
hit bool
i int
k indexKey
q *xd
t *xtree
ver int64
}
// xtree is a B+tree.
xtree struct {
c int
first *xd
last *xd
r interface{}
ver int64
}
xxe struct { // xx element
ch interface{}
sep *xd
}
xx struct { // index page
c int
xx [2*kx + 2]xxe
}
)
func (a *indexKey) cmp(b *indexKey) int {
r := collate(a.value, b.value)
if r != 0 {
return r
}
return int(a.h) - int(b.h)
}
var ( // R/O zero values
zxd xd
zxde xde
zxx xx
zxxe xxe
)
func xclr(q interface{}) {
switch xx := q.(type) {
case *xx:
for i := 0; i <= xx.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn
xclr(xx.xx[i].ch)
}
*xx = zxx // GC
case *xd:
*xx = zxd // GC
}
}
// -------------------------------------------------------------------------- xx
func xnewX(ch0 interface{}) *xx {
r := &xx{}
r.xx[0].ch = ch0
return r
}
func (q *xx) extract(i int) {
q.c--
if i < q.c {
copy(q.xx[i:], q.xx[i+1:q.c+1])
q.xx[q.c].ch = q.xx[q.c+1].ch
q.xx[q.c].sep = nil // GC
q.xx[q.c+1] = zxxe // GC
}
}
func (q *xx) insert(i int, xd *xd, ch interface{}) *xx {
c := q.c
if i < c {
q.xx[c+1].ch = q.xx[c].ch
copy(q.xx[i+2:], q.xx[i+1:c])
q.xx[i+1].sep = q.xx[i].sep
}
c++
q.c = c
q.xx[i].sep = xd
q.xx[i+1].ch = ch
return q
}
func (q *xx) siblings(i int) (l, r *xd) {
if i >= 0 {
if i > 0 {
l = q.xx[i-1].ch.(*xd)
}
if i < q.c {
r = q.xx[i+1].ch.(*xd)
}
}
return
}
// -------------------------------------------------------------------------- xd
func (l *xd) mvL(r *xd, c int) {
copy(l.xd[l.c:], r.xd[:c])
copy(r.xd[:], r.xd[c:r.c])
l.c += c
r.c -= c
}
func (l *xd) mvR(r *xd, c int) {
copy(r.xd[c:], r.xd[:r.c])
copy(r.xd[:c], l.xd[l.c-c:])
r.c += c
l.c -= c
}
// ----------------------------------------------------------------------- xtree
// xtreeNew returns a newly created, empty xtree. The compare function is used
// for key collation.
func xtreeNew() *xtree {
return &xtree{}
}
// Clear removes all K/V pairs from the tree.
func (t *xtree) Clear() {
if t.r == nil {
return
}
xclr(t.r)
t.c, t.first, t.last, t.r = 0, nil, nil, nil
t.ver++
}
func (t *xtree) cat(p *xx, q, r *xd, pi int) {
t.ver++
q.mvL(r, r.c)
if r.n != nil {
r.n.p = q
} else {
t.last = q
}
q.n = r.n
if p.c > 1 {
p.extract(pi)
p.xx[pi].ch = q
} else {
t.r = q
}
}
func (t *xtree) catX(p, q, r *xx, pi int) {
t.ver++
q.xx[q.c].sep = p.xx[pi].sep
copy(q.xx[q.c+1:], r.xx[:r.c])
q.c += r.c + 1
q.xx[q.c].ch = r.xx[r.c].ch
if p.c > 1 {
p.c--
pc := p.c
if pi < pc {
p.xx[pi].sep = p.xx[pi+1].sep
copy(p.xx[pi+1:], p.xx[pi+2:pc+1])
p.xx[pc].ch = p.xx[pc+1].ch
p.xx[pc].sep = nil // GC
p.xx[pc+1].ch = nil // GC
}
return
}
t.r = q
}
//Delete removes the k's KV pair, if it exists, in which case Delete returns
//true.
func (t *xtree) delete(k indexKey) (ok bool) {
pi := -1
var p *xx
q := t.r
if q == nil {
return
}
for {
var i int
i, ok = t.find(q, k)
if ok {
switch xx := q.(type) {
case *xx:
dp := xx.xx[i].sep
switch {
case dp.c > kd:
t.extract(dp, 0)
default:
if xx.c < kx && q != t.r {
t.underflowX(p, &xx, pi, &i)
}
pi = i + 1
p = xx
q = xx.xx[pi].ch
ok = false
continue
}
case *xd:
t.extract(xx, i)
if xx.c >= kd {
return
}
if q != t.r {
t.underflow(p, xx, pi)
} else if t.c == 0 {
t.Clear()
}
}
return
}
switch xx := q.(type) {
case *xx:
if xx.c < kx && q != t.r {
t.underflowX(p, &xx, pi, &i)
}
pi = i
p = xx
q = xx.xx[i].ch
case *xd:
return
}
}
}
func (t *xtree) extract(q *xd, i int) { // (r int64) {
t.ver++
//r = q.xd[i].v // prepared for Extract
q.c--
if i < q.c {
copy(q.xd[i:], q.xd[i+1:q.c+1])
}
q.xd[q.c] = zxde // GC
t.c--
return
}
func (t *xtree) find(q interface{}, k indexKey) (i int, ok bool) {
var mk indexKey
l := 0
switch xx := q.(type) {
case *xx:
h := xx.c - 1
for l <= h {
m := (l + h) >> 1
mk = xx.xx[m].sep.xd[0].k
switch cmp := k.cmp(&mk); {
case cmp > 0:
l = m + 1
case cmp == 0:
return m, true
default:
h = m - 1
}
}
case *xd:
h := xx.c - 1
for l <= h {
m := (l + h) >> 1
mk = xx.xd[m].k
switch cmp := k.cmp(&mk); {
case cmp > 0:
l = m + 1
case cmp == 0:
return m, true
default:
h = m - 1
}
}
}
return l, false
}
// First returns the first item of the tree in the key collating order, or
// (nil, nil) if the tree is empty.
func (t *xtree) First() (k indexKey, v int) {
if q := t.first; q != nil {
q := &q.xd[0]
k, v = q.k, q.v
}
return
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (nil, false).
func (t *xtree) Get(k indexKey) (v int, ok bool) {
q := t.r
if q == nil {
return
}
for {
var i int
if i, ok = t.find(q, k); ok {
switch xx := q.(type) {
case *xx:
return xx.xx[i].sep.xd[0].v, true
case *xd:
return xx.xd[i].v, true
}
}
switch xx := q.(type) {
case *xx:
q = xx.xx[i].ch
default:
return
}
}
}
func (t *xtree) insert(q *xd, i int, k indexKey, v int) *xd {
t.ver++
c := q.c
if i < c {
copy(q.xd[i+1:], q.xd[i:c])
}
c++
q.c = c
q.xd[i].k, q.xd[i].v = k, v
t.c++
return q
}
// Last returns the last item of the tree in the key collating order, or (nil,
// nil) if the tree is empty.
func (t *xtree) Last() (k indexKey, v int) {
if q := t.last; q != nil {
q := &q.xd[q.c-1]
k, v = q.k, q.v
}
return
}
// Len returns the number of items in the tree.
func (t *xtree) Len() int {
return t.c
}
func (t *xtree) overflow(p *xx, q *xd, pi, i int, k indexKey, v int) {
t.ver++
l, r := p.siblings(pi)
if l != nil && l.c < 2*kd {
l.mvL(q, 1)
t.insert(q, i-1, k, v)
return
}
if r != nil && r.c < 2*kd {
if i < 2*kd {
q.mvR(r, 1)
t.insert(q, i, k, v)
} else {
t.insert(r, 0, k, v)
}
return
}
t.split(p, q, pi, i, k, v)
}
// Seek returns an xenumerator positioned on a an item such that k >= item's
// key. ok reports if k == item.key The xenumerator's position is possibly
// after the last item in the tree.
func (t *xtree) Seek(k indexKey) (e *xenumerator, ok bool) {
q := t.r
if q == nil {
e = &xenumerator{nil, false, 0, k, nil, t, t.ver}
return
}
for {
var i int
if i, ok = t.find(q, k); ok {
switch xx := q.(type) {
case *xx:
e = &xenumerator{nil, ok, 0, k, xx.xx[i].sep, t, t.ver}
return
case *xd:
e = &xenumerator{nil, ok, i, k, xx, t, t.ver}
return
}
}
switch xx := q.(type) {
case *xx:
q = xx.xx[i].ch
case *xd:
e = &xenumerator{nil, ok, i, k, xx, t, t.ver}
return
}
}
}
// SeekFirst returns an enumerator positioned on the first KV pair in the tree,
// if any. For an empty tree, err == io.EOF is returned and e will be nil.
func (t *xtree) SeekFirst() (e *xenumerator, err error) {
q := t.first
if q == nil {
return nil, io.EOF
}
return &xenumerator{nil, true, 0, q.xd[0].k, q, t, t.ver}, nil
}
// SeekLast returns an enumerator positioned on the last KV pair in the tree,
// if any. For an empty tree, err == io.EOF is returned and e will be nil.
func (t *xtree) SeekLast() (e *xenumerator, err error) {
q := t.last
if q == nil {
return nil, io.EOF
}
return &xenumerator{nil, true, q.c - 1, q.xd[q.c-1].k, q, t, t.ver}, nil
}
// Set sets the value associated with k.
func (t *xtree) Set(k indexKey, v int) {
pi := -1
var p *xx
q := t.r
if q != nil {
for {
i, ok := t.find(q, k)
if ok {
switch xx := q.(type) {
case *xx:
xx.xx[i].sep.xd[0].v = v
case *xd:
xx.xd[i].v = v
}
return
}
switch xx := q.(type) {
case *xx:
if xx.c > 2*kx {
t.splitX(p, &xx, pi, &i)
}
pi = i
p = xx
q = xx.xx[i].ch
case *xd:
switch {
case xx.c < 2*kd:
t.insert(xx, i, k, v)
default:
t.overflow(p, xx, pi, i, k, v)
}
return
}
}
}
z := t.insert(&xd{}, 0, k, v)
t.r, t.first, t.last = z, z, z
return
}
func (t *xtree) split(p *xx, q *xd, pi, i int, k indexKey, v int) {
t.ver++
r := &xd{}
if q.n != nil {
r.n = q.n
r.n.p = r
} else {
t.last = r
}
q.n = r
r.p = q
copy(r.xd[:], q.xd[kd:2*kd])
for i := range q.xd[kd:] {
q.xd[kd+i] = zxde
}
q.c = kd
r.c = kd
if pi >= 0 {
p.insert(pi, r, r)
} else {
t.r = xnewX(q).insert(0, r, r)
}
if i > kd {
t.insert(r, i-kd, k, v)
return
}
t.insert(q, i, k, v)
}
func (t *xtree) splitX(p *xx, pp **xx, pi int, i *int) {
t.ver++
q := *pp
r := &xx{}
copy(r.xx[:], q.xx[kx+1:])
q.c = kx
r.c = kx
if pi >= 0 {
p.insert(pi, q.xx[kx].sep, r)
} else {
t.r = xnewX(q).insert(0, q.xx[kx].sep, r)
}
q.xx[kx].sep = nil
for i := range q.xx[kx+1:] {
q.xx[kx+i+1] = zxxe
}
if *i > kx {
*pp = r
*i -= kx + 1
}
}
func (t *xtree) underflow(p *xx, q *xd, pi int) {
t.ver++
l, r := p.siblings(pi)
if l != nil && l.c+q.c >= 2*kd {
l.mvR(q, 1)
} else if r != nil && q.c+r.c >= 2*kd {
q.mvL(r, 1)
r.xd[r.c] = zxde // GC
} else if l != nil {
t.cat(p, l, q, pi-1)
} else {
t.cat(p, q, r, pi)
}
}
func (t *xtree) underflowX(p *xx, pp **xx, pi int, i *int) {
t.ver++
var l, r *xx
q := *pp
if pi >= 0 {
if pi > 0 {
l = p.xx[pi-1].ch.(*xx)
}
if pi < p.c {
r = p.xx[pi+1].ch.(*xx)
}
}
if l != nil && l.c > kx {
q.xx[q.c+1].ch = q.xx[q.c].ch
copy(q.xx[1:], q.xx[:q.c])
q.xx[0].ch = l.xx[l.c].ch
q.xx[0].sep = p.xx[pi-1].sep
q.c++
*i++
l.c--
p.xx[pi-1].sep = l.xx[l.c].sep
return
}
if r != nil && r.c > kx {
q.xx[q.c].sep = p.xx[pi].sep
q.c++
q.xx[q.c].ch = r.xx[0].ch
p.xx[pi].sep = r.xx[0].sep
copy(r.xx[:], r.xx[1:r.c])
r.c--
rc := r.c
r.xx[rc].ch = r.xx[rc+1].ch
r.xx[rc].sep = nil
r.xx[rc+1].ch = nil
return
}
if l != nil {
*i += l.c + 1
t.catX(p, l, q, pi-1)
*pp = l
return
}
t.catX(p, q, r, pi)
}
// ----------------------------------------------------------------- xenumerator
// Next returns the currently enumerated item, if it exists and moves to the
// next item in the key collation order. If there is no item to return, err ==
// io.EOF is returned.
func (e *xenumerator) Next() (k indexKey, v int64, err error) {
if err = e.err; err != nil {
return
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.next(); err != nil {
return
}
}
*e = *f
}
if e.q == nil {
e.err, err = io.EOF, io.EOF
return
}
if e.i >= e.q.c {
if err = e.next(); err != nil {
return
}
}
i := e.q.xd[e.i]
k, v = i.k, int64(i.v)
e.k, e.hit = k, false
e.next()
return
}
func (e *xenumerator) next() error {
if e.q == nil {
e.err = io.EOF
return io.EOF
}
switch {
case e.i < e.q.c-1:
e.i++
default:
if e.q, e.i = e.q.n, 0; e.q == nil {
e.err = io.EOF
}
}
return e.err
}
// Prev returns the currently enumerated item, if it exists and moves to the
// previous item in the key collation order. If there is no item to return, err
// == io.EOF is returned.
func (e *xenumerator) Prev() (k indexKey, v int64, err error) {
if err = e.err; err != nil {
return
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.prev(); err != nil {
return
}
}
*e = *f
}
if e.q == nil {
e.err, err = io.EOF, io.EOF
return
}
if e.i >= e.q.c {
if err = e.next(); err != nil {
return
}
}
i := e.q.xd[e.i]
k, v = i.k, int64(i.v)
e.k, e.hit = k, false
e.prev()
return
}
func (e *xenumerator) prev() error {
if e.q == nil {
e.err = io.EOF
return io.EOF
}
switch {
case e.i > 0:
e.i--
default:
if e.q = e.q.p; e.q == nil {
e.err = io.EOF
break
}
e.i = e.q.c - 1
}
return e.err
}