Commit 2ef35dde authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 230cf05d
...@@ -524,17 +524,13 @@ func (fs *FileStorage) saveIndex() (err error) { ...@@ -524,17 +524,13 @@ func (fs *FileStorage) saveIndex() (err error) {
// XXX lock? // XXX lock?
defer xerr.Contextf(&err, "%s: index save", fs.file.Name()) defer xerr.Contextf(&err, "%s: index save", fs.file.Name())
idxname := fs.file.Name() + ".index" err = fs.index.SaveFile(fs.file.Name() + ".index")
idxtmp := idxname + ".index_tmp"
err = fs.index.SaveFile(idxtmp)
if err != nil { if err != nil {
return err return err
} }
// XXX fsync here? // XXX fsync here?
return nil
err = os.Rename(idxtmp, idxname)
return err
} }
// IndexCorruptError is the error returned when index verification fails // IndexCorruptError is the error returned when index verification fails
......
...@@ -32,54 +32,38 @@ import ( ...@@ -32,54 +32,38 @@ import (
// Reindex rebuilds index for FileStorage file @ path // Reindex rebuilds index for FileStorage file @ path
func Reindex(path string) error { func Reindex(path string) error {
// XXX open read-only // XXX lock path.lock ?
fs, err := fs1.Open(context.Background(), path) // XXX , fs1.OpenWithoutIndex) index, err := fs1.BuildIndexForFile(context.Background(), path)
if err != nil { if err != nil {
return nil // XXX err ctx return err
} }
defer fs.Close() // XXX err
err = fs.Reindex(nil)
return err // XXX ok?
}
// VerifyIndexFor verifies that on-disk index for FileStorage file @ path is correct err = index.SaveFile(path + ".index")
func VerifyIndexFor(path string) error {
// XXX open read-only
fs, err := fs1.Open(context.Background(), path) // XXX , 0)
if err != nil { if err != nil {
return nil // XXX err ctx return err // XXX err ctx
} }
defer fs.Close() // XXX err
err = fs.VerifyIndex(nil) return nil
return err
//fs.Index()
//fs.ComputeIndex
} }
// ---------------------------------------- const reindexSummary = "rebuild database index"
const reindexSummary = "XXX" // XXX
func reindexUsage(w io.Writer) { func reindexUsage(w io.Writer) {
fmt.Fprintf(w, fmt.Fprintf(w,
`Usage: fs1 reindex [options] <storage> `Usage: fs1 reindex [options] <storage>
Dump transactions from a FileStorage in reverse order XXX Rebuild FileStorage index
<storage> is a path to FileStorage <storage> is a path to FileStorage
options: options:
-h --help this help text. -h --help this help text.
-verify verify that existing index is correct; don't overwrite it `)
`, ntxnDefault)
} }
func reindexMain(argv []string) { func reindexMain(argv []string) {
flags := flag.FlagSet{Usage: func() { reindexUsage(os.Stderr) }} flags := flag.FlagSet{Usage: func() { reindexUsage(os.Stderr) }}
flags.Init("", flag.ExitOnError) flags.Init("", flag.ExitOnError)
// XXX -verify
flags.Parse(argv[1:]) flags.Parse(argv[1:])
argv = flags.Args() argv = flags.Args()
...@@ -95,5 +79,35 @@ func reindexMain(argv []string) { ...@@ -95,5 +79,35 @@ func reindexMain(argv []string) {
} }
} }
// ----------------------------------------
// TODO verify-index // TODO verify-index
// TODO verify-index -quick (only small sanity check) // TODO verify-index -quick (only small sanity check)
// VerifyIndexFor verifies that on-disk index for FileStorage file @ path is correct
func VerifyIndexFor(path string) error {
panic("TODO")
/*
// XXX open read-only
fs, err := fs1.Open(context.Background(), path) // XXX , 0)
if err != nil {
return nil // XXX err ctx
}
defer fs.Close() // XXX err
err = fs.VerifyIndex(nil)
return err
//fs.Index()
//fs.ComputeIndex
*/
}
const verifyIdxSummary = "verify database index"
func verifyIdxUsage(w io.Writer) {
panic("TODO") // XXX
}
func verifyIdxMaxin(argv []string) {
panic("TODO") // XXX
}
...@@ -26,8 +26,10 @@ import ( ...@@ -26,8 +26,10 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"math/big" "math/big"
"os" "os"
"path/filepath"
"strconv" "strconv"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
...@@ -169,22 +171,35 @@ out: ...@@ -169,22 +171,35 @@ out:
} }
// SaveFile saves index to a file @ path // SaveFile saves index to a file @ path
func (fsi *Index) SaveFile(path string) (err error) { //
f, err := os.Create(path) // Index data is first saved to a temporary file and when complete the
// temporary is renamed to be at requested path. This way file @ path will be
// updated only with complete index data.
func (fsi *Index) SaveFile(path string) error {
dir, name := filepath.Dir(path), filepath.Base(path)
f, err := ioutil.TempFile(dir, name + ".tmp")
if err != nil { if err != nil {
return &IndexSaveError{err} return &IndexSaveError{err} // XXX needed?
} }
// TODO use buffering for f (ogórek does not buffer itself on encoding) // TODO use buffering for f (ogórek does not buffer itself on encoding)
err1 := fsi.Save(f)
defer func() {
err2 := f.Close() err2 := f.Close()
if err2 != nil && err == nil { if err1 != nil || err2 != nil {
err = &IndexSaveError{err2} os.Remove(f.Name())
err = err1
if err == nil {
err = &IndexSaveError{err2} // XXX needed?
}
return err
}
err = os.Rename(f.Name(), path)
if err != nil {
return &IndexSaveError{err} // XXX needed?
} }
}()
return fsi.Save(f) return nil
} }
// IndexLoadError is the error type returned by index load routines // IndexLoadError is the error type returned by index load routines
...@@ -507,7 +522,7 @@ func BuildIndex(ctx context.Context, r io.ReaderAt) (*Index, error) { ...@@ -507,7 +522,7 @@ func BuildIndex(ctx context.Context, r io.ReaderAt) (*Index, error) {
func BuildIndexForFile(ctx context.Context, path string) (index *Index, err error) { func BuildIndexForFile(ctx context.Context, path string) (index *Index, err error) {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return IndexNew(), err return IndexNew(), err // XXX add err ctx?
} }
defer func() { defer func() {
......
...@@ -121,6 +121,8 @@ Usage: ...@@ -121,6 +121,8 @@ Usage:
The commands are: The commands are:
`, prog.Summary, prog.Name) `, prog.Summary, prog.Name)
// XXX 11 -> max width of cmd.Name
for _, cmd := range prog.Commands { for _, cmd := range prog.Commands {
fmt.Fprintf(w, "\t%-11s %s\n", cmd.Name, cmd.Summary) fmt.Fprintf(w, "\t%-11s %s\n", cmd.Name, cmd.Summary)
} }
...@@ -138,6 +140,7 @@ Additional help topics: ...@@ -138,6 +140,7 @@ Additional help topics:
`) `)
// XXX 11 -> max width of topic.Name
for _, topic := range prog.HelpTopics { for _, topic := range prog.HelpTopics {
fmt.Fprintf(w, "\t%-11s %s\n", topic.Name, topic.Summary) fmt.Fprintf(w, "\t%-11s %s\n", topic.Name, topic.Summary)
} }
......
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