git-svn-id: https://weed-fs.googlecode.com/svn/trunk@12 282b0af5-e82d-9cf1-ede4-77906d7719d0

This commit is contained in:
chris.lu@gmail.com
2011-12-17 06:47:23 +00:00
parent 25d0caa901
commit 10930ce6b6
6 changed files with 137 additions and 74 deletions

View File

@@ -12,12 +12,14 @@ import (
type Machine struct {
Server string //<server name/ip>[:port]
PublicServer string
CanWrite bool
}
type Mapper struct {
dir string
FileName string
Id2Machine map[uint32][]*Machine
LastId uint32
dir string
fileName string
capacity int
Machines [][]Machine //initial version only support one copy per machine
writers [][]Machine // transient value to lookup writers fast
}
func NewMachine(server, publicServer string) (m *Machine) {
@@ -26,57 +28,88 @@ func NewMachine(server, publicServer string) (m *Machine) {
return
}
func NewMapper(dirname string, filename string) (m *Mapper) {
func NewMapper(dirname string, filename string, capacity int) (m *Mapper) {
m = new(Mapper)
m.dir = dirname
m.FileName = filename
log.Println("Loading virtual to physical:", path.Join(m.dir,m.FileName+".map"))
dataFile, e := os.OpenFile(path.Join(m.dir,m.FileName+".map"), os.O_RDONLY, 0644)
m.Id2Machine = make(map[uint32][]*Machine)
m.dir, m.fileName, m.capacity = dirname, filename, capacity
log.Println("Loading volume id to maching mapping:", path.Join(m.dir, m.fileName+".map"))
dataFile, e := os.OpenFile(path.Join(m.dir, m.fileName+".map"), os.O_RDONLY, 0644)
m.Machines = *new([][]Machine)
m.writers = *new([][]Machine)
if e != nil {
log.Println("Mapping File Read", e)
} else {
decoder := gob.NewDecoder(dataFile)
decoder.Decode(m.LastId)
decoder.Decode(m.Id2Machine)
decoder.Decode(m.Machines)
for _, list := range m.Machines {
//TODO: what if a list has mixed readers and writers? Now it's treated as readonly
allCanWrite := false
for _, entry := range list {
allCanWrite = allCanWrite && entry.CanWrite
}
if allCanWrite {
m.writers = append(m.writers, list)
}
}
dataFile.Close()
log.Println("Loaded mapping size", len(m.Machines))
}
return
}
func (m *Mapper) PickForWrite() []*Machine {
vid := uint32(rand.Intn(len(m.Id2Machine)))
return m.Id2Machine[vid]
func (m *Mapper) PickForWrite() []Machine {
vid := rand.Intn(len(m.Machines))
return m.Machines[vid]
}
func (m *Mapper) Get(vid uint32) []*Machine {
return m.Id2Machine[vid]
func (m *Mapper) Get(vid int) []Machine {
return m.Machines[vid]
}
func (m *Mapper) Add(machine *Machine, volumes []storage.VolumeStat) {
log.Println("Adding store node", machine.Server)
func (m *Mapper) Add(machine Machine, volumes []storage.VolumeStat, capacity int) []int {
log.Println("Adding existing", machine.Server, len(volumes), "volumes to dir", len(m.Machines))
log.Println("Adding new ", machine.Server, capacity - len(volumes), "volumes to dir", len(m.Machines))
maxId := len(m.Machines)-1
for _, v := range volumes {
if maxId < int(v.Id) {
maxId = int(v.Id)
}
}
for i := len(m.Machines); i <= maxId; i++ {
m.Machines = append(m.Machines, nil)
}
log.Println("Machine list now is", len(m.Machines))
for _, v := range volumes {
existing := m.Id2Machine[uint32(v.Id)]
found := false
existing := m.Machines[v.Id]
for _, entry := range existing {
if machine == entry {
if machine.Server == entry.Server {
found = true
break
}
}
if !found {
m.Id2Machine[uint32(v.Id)] = append(existing, machine)
m.Machines[v.Id] = append(existing, machine)
log.Println("Setting volume", v.Id, "to", machine.Server)
}
log.Println(v.Id, "=>", machine.Server)
}
vids := new([]int)
for vid,i := len(m.Machines),len(volumes); i < capacity; i,vid=i+1,vid+1 {
list := new([]Machine)
*list = append(*list, machine)
m.Machines = append(m.Machines, *list)
log.Println("Adding volume", vid, "from", machine.Server)
*vids = append(*vids, vid)
}
m.Save()
log.Println("Dir size =>", len(m.Machines))
return *vids
}
func (m *Mapper) Save() {
log.Println("Saving virtual to physical:", path.Join(m.dir,m.FileName+".map"))
dataFile, e := os.OpenFile(path.Join(m.dir,m.FileName+".map"), os.O_CREATE|os.O_WRONLY, 0644)
log.Println("Saving virtual to physical:", path.Join(m.dir, m.fileName+".map"))
dataFile, e := os.OpenFile(path.Join(m.dir, m.fileName+".map"), os.O_CREATE|os.O_WRONLY, 0644)
if e != nil {
log.Fatalf("Mapping File Save [ERROR] %s\n", e)
}
defer dataFile.Close()
m.Id2Machine = make(map[uint32][]*Machine)
encoder := gob.NewEncoder(dataFile)
encoder.Encode(m.LastId)
encoder.Encode(m.Id2Machine)
encoder.Encode(m.Machines)
}