From 78391c92be8cf43eb3487484548751abd36fe1c7 Mon Sep 17 00:00:00 2001
From: Kirill Smelkov <kirr@nexedi.com>
Date: Tue, 14 Feb 2017 19:56:47 +0300
Subject: [PATCH] .

---
 t/neo/storage/fs1/fsb/cmp.go      | 15 ++++++++
 t/neo/storage/fs1/fsb/fsbtree.go  | 12 +++---
 t/neo/storage/fs1/fsb/gen-fsbtree |  9 ++++-
 t/neo/storage/fs1/index.go        | 61 +++++++++++++++++--------------
 t/neo/storage/fs1/index_test.go   |  9 ++++-
 5 files changed, 69 insertions(+), 37 deletions(-)
 create mode 100644 t/neo/storage/fs1/fsb/cmp.go

diff --git a/t/neo/storage/fs1/fsb/cmp.go b/t/neo/storage/fs1/fsb/cmp.go
new file mode 100644
index 00000000..9d60b8d1
--- /dev/null
+++ b/t/neo/storage/fs1/fsb/cmp.go
@@ -0,0 +1,15 @@
+package fsb
+
+import "../../../zodb"
+
+// comparison function for fsbTree
+// kept short & inlineable
+func oidCmp(a, b zodb.Oid) int {
+	if a < b {
+		return -1
+	} else if a > b {
+		return +1
+	} else {
+		return 0
+	}
+}
diff --git a/t/neo/storage/fs1/fsb/fsbtree.go b/t/neo/storage/fs1/fsb/fsbtree.go
index 4f8b1367..541c9dbb 100644
--- a/t/neo/storage/fs1/fsb/fsbtree.go
+++ b/t/neo/storage/fs1/fsb/fsbtree.go
@@ -40,9 +40,8 @@ var (
 
 type btTpool struct{ sync.Pool }
 
-func (p *btTpool) get(cmp Cmp) *Tree {
+func (p *btTpool) get() *Tree {
 	x := p.Get().(*Tree)
-	x.cmp = cmp
 	return x
 }
 
@@ -96,7 +95,6 @@ type (
 	// Tree is a B+tree.
 	Tree struct {
 		c     int
-		cmp   Cmp
 		first *d
 		last  *d
 		r     interface{}
@@ -202,8 +200,8 @@ func (l *d) mvR(r *d, c int) {
 
 // TreeNew returns a newly created, empty Tree. The compare function is used
 // for key collation.
-func TreeNew(cmp Cmp) *Tree {
-	return btTPool.get(cmp)
+func TreeNew() *Tree {
+	return btTPool.get()
 }
 
 // Clear removes all K/V pairs from the tree.
@@ -359,7 +357,7 @@ func (t *Tree) find(q interface{}, k zodb.Oid) (i int, ok bool) {
 		for l <= h {
 			m := (l + h) >> 1
 			mk = x.x[m].k
-			switch cmp := t.cmp(k, mk); {
+			switch cmp := oidCmp(k, mk); {
 			case cmp > 0:
 				l = m + 1
 			case cmp == 0:
@@ -373,7 +371,7 @@ func (t *Tree) find(q interface{}, k zodb.Oid) (i int, ok bool) {
 		for l <= h {
 			m := (l + h) >> 1
 			mk = x.d[m].k
-			switch cmp := t.cmp(k, mk); {
+			switch cmp := oidCmp(k, mk); {
 			case cmp > 0:
 				l = m + 1
 			case cmp == 0:
diff --git a/t/neo/storage/fs1/fsb/gen-fsbtree b/t/neo/storage/fs1/fsb/gen-fsbtree
index 6ccda692..d8f7daf9 100755
--- a/t/neo/storage/fs1/fsb/gen-fsbtree
+++ b/t/neo/storage/fs1/fsb/gen-fsbtree
@@ -1,5 +1,5 @@
 #!/bin/sh -e
-# generate b.Tree with compile-time KEY=zodb.Oid, VALUE=int64
+# generate b.Tree with compile-time KEY=zodb.Oid, VALUE=int64 and direct oidCmp calls
 
 KEY=zodb.Oid
 VALUE=int64
@@ -18,4 +18,11 @@ make -s -C $Bdir generic |sed	\
 	-e 's/package b/package fsb/g'	\
 	-e "s/KEY/$KEY/g"	\
 	-e "s/VALUE/$VALUE/g"	\
+ \
+	-e '/cmp *Cmp$/d'	\
+	-e 's/t\.cmp(/oidCmp(/g'	\
+	-e 's/func TreeNew(cmp Cmp)/func TreeNew()/g'	\
+	-e 's/btTPool.get(cmp)/btTPool.get()/g'	\
+	-e 's/func (p \*btTpool) get(cmp Cmp)/func (p *btTpool) get()/g'	\
+	-e '/x\.cmp = cmp$/d'	\
 	>>$out
diff --git a/t/neo/storage/fs1/index.go b/t/neo/storage/fs1/index.go
index 2f2b038b..25102cbb 100644
--- a/t/neo/storage/fs1/index.go
+++ b/t/neo/storage/fs1/index.go
@@ -37,7 +37,11 @@ import (
 // fsIndex is Oid -> Tid's position mapping used to associate Oid with latest
 // transaction which changed it.
 type fsIndex struct {
-	fsb.Tree
+	*fsb.Tree
+}
+
+func fsIndexNew() *fsIndex {
+	return &fsIndex{fsb.TreeNew()}
 }
 
 
@@ -62,24 +66,23 @@ type fsIndex struct {
 
 const oidPrefixMask zodb.Oid = ((1<<64-1) ^ (1<<16 -1))	// 0xffffffffffff0000
 
-// IndexIOError is the error type returned by index save and load routines
-type IndexIOError struct {
-	Op  string	// operation performed - "save" or "load"
-	Err error	// error that occured during the operation
+// IndexSaveError is the error type returned by index save routines
+type IndexSaveError struct {
+	Err error // error that occured during the operation
 }
 
-func (e *IndexIOError) Error() string {
-	s := "index " + e.Op + ": " + e.Err.Error()
-	return s
+func (e *IndexSaveError) Error() string {
+	return "index save: " + e.Err.Error()
 }
 
 // Save saves the index to a writer
 func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
-	p := pickle.NewEncoder(w)
-
-	err := p.Encode(topPos)
+	var err error
 
 	{
+		p := pickle.NewEncoder(w)
+
+		err = p.Encode(topPos)
 		if err != nil {
 			goto out
 		}
@@ -144,11 +147,14 @@ out:
 
 	// otherwise it is an error returned by writer, which should already
 	// have filename & op as context.
-	return &IndexIOError{"save", err}
+	return &IndexSaveError{err}
 }
 
+// XXX do we need it?
+// func (fsi *fsIndex) SaveFile(topPos int64, path string) error {
+// }
 
-// IndexLoadError is the errortype returned by index load routines
+// IndexLoadError is the error type returned by index load routines
 type IndexLoadError struct {
 	Filename string
 	Pos      int64
@@ -160,6 +166,7 @@ func (e *IndexLoadError) Error() string {
 	if s != "" {
 		s += ": "
 	}
+	s += "index load: "
 	s += "pickle @" + strconv.FormatInt(e.Pos, 10) + ": "
 	s += e.Err.Error()
 	return s
@@ -167,33 +174,36 @@ func (e *IndexLoadError) Error() string {
 
 // LoadIndex loads index from a reader
 func LoadIndex(r io.Reader) (topPos int64, fsi *fsIndex, err error) {
-	xr := NewBufReader(r)
-	// by passing bufio.Reader directly we make sure it won't create one internally
-	p := pickle.NewDecoder(xr.Reader)
 	var picklePos int64
 
 	{
+		var ok bool
+		var xtopPos, xv interface{}
+
+		xr := NewBufReader(r)
+		// by passing bufio.Reader directly we make sure it won't create one internally
+		p := pickle.NewDecoder(xr.Reader)
+
 		picklePos = xr.InputOffset()
-		xtopPos, err := p.Decode()
+		xtopPos, err = p.Decode()
 		if err != nil {
 			goto out
 		}
-		var ok bool
 		topPos, ok = xtopPos.(int64)
 		if !ok {
 			err = fmt.Errorf("topPos is %T  (expected int64)", xtopPos)
 			goto out
 		}
 
-		fsi = &fsIndex{}	// TODO cmpFunc ...
+		fsi = fsIndexNew()
 		var oidb [8]byte
 		var posb [8]byte
 
-loop:
+	loop:
 		for {
 			// load/decode next entry
 			picklePos = xr.InputOffset()
-			xv, err := p.Decode()
+			xv, err = p.Decode()
 			if err != nil {
 				goto out
 			}
@@ -269,9 +279,10 @@ out:
 	return 0, nil, &IndexLoadError{IOName(r), picklePos, err}
 }
 
+// XXX LoadIndexFile - do we need it ?
 
 
-// CountReader is an io.Reader that count total bytes read.
+// CountReader is an io.Reader that count total bytes read
 type CountReader struct {
 	io.Reader
 	nread int64
@@ -306,7 +317,6 @@ func NewBufReader(r io.Reader) *BufReader {
 		cr = &CountReader{r, 0}
 	}
 
-
 	return &BufReader{bufio.NewReader(cr), cr}
 }
 
@@ -338,10 +348,7 @@ func IOName(f interface {}) string {
 		return "pipe"
 
 	// XXX SectionReader MultiReader TeeReader
-
-	// bufio.Reader bufio.Writer bufio.Scanner
-
-
+	// XXX bufio.Reader bufio.Writer bufio.Scanner
 	default:
 		return ""
 	}
diff --git a/t/neo/storage/fs1/index_test.go b/t/neo/storage/fs1/index_test.go
index f71657f3..d393ed1c 100644
--- a/t/neo/storage/fs1/index_test.go
+++ b/t/neo/storage/fs1/index_test.go
@@ -6,6 +6,11 @@ import (
 	"testing"
 )
 
-func TestXXX(t *testing.T) {
-	// TODO
+func TestIndexLookup(t *testing.T) {
+	// the lookup is tested in cznic.b itself
+	// here we only lightly excersize it
+}
+
+
+func TestIndexSaveLoad(t *testing.T) {
 }
-- 
2.30.9