Commit 78391c92 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 5404250a
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
}
}
...@@ -40,9 +40,8 @@ var ( ...@@ -40,9 +40,8 @@ var (
type btTpool struct{ sync.Pool } type btTpool struct{ sync.Pool }
func (p *btTpool) get(cmp Cmp) *Tree { func (p *btTpool) get() *Tree {
x := p.Get().(*Tree) x := p.Get().(*Tree)
x.cmp = cmp
return x return x
} }
...@@ -96,7 +95,6 @@ type ( ...@@ -96,7 +95,6 @@ type (
// Tree is a B+tree. // Tree is a B+tree.
Tree struct { Tree struct {
c int c int
cmp Cmp
first *d first *d
last *d last *d
r interface{} r interface{}
...@@ -202,8 +200,8 @@ func (l *d) mvR(r *d, c int) { ...@@ -202,8 +200,8 @@ func (l *d) mvR(r *d, c int) {
// TreeNew returns a newly created, empty Tree. The compare function is used // TreeNew returns a newly created, empty Tree. The compare function is used
// for key collation. // for key collation.
func TreeNew(cmp Cmp) *Tree { func TreeNew() *Tree {
return btTPool.get(cmp) return btTPool.get()
} }
// Clear removes all K/V pairs from the tree. // 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) { ...@@ -359,7 +357,7 @@ func (t *Tree) find(q interface{}, k zodb.Oid) (i int, ok bool) {
for l <= h { for l <= h {
m := (l + h) >> 1 m := (l + h) >> 1
mk = x.x[m].k mk = x.x[m].k
switch cmp := t.cmp(k, mk); { switch cmp := oidCmp(k, mk); {
case cmp > 0: case cmp > 0:
l = m + 1 l = m + 1
case cmp == 0: case cmp == 0:
...@@ -373,7 +371,7 @@ func (t *Tree) find(q interface{}, k zodb.Oid) (i int, ok bool) { ...@@ -373,7 +371,7 @@ func (t *Tree) find(q interface{}, k zodb.Oid) (i int, ok bool) {
for l <= h { for l <= h {
m := (l + h) >> 1 m := (l + h) >> 1
mk = x.d[m].k mk = x.d[m].k
switch cmp := t.cmp(k, mk); { switch cmp := oidCmp(k, mk); {
case cmp > 0: case cmp > 0:
l = m + 1 l = m + 1
case cmp == 0: case cmp == 0:
......
#!/bin/sh -e #!/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 KEY=zodb.Oid
VALUE=int64 VALUE=int64
...@@ -18,4 +18,11 @@ make -s -C $Bdir generic |sed \ ...@@ -18,4 +18,11 @@ make -s -C $Bdir generic |sed \
-e 's/package b/package fsb/g' \ -e 's/package b/package fsb/g' \
-e "s/KEY/$KEY/g" \ -e "s/KEY/$KEY/g" \
-e "s/VALUE/$VALUE/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 >>$out
...@@ -37,7 +37,11 @@ import ( ...@@ -37,7 +37,11 @@ import (
// fsIndex is Oid -> Tid's position mapping used to associate Oid with latest // fsIndex is Oid -> Tid's position mapping used to associate Oid with latest
// transaction which changed it. // transaction which changed it.
type fsIndex struct { type fsIndex struct {
fsb.Tree *fsb.Tree
}
func fsIndexNew() *fsIndex {
return &fsIndex{fsb.TreeNew()}
} }
...@@ -62,24 +66,23 @@ type fsIndex struct { ...@@ -62,24 +66,23 @@ type fsIndex struct {
const oidPrefixMask zodb.Oid = ((1<<64-1) ^ (1<<16 -1)) // 0xffffffffffff0000 const oidPrefixMask zodb.Oid = ((1<<64-1) ^ (1<<16 -1)) // 0xffffffffffff0000
// IndexIOError is the error type returned by index save and load routines // IndexSaveError is the error type returned by index save routines
type IndexIOError struct { type IndexSaveError struct {
Op string // operation performed - "save" or "load"
Err error // error that occured during the operation Err error // error that occured during the operation
} }
func (e *IndexIOError) Error() string { func (e *IndexSaveError) Error() string {
s := "index " + e.Op + ": " + e.Err.Error() return "index save: " + e.Err.Error()
return s
} }
// Save saves the index to a writer // Save saves the index to a writer
func (fsi *fsIndex) Save(topPos int64, w io.Writer) error { func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
p := pickle.NewEncoder(w) var err error
err := p.Encode(topPos)
{ {
p := pickle.NewEncoder(w)
err = p.Encode(topPos)
if err != nil { if err != nil {
goto out goto out
} }
...@@ -144,11 +147,14 @@ out: ...@@ -144,11 +147,14 @@ out:
// otherwise it is an error returned by writer, which should already // otherwise it is an error returned by writer, which should already
// have filename & op as context. // 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 { type IndexLoadError struct {
Filename string Filename string
Pos int64 Pos int64
...@@ -160,6 +166,7 @@ func (e *IndexLoadError) Error() string { ...@@ -160,6 +166,7 @@ func (e *IndexLoadError) Error() string {
if s != "" { if s != "" {
s += ": " s += ": "
} }
s += "index load: "
s += "pickle @" + strconv.FormatInt(e.Pos, 10) + ": " s += "pickle @" + strconv.FormatInt(e.Pos, 10) + ": "
s += e.Err.Error() s += e.Err.Error()
return s return s
...@@ -167,33 +174,36 @@ func (e *IndexLoadError) Error() string { ...@@ -167,33 +174,36 @@ func (e *IndexLoadError) Error() string {
// LoadIndex loads index from a reader // LoadIndex loads index from a reader
func LoadIndex(r io.Reader) (topPos int64, fsi *fsIndex, err error) { func LoadIndex(r io.Reader) (topPos int64, fsi *fsIndex, err error) {
var picklePos int64
{
var ok bool
var xtopPos, xv interface{}
xr := NewBufReader(r) xr := NewBufReader(r)
// by passing bufio.Reader directly we make sure it won't create one internally // by passing bufio.Reader directly we make sure it won't create one internally
p := pickle.NewDecoder(xr.Reader) p := pickle.NewDecoder(xr.Reader)
var picklePos int64
{
picklePos = xr.InputOffset() picklePos = xr.InputOffset()
xtopPos, err := p.Decode() xtopPos, err = p.Decode()
if err != nil { if err != nil {
goto out goto out
} }
var ok bool
topPos, ok = xtopPos.(int64) topPos, ok = xtopPos.(int64)
if !ok { if !ok {
err = fmt.Errorf("topPos is %T (expected int64)", xtopPos) err = fmt.Errorf("topPos is %T (expected int64)", xtopPos)
goto out goto out
} }
fsi = &fsIndex{} // TODO cmpFunc ... fsi = fsIndexNew()
var oidb [8]byte var oidb [8]byte
var posb [8]byte var posb [8]byte
loop: loop:
for { for {
// load/decode next entry // load/decode next entry
picklePos = xr.InputOffset() picklePos = xr.InputOffset()
xv, err := p.Decode() xv, err = p.Decode()
if err != nil { if err != nil {
goto out goto out
} }
...@@ -269,9 +279,10 @@ out: ...@@ -269,9 +279,10 @@ out:
return 0, nil, &IndexLoadError{IOName(r), picklePos, err} 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 { type CountReader struct {
io.Reader io.Reader
nread int64 nread int64
...@@ -306,7 +317,6 @@ func NewBufReader(r io.Reader) *BufReader { ...@@ -306,7 +317,6 @@ func NewBufReader(r io.Reader) *BufReader {
cr = &CountReader{r, 0} cr = &CountReader{r, 0}
} }
return &BufReader{bufio.NewReader(cr), cr} return &BufReader{bufio.NewReader(cr), cr}
} }
...@@ -338,10 +348,7 @@ func IOName(f interface {}) string { ...@@ -338,10 +348,7 @@ func IOName(f interface {}) string {
return "pipe" return "pipe"
// XXX SectionReader MultiReader TeeReader // XXX SectionReader MultiReader TeeReader
// XXX bufio.Reader bufio.Writer bufio.Scanner
// bufio.Reader bufio.Writer bufio.Scanner
default: default:
return "" return ""
} }
......
...@@ -6,6 +6,11 @@ import ( ...@@ -6,6 +6,11 @@ import (
"testing" "testing"
) )
func TestXXX(t *testing.T) { func TestIndexLookup(t *testing.T) {
// TODO // the lookup is tested in cznic.b itself
// here we only lightly excersize it
}
func TestIndexSaveLoad(t *testing.T) {
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment