cmd/swarm: added cleandb subcommand

This commit is contained in:
aron 2017-02-11 21:55:06 +01:00 committed by zelig
parent 3ef42985e6
commit 043d3c593f
3 changed files with 85 additions and 2 deletions

39
cmd/swarm/cleandb.go Normal file
View file

@ -0,0 +1,39 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"log"
"github.com/ethereum/go-ethereum/swarm/storage"
"gopkg.in/urfave/cli.v1"
)
func cleandb(ctx *cli.Context) {
args := ctx.Args()
if len(args) != 1 {
log.Fatal("need path to chunks database as the first and only argument")
}
chunkDbPath := args[0]
hash := storage.MakeHashFunc("SHA3")
dbStore, err := storage.NewDbStore(chunkDbPath, hash, 10000000, 0)
if err != nil {
log.Fatalf("cannot initialise dbstore: %v", err)
}
dbStore.Cleanup()
}

View file

@ -191,6 +191,15 @@ Removes a path from the manifest
}, },
}, },
}, },
{
Action: cleandb,
Name: "cleandb",
Usage: "Cleans database of corrupted entries",
ArgsUsage: " ",
Description: `
Cleans database of corrupted entries.
`,
},
} }
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{

View file

@ -261,6 +261,43 @@ func (s *DbStore) collectGarbage(ratio float32) {
s.db.Put(keyGCPos, s.gcPos) s.db.Put(keyGCPos, s.gcPos)
} }
func (s *DbStore) Cleanup() {
//Iterates over the database and checks that there are no faulty chunks
it := s.db.NewIterator()
startPosition := []byte{kpIndex}
it.Seek(startPosition)
var key []byte
var errorsFound, total int
for it.Valid() {
key = it.Key()
if (key == nil) || (key[0] != kpIndex) {
break
}
total++
var index dpaDBIndex
decodeIndex(it.Value(), &index)
data, err := s.db.Get(getDataKey(index.Idx))
if err != nil {
glog.V(logger.Warn).Infof("Chunk %x found but could not be accessed: %v", key[:], err)
s.delete(index.Idx, getIndexKey(key[1:]))
errorsFound++
} else {
hasher := s.hashfunc()
hasher.Write(data)
hash := hasher.Sum(nil)
if !bytes.Equal(hash, key[1:]) {
glog.V(logger.Warn).Infof("Found invalid chunk. Hash mismatch. hash=%x, key=%x", hash, key[:])
s.delete(index.Idx, getIndexKey(key[1:]))
errorsFound++
}
}
it.Next()
}
it.Release()
glog.V(logger.Warn).Infof("Found %v errors out of %v entries", errorsFound, total)
}
func (s *DbStore) delete(idx uint64, idxKey []byte) { func (s *DbStore) delete(idx uint64, idxKey []byte) {
batch := new(leveldb.Batch) batch := new(leveldb.Batch)
batch.Delete(idxKey) batch.Delete(idxKey)
@ -363,9 +400,7 @@ func (s *DbStore) Get(key Key) (chunk *Chunk, err error) {
hash := hasher.Sum(nil) hash := hasher.Sum(nil)
if !bytes.Equal(hash, key) { if !bytes.Equal(hash, key) {
s.delete(index.Idx, getIndexKey(key)) s.delete(index.Idx, getIndexKey(key))
err = fmt.Errorf("invalid chunk. hash=%x, key=%v", hash, key[:])
panic("Invalid Chunk in Database. Please repair with command: 'swarm cleandb'") panic("Invalid Chunk in Database. Please repair with command: 'swarm cleandb'")
return
} }
chunk = &Chunk{ chunk = &Chunk{