func GetHandler(w http.ResponseWriter, r *http.Request) { n := new(storage.Needle) vid, fid, ext := parseURLPath(r.URL.Path) volumeId, err := storage.NewVolumeId(vid) if err != nil { debug("parsing error:", err, r.URL.Path) return } n.ParsePath(fid) debug("volume", volumeId, "reading", n) if !store.HasVolume(volumeId) { lookupResult, err := operation.Lookup(*masterNode, volumeId) debug("volume", volumeId, "found on", lookupResult, "error", err) if err == nil { http.Redirect(w, r, "http://"+lookupResult.Locations[0].PublicUrl+r.URL.Path, http.StatusMovedPermanently) } else { debug("lookup error:", err, r.URL.Path) w.WriteHeader(http.StatusNotFound) } return } cookie := n.Cookie count, e := store.Read(volumeId, n) debug("read bytes", count, "error", e) if e != nil || count <= 0 { debug("read error:", e, r.URL.Path) w.WriteHeader(http.StatusNotFound) return } if n.Cookie != cookie { log.Println("request with unmaching cookie from ", r.RemoteAddr, "agent", r.UserAgent()) w.WriteHeader(http.StatusNotFound) return } if ext != "" { mtype := mime.TypeByExtension(ext) w.Header().Set("Content-Type", mtype) if storage.IsGzippable(ext, mtype) { if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { w.Header().Set("Content-Encoding", "gzip") } else { n.Data = storage.UnGzipData(n.Data) } } } w.Write(n.Data) }
func distributedOperation(volumeId storage.VolumeId, op func(location operation.Location) bool) bool { if lookupResult, lookupErr := operation.Lookup(*masterNode, volumeId); lookupErr == nil { length := 0 selfUrl := (*ip + ":" + strconv.Itoa(*vport)) 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 }