/* 此api实现复制写入操作 步骤如下: 1.先写入本地 2. 如果需要复制则 将消息投递replicate到master 3. 如果2操作成功完成则返回 4. 如果2失败,则删除本地副本并投递删除消息到master 5. 返回4的结果 同理删除 */ 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" } //??? --lewgun if !needToReplicate && ret > 0 { needToReplicate = s.GetVolume(volumeId).NeedToReplicate() } if needToReplicate { //send to other replica locations if r.FormValue("type") != "replicate" { //只有最原始的才会执行distributedOperation //向master复制 if !distributedOperation(masterNode, s, volumeId, func(location operation.Location) bool { _, err := operation.Upload( "http://"+location.Url+r.URL.Path+"?type=replicate&ts="+strconv.FormatUint(needle.LastModified, 10), string(needle.Name), bytes.NewReader(needle.Data), needle.IsGzipped(), string(needle.Mime)) return err == nil }) { ret = 0 errorStatus = "Failed to write to replicas for volume " + volumeId.String() }// if !distributedOperation(masterNode, } // if r.FormValue("type") != "replicate" { } //复制失败,删除本地副本 if errorStatus != "" { if _, err = s.Delete(volumeId, needle); err != nil { errorStatus += "\nCannot delete " + strconv.FormatUint(needle.Id, 10) + " from " + volumeId.String() + ": " + err.Error() } else { distributedOperation( masterNode, s, volumeId, func(location operation.Location) bool { return nil == util.Delete("http://"+location.Url+r.URL.Path+"?type=replicate") } ) // distributedOperation(...) } // if errorStatus != "" { } size = ret return }
func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) { m := make(map[string]interface{}) if r.Method != "POST" { m["error"] = "Only submit via POST!" writeJsonQuiet(w, r, m) return } debug("parsing upload file...") //解析上传文件 fname, data, mimeType, isGzipped, lastModified, _, pe := storage.ParseUpload(r) if pe != nil { writeJsonError(w, r, pe) return } debug("assigning file id for", fname) //为文件分配id assignResult, ae := operation.Assign(masterUrl, 1, r.FormValue("replication"), r.FormValue("collection"), r.FormValue("ttl")) if ae != nil { writeJsonError(w, r, ae) return } url := "http://" + assignResult.PublicUrl + "/" + assignResult.Fid if lastModified != 0 { url = url + "?ts=" + strconv.FormatUint(lastModified, 10) } debug("upload file to store", url) //上传文件 uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType) if err != nil { writeJsonError(w, r, err) return } //返回成功后的处理消息 m["fileName"] = fname m["fid"] = assignResult.Fid m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid m["size"] = uploadResult.Size writeJsonQuiet(w, r, m) return }