Example #1
0
/*
此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
}
Example #2
0
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
}