Browse Source

volume layout for each replication level

pull/2/head
Chris Lu 12 years ago
parent
commit
6daf221937
  1. 7
      weed-fs/note/startup_process.txt
  2. 46
      weed-fs/src/pkg/storage/volume_info.go
  3. 25
      weed-fs/src/pkg/topology/data_node.go
  4. 24
      weed-fs/src/pkg/topology/node.go
  5. 24
      weed-fs/src/pkg/topology/topology.go
  6. 48
      weed-fs/src/pkg/topology/volume_layout.go
  7. 21
      weed-fs/src/pkg/topology/volume_location.go

7
weed-fs/note/startup_process.txt

@ -1,7 +0,0 @@
1. clients report its own server info, volumes info,
2. master collect all volumes, separated into readable volumes, writable volumes, volume2machine mapping
machines is an array of machine info
writable volumes is an array of vids
vid2machineId maps volume id to machineId, which is the index of machines array

46
weed-fs/src/pkg/storage/volume_info.go

@ -1,10 +1,50 @@
package storage package storage
import (
)
import ()
type VolumeInfo struct { type VolumeInfo struct {
Id VolumeId Id VolumeId
Size int64 Size int64
ReplicationType ReplicationType
}
type ReplicationType int
const (
Copy00 = ReplicationType(00) // single copy
Copy01 = ReplicationType(01) // 2 copies, each on different racks, same data center
Copy10 = ReplicationType(10) // 2 copies, each on different data center
Copy11 = ReplicationType(11) // 3 copies, 2 on different racks and local data center, 1 on different data center
Copy20 = ReplicationType(20) // 3 copies, each on dffereint data center
LengthRelicationType = 5
)
func GetReplicationLevelIndex(v *VolumeInfo) int {
switch v.ReplicationType {
case Copy00:
return 0
case Copy01:
return 1
case Copy10:
return 2
case Copy11:
return 3
case Copy20:
return 4
}
return -1
}
func GetCopyCount(v *VolumeInfo) int {
switch v.ReplicationType {
case Copy00:
return 1
case Copy01:
return 2
case Copy10:
return 2
case Copy11:
return 3
case Copy20:
return 3
}
return 0
} }

25
weed-fs/src/pkg/topology/data_node.go

@ -8,6 +8,10 @@ import (
type DataNode struct { type DataNode struct {
NodeImpl NodeImpl
volumes map[storage.VolumeId]*storage.VolumeInfo volumes map[storage.VolumeId]*storage.VolumeInfo
ip string
port int
publicUrl string
lastSeen int64 // unix time in seconds
} }
func NewDataNode(id string) *DataNode { func NewDataNode(id string) *DataNode {
@ -17,12 +21,21 @@ func NewDataNode(id string) *DataNode {
s.volumes = make(map[storage.VolumeId]*storage.VolumeInfo) s.volumes = make(map[storage.VolumeId]*storage.VolumeInfo)
return s return s
} }
func (s *DataNode) CreateOneVolume(r int, vid storage.VolumeId) storage.VolumeId {
s.AddVolume(&storage.VolumeInfo{Id: vid, Size: 32 * 1024 * 1024 * 1024})
func (dn *DataNode) CreateOneVolume(r int, vid storage.VolumeId) storage.VolumeId {
dn.AddVolume(&storage.VolumeInfo{Id: vid, Size: 32 * 1024 * 1024 * 1024})
return vid return vid
} }
func (s *DataNode) AddVolume(v *storage.VolumeInfo) {
s.volumes[v.Id] = v
s.UpAdjustActiveVolumeCountDelta(1)
s.UpAdjustMaxVolumeId(v.Id)
func (dn *DataNode) AddVolume(v *storage.VolumeInfo) {
dn.volumes[v.Id] = v
dn.UpAdjustActiveVolumeCountDelta(1)
dn.UpAdjustMaxVolumeId(v.Id)
dn.GetTopology().RegisterVolume(v,dn)
}
func (dn *DataNode) GetTopology() *Topology {
p := dn.parent
for p.Parent()!=nil{
p = p.Parent()
}
t := p.(*Topology)
return t
} }

24
weed-fs/src/pkg/topology/node.go

@ -20,6 +20,7 @@ type Node interface {
setParent(Node) setParent(Node)
LinkChildNode(node Node) LinkChildNode(node Node)
UnlinkChildNode(nodeId NodeId) UnlinkChildNode(nodeId NodeId)
CollectWritableVolumes(freshThreshHold int64, volumeSizeLimit uint64) []storage.VolumeId
IsDataNode() bool IsDataNode() bool
Children() map[NodeId]Node Children() map[NodeId]Node
@ -146,3 +147,26 @@ func (n *NodeImpl) UnlinkChildNode(nodeId NodeId) {
fmt.Println(n, "removes", node, "volumeCount =", n.activeVolumeCount) fmt.Println(n, "removes", node, "volumeCount =", n.activeVolumeCount)
} }
} }
func (n *NodeImpl) CollectWritableVolumes(freshThreshHold int64, volumeSizeLimit uint64) []storage.VolumeId {
var ret []storage.VolumeId
if n.IsRack() {
for _, c := range n.Children() {
dn := c.(*DataNode) //can not cast n to DataNode
if dn.lastSeen > freshThreshHold {
continue
}
for _, v := range dn.volumes {
if uint64(v.Size) < volumeSizeLimit {
ret = append(ret, v.Id)
}
}
}
} else {
for _, c := range n.Children() {
ret = append(ret, c.CollectWritableVolumes(freshThreshHold, volumeSizeLimit)...)
}
}
return ret
}

24
weed-fs/src/pkg/topology/topology.go

@ -3,18 +3,32 @@ package topology
import ( import (
_ "fmt" _ "fmt"
"math/rand" "math/rand"
"pkg/sequence"
"pkg/storage" "pkg/storage"
) )
type Topology struct { type Topology struct {
NodeImpl NodeImpl
//transient vid~servers mapping for each replication type
replicaType2VolumeLayout []*VolumeLayout
pulse int64
volumeSizeLimit uint64
sequence sequence.Sequencer
} }
func NewTopology(id string) *Topology {
func NewTopology(id string, dirname string, filename string, volumeSizeLimit uint64, pulse int) *Topology {
t := &Topology{} t := &Topology{}
t.id = NodeId(id) t.id = NodeId(id)
t.nodeType = "Topology" t.nodeType = "Topology"
t.children = make(map[NodeId]Node) t.children = make(map[NodeId]Node)
t.replicaType2VolumeLayout = make([]*VolumeLayout, storage.LengthRelicationType)
t.pulse = int64(pulse)
t.volumeSizeLimit = volumeSizeLimit
t.sequence = sequence.NewSequencer(dirname, filename)
return t return t
} }
func (t *Topology) RandomlyReserveOneVolume() (bool, *DataNode, storage.VolumeId) { func (t *Topology) RandomlyReserveOneVolume() (bool, *DataNode, storage.VolumeId) {
@ -37,3 +51,11 @@ func (t *Topology) NextVolumeId() storage.VolumeId {
vid := t.GetMaxVolumeId() vid := t.GetMaxVolumeId()
return vid.Next() return vid.Next()
} }
func (t *Topology) RegisterVolume(v *storage.VolumeInfo, dn *DataNode) {
replicationTypeIndex := storage.GetReplicationLevelIndex(v)
if t.replicaType2VolumeLayout[replicationTypeIndex] == nil {
t.replicaType2VolumeLayout[replicationTypeIndex] = NewVolumeLayout(t.volumeSizeLimit, t.pulse)
}
t.replicaType2VolumeLayout[replicationTypeIndex].RegisterVolume(v, dn)
}

48
weed-fs/src/pkg/topology/volume_layout.go

@ -0,0 +1,48 @@
package topology
import (
"errors"
"fmt"
"math/rand"
"pkg/storage"
)
type VolumeLayout struct {
vid2location map[storage.VolumeId]*DataNodeLocationList
writables []storage.VolumeId // transient array of writable volume id
pulse int64
volumeSizeLimit uint64
}
func NewVolumeLayout(volumeSizeLimit uint64, pulse int64) *VolumeLayout {
return &VolumeLayout{
vid2location: make(map[storage.VolumeId]*DataNodeLocationList),
writables: *new([]storage.VolumeId),
pulse: pulse,
volumeSizeLimit: volumeSizeLimit,
}
}
func (vl *VolumeLayout) RegisterVolume(v *storage.VolumeInfo, dn *DataNode) {
if _, ok := vl.vid2location[v.Id]; !ok {
vl.vid2location[v.Id] = NewDataNodeLocationList()
}
vl.vid2location[v.Id].Add(dn)
if len(vl.vid2location[v.Id].list) >= storage.GetCopyCount(v) {
vl.writables = append(vl.writables,v.Id)
}
}
func (vl *VolumeLayout) PickForWrite(count int) (int, *DataNodeLocationList, error) {
len_writers := len(vl.writables)
if len_writers <= 0 {
fmt.Println("No more writable volumes!")
return 0, nil, errors.New("No more writable volumes!")
}
vid := vl.writables[rand.Intn(len_writers)]
locationList := vl.vid2location[vid]
if locationList != nil {
return count, locationList, nil
}
return 0, nil, errors.New("Strangely vid " + vid.String() + " is on no machine!")
}

21
weed-fs/src/pkg/topology/volume_location.go

@ -0,0 +1,21 @@
package topology
import (
)
type DataNodeLocationList struct {
list []*DataNode
}
func NewDataNodeLocationList() *DataNodeLocationList {
return &DataNodeLocationList{}
}
func (dnll *DataNodeLocationList) Add(loc *DataNode){
for _, dnl := range dnll.list {
if loc.ip == dnl.ip && loc.port == dnl.port {
break
}
}
dnll.list = append(dnll.list, loc)
}
Loading…
Cancel
Save