From 8fb8ebdf148414eeece04739c5df3916b007fd43 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Fri, 4 Jan 2013 01:02:52 -0800 Subject: [PATCH] master can redirect GET/DELETE/POST requests to volume servers. So clients does not always need to remember the volume server locations. This is good for low~medium sized web site traffic. --- weed-fs/src/cmd/weed/master.go | 27 ++++++++++++++++++----- weed-fs/src/pkg/topology/topology.go | 2 +- weed-fs/src/pkg/topology/volume_layout.go | 4 ++-- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/weed-fs/src/cmd/weed/master.go b/weed-fs/src/cmd/weed/master.go index 2ee2fcc85..c60974a67 100644 --- a/weed-fs/src/cmd/weed/master.go +++ b/weed-fs/src/cmd/weed/master.go @@ -54,7 +54,7 @@ func dirLookupHandler(w http.ResponseWriter, r *http.Request) { machines := topo.Lookup(volumeId) if machines != nil { ret := []map[string]string{} - for _, dn := range *machines { + for _, dn := range machines { ret = append(ret, map[string]string{"url": dn.Url(), "publicUrl": dn.PublicUrl}) } writeJson(w, r, map[string]interface{}{"locations": ret}) @@ -102,7 +102,7 @@ func dirAssignHandler(w http.ResponseWriter, r *http.Request) { } func dirJoinHandler(w http.ResponseWriter, r *http.Request) { - init := r.FormValue("init")=="true" + init := r.FormValue("init") == "true" ip := r.FormValue("ip") if ip == "" { ip = r.RemoteAddr[0:strings.Index(r.RemoteAddr, ":")] @@ -115,9 +115,9 @@ func dirJoinHandler(w http.ResponseWriter, r *http.Request) { json.Unmarshal([]byte(r.FormValue("volumes")), volumes) debug(s, "volumes", r.FormValue("volumes")) topo.RegisterVolumes(init, *volumes, ip, port, publicUrl, maxVolumeCount) - m := make(map[string]interface{}) - m["VolumeSizeLimit"] = uint64(*volumeSizeLimitMB)*1024*1024 - writeJson(w, r, m) + m := make(map[string]interface{}) + m["VolumeSizeLimit"] = uint64(*volumeSizeLimitMB) * 1024 * 1024 + writeJson(w, r, m) } func dirStatusHandler(w http.ResponseWriter, r *http.Request) { @@ -178,6 +178,22 @@ func volumeStatusHandler(w http.ResponseWriter, r *http.Request) { writeJson(w, r, m) } +func redirectHandler(w http.ResponseWriter, r *http.Request) { + vid, _, _ := parseURLPath(r.URL.Path) + volumeId, err := storage.NewVolumeId(vid) + if err != nil { + debug("parsing error:", err, r.URL.Path) + return + } + machines := topo.Lookup(volumeId) + if machines != nil && len(machines) > 0 { + http.Redirect(w, r, "http://"+machines[0].PublicUrl+r.URL.Path, http.StatusMovedPermanently) + } else { + w.WriteHeader(http.StatusNotFound) + writeJson(w, r, map[string]string{"error": "volume id " + volumeId.String() + " not found. "}) + } +} + func runMaster(cmd *Command, args []string) bool { if *mMaxCpu < 1 { *mMaxCpu = runtime.NumCPU() @@ -192,6 +208,7 @@ func runMaster(cmd *Command, args []string) bool { http.HandleFunc("/dir/status", dirStatusHandler) http.HandleFunc("/vol/grow", volumeGrowHandler) http.HandleFunc("/vol/status", volumeStatusHandler) + http.HandleFunc("/", redirectHandler) topo.StartRefreshWritableVolumes(*garbageThreshold) diff --git a/weed-fs/src/pkg/topology/topology.go b/weed-fs/src/pkg/topology/topology.go index e0a2b0c34..4fd109a99 100644 --- a/weed-fs/src/pkg/topology/topology.go +++ b/weed-fs/src/pkg/topology/topology.go @@ -57,7 +57,7 @@ func (t *Topology) loadConfiguration(configurationFile string) error { return e } -func (t *Topology) Lookup(vid storage.VolumeId) *[]*DataNode { +func (t *Topology) Lookup(vid storage.VolumeId) []*DataNode { for _, vl := range t.replicaType2VolumeLayout { if vl != nil { if list := vl.Lookup(vid); list != nil { diff --git a/weed-fs/src/pkg/topology/volume_layout.go b/weed-fs/src/pkg/topology/volume_layout.go index 80eff5061..314aca69f 100644 --- a/weed-fs/src/pkg/topology/volume_layout.go +++ b/weed-fs/src/pkg/topology/volume_layout.go @@ -42,8 +42,8 @@ func (vl *VolumeLayout) isWritable(v *storage.VolumeInfo) bool{ return uint64(v.Size) < vl.volumeSizeLimit && v.Version == storage.CurrentVersion } -func (vl *VolumeLayout) Lookup(vid storage.VolumeId) *[]*DataNode { - return &vl.vid2location[vid].list +func (vl *VolumeLayout) Lookup(vid storage.VolumeId) []*DataNode { + return vl.vid2location[vid].list } func (vl *VolumeLayout) PickForWrite(count int) (*storage.VolumeId, int, *VolumeLocationList, error) {