Commit c38ab95d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent d1866974
......@@ -24,55 +24,96 @@ package main
import (
"crypto/sha1"
"flag"
"fmt"
"io"
"log"
"os"
"../../../../storage/fs1"
)
fsDump(w io.Writer, path string, ntxn int) error {
func fsDump(w io.Writer, path string, ntxn int) (err error) {
// path & fsdump on error context
defer func() {
if err != nil {
err = fmt.Errorf("%s: fsdump: %v", err)
}
}()
// we are not using fs1.Open here, since the file could be e.g. corrupt
// (same logic as in fstail/py)
f, err := os.Open(path)
// XXX err
if err != nil {
return err
}
// TODO get fSize
// get file size as topPos
fi, err := f.Stat()
if err != nil {
return err
}
topPos := fi.Size()
// txn header & data buffer for iterating
txnh := fs1.TxnHeader{}
data := []byte{}
// start iterating at tail.
// this should get EOF but read txnh.LenPrev ok.
err = txnh.Load(f, fSize, LoadAll)
err = txnh.Load(f, topPos, fs1.LoadAll)
if err != io.EOF {
if err == nil {
// XXX or allow this?
// though then, if we start not from a txn boundary - there are
// high chances further iteration will go wrong.
err = fmt.Errorf("%s @%v: reading past file end was unexpectedly successful: probably the file is being modified simultaneously",
path, fSize)
err = fmt.Errorf("@%v: reading past file end was unexpectedly successful: probably the file is being modified simultaneously", topPos)
}
// otherwise err already has the context
return err
}
if txnh.LenPrev <= 0 {
return fmt.Errorf("%s @%v: previous record could not be read", path, fSize)
return fmt.Errorf("@%v: previous record could not be read", topPos)
}
// now loop loading previous txn until EOF / ntxn limit
for {
err = txnh.LoadPrev(fs1.LoadAll)
for i := ntxn; i > 0; i-- {
err = txnh.LoadPrev(f, fs1.LoadAll)
if err != nil {
if err == io.EOF {
err = nil
err = nil // XXX -> okEOF(err)
}
break
}
// TODO read raw data (get_raw_data) -> sha1
// txnh.Tid.TimeStamp() ? XXX -> PerTimeStamp ? (get_timestamp)
// read raw data inside transaction record
dataLen := txnh.DataLen()
if int64(cap(data)) < dataLen {
data = make([]byte, dataLen)
} else {
data = data[:dataLen]
}
//"user=%'q description=%'q length=%d offset=%d (+%d)", txnh.User, txnh.Description, // .Len, .offset ...
_, err = f.ReadAt(data, txnh.DataPos())
if err != nil {
// XXX -> txnh.Err(...) ?
// XXX err = noEOF(err)
err = &fs1.ErrTxnRecord{txnh.Pos, "read data payload", err}
break
}
// print information about read txn record
_, err = fmt.Fprintf(w, "%s: hash=%x\nuser=%q description=%q length=%d offset=%d (+%d)\n\n",
txnh.Tid.Time(), sha1.Sum(data),
txnh.User, txnh.Description,
// NOTE in zodb/py .length is len - 8, in zodb/go - whole txn record length
txnh.Len - 8,
txnh.Pos, txnh.HeaderLen())
if err != nil {
// TODO
break
}
}
return err
}
func usage() {
......@@ -101,7 +142,7 @@ func main() {
}
storPath := argv[0]
err = fsDump(os.Stdout, storPath, n)
err := fsDump(os.Stdout, storPath, n)
if err != nil {
log.Fatal(err)
}
......
......@@ -174,6 +174,16 @@ func (txnh *TxnHeader) HeaderLen() int64 {
return TxnHeaderFixSize + int64(len(txnh.workMem))
}
// DataPos returns start position of data inside transaction record
func (txnh *TxnHeader) DataPos() int64 {
return txnh.Pos + txnh.HeaderLen()
}
// DataLen returns length of all data inside transaction record container
func (txnh *TxnHeader) DataLen() int64 {
return txnh.Len - txnh.HeaderLen() - 8 /* trailer redundant length */
}
// CloneFrom copies txnh2 to txnh making sure underlying slices (.workMem .User
// .Desc ...) are not shared.
func (txnh *TxnHeader) CloneFrom(txnh2 *TxnHeader) {
......@@ -899,7 +909,7 @@ func (fsi *iterator) NextTxn() (*zodb.TxnInfo, zodb.IStorageRecordIterator, erro
}
// set .dataIter to iterate over .txnIter.Txnh
fsi.dataIter.Datah.Pos = fsi.txnIter.Txnh.Pos + fsi.txnIter.Txnh.HeaderLen()
fsi.dataIter.Datah.Pos = fsi.txnIter.Txnh.DataPos()
fsi.dataIter.Datah.DataLen = -DataHeaderSize // first iteration will go to first data record
return &fsi.txnIter.Txnh.TxnInfo, &fsi.dataIter, nil
......
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