add cmd/dump - a dumper

Walk needed to be added to NeedleMap and CompactMap, to be able to add WalkKeys and WalkValues to volume. This is needed for iterating through all the stored needles in a volume - this was dump's purpose.
This commit is contained in:
Tamás Gulácsi
2013-01-05 23:06:44 +01:00
parent 8243710351
commit 5d2a1e8d48
36 changed files with 624 additions and 468 deletions

View File

@@ -0,0 +1,96 @@
// Copyright Tamás Gulácsi 2013 All rights reserved
// Use of this source is governed by the same rules as the weed-fs library.
// If this would be ambigous, than Apache License 2.0 has to be used.
//
// dump dumps the files of a volume to tar or unique files.
// Each file will have id#mimetype#original_name file format
package main
import (
"archive/tar"
"bytes"
"flag"
"fmt"
// "io"
"log"
"os"
"pkg/storage"
"strings"
"time"
)
var (
volumePath = flag.String("dir", "/tmp", "volume directory")
volumeId = flag.Int("id", 0, "volume Id")
dest = flag.String("out", "-", "output path. Produces tar if path ends with .tar; creates files otherwise.")
tarFh *tar.Writer
tarHeader tar.Header
counter int
)
func main() {
var err error
flag.Parse()
if *dest == "-" {
*dest = ""
}
if *dest == "" || strings.HasSuffix(*dest, ".tar") {
var fh *os.File
if *dest == "" {
fh = os.Stdout
} else {
if fh, err = os.Create(*dest); err != nil {
log.Printf("cannot open output tar %s: %s", *dest, err)
return
}
}
defer fh.Close()
tarFh = tar.NewWriter(fh)
defer tarFh.Close()
t := time.Now()
tarHeader = tar.Header{Mode: 0644,
ModTime: t, Uid: os.Getuid(), Gid: os.Getgid(),
Typeflag: tar.TypeReg,
AccessTime: t, ChangeTime: t}
}
v, err := storage.NewVolume(*volumePath, storage.VolumeId(*volumeId), storage.CopyNil)
if v == nil || v.Version() == 0 || err != nil {
log.Printf("cannot load volume %d from %s (%s): %s", *volumeId, *volumePath, v, err)
return
}
log.Printf("volume: %s (ver. %d)", v, v.Version())
if err := v.WalkValues(walker); err != nil {
log.Printf("error while walking: %s", err)
return
}
log.Printf("%d files written.", counter)
}
func walker(n *storage.Needle) (err error) {
// log.Printf("Id=%d Size=%d Name=%s mime=%s", n.Id, n.Size, n.Name, n.Mime)
nm := fmt.Sprintf("%d#%s#%s", n.Id, bytes.Replace(n.Mime, []byte{'/'}, []byte{'_'}, -1), n.Name)
// log.Print(nm)
if tarFh != nil {
tarHeader.Name, tarHeader.Size = nm, int64(len(n.Data))
if err = tarFh.WriteHeader(&tarHeader); err != nil {
return err
}
_, err = tarFh.Write(n.Data)
} else {
if fh, e := os.Create(*dest + "/" + nm); e != nil {
return e
} else {
defer fh.Close()
_, err = fh.Write(n.Data)
}
}
if err == nil {
counter++
}
return
}

View File

@@ -24,7 +24,6 @@ type Command struct {
// Flag is a set of flags specific to this command. // Flag is a set of flags specific to this command.
Flag flag.FlagSet Flag flag.FlagSet
} }
// Name returns the command's name: the first word in the usage line. // Name returns the command's name: the first word in the usage line.

View File

@@ -2,8 +2,8 @@ package main
import ( import (
"bufio" "bufio"
"os"
"fmt" "fmt"
"os"
) )
func init() { func init() {
@@ -18,26 +18,25 @@ var cmdShell = &Command{
`, `,
} }
var ( var ()
)
func runShell(command *Command, args []string) bool { func runShell(command *Command, args []string) bool {
r := bufio.NewReader(os.Stdin) r := bufio.NewReader(os.Stdin)
o := bufio.NewWriter(os.Stdout) o := bufio.NewWriter(os.Stdout)
e := bufio.NewWriter(os.Stderr) e := bufio.NewWriter(os.Stderr)
prompt := func () { prompt := func() {
o.WriteString("> ") o.WriteString("> ")
o.Flush() o.Flush()
}; }
readLine := func () string { readLine := func() string {
ret, err := r.ReadString('\n') ret, err := r.ReadString('\n')
if err != nil { if err != nil {
fmt.Fprint(e,err); fmt.Fprint(e, err)
os.Exit(1) os.Exit(1)
} }
return ret return ret
} }
execCmd := func (cmd string) int { execCmd := func(cmd string) int {
if cmd != "" { if cmd != "" {
o.WriteString(cmd) o.WriteString(cmd)
} }

View File

@@ -3,8 +3,8 @@ package directory
import ( import (
"encoding/hex" "encoding/hex"
"pkg/storage" "pkg/storage"
"strings"
"pkg/util" "pkg/util"
"strings"
) )
type FileId struct { type FileId struct {
@@ -16,7 +16,7 @@ type FileId struct {
func NewFileId(VolumeId storage.VolumeId, Key uint64, Hashcode uint32) *FileId { func NewFileId(VolumeId storage.VolumeId, Key uint64, Hashcode uint32) *FileId {
return &FileId{VolumeId: VolumeId, Key: Key, Hashcode: Hashcode} return &FileId{VolumeId: VolumeId, Key: Key, Hashcode: Hashcode}
} }
func ParseFileId(fid string) *FileId{ func ParseFileId(fid string) *FileId {
a := strings.Split(fid, ",") a := strings.Split(fid, ",")
if len(a) != 2 { if len(a) != 2 {
println("Invalid fid", fid, ", split length", len(a)) println("Invalid fid", fid, ", split length", len(a))

View File

@@ -1,8 +1,8 @@
package operation package operation
import ( import (
"net/http"
"log" "log"
"net/http"
) )
func Delete(url string) error { func Delete(url string) error {

View File

@@ -2,11 +2,11 @@ package operation
import ( import (
"encoding/json" "encoding/json"
"errors"
_ "fmt"
"net/url" "net/url"
"pkg/storage" "pkg/storage"
"pkg/util" "pkg/util"
_ "fmt"
"errors"
) )
type Location struct { type Location struct {
@@ -31,7 +31,7 @@ func Lookup(server string, vid storage.VolumeId) (*LookupResult, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if ret.Error != ""{ if ret.Error != "" {
return nil, errors.New(ret.Error) return nil, errors.New(ret.Error)
} }
return &ret, nil return &ret, nil

View File

@@ -3,13 +3,13 @@ package operation
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
_ "fmt" _ "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"errors"
) )
type UploadResult struct { type UploadResult struct {
@@ -40,7 +40,7 @@ func Upload(uploadUrl string, filename string, reader io.Reader) (*UploadResult,
log.Println("failing to read upload resonse", uploadUrl, resp_body) log.Println("failing to read upload resonse", uploadUrl, resp_body)
return nil, err return nil, err
} }
if ret.Error != ""{ if ret.Error != "" {
return nil, errors.New(ret.Error) return nil, errors.New(ret.Error)
} }
return &ret, nil return &ret, nil

View File

@@ -182,7 +182,7 @@ func (vg *VolumeGrowth) GrowByCountAndType(count int, repType storage.Replicatio
func (vg *VolumeGrowth) grow(topo *topology.Topology, vid storage.VolumeId, repType storage.ReplicationType, servers ...*topology.DataNode) error { func (vg *VolumeGrowth) grow(topo *topology.Topology, vid storage.VolumeId, repType storage.ReplicationType, servers ...*topology.DataNode) error {
for _, server := range servers { for _, server := range servers {
if err := operation.AllocateVolume(server, vid, repType); err == nil { if err := operation.AllocateVolume(server, vid, repType); err == nil {
vi := storage.VolumeInfo{Id: vid, Size: 0, RepType: repType, Version:storage.CurrentVersion} vi := storage.VolumeInfo{Id: vid, Size: 0, RepType: repType, Version: storage.CurrentVersion}
server.AddOrUpdateVolume(vi) server.AddOrUpdateVolume(vi)
topo.RegisterVolumeLayout(&vi, server) topo.RegisterVolumeLayout(&vi, server)
fmt.Println("Created Volume", vid, "on", server) fmt.Println("Created Volume", vid, "on", server)

View File

@@ -80,7 +80,7 @@ func setup(topologyLayout string) *topology.Topology {
fmt.Println("data:", data) fmt.Println("data:", data)
//need to connect all nodes first before server adding volumes //need to connect all nodes first before server adding volumes
topo := topology.NewTopology("mynetwork","/etc/weedfs/weedfs.conf","/tmp","testing",32*1024, 5) topo := topology.NewTopology("mynetwork", "/etc/weedfs/weedfs.conf", "/tmp", "testing", 32*1024, 5)
mTopology := data.(map[string]interface{}) mTopology := data.(map[string]interface{})
for dcKey, dcValue := range mTopology { for dcKey, dcValue := range mTopology {
dc := topology.NewDataCenter(dcKey) dc := topology.NewDataCenter(dcKey)
@@ -96,7 +96,7 @@ func setup(topologyLayout string) *topology.Topology {
rack.LinkChildNode(server) rack.LinkChildNode(server)
for _, v := range serverMap["volumes"].([]interface{}) { for _, v := range serverMap["volumes"].([]interface{}) {
m := v.(map[string]interface{}) m := v.(map[string]interface{})
vi := storage.VolumeInfo{Id: storage.VolumeId(int64(m["id"].(float64))), Size: int64(m["size"].(float64)), Version:storage.CurrentVersion} vi := storage.VolumeInfo{Id: storage.VolumeId(int64(m["id"].(float64))), Size: int64(m["size"].(float64)), Version: storage.CurrentVersion}
server.AddOrUpdateVolume(vi) server.AddOrUpdateVolume(vi)
} }
server.UpAdjustMaxVolumeCountDelta(int(serverMap["limit"].(float64))) server.UpAdjustMaxVolumeCountDelta(int(serverMap["limit"].(float64)))
@@ -122,9 +122,8 @@ func TestRemoveDataCenter(t *testing.T) {
func TestReserveOneVolume(t *testing.T) { func TestReserveOneVolume(t *testing.T) {
topo := setup(topologyLayout) topo := setup(topologyLayout)
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
vg:=&VolumeGrowth{copy1factor:3,copy2factor:2,copy3factor:1,copyAll:4} vg := &VolumeGrowth{copy1factor: 3, copy2factor: 2, copy3factor: 1, copyAll: 4}
if c, e := vg.GrowByCountAndType(1,storage.Copy000,topo);e==nil{ if c, e := vg.GrowByCountAndType(1, storage.Copy000, topo); e == nil {
t.Log("reserved", c) t.Log("reserved", c)
} }
} }

View File

@@ -2,10 +2,10 @@ package sequence
import ( import (
"encoding/gob" "encoding/gob"
"log"
"os" "os"
"path" "path"
"sync" "sync"
"log"
) )
const ( const (

View File

@@ -175,3 +175,23 @@ func (cm *CompactMap) Peek() {
} }
} }
} }
// iterate over the keys by calling iterate on each key till error is returned
func (cm *CompactMap) Walk(pedestrian func(*NeedleValue) error) (err error) {
var i int
for _, cs := range cm.list {
for key := cs.start; key < cs.end; key++ {
if i = cs.binarySearchValues(key); i >= 0 {
if err = pedestrian(&cs.values[i]); err != nil {
return
}
}
}
for _, val := range cs.overflow {
if err = pedestrian(val); err != nil {
return err
}
}
}
return nil
}

View File

@@ -1,10 +1,10 @@
package storage package storage
import ( import (
"testing"
"log" "log"
"os" "os"
"pkg/util" "pkg/util"
"testing"
) )
func TestMemoryUsage(t *testing.T) { func TestMemoryUsage(t *testing.T) {

View File

@@ -18,11 +18,11 @@ func TestXYZ(t *testing.T) {
m.Set(Key(i), i+11, i+5) m.Set(Key(i), i+11, i+5)
} }
// for i := uint32(0); i < 100; i++ { // for i := uint32(0); i < 100; i++ {
// if v := m.Get(Key(i)); v != nil { // if v := m.Get(Key(i)); v != nil {
// println(i, "=", v.Key, v.Offset, v.Size) // println(i, "=", v.Key, v.Offset, v.Size)
// } // }
// } // }
for i := uint32(0); i < 10*batch; i++ { for i := uint32(0); i < 10*batch; i++ {
v, ok := m.Get(Key(i)) v, ok := m.Get(Key(i))
@@ -51,7 +51,7 @@ func TestXYZ(t *testing.T) {
t.Fatal("key", i, "should have been deleted needle value", v) t.Fatal("key", i, "should have been deleted needle value", v)
} }
} else if i%2 == 0 { } else if i%2 == 0 {
if v==nil{ if v == nil {
t.Fatal("key", i, "missing") t.Fatal("key", i, "missing")
} }
if v.Size != i { if v.Size != i {

View File

@@ -98,3 +98,8 @@ func (nm *NeedleMap) Close() {
func (nm *NeedleMap) ContentSize() uint64 { func (nm *NeedleMap) ContentSize() uint64 {
return nm.fileByteCounter return nm.fileByteCounter
} }
// iterate through all needles using the iterator function
func (nm *NeedleMap) Walk(pedestrian func(*NeedleValue) error) (err error) {
return nm.m.Walk(pedestrian)
}

View File

@@ -2,10 +2,10 @@ package storage
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"os" "os"
"pkg/util" "pkg/util"
"fmt"
) )
func (n *Needle) Append(w io.Writer, version Version) uint32 { func (n *Needle) Append(w io.Writer, version Version) uint32 {
@@ -62,7 +62,8 @@ func (n *Needle) Append(w io.Writer, version Version) uint32 {
return n.Size return n.Size
} }
func (n *Needle) Read(r io.Reader, size uint32, version Version) (int, error) { func (n *Needle) Read(r io.Reader, size uint32, version Version) (int, error) {
if version == Version1 { switch version {
case Version1:
bytes := make([]byte, NeedleHeaderSize+size+NeedleChecksumSize) bytes := make([]byte, NeedleHeaderSize+size+NeedleChecksumSize)
ret, e := r.Read(bytes) ret, e := r.Read(bytes)
n.readNeedleHeader(bytes) n.readNeedleHeader(bytes)
@@ -72,7 +73,7 @@ func (n *Needle) Read(r io.Reader, size uint32, version Version) (int, error) {
return 0, errors.New("CRC error! Data On Disk Corrupted!") return 0, errors.New("CRC error! Data On Disk Corrupted!")
} }
return ret, e return ret, e
} else if version == Version2 { case Version2:
if size == 0 { if size == 0 {
return 0, nil return 0, nil
} }
@@ -95,7 +96,7 @@ func (n *Needle) Read(r io.Reader, size uint32, version Version) (int, error) {
} }
return ret, e return ret, e
} }
return 0, errors.New("Unsupported Version!") return 0, fmt.Errorf("Unsupported Version! (%d)", version)
} }
func (n *Needle) readNeedleHeader(bytes []byte) { func (n *Needle) readNeedleHeader(bytes []byte) {
n.Cookie = util.BytesToUint32(bytes[0:4]) n.Cookie = util.BytesToUint32(bytes[0:4])

View File

@@ -32,7 +32,7 @@ func NewReplicationTypeFromString(t string) (ReplicationType, error) {
case "200": case "200":
return Copy200, nil return Copy200, nil
} }
return Copy000, errors.New("Unknown Replication Type:"+t) return Copy000, errors.New("Unknown Replication Type:" + t)
} }
func NewReplicationTypeFromByte(b byte) (ReplicationType, error) { func NewReplicationTypeFromByte(b byte) (ReplicationType, error) {
switch b { switch b {
@@ -49,7 +49,7 @@ func NewReplicationTypeFromByte(b byte) (ReplicationType, error) {
case byte(200): case byte(200):
return Copy200, nil return Copy200, nil
} }
return Copy000, errors.New("Unknown Replication Type:"+string(b)) return Copy000, errors.New("Unknown Replication Type:" + string(b))
} }
func (r *ReplicationType) String() string { func (r *ReplicationType) String() string {
@@ -87,7 +87,7 @@ func (r *ReplicationType) Byte() byte {
return byte(000) return byte(000)
} }
func (repType ReplicationType)GetReplicationLevelIndex() int { func (repType ReplicationType) GetReplicationLevelIndex() int {
switch repType { switch repType {
case Copy000: case Copy000:
return 0 return 0
@@ -104,7 +104,7 @@ func (repType ReplicationType)GetReplicationLevelIndex() int {
} }
return -1 return -1
} }
func (repType ReplicationType)GetCopyCount() int { func (repType ReplicationType) GetCopyCount() int {
switch repType { switch repType {
case Copy000: case Copy000:
return 1 return 1

View File

@@ -65,13 +65,13 @@ func (s *Store) AddVolume(volumeListString string, replicationType string) error
} }
return e return e
} }
func (s *Store) addVolume(vid VolumeId, replicationType ReplicationType) error { func (s *Store) addVolume(vid VolumeId, replicationType ReplicationType) (err error) {
if s.volumes[vid] != nil { if s.volumes[vid] != nil {
return errors.New("Volume Id " + vid.String() + " already exists!") return errors.New("Volume Id " + vid.String() + " already exists!")
} }
log.Println("In dir", s.dir, "adds volume =", vid, ", replicationType =", replicationType) log.Println("In dir", s.dir, "adds volume =", vid, ", replicationType =", replicationType)
s.volumes[vid] = NewVolume(s.dir, vid, replicationType) s.volumes[vid], err = NewVolume(s.dir, vid, replicationType)
return nil return err
} }
func (s *Store) CheckCompactVolume(volumeIdString string, garbageThresholdString string) (error, bool) { func (s *Store) CheckCompactVolume(volumeIdString string, garbageThresholdString string) (error, bool) {
@@ -107,7 +107,7 @@ func (s *Store) loadExistingVolumes() {
base := name[:len(name)-len(".dat")] base := name[:len(name)-len(".dat")]
if vid, err := NewVolumeId(base); err == nil { if vid, err := NewVolumeId(base); err == nil {
if s.volumes[vid] == nil { if s.volumes[vid] == nil {
v := NewVolume(s.dir, vid, CopyNil) if v, e := NewVolume(s.dir, vid, CopyNil); e == nil {
s.volumes[vid] = v s.volumes[vid] = v
log.Println("In dir", s.dir, "read volume =", vid, "replicationType =", v.replicaType, "version =", v.version, "size =", v.Size()) log.Println("In dir", s.dir, "read volume =", vid, "replicationType =", v.replicaType, "version =", v.version, "size =", v.Size())
} }
@@ -115,6 +115,7 @@ func (s *Store) loadExistingVolumes() {
} }
} }
} }
}
} }
func (s *Store) Status() []*VolumeInfo { func (s *Store) Status() []*VolumeInfo {
var stats []*VolumeInfo var stats []*VolumeInfo

View File

@@ -24,9 +24,9 @@ type Volume struct {
accessLock sync.Mutex accessLock sync.Mutex
} }
func NewVolume(dirname string, id VolumeId, replicationType ReplicationType) (v *Volume) { func NewVolume(dirname string, id VolumeId, replicationType ReplicationType) (v *Volume, e error) {
v = &Volume{dir: dirname, Id: id, replicaType: replicationType} v = &Volume{dir: dirname, Id: id, replicaType: replicationType}
v.load() e = v.load()
return return
} }
func (v *Volume) load() error { func (v *Volume) load() error {
@@ -43,6 +43,7 @@ func (v *Volume) load() error {
} else { } else {
v.maybeWriteSuperBlock() v.maybeWriteSuperBlock()
} }
// TODO: if .idx not exists, but .cdb exists, then use (but don't load!) that
indexFile, ie := os.OpenFile(fileName+".idx", os.O_RDWR|os.O_CREATE, 0644) indexFile, ie := os.OpenFile(fileName+".idx", os.O_RDWR|os.O_CREATE, 0644)
if ie != nil { if ie != nil {
return fmt.Errorf("cannot create Volume Data %s.dat: %s", fileName, e) return fmt.Errorf("cannot create Volume Data %s.dat: %s", fileName, e)
@@ -79,21 +80,23 @@ func (v *Volume) maybeWriteSuperBlock() {
v.dataFile.Write(header) v.dataFile.Write(header)
} }
} }
func (v *Volume) readSuperBlock() error { func (v *Volume) readSuperBlock() (err error) {
v.dataFile.Seek(0, 0) v.dataFile.Seek(0, 0)
header := make([]byte, SuperBlockSize) header := make([]byte, SuperBlockSize)
if _, e := v.dataFile.Read(header); e != nil { if _, e := v.dataFile.Read(header); e != nil {
return fmt.Errorf("cannot read superblock: %s", e) return fmt.Errorf("cannot read superblock: %s", e)
} }
var err error
v.version, v.replicaType, err = ParseSuperBlock(header) v.version, v.replicaType, err = ParseSuperBlock(header)
return err return err
} }
func ParseSuperBlock(header []byte) (version Version, replicaType ReplicationType, e error) { func ParseSuperBlock(header []byte) (version Version, replicaType ReplicationType, err error) {
version = Version(header[0]) version = Version(header[0])
var err error if version == 0 {
err = errors.New("Zero version impossible - bad superblock!")
return
}
if replicaType, err = NewReplicationTypeFromByte(header[1]); err != nil { if replicaType, err = NewReplicationTypeFromByte(header[1]); err != nil {
e = fmt.Errorf("cannot read replica type: %s", err) err = fmt.Errorf("cannot read replica type: %s", err)
} }
return return
} }
@@ -221,3 +224,39 @@ func (v *Volume) copyDataAndGenerateIndexFile(srcName, dstName, idxName string)
func (v *Volume) ContentSize() uint64 { func (v *Volume) ContentSize() uint64 {
return v.nm.fileByteCounter return v.nm.fileByteCounter
} }
// Walk over the contained needles (call the function with each NeedleValue till error is returned)
func (v *Volume) WalkValues(pedestrian func(*Needle) error) error {
pedplus := func(nv *NeedleValue) (err error) {
n := new(Needle)
if nv.Offset > 0 {
v.dataFile.Seek(int64(nv.Offset)*NeedlePaddingSize, 0)
if _, err = n.Read(v.dataFile, nv.Size, v.version); err != nil {
return
}
if err = pedestrian(n); err != nil {
return
}
}
return nil
}
return v.nm.Walk(pedplus)
}
// Walk over the keys
func (v *Volume) WalkKeys(pedestrian func(Key) error) error {
pedplus := func(nv *NeedleValue) (err error) {
if nv.Offset > 0 && nv.Key > 0 {
if err = pedestrian(nv.Key); err != nil {
return
}
}
return nil
}
return v.nm.Walk(pedplus)
}
func (v *Volume) String() string {
return fmt.Sprintf("%d@%s:v%d:r%s", v.Id, v.dataFile.Name(),
v.Version(), v.replicaType)
}

View File

@@ -5,13 +5,14 @@ import (
) )
type VolumeId uint32 type VolumeId uint32
func NewVolumeId(vid string) (VolumeId,error) {
func NewVolumeId(vid string) (VolumeId, error) {
volumeId, err := strconv.ParseUint(vid, 10, 64) volumeId, err := strconv.ParseUint(vid, 10, 64)
return VolumeId(volumeId), err return VolumeId(volumeId), err
} }
func (vid *VolumeId) String() string{ func (vid *VolumeId) String() string {
return strconv.FormatUint(uint64(*vid), 10) return strconv.FormatUint(uint64(*vid), 10)
} }
func (vid *VolumeId) Next() VolumeId{ func (vid *VolumeId) Next() VolumeId {
return VolumeId(uint32(*vid)+1) return VolumeId(uint32(*vid) + 1)
} }

View File

@@ -1,7 +1,6 @@
package storage package storage
import ( import ()
)
type Version uint8 type Version uint8

View File

@@ -32,11 +32,11 @@ func TestLoadConfiguration(t *testing.T) {
c, err := NewConfiguration([]byte(confContent)) c, err := NewConfiguration([]byte(confContent))
fmt.Printf("%s\n", c) fmt.Printf("%s\n", c)
if err!=nil{ if err != nil {
t.Fatalf("unmarshal error:%s",err.Error()) t.Fatalf("unmarshal error:%s", err.Error())
} }
if len(c.Topo.DataCenters) <= 0 || c.Topo.DataCenters[0].Name != "dc1" { if len(c.Topo.DataCenters) <= 0 || c.Topo.DataCenters[0].Name != "dc1" {
t.Fatalf("unmarshal error:%s",c) t.Fatalf("unmarshal error:%s", c)
} }
} }

View File

@@ -1,7 +1,6 @@
package topology package topology
import ( import ()
)
type DataCenter struct { type DataCenter struct {
NodeImpl NodeImpl
@@ -28,7 +27,7 @@ func (dc *DataCenter) GetOrCreateRack(rackName string) *Rack {
return rack return rack
} }
func (dc *DataCenter) ToMap() interface{}{ func (dc *DataCenter) ToMap() interface{} {
m := make(map[string]interface{}) m := make(map[string]interface{})
m["Max"] = dc.GetMaxVolumeCount() m["Max"] = dc.GetMaxVolumeCount()
m["Free"] = dc.FreeSpace() m["Free"] = dc.FreeSpace()

View File

@@ -37,8 +37,8 @@ func (nl *NodeList) RandomlyPickN(n int, min int) ([]Node, bool) {
list = append(list, n) list = append(list, n)
} }
} }
if n > len(list){ if n > len(list) {
return nil,false return nil, false
} }
for i := n; i > 0; i-- { for i := n; i > 0; i-- {
r := rand.Intn(i) r := rand.Intn(i)

View File

@@ -1,38 +1,38 @@
package topology package topology
import ( import (
_ "fmt"
"strconv" "strconv"
"testing" "testing"
_ "fmt"
) )
func TestXYZ(t *testing.T) { func TestXYZ(t *testing.T) {
topo := NewTopology("topo","/etc/weed.conf", "/tmp","test",234,5) topo := NewTopology("topo", "/etc/weed.conf", "/tmp", "test", 234, 5)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
dc := NewDataCenter("dc" + strconv.Itoa(i)) dc := NewDataCenter("dc" + strconv.Itoa(i))
dc.activeVolumeCount = i dc.activeVolumeCount = i
dc.maxVolumeCount = 5 dc.maxVolumeCount = 5
topo.LinkChildNode(dc) topo.LinkChildNode(dc)
} }
nl := NewNodeList(topo.Children(),nil) nl := NewNodeList(topo.Children(), nil)
picked, ret := nl.RandomlyPickN(1) picked, ret := nl.RandomlyPickN(1)
if !ret || len(picked)!=1 { if !ret || len(picked) != 1 {
t.Errorf("need to randomly pick 1 node") t.Errorf("need to randomly pick 1 node")
} }
picked, ret = nl.RandomlyPickN(4) picked, ret = nl.RandomlyPickN(4)
if !ret || len(picked)!=4 { if !ret || len(picked) != 4 {
t.Errorf("need to randomly pick 4 nodes") t.Errorf("need to randomly pick 4 nodes")
} }
picked, ret = nl.RandomlyPickN(5) picked, ret = nl.RandomlyPickN(5)
if !ret || len(picked)!=5 { if !ret || len(picked) != 5 {
t.Errorf("need to randomly pick 5 nodes") t.Errorf("need to randomly pick 5 nodes")
} }
picked, ret = nl.RandomlyPickN(6) picked, ret = nl.RandomlyPickN(6)
if ret || len(picked)!=0 { if ret || len(picked) != 0 {
t.Errorf("can not randomly pick 6 nodes:", ret, picked) t.Errorf("can not randomly pick 6 nodes:", ret, picked)
} }

View File

@@ -78,7 +78,7 @@ func setup(topologyLayout string) *Topology {
} }
//need to connect all nodes first before server adding volumes //need to connect all nodes first before server adding volumes
topo := NewTopology("mynetwork","/etc/weed.conf","/tmp","test",234,5) topo := NewTopology("mynetwork", "/etc/weed.conf", "/tmp", "test", 234, 5)
mTopology := data.(map[string]interface{}) mTopology := data.(map[string]interface{})
for dcKey, dcValue := range mTopology { for dcKey, dcValue := range mTopology {
dc := NewDataCenter(dcKey) dc := NewDataCenter(dcKey)
@@ -94,7 +94,7 @@ func setup(topologyLayout string) *Topology {
rack.LinkChildNode(server) rack.LinkChildNode(server)
for _, v := range serverMap["volumes"].([]interface{}) { for _, v := range serverMap["volumes"].([]interface{}) {
m := v.(map[string]interface{}) m := v.(map[string]interface{})
vi := storage.VolumeInfo{Id: storage.VolumeId(int64(m["id"].(float64))), Size: int64(m["size"].(float64)), Version:storage.CurrentVersion} vi := storage.VolumeInfo{Id: storage.VolumeId(int64(m["id"].(float64))), Size: int64(m["size"].(float64)), Version: storage.CurrentVersion}
server.AddOrUpdateVolume(vi) server.AddOrUpdateVolume(vi)
} }
server.UpAdjustMaxVolumeCountDelta(int(serverMap["limit"].(float64))) server.UpAdjustMaxVolumeCountDelta(int(serverMap["limit"].(float64)))
@@ -122,6 +122,6 @@ func TestReserveOneVolume(t *testing.T) {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
rand.Seed(1) rand.Seed(1)
ret, node, vid := topo.RandomlyReserveOneVolume() ret, node, vid := topo.RandomlyReserveOneVolume()
fmt.Println("assigned :", ret, ", node :", node,", volume id:", vid) fmt.Println("assigned :", ret, ", node :", node, ", volume id:", vid)
} }

View File

@@ -104,7 +104,7 @@ func vacuumVolume_Check(urlLocation string, vid storage.VolumeId, garbageThresho
values.Add("garbageThreshold", garbageThreshold) values.Add("garbageThreshold", garbageThreshold)
jsonBlob, err := util.Post("http://"+urlLocation+"/admin/vacuum_volume_check", values) jsonBlob, err := util.Post("http://"+urlLocation+"/admin/vacuum_volume_check", values)
if err != nil { if err != nil {
fmt.Println("parameters:",values) fmt.Println("parameters:", values)
return err, false return err, false
} }
var ret VacuumVolumeResult var ret VacuumVolumeResult

View File

@@ -1,7 +1,6 @@
package topology package topology
import ( import ()
)
func (t *Topology) ToMap() interface{} { func (t *Topology) ToMap() interface{} {
m := make(map[string]interface{}) m := make(map[string]interface{})

View File

@@ -31,7 +31,7 @@ func (dnll *VolumeLocationList) Add(loc *DataNode) bool {
func (dnll *VolumeLocationList) Remove(loc *DataNode) bool { func (dnll *VolumeLocationList) Remove(loc *DataNode) bool {
for i, dnl := range dnll.list { for i, dnl := range dnll.list {
if loc.Ip == dnl.Ip && loc.Port == dnl.Port { if loc.Ip == dnl.Ip && loc.Port == dnl.Port {
dnll.list = append(dnll.list[:i],dnll.list[i+1:]...) dnll.list = append(dnll.list[:i], dnll.list[i+1:]...)
return true return true
} }
} }

View File

@@ -1,34 +1,33 @@
package util package util
func BytesToUint64(b []byte)(v uint64){ func BytesToUint64(b []byte) (v uint64) {
length := uint(len(b)) length := uint(len(b))
for i :=uint(0);i<length-1;i++ { for i := uint(0); i < length-1; i++ {
v += uint64(b[i]) v += uint64(b[i])
v <<= 8 v <<= 8
} }
v+=uint64(b[length-1]) v += uint64(b[length-1])
return return
} }
func BytesToUint32(b []byte)(v uint32){ func BytesToUint32(b []byte) (v uint32) {
length := uint(len(b)) length := uint(len(b))
for i :=uint(0);i<length-1;i++ { for i := uint(0); i < length-1; i++ {
v += uint32(b[i]) v += uint32(b[i])
v <<= 8 v <<= 8
} }
v+=uint32(b[length-1]) v += uint32(b[length-1])
return return
} }
func Uint64toBytes(b []byte, v uint64){ func Uint64toBytes(b []byte, v uint64) {
for i :=uint(0);i<8;i++ { for i := uint(0); i < 8; i++ {
b[7-i] = byte(v>>(i*8)) b[7-i] = byte(v >> (i * 8))
} }
} }
func Uint32toBytes(b []byte, v uint32){ func Uint32toBytes(b []byte, v uint32) {
for i :=uint(0);i<4;i++ { for i := uint(0); i < 4; i++ {
b[3-i] = byte(v>>(i*8)) b[3-i] = byte(v >> (i * 8))
} }
} }
func Uint8toBytes(b []byte, v uint8){ func Uint8toBytes(b []byte, v uint8) {
b[0] = byte(v) b[0] = byte(v)
} }

View File

@@ -4,10 +4,10 @@ import (
"strconv" "strconv"
) )
func ParseInt(text string, defaultValue int) int{ func ParseInt(text string, defaultValue int) int {
count, parseError := strconv.ParseUint(text,10,64) count, parseError := strconv.ParseUint(text, 10, 64)
if parseError!=nil { if parseError != nil {
if len(text)>0{ if len(text) > 0 {
return 0 return 0
} }
return defaultValue return defaultValue