func (t *BTree) SeekFirst() (enum *BTreeEnumerator, err error) {
	enum0, err := t.seekFirst()
	if err != nil {
		return
	}
	var key []byte
	if key, _, err = enum0.current(); err != nil {
		return
	}
	enum = &BTreeEnumerator{
		enum:     enum0,
		firstHit: true,
		key:      append([]byte(nil), key...),
	}
	return
}
seekFirst returns an enumerator positioned on the first KV pair in the tree,
if any.  For an empty tree, err == io.EOF is returend.

SeekFirst is safe for concurrent access by multiple goroutines iff no other
goroutine mutates the tree.
package lldb
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"sort"
	"strings"
	"github.com/cznic/fileutil"
	"github.com/cznic/internal/buffer"
	"github.com/cznic/sortutil"
)
const (
	kData             = 256          
	kIndex            = 256          
	kKV               = 19           
	kSz               = kKV - 1 - 7  
	kH                = kKV - 7      
	tagBTreeDataPage  = 1
	tagBTreeIndexPage = 0
)
type BTree struct {
	store   btreeStore
	root    btree
	collate func(a, b []byte) int
	serial  uint64
}
func NewBTree(collate func(a, b []byte) int) *BTree {
	store := newMemBTreeStore()
	root, err := newBTree(store)
	if err != nil {  
		panic(err.Error())
	}
	return &BTree{store, root, collate, 0}
}
func (t *BTree) IsMem() (r bool) {
	_, r = t.store.(*memBTreeStore)
	return
}
func (t *BTree) Clear() (err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	t.serial++
	return t.root.clear(t.store)
}
func (t *BTree) Delete(key []byte) (err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	t.serial++
	_, err = t.root.extract(t.store, nil, t.collate, key)
	return
}
func (t *BTree) DeleteAny() (empty bool, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	t.serial++
	return t.root.deleteAny(t.store)
}
func elem(v interface{}) string {
	switch x := v.(type) {
	default:
		panic("internal error")
	case nil:
		return "nil"
	case bool:
		if x {
			return "true"
		}
		return "false"
	case int64:
		return fmt.Sprint(x)
	case uint64:
		return fmt.Sprint(x)
	case float64:
		s := fmt.Sprintf("%g", x)
		if !strings.Contains(s, ".") {
			s += "."
		}
		return s
	case complex128:
		s := fmt.Sprint(x)
		return s[1 : len(s)-1]
	case []byte:
		return fmt.Sprintf("[]byte{% 02x}", x)
	case string:
		return fmt.Sprintf("%q", x)
	}
}
func (t *BTree) Dump(w io.Writer) (err error) {
	enum, err := t.seekFirst()
	if err != nil {
		return
	}
	for {
		bkey, bval, err := enum.current()
		if err != nil {
			return err
		}
		key, err := DecodeScalars(bkey)
		if err != nil {
			return err
		}
		val, err := DecodeScalars(bval)
		if err != nil {
			return err
		}
		kk := []string{}
		if key == nil {
			kk = []string{"null"}
		}
		for _, v := range key {
			kk = append(kk, elem(v))
		}
		vv := []string{}
		if val == nil {
			vv = []string{"null"}
		}
		for _, v := range val {
			vv = append(vv, elem(v))
		}
		skey := strings.Join(kk, ", ")
		sval := strings.Join(vv, ", ")
		if len(vv) > 1 {
			sval = fmt.Sprintf("[]interface{%s}", sval)
		}
		if _, err = fmt.Fprintf(w, "%s → %s\n", skey, sval); err != nil {
			return err
		}
		err = enum.next()
		if err != nil {
			if fileutil.IsEOF(err) {
				err = nil
				break
			}
			return err
		}
	}
	return
}
func (t *BTree) Extract(buf, key []byte) (value []byte, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	t.serial++
	return t.root.extract(t.store, buf, t.collate, key)
}
func (t *BTree) First() (key, value []byte, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	var p btreeDataPage
	if _, p, err = t.root.first(t.store); err != nil || p == nil {
		return
	}
	if key, err = p.key(t.store, 0); err != nil {
		return
	}
	value, err = p.value(t.store, 0)
	return
}
func (t *BTree) Get(buf, key []byte) (value []byte, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	pbuffer := buffer.Get(maxBuf)
	defer buffer.Put(pbuffer)
	buffer := *pbuffer
	if buffer, err = t.root.get(t.store, buffer, t.collate, key); buffer == nil || err != nil {
		return
	}
	if len(buffer) != 0 {
		value = need(len(buffer), buf)
	} else {
		value = []byte{}
	}
	copy(value, buffer)
	return
}
func (t *BTree) Handle() int64 {
	return int64(t.root)
}
func (t *BTree) Last() (key, value []byte, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	var p btreeDataPage
	if _, p, err = t.root.last(t.store); err != nil || p == nil {
		return
	}
	index := p.len() - 1
	if key, err = p.key(t.store, index); err != nil {
		return
	}
	value, err = p.value(t.store, index)
	return
}
func (t *BTree) Put(buf, key []byte, upd func(key, old []byte) (new []byte, write bool, err error)) (old []byte, written bool, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	t.serial++
	return t.root.put2(buf, t.store, t.collate, key, upd)
}
func (t *BTree) Seek(key []byte) (enum *BTreeEnumerator, hit bool, err error) {
	enum0, hit, err := t.seek(key)
	if err != nil {
		return
	}
	enum = &BTreeEnumerator{
		enum:     enum0,
		firstHit: hit,
		key:      append([]byte(nil), key...),
	}
	return
}
func (t *BTree) seek(key []byte) (enum *bTreeEnumerator, hit bool, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	r := &bTreeEnumerator{t: t, collate: t.collate, serial: t.serial}
	if r.p, r.index, hit, err = t.root.seek(t.store, r.collate, key); err != nil {
		return
	}
	enum = r
	return
}
func (t *BTree) IndexSeek(key []byte, c func(a, b []byte) int) (enum *BTreeEnumerator, hit bool, err error) {  
	enum0, hit, err := t.indexSeek(key, c)
	if err != nil {
		return
	}
	enum = &BTreeEnumerator{
		enum:     enum0,
		firstHit: hit,
		key:      append([]byte(nil), key...),
	}
	return
}
func (t *BTree) indexSeek(key []byte, c func(a, b []byte) int) (enum *bTreeEnumerator, hit bool, err error) {
	if t == nil {
		err = errors.New("BTree method invoked on nil receiver")
		return
	}
	r := &bTreeEnumerator{t: t, collate: t.collate, serial: t.serial}
	if r.p, r.index, hit, err = t.root.seek(t.store, c, key); err != nil {
		return
	}
	enum = r
	return
}