Commit 55f5a80c authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 3df8a3a8
......@@ -61,7 +61,10 @@ func fsIndexNew() *fsIndex {
// oid[6:8]oid[6:8]oid[6:8]...pos[0:6]pos[0:6]pos[0:6]...
const oidPrefixMask zodb.Oid = ((1<<64-1) ^ (1<<16 -1)) // 0xffffffffffff0000
const (
oidPrefixMask zodb.Oid = (1<<64-1) ^ (1<<16 - 1) // 0xffffffffffff0000
posInvalidMask uint64 = (1<<64-1) ^ (1<<48 - 1) // 0xffff000000000000
)
// IndexSaveError is the error type returned by index save routines
type IndexSaveError struct {
......@@ -72,7 +75,7 @@ func (e *IndexSaveError) Error() string {
return "index save: " + e.Err.Error()
}
// Save saves the index to a writer
// Save saves index to a writer
func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
var err error
......@@ -91,45 +94,47 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
posBuf := []byte{} // current pos[0:6]pos[0:6]...
var t [2]interface{} // tuple for (oid, fsBucket.toString())
e, err := fsi.SeekFirst()
if err == io.EOF { // always only io.EOF indicating an empty btree
goto skip
}
e, _ := fsi.SeekFirst()
if e != nil {
defer e.Close()
for {
oid, pos, errStop := e.Next()
oidPrefix := oid & oidPrefixMask
if oidPrefix != oidPrefixCur || errStop != nil {
// emit (oid[0:6], oid[6:8]oid[6:8]...pos[0:6]pos[0:6]...)
binary.BigEndian.PutUint64(oidb[:], uint64(oid))
t[0] = oidb[0:6]
t[1] = bytes.Join([][]byte{oidBuf, posBuf}, nil)
err = p.Encode(t)
if err != nil {
goto out
}
oidPrefixCur = oidPrefix
oidBuf = oidBuf[:0]
posBuf = posBuf[:0]
}
for {
oid, pos, errStop := e.Next()
oidPrefix := oid & oidPrefixMask
if errStop != nil {
break
}
if oidPrefix != oidPrefixCur || errStop != nil {
// emit (oid[:6], oid[6:8]oid[6:8]...pos[0:6]pos[0:6]...)
binary.BigEndian.PutUint64(oidb[:], uint64(oid))
t[0] = oidb[0:6]
t[1] = bytes.Join([][]byte{oidBuf, posBuf}, nil)
err = p.Encode(t)
if err != nil {
// check pos does not overflow 6 bytes
if uint64(pos) & posInvalidMask != 0 {
err = fmt.Errorf("entry position too large: 0x%x", pos)
goto out
}
oidPrefixCur = oidPrefix
oidBuf = oidBuf[:0]
posBuf = posBuf[:0]
}
binary.BigEndian.PutUint64(oidb[:], uint64(oid))
binary.BigEndian.PutUint64(posb[:], uint64(pos))
if errStop != nil {
break
oidBuf = append(oidBuf, oidb[6:8]...)
posBuf = append(posBuf, posb[0:6]...)
}
binary.BigEndian.PutUint64(oidb[:], uint64(oid))
binary.BigEndian.PutUint64(posb[:], uint64(pos))
// XXX check pos does not overflow 6 bytes
oidBuf = append(oidBuf, oidb[6:8]...)
posBuf = append(posBuf, posb[0:6]...)
}
e.Close()
skip:
err = p.Encode(pickle.None{})
}
......
......@@ -9,6 +9,7 @@ import (
"testing"
"../../zodb"
"./fsb"
)
type indexEntry struct {
......@@ -32,7 +33,7 @@ var indexTest1 = [...]indexEntry {
{0xffffffffffffffff, 777},
{0xfffffffffffffff0, 888},
{0x8000000000000000, 999},
{0xa000000000000000, 0x7fffffffffffffff},
{0xa000000000000000, 0x0000ffffffffffff},
}
func setIndex(fsi *fsIndex, kv []indexEntry) {
......@@ -41,6 +42,39 @@ func setIndex(fsi *fsIndex, kv []indexEntry) {
}
}
// test whether two trees are equal
func treeEqual(a, b *fsb.Tree) bool {
if a.Len() != b.Len() {
return false
}
ea, _ := a.SeekFirst()
eb, _ := b.SeekFirst()
if ea == nil {
// this means len(a) == 0 -> len(b) == 0 -> eb = nil
return true
}
for {
ka, va, stopa := ea.Next()
kb, vb, stopb := eb.Next()
if stopa != nil || stopb != nil {
if stopa != stopb {
panic("same-length trees iteration did not end at the same time")
}
break
}
if !(ka == kb && va == vb) {
return false
}
}
return true
}
func TestIndexLookup(t *testing.T) {
// the lookup is tested in cznic.b itself
// here we only lightly exercise it
......@@ -125,5 +159,12 @@ func TestIndexSaveLoad(t *testing.T) {
t.Errorf("index load: topPos mismatch: %v ; want %v", topPos2, topPos)
}
_ = fsi2
// XXX is it ok to compare trees via reflect.DeepEqual ?
if !treeEqual(fsi2.Tree, fsi.Tree) {
t.Errorf("index load: trees mismatch: %v ; want %v", fsi2.Tree, fsi.Tree)
}
// TODO check with
// {0xb000000000000000, 0x7fffffffffffffff}, // will cause 'entry position too large'
}
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