Commit 7d57d607 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 55a64368
...@@ -486,7 +486,7 @@ func TestMasterStorage(t *testing.T) { ...@@ -486,7 +486,7 @@ func TestMasterStorage(t *testing.T) {
pg.Done() pg.Done()
for { for {
_, dataIter, err := ziter.NextTxn() _, dataIter, err := ziter.NextTxn(bg)
if err == io.EOF { if err == io.EOF {
break break
} }
...@@ -495,7 +495,7 @@ func TestMasterStorage(t *testing.T) { ...@@ -495,7 +495,7 @@ func TestMasterStorage(t *testing.T) {
} }
for { for {
datai, err := dataIter.NextData() datai, err := dataIter.NextData(bg)
if err == io.EOF { if err == io.EOF {
break break
} }
......
...@@ -205,19 +205,17 @@ func (fs *FileStorage) Close() error { ...@@ -205,19 +205,17 @@ func (fs *FileStorage) Close() error {
func (fs *FileStorage) LastTid(_ context.Context) (zodb.Tid, error) { func (fs *FileStorage) LastTid(_ context.Context) (zodb.Tid, error) {
// XXX check we have transactions at all // XXX check we have transactions at all - what to return if not?
// XXX what to return if not?
// XXX must be under lock // XXX must be under lock
return fs.txnhMax.Tid, nil // XXX error always nil ? return fs.txnhMax.Tid, nil
} }
func (fs *FileStorage) LastOid(_ context.Context) (zodb.Oid, error) { func (fs *FileStorage) LastOid(_ context.Context) (zodb.Oid, error) {
// XXX check we have objects at all? // XXX check we have objects at all - what to return if not?
// XXX what to return if not?
// XXX must be under lock // XXX must be under lock
// XXX what if an oid was deleted? // XXX what if an oid was deleted?
lastOid, _ := fs.index.Last() // returns zero-value, if empty lastOid, _ := fs.index.Last() // returns zero-value, if empty
return lastOid, nil // XXX error always nil? return lastOid, nil
} }
// ErrXidLoad is returned when there is an error while loading xid // ErrXidLoad is returned when there is an error while loading xid
...@@ -334,7 +332,7 @@ const ( ...@@ -334,7 +332,7 @@ const (
) )
// NextTxn iterates to next/previous transaction record according to iteration direction // NextTxn iterates to next/previous transaction record according to iteration direction
func (zi *zIter) NextTxn() (*zodb.TxnInfo, zodb.IDataIterator, error) { func (zi *zIter) NextTxn(_ context.Context) (*zodb.TxnInfo, zodb.IDataIterator, error) {
switch { switch {
case zi.zFlags & zIterEOF != 0: case zi.zFlags & zIterEOF != 0:
//println("already eof") //println("already eof")
...@@ -366,7 +364,7 @@ func (zi *zIter) NextTxn() (*zodb.TxnInfo, zodb.IDataIterator, error) { ...@@ -366,7 +364,7 @@ func (zi *zIter) NextTxn() (*zodb.TxnInfo, zodb.IDataIterator, error) {
} }
// NextData iterates to next data record and loads data content // NextData iterates to next data record and loads data content
func (zi *zIter) NextData() (*zodb.DataInfo, error) { func (zi *zIter) NextData(_ context.Context) (*zodb.DataInfo, error) {
err := zi.iter.NextData() err := zi.iter.NextData()
if err != nil { if err != nil {
return nil, err // XXX recheck return nil, err // XXX recheck
...@@ -395,7 +393,8 @@ func (zi *zIter) NextData() (*zodb.DataInfo, error) { ...@@ -395,7 +393,8 @@ func (zi *zIter) NextData() (*zodb.DataInfo, error) {
// iterStartError is the iterator created when there are preparatory errors // iterStartError is the iterator created when there are preparatory errors.
//
// this way we offload clients, besides handling NextTxn errors, from also // this way we offload clients, besides handling NextTxn errors, from also
// handling error cases from Iterate. // handling error cases from Iterate.
// //
...@@ -404,7 +403,7 @@ type iterStartError struct { ...@@ -404,7 +403,7 @@ type iterStartError struct {
err error err error
} }
func (e *iterStartError) NextTxn() (*zodb.TxnInfo, zodb.IDataIterator, error) { func (e *iterStartError) NextTxn(_ context.Context) (*zodb.TxnInfo, zodb.IDataIterator, error) {
return nil, nil, e.err return nil, nil, e.err
} }
......
...@@ -145,10 +145,11 @@ func TestLoad(t *testing.T) { ...@@ -145,10 +145,11 @@ func TestLoad(t *testing.T) {
// iterate tidMin..tidMax and expect db entries in expectv // iterate tidMin..tidMax and expect db entries in expectv
func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv []dbEntry) { func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv []dbEntry) {
ctx := context.Background()
iter := fs.Iterate(tidMin, tidMax) iter := fs.Iterate(tidMin, tidMax)
fsi, ok := iter.(*zIter) fsi, ok := iter.(*zIter)
if !ok { if !ok {
_, _, err := iter.NextTxn() _, _, err := iter.NextTxn(ctx)
t.Errorf("iterating %v..%v: iter type is %T ; want zIter\nNextTxn gives: _, _, %v", tidMin, tidMax, iter, err) t.Errorf("iterating %v..%v: iter type is %T ; want zIter\nNextTxn gives: _, _, %v", tidMin, tidMax, iter, err)
return return
} }
...@@ -161,7 +162,7 @@ func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv ...@@ -161,7 +162,7 @@ func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv
t.Errorf("%v: %v", subj, msg) t.Errorf("%v: %v", subj, msg)
} }
txni, dataIter, err := iter.NextTxn() txni, dataIter, err := iter.NextTxn(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
if k != len(expectv) { if k != len(expectv) {
...@@ -203,7 +204,7 @@ func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv ...@@ -203,7 +204,7 @@ func testIterate(t *testing.T, fs *FileStorage, tidMin, tidMax zodb.Tid, expectv
txnErrorf("%v: %v", dsubj, msg) txnErrorf("%v: %v", dsubj, msg)
} }
datai, err := dataIter.NextData() datai, err := dataIter.NextData(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
if kdata != len(dbe.Entryv) { if kdata != len(dbe.Entryv) {
...@@ -293,12 +294,14 @@ func BenchmarkIterate(b *testing.B) { ...@@ -293,12 +294,14 @@ func BenchmarkIterate(b *testing.B) {
fs := xfsopen(b, "testdata/1.fs") // TODO open ro fs := xfsopen(b, "testdata/1.fs") // TODO open ro
defer exc.XRun(fs.Close) defer exc.XRun(fs.Close)
ctx := context.Background()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
iter := fs.Iterate(zodb.Tid(0), zodb.TidMax) iter := fs.Iterate(zodb.Tid(0), zodb.TidMax)
for { for {
txni, dataIter, err := iter.NextTxn() txni, dataIter, err := iter.NextTxn(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
break break
...@@ -310,7 +313,7 @@ func BenchmarkIterate(b *testing.B) { ...@@ -310,7 +313,7 @@ func BenchmarkIterate(b *testing.B) {
_ = txni.Tid _ = txni.Tid
for { for {
datai, err := dataIter.NextData() datai, err := dataIter.NextData(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
break break
......
...@@ -31,8 +31,7 @@ import ( ...@@ -31,8 +31,7 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1" "lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
"github.com/sergi/go-diff/diffmatchpatch" "github.com/kylelemons/godebug/diff"
//diffpkg "github.com/kylelemons/godebug/diff"
) )
// XXX -> xtesting ? // XXX -> xtesting ?
...@@ -44,14 +43,6 @@ func loadFile(t *testing.T, path string) string { ...@@ -44,14 +43,6 @@ func loadFile(t *testing.T, path string) string {
return string(data) return string(data)
} }
// XXX -> xtesting ?
// XXX dup in zodbdump_test.go
func diff(a, b string) string {
dmp := diffmatchpatch.New()
diffv := dmp.DiffMain(a, b, /*checklines=*/false)
return dmp.DiffPrettyText(diffv)
}
func testDump(t *testing.T, dir fs1.IterDir, d Dumper) { func testDump(t *testing.T, dir fs1.IterDir, d Dumper) {
buf := bytes.Buffer{} buf := bytes.Buffer{}
...@@ -63,7 +54,7 @@ func testDump(t *testing.T, dir fs1.IterDir, d Dumper) { ...@@ -63,7 +54,7 @@ func testDump(t *testing.T, dir fs1.IterDir, d Dumper) {
dumpOk := loadFile(t, fmt.Sprintf("testdata/1.%s.ok", d.DumperName())) dumpOk := loadFile(t, fmt.Sprintf("testdata/1.%s.ok", d.DumperName()))
if dumpOk != buf.String() { if dumpOk != buf.String() {
t.Errorf("%s: dump different:\n%v", d.DumperName(), diff(dumpOk, buf.String())) t.Errorf("%s: dump different:\n%v", d.DumperName(), diff.Diff(dumpOk, buf.String()))
} }
} }
......
...@@ -75,7 +75,7 @@ type DataInfo struct { ...@@ -75,7 +75,7 @@ type DataInfo struct {
Tid Tid Tid Tid
Data []byte // nil means: deleted XXX -> *Buf ? Data []byte // nil means: deleted XXX -> *Buf ?
// original tid data was committed (e.g. in case of undo) // original tid data was committed at (e.g. in case of undo)
// //
// FIXME we don't really need this and this unnecessarily constraints interfaces. // FIXME we don't really need this and this unnecessarily constraints interfaces.
DataTid Tid DataTid Tid
...@@ -133,8 +133,6 @@ func (e *ErrXidMissing) Error() string { ...@@ -133,8 +133,6 @@ func (e *ErrXidMissing) Error() string {
// IStorage is the interface provided by ZODB storages // IStorage is the interface provided by ZODB storages
type IStorage interface { type IStorage interface {
// TODO add invalidation channel
// StorageName returns storage name // StorageName returns storage name
StorageName() string StorageName() string
...@@ -148,7 +146,7 @@ type IStorage interface { ...@@ -148,7 +146,7 @@ type IStorage interface {
// LastOid returns highest object id of objects committed to storage. // LastOid returns highest object id of objects committed to storage.
// //
// if there is no data committed yet, LastOid returns Oid zero value XXX -> better -1 // if there is no data committed yet, LastOid returns Oid zero value XXX -> better -1 ?
// XXX ZODB/py does not define this in IStorage. // XXX ZODB/py does not define this in IStorage.
LastOid(ctx context.Context) (Oid, error) LastOid(ctx context.Context) (Oid, error)
...@@ -166,6 +164,8 @@ type IStorage interface { ...@@ -166,6 +164,8 @@ type IStorage interface {
// Prefetch(ctx, xid Xid) (no error) // Prefetch(ctx, xid Xid) (no error)
// TODO add invalidation channel (notify about changes made to DB not by us)
// Store(oid Oid, serial Tid, data []byte, txn ITransaction) error // Store(oid Oid, serial Tid, data []byte, txn ITransaction) error
// XXX Restore ? // XXX Restore ?
// CheckCurrentSerialInTransaction(oid Oid, serial Tid, txn ITransaction) // XXX naming // CheckCurrentSerialInTransaction(oid Oid, serial Tid, txn ITransaction) // XXX naming
...@@ -191,7 +191,7 @@ type ITxnIterator interface { ...@@ -191,7 +191,7 @@ type ITxnIterator interface {
// 2. iterator over transaction's data records. // 2. iterator over transaction's data records.
// transaction metadata stays valid until next call to NextTxn(). // transaction metadata stays valid until next call to NextTxn().
// end of iteration is indicated with io.EOF // end of iteration is indicated with io.EOF
NextTxn() (*TxnInfo, IDataIterator, error) // XXX ctx NextTxn(ctx context.Context) (*TxnInfo, IDataIterator, error)
} }
// IDataIterator is the interface to iterate data records. // IDataIterator is the interface to iterate data records.
...@@ -199,7 +199,7 @@ type IDataIterator interface { ...@@ -199,7 +199,7 @@ type IDataIterator interface {
// NextData yields information about next storage data record. // NextData yields information about next storage data record.
// returned data stays valid until next call to NextData(). // returned data stays valid until next call to NextData().
// end of iteration is indicated with io.EOF // end of iteration is indicated with io.EOF
NextData() (*DataInfo, error) // XXX ctx NextData(ctx context.Context) (*DataInfo, error)
} }
// ---- misc ---- // ---- misc ----
......
...@@ -144,7 +144,7 @@ out: ...@@ -144,7 +144,7 @@ out:
} }
// DumpTxn dumps one transaction record // DumpTxn dumps one transaction record
func (d *dumper) DumpTxn(txni *zodb.TxnInfo, dataIter zodb.IDataIterator) error { func (d *dumper) DumpTxn(ctx context.Context, txni *zodb.TxnInfo, dataIter zodb.IDataIterator) error {
var datai *zodb.DataInfo var datai *zodb.DataInfo
// LF in-between txn records // LF in-between txn records
...@@ -162,7 +162,7 @@ func (d *dumper) DumpTxn(txni *zodb.TxnInfo, dataIter zodb.IDataIterator) error ...@@ -162,7 +162,7 @@ func (d *dumper) DumpTxn(txni *zodb.TxnInfo, dataIter zodb.IDataIterator) error
// data records // data records
for { for {
datai, err = dataIter.NextData() datai, err = dataIter.NextData(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
err = nil // XXX -> okEOF ? err = nil // XXX -> okEOF ?
...@@ -189,7 +189,7 @@ out: ...@@ -189,7 +189,7 @@ out:
} }
// Dump dumps transaction records in between tidMin..tidMax // Dump dumps transaction records in between tidMin..tidMax
func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error { func (d *dumper) Dump(ctx context.Context, stor zodb.IStorage, tidMin, tidMax zodb.Tid) error {
var txni *zodb.TxnInfo var txni *zodb.TxnInfo
var dataIter zodb.IDataIterator var dataIter zodb.IDataIterator
var err error var err error
...@@ -198,7 +198,7 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error { ...@@ -198,7 +198,7 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error {
// transactions // transactions
for { for {
txni, dataIter, err = iter.NextTxn() txni, dataIter, err = iter.NextTxn(ctx)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
err = nil // XXX -> okEOF ? err = nil // XXX -> okEOF ?
...@@ -207,7 +207,7 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error { ...@@ -207,7 +207,7 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error {
break break
} }
err = d.DumpTxn(txni, dataIter) err = d.DumpTxn(ctx, txni, dataIter)
if err != nil { if err != nil {
break break
} }
...@@ -221,10 +221,11 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error { ...@@ -221,10 +221,11 @@ func (d *dumper) Dump(stor zodb.IStorage, tidMin, tidMax zodb.Tid) error {
} }
// Dump dumps contents of a storage in between tidMin..tidMax range to a writer. // Dump dumps contents of a storage in between tidMin..tidMax range to a writer.
//
// see top-level documentation for the dump format. // see top-level documentation for the dump format.
func Dump(w io.Writer, stor zodb.IStorage, tidMin, tidMax zodb.Tid, hashOnly bool) error { func Dump(ctx context.Context, w io.Writer, stor zodb.IStorage, tidMin, tidMax zodb.Tid, hashOnly bool) error {
d := dumper{W: w, HashOnly: hashOnly} d := dumper{W: w, HashOnly: hashOnly}
return d.Dump(stor, tidMin, tidMax) return d.Dump(ctx, stor, tidMin, tidMax)
} }
// ---------------------------------------- // ----------------------------------------
...@@ -270,13 +271,15 @@ func dumpMain(argv []string) { ...@@ -270,13 +271,15 @@ func dumpMain(argv []string) {
prog.Fatal(err) prog.Fatal(err)
} }
stor, err := zodb.OpenStorage(context.Background(), storUrl, &zodb.OpenOptions{ReadOnly: true}) ctx := context.Background()
stor, err := zodb.OpenStorage(ctx, storUrl, &zodb.OpenOptions{ReadOnly: true})
if err != nil { if err != nil {
prog.Fatal(err) prog.Fatal(err)
} }
// TODO defer stor.Close() // TODO defer stor.Close()
err = Dump(os.Stdout, stor, tidMin, tidMax, hashOnly) err = Dump(ctx, os.Stdout, stor, tidMin, tidMax, hashOnly)
if err != nil { if err != nil {
prog.Fatal(err) prog.Fatal(err)
} }
......
...@@ -28,22 +28,13 @@ import ( ...@@ -28,22 +28,13 @@ import (
"regexp" "regexp"
"testing" "testing"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
_ "lab.nexedi.com/kirr/neo/go/zodb/wks"
"github.com/sergi/go-diff/diffmatchpatch" "github.com/kylelemons/godebug/diff"
"lab.nexedi.com/kirr/go123/exc" "lab.nexedi.com/kirr/go123/exc"
) )
// diff computes difference for two strings a and b
// XXX -> xtesting ?
// XXX dup in fstail_test.go
func diff(a, b string) string {
dmp := diffmatchpatch.New()
diffv := dmp.DiffMain(a, b, /*checklines=*/false)
return dmp.DiffPrettyText(diffv)
}
// loadZdumpPy loads a zdump file and normalizes escaped strings to the way go // loadZdumpPy loads a zdump file and normalizes escaped strings to the way go
// would escape them. // would escape them.
func loadZdumpPy(t *testing.T, path string) string { func loadZdumpPy(t *testing.T, path string) string {
...@@ -73,23 +64,22 @@ func loadZdumpPy(t *testing.T, path string) string { ...@@ -73,23 +64,22 @@ func loadZdumpPy(t *testing.T, path string) string {
return string(dump) return string(dump)
} }
func withTestdata1Fs(t testing.TB, f func(fs *fs1.FileStorage)) { func withTestdata1Fs(t testing.TB, f func(zstor zodb.IStorage)) {
// XXX -> zodb.OpenURL zstor, err := zodb.OpenStorage(context.Background(), "../../zodb/storage/fs1/testdata/1.fs", &zodb.OpenOptions{ReadOnly: true})
fs, err := fs1.Open(context.Background(), "../../zodb/storage/fs1/testdata/1.fs") // XXX read-only, path?
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer exc.XRun(fs.Close) defer exc.XRun(zstor.Close)
f(fs) f(zstor)
} }
func TestZodbDump(t *testing.T) { func TestZodbDump(t *testing.T) {
withTestdata1Fs(t, func(fs *fs1.FileStorage) { withTestdata1Fs(t, func(zstor zodb.IStorage) {
buf := bytes.Buffer{} buf := bytes.Buffer{}
err := Dump(&buf, fs, 0, zodb.TidMax, false) err := Dump(context.Background(), &buf, zstor, 0, zodb.TidMax, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -97,7 +87,7 @@ func TestZodbDump(t *testing.T) { ...@@ -97,7 +87,7 @@ func TestZodbDump(t *testing.T) {
dumpOk := loadZdumpPy(t, "testdata/1.zdump.pyok") dumpOk := loadZdumpPy(t, "testdata/1.zdump.pyok")
if dumpOk != buf.String() { if dumpOk != buf.String() {
t.Errorf("dump different:\n%v", diff(dumpOk, buf.String())) t.Errorf("dump different:\n%v", diff.Diff(dumpOk, buf.String()))
} }
}) })
} }
...@@ -105,11 +95,11 @@ func TestZodbDump(t *testing.T) { ...@@ -105,11 +95,11 @@ func TestZodbDump(t *testing.T) {
func BenchmarkZodbDump(b *testing.B) { func BenchmarkZodbDump(b *testing.B) {
// FIXME small testdata/1.fs is not representative for benchmarking // FIXME small testdata/1.fs is not representative for benchmarking
withTestdata1Fs(b, func(fs *fs1.FileStorage) { withTestdata1Fs(b, func(zstor zodb.IStorage) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
err := Dump(ioutil.Discard, fs, 0, zodb.TidMax, false) err := Dump(context.Background(), ioutil.Discard, zstor, 0, zodb.TidMax, false)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
......
...@@ -51,19 +51,20 @@ http://docs.pylonsproject.org/projects/zodburi/ ...@@ -51,19 +51,20 @@ http://docs.pylonsproject.org/projects/zodburi/
` `
const helpXid = const helpXid =
`TODO describe `An object address for loading from ZODB should be specified as follows:
=tid:oid - "=" or "<" character depending on whether it is exact or "tid before" query
<tid:oid - tid
` - ":"
- oid
for example
// TODO dump format =0285cbac258bf266:0000000000000001 - oid 1 at exactly 0285cbac258bf266 transaction
const helpZDump = <0285cbac258bf266:0000000000000001 - oid 1 at first newest transaction changing it with tid < 0285cbac258bf266
`TODO describe zodb dump format
` `
var helpTopics = prog.HelpRegistry{ var helpTopics = prog.HelpRegistry{
{"zurl", "specifying database URL", helpZURL}, {"zurl", "specifying database URL", helpZURL},
{"xid", "specifying object address", helpXid}, {"xid", "specifying object address", helpXid},
{"zdump", "description of ZODB dump format", helpZDump},
} }
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