Browse Source
refactoring, same logic, but the store replication logic is moved to a
refactoring, same logic, but the store replication logic is moved to a
stand-alone file, for later easier improvementspull/2/head
Chris Lu
12 years ago
6 changed files with 108 additions and 89 deletions
-
95go/replication/store_replicate.go
-
11go/storage/file_id.go
-
4go/storage/needle.go
-
3go/topology/topology.go
-
3go/weed/export.go
-
81go/weed/volume.go
@ -0,0 +1,95 @@ |
|||||
|
package replication |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"code.google.com/p/weed-fs/go/operation" |
||||
|
"code.google.com/p/weed-fs/go/storage" |
||||
|
"log" |
||||
|
"net/http" |
||||
|
"strconv" |
||||
|
) |
||||
|
|
||||
|
func ReplicatedWrite(masterNode string, s *storage.Store, volumeId storage.VolumeId, needle *storage.Needle, r *http.Request) (size uint32, errorStatus string) { |
||||
|
ret, err := s.Write(volumeId, needle) |
||||
|
needToReplicate := !s.HasVolume(volumeId) |
||||
|
if err != nil { |
||||
|
errorStatus = "Failed to write to local disk (" + err.Error() + ")" |
||||
|
} else if ret > 0 { |
||||
|
needToReplicate = needToReplicate || s.GetVolume(volumeId).NeedToReplicate() |
||||
|
} else { |
||||
|
errorStatus = "Failed to write to local disk" |
||||
|
} |
||||
|
if !needToReplicate && ret > 0 { |
||||
|
needToReplicate = s.GetVolume(volumeId).NeedToReplicate() |
||||
|
} |
||||
|
if needToReplicate { //send to other replica locations
|
||||
|
if r.FormValue("type") != "standard" { |
||||
|
if !distributedOperation(masterNode, s, volumeId, func(location operation.Location) bool { |
||||
|
_, err := operation.Upload("http://"+location.Url+r.URL.Path+"?type=standard", string(needle.Name), bytes.NewReader(needle.Data)) |
||||
|
return err == nil |
||||
|
}) { |
||||
|
ret = 0 |
||||
|
errorStatus = "Failed to write to replicas for volume " + volumeId.String() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if errorStatus != "" { |
||||
|
if _, err = s.Delete(volumeId, needle); err != nil { |
||||
|
errorStatus += "\nCannot delete " + strconv.FormatUint(needle.Id, 10) + " from " + |
||||
|
strconv.FormatUint(uint64(volumeId), 10) + ": " + err.Error() |
||||
|
} else { |
||||
|
distributedOperation(masterNode, s, volumeId, func(location operation.Location) bool { |
||||
|
return nil == operation.Delete("http://"+location.Url+r.URL.Path+"?type=standard") |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
size = ret |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
func ReplicatedDelete(masterNode string, store *storage.Store, volumeId storage.VolumeId, n *storage.Needle, r *http.Request) (ret uint32) { |
||||
|
ret, err := store.Delete(volumeId, n) |
||||
|
if err != nil { |
||||
|
log.Println("delete error:", err) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
needToReplicate := !store.HasVolume(volumeId) |
||||
|
if !needToReplicate && ret > 0 { |
||||
|
needToReplicate = store.GetVolume(volumeId).NeedToReplicate() |
||||
|
} |
||||
|
if needToReplicate { //send to other replica locations
|
||||
|
if r.FormValue("type") != "standard" { |
||||
|
if !distributedOperation(masterNode, store, volumeId, func(location operation.Location) bool { |
||||
|
return nil == operation.Delete("http://"+location.Url+r.URL.Path+"?type=standard") |
||||
|
}) { |
||||
|
ret = 0 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
func distributedOperation(masterNode string, store *storage.Store, volumeId storage.VolumeId, op func(location operation.Location) bool) bool { |
||||
|
if lookupResult, lookupErr := operation.Lookup(masterNode, volumeId); lookupErr == nil { |
||||
|
length := 0 |
||||
|
selfUrl := (store.Ip + ":" + strconv.Itoa(store.Port)) |
||||
|
results := make(chan bool) |
||||
|
for _, location := range lookupResult.Locations { |
||||
|
if location.Url != selfUrl { |
||||
|
length++ |
||||
|
go func(location operation.Location, results chan bool) { |
||||
|
results <- op(location) |
||||
|
}(location, results) |
||||
|
} |
||||
|
} |
||||
|
ret := true |
||||
|
for i := 0; i < length; i++ { |
||||
|
ret = ret && <-results |
||||
|
} |
||||
|
return ret |
||||
|
} else { |
||||
|
log.Println("Failed to lookup for", volumeId, lookupErr.Error()) |
||||
|
} |
||||
|
return false |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue