mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-24 11:55:40 +00:00
1278 lines
23 KiB
Go
1278 lines
23 KiB
Go
// 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
|
|
}
|