Commit 6103fd3e authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent eab0c6e3
...@@ -37,6 +37,9 @@ import ( ...@@ -37,6 +37,9 @@ import (
// Dumper is interface to implement various dumping modes // Dumper is interface to implement various dumping modes
type Dumper interface { type Dumper interface {
// DumperName defines concise name to use in error-reporting when using this dumper.
DumperName() string
// DumpFileHeader dumps fh to buf // DumpFileHeader dumps fh to buf
DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error
...@@ -54,7 +57,7 @@ type Dumper interface { ...@@ -54,7 +57,7 @@ type Dumper interface {
// To do so it reads file header and then iterates over all transactions in the file. // To do so it reads file header and then iterates over all transactions in the file.
// The logic to actually output information and if needed read/process data is implemented by Dumper d. // The logic to actually output information and if needed read/process data is implemented by Dumper d.
func Dump(w io.Writer, path string, dir fs1.IterDir, d Dumper) (err error) { func Dump(w io.Writer, path string, dir fs1.IterDir, d Dumper) (err error) {
defer xerr.Contextf(&err, "%s: dump", path) // XXX ok? XXX name ? defer xerr.Contextf(&err, "%s: %s", path, d.DumperName()) // XXX ok?
it, f, err := fs1.IterateFile(path, dir) it, f, err := fs1.IterateFile(path, dir)
if err != nil { if err != nil {
...@@ -128,6 +131,10 @@ type DumperFsDump struct { ...@@ -128,6 +131,10 @@ type DumperFsDump struct {
ntxn int // current transaction record # ntxn int // current transaction record #
} }
func (d *DumperFsDump) DumperName() string {
return "fsdump"
}
func (d *DumperFsDump) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error { func (d *DumperFsDump) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error {
return nil return nil
} }
...@@ -184,7 +191,6 @@ func (d *DumperFsDump) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error { ...@@ -184,7 +191,6 @@ func (d *DumperFsDump) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error {
return nil return nil
} }
// DumperFsDumpVerbose implements a very verbose dumper with output identical // DumperFsDumpVerbose implements a very verbose dumper with output identical
// to fsdump.Dumper in zodb/py originally written by Jeremy Hylton: // to fsdump.Dumper in zodb/py originally written by Jeremy Hylton:
// //
...@@ -193,6 +199,10 @@ func (d *DumperFsDump) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error { ...@@ -193,6 +199,10 @@ func (d *DumperFsDump) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error {
type DumperFsDumpVerbose struct { type DumperFsDumpVerbose struct {
} }
func (d *DumperFsDumpVerbose) DumperName() string {
return "fsdumpv"
}
func (d *DumperFsDumpVerbose) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error { func (d *DumperFsDumpVerbose) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error {
for i := 0; i < 60; i++ { for i := 0; i < 60; i++ {
buf .S("*") buf .S("*")
...@@ -254,6 +264,49 @@ func (d *DumperFsDumpVerbose) dumpData(buf *xfmt.Buffer, it *fs1.Iter) error { ...@@ -254,6 +264,49 @@ func (d *DumperFsDumpVerbose) dumpData(buf *xfmt.Buffer, it *fs1.Iter) error {
return nil return nil
} }
const dumpSummary = "dump database transactions"
func dumpUsage(w io.Writer) {
fmt.Fprintf(w,
`Usage: fs1 dump [options] <storage>
Dump transactions from a FileStorage
<storage> is a path to FileStorage
options:
-h --help this help text.
-v verbose mode.
`)
}
func dumpMain(argv []string) {
var verbose bool
flags := flag.FlagSet{Usage: func() { tailUsage(os.Stderr) }}
flags.Init("", flag.ExitOnError)
flags.BoolVar(&verbose, "v", verbose, "verbose mode")
flags.Parse(argv[1:])
argv = flags.Args()
if len(argv) < 1 {
flags.Usage()
os.Exit(2)
}
storPath := argv[0]
var d Dumper
if verbose {
d = &DumperFsDumpVerbose{}
} else {
d = &DumperFsDump{}
}
err := Dump(os.Stdout, storPath, fs1.IterForward, d)
if err != nil {
log.Fatal(err)
}
}
// ---------------------------------------- // ----------------------------------------
// DumperFsTail implements dumping with the same format as in fstail/py // DumperFsTail implements dumping with the same format as in fstail/py
...@@ -266,6 +319,10 @@ type DumperFsTail struct { ...@@ -266,6 +319,10 @@ type DumperFsTail struct {
data []byte // buffer for reading txn data data []byte // buffer for reading txn data
} }
func (d *DumperFsTail) DumperName() string {
return "fstail"
}
func (d *DumperFsTail) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error { func (d *DumperFsTail) DumpFileHeader(buf *xfmt.Buffer, fh *fs1.FileHeader) error {
return nil return nil
} }
......
...@@ -23,8 +23,8 @@ package fs1tools ...@@ -23,8 +23,8 @@ package fs1tools
import "lab.nexedi.com/kirr/neo/go/zodb/zodbtools" import "lab.nexedi.com/kirr/neo/go/zodb/zodbtools"
var commands = zodbtools.CommandRegistry{ var commands = zodbtools.CommandRegistry{
{"dump", dumpSummary, dumpUsage, dumpMain},
{"tail", tailSummary, tailUsage, tailMain}, {"tail", tailSummary, tailUsage, tailMain},
// dump, dump+verbose (fsdump.py)
// + fsstats? (fsstats.py) // + fsstats? (fsstats.py)
{"reindex", reindexSummary, reindexUsage, reindexMain}, {"reindex", reindexSummary, reindexUsage, reindexMain},
......
...@@ -49,24 +49,24 @@ func diff(a, b string) string { ...@@ -49,24 +49,24 @@ func diff(a, b string) string {
return dmp.DiffPrettyText(diffv) return dmp.DiffPrettyText(diffv)
} }
func testDump(t *testing.T, name string, dir fs1.IterDir, d Dumper) { func testDump(t *testing.T, dir fs1.IterDir, d Dumper) {
buf := bytes.Buffer{} buf := bytes.Buffer{}
err := Dump(&buf, "../testdata/1.fs", dir, d) err := Dump(&buf, "../testdata/1.fs", dir, d)
if err != nil { if err != nil {
t.Fatalf("%s: %v", name, err) t.Fatalf("%s: %v", d.DumperName(), err)
} }
dumpOk := loadFile(t, fmt.Sprintf("testdata/1.%s.ok", name)) 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", name, diff(dumpOk, buf.String())) t.Errorf("%s: dump different:\n%v", d.DumperName(), diff(dumpOk, buf.String()))
} }
} }
func TestFsDump(t *testing.T) { testDump(t, "fsdump", fs1.IterForward, &DumperFsDump{}) } func TestFsDump(t *testing.T) { testDump(t, fs1.IterForward, &DumperFsDump{}) }
func TestFsDumpv(t *testing.T) { testDump(t, "fsdumpv", fs1.IterForward, &DumperFsDumpVerbose{}) } func TestFsDumpv(t *testing.T) { testDump(t, fs1.IterForward, &DumperFsDumpVerbose{}) }
func TestFsTail(t *testing.T) { testDump(t, "fstail", fs1.IterBackward, &DumperFsTail{Ntxn: 1000000}) } func TestFsTail(t *testing.T) { testDump(t, fs1.IterBackward, &DumperFsTail{Ntxn: 1000000}) }
func BenchmarkTail(b *testing.B) { func BenchmarkTail(b *testing.B) {
// FIXME small testdata/1.fs is not representative for benchmarking // FIXME small testdata/1.fs is not representative for benchmarking
......
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