2012-08-07 01:20:26 +00:00
package main
import (
2013-01-14 20:42:35 +00:00
"errors"
2012-12-21 06:32:21 +00:00
"log"
"os"
"path"
"pkg/storage"
"strconv"
2012-08-07 01:20:26 +00:00
)
func init ( ) {
2012-12-21 06:32:21 +00:00
cmdFix . Run = runFix // break init cycle
IsDebug = cmdFix . Flag . Bool ( "debug" , false , "enable debug mode" )
2012-08-07 01:20:26 +00:00
}
var cmdFix = & Command {
2012-12-21 06:32:21 +00:00
UsageLine : "fix -dir=/tmp -volumeId=234 -debug=1" ,
Short : "run weed tool fix on index file if corrupted" ,
Long : ` Fix runs the WeedFS fix command to re - create the index . idx file .
2012-08-07 01:20:26 +00:00
` ,
}
var (
2012-12-21 06:32:21 +00:00
dir = cmdFix . Flag . String ( "dir" , "/tmp" , "data directory to store files" )
volumeId = cmdFix . Flag . Int ( "volumeId" , - 1 , "a non-negative volume id. The volume should already exist in the dir. The volume index file should not exist." )
2012-08-07 01:20:26 +00:00
)
func runFix ( cmd * Command , args [ ] string ) bool {
2012-12-21 06:32:21 +00:00
if * volumeId == - 1 {
return false
}
2012-08-07 01:20:26 +00:00
2012-12-21 06:32:21 +00:00
fileName := strconv . Itoa ( * volumeId )
2013-01-14 20:42:35 +00:00
if err := createIndexFile ( path . Join ( * dir , fileName + ".dat" ) ) ; err != nil {
log . Fatalf ( "[ERROR] " + err . Error ( ) )
}
return true
}
func createIndexFile ( datafn string ) error {
dataFile , e := os . OpenFile ( datafn , os . O_RDONLY , 0644 )
2012-12-21 06:32:21 +00:00
if e != nil {
2013-01-14 20:42:35 +00:00
return errors . New ( "Read Volume " + e . Error ( ) )
2012-12-21 06:32:21 +00:00
}
defer dataFile . Close ( )
2013-01-14 20:42:35 +00:00
// log.Printf("dataFile=%s", dataFile)
indexFile , ie := os . OpenFile ( datafn [ : len ( datafn ) - 4 ] + ".idx" , os . O_WRONLY | os . O_CREATE , 0644 )
2012-12-21 06:32:21 +00:00
if ie != nil {
2013-01-14 20:42:35 +00:00
return errors . New ( "Create Volume Index " + ie . Error ( ) )
2012-12-21 06:32:21 +00:00
}
defer indexFile . Close ( )
2012-08-07 01:20:26 +00:00
2012-12-21 06:32:21 +00:00
dataFile . Seek ( 0 , 0 )
header := make ( [ ] byte , storage . SuperBlockSize )
if _ , e := dataFile . Read ( header ) ; e != nil {
2013-01-14 20:42:35 +00:00
return errors . New ( "cannot read superblock: " + e . Error ( ) )
2012-12-21 06:32:21 +00:00
}
2012-08-07 01:20:26 +00:00
2013-01-14 20:42:35 +00:00
ver , _ , e := storage . ParseSuperBlock ( header )
if e != nil {
return errors . New ( "cannot parse superblock: " + e . Error ( ) )
}
2012-12-21 06:32:21 +00:00
2012-12-21 08:36:55 +00:00
n , rest := storage . ReadNeedleHeader ( dataFile , ver )
2012-12-21 06:32:21 +00:00
dataFile . Seek ( int64 ( rest ) , 1 )
nm := storage . NewNeedleMap ( indexFile )
offset := uint32 ( storage . SuperBlockSize )
for n != nil {
debug ( "key" , n . Id , "volume offset" , offset , "data_size" , n . Size , "rest" , rest )
if n . Size > 0 {
count , pe := nm . Put ( n . Id , offset / 8 , n . Size )
debug ( "saved" , count , "with error" , pe )
}
offset += rest + 16
2012-12-21 08:36:55 +00:00
n , rest = storage . ReadNeedleHeader ( dataFile , ver )
2012-12-21 06:32:21 +00:00
dataFile . Seek ( int64 ( rest ) , 1 )
}
2013-01-14 20:42:35 +00:00
return nil
2012-08-07 01:20:26 +00:00
}