示例#1
0
文件: srv.go 项目: cmars/replican-web
func BlockHandler(store fs.LocalStore) http.HandlerFunc {
	return func(resp http.ResponseWriter, req *http.Request) {
		setBinaryResp(resp)

		strong, hasVar := mux.Vars(req)["strong"]
		if !hasVar {
			writeResponseError(resp, http.StatusInternalServerError,
				"Missing parameter: strong")
			return
		}

		if !hasVar {
			resp.WriteHeader(http.StatusNotFound)
			return
		}

		buf, err := store.ReadBlock(strong)
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError, err.String())
			return
		}

		resp.Write(buf)
	}
}
示例#2
0
文件: srv.go 项目: cmars/replican-web
func FileHandler(store fs.LocalStore) http.HandlerFunc {
	return func(resp http.ResponseWriter, req *http.Request) {
		setBinaryResp(resp)

		strong, hasStrong := mux.Vars(req)["strong"]
		if !hasStrong {
			writeResponseError(resp, http.StatusInternalServerError,
				"Missing parameter: strong")
			return
		}

		offsetStr, hasOffset := mux.Vars(req)["offset"]
		if !hasOffset {
			writeResponseError(resp, http.StatusInternalServerError,
				"Missing parameter: offset")
			return
		}
		offset, err := strconv.Atoi64(offsetStr)
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError,
				fmt.Sprintf("Invalid format for length: %s", offsetStr))
			return
		}

		lengthStr, hasLength := mux.Vars(req)["length"]
		if !hasLength {
			writeResponseError(resp, http.StatusInternalServerError,
				"Missing parameter: length")
			return
		}
		length, err := strconv.Atoi64(lengthStr)
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError,
				fmt.Sprintf("Invalid format for length: %s", lengthStr))
			return
		}

		buffer := bytes.NewBuffer([]byte{})
		n, err := store.ReadInto(strong, offset, length, buffer)
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError, err.String())
			return
		}
		if n < length {
			writeResponseError(resp, http.StatusInternalServerError, io.ErrShortWrite.String())
		}

		resp.Write(buffer.Bytes())
	}
}
示例#3
0
文件: srv.go 项目: cmars/replican-web
func TreeHandler(store fs.LocalStore) http.HandlerFunc {
	return func(resp http.ResponseWriter, req *http.Request) {
		setBinaryResp(resp)

		// gob the root
		buffer := bytes.NewBuffer([]byte{})
		encoder := gob.NewEncoder(buffer)
		err := encoder.Encode(store.Root())
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError, err.String())
			return
		}

		rootGob := buffer.Bytes()

		resp.Write(rootGob)
	}
}
示例#4
0
func NewPatchPlan(srcStore fs.BlockStore, dstStore fs.LocalStore) *PatchPlan {
	plan := &PatchPlan{srcStore: srcStore, dstStore: dstStore}

	plan.dstFileUnmatch = make(map[string]fs.File)

	fs.Walk(dstStore.Repo().Root(), func(dstNode fs.Node) bool {

		dstFile, isDstFile := dstNode.(fs.File)
		if isDstFile {
			plan.dstFileUnmatch[fs.RelPath(dstFile)] = dstFile
		}

		return !isDstFile
	})

	relocRefs := make(map[string]int)

	// Find all the FsNode matches
	fs.Walk(srcStore.Repo().Root(), func(srcNode fs.Node) bool {

		// Ignore non-FsNodes
		srcFsNode, isSrcFsNode := srcNode.(fs.FsNode)
		if !isSrcFsNode {
			return false
		}

		//		log.Printf("In src: %s", fs.RelPath(srcFsNode))

		srcFile, isSrcFile := srcNode.(fs.File)
		srcPath := fs.RelPath(srcFsNode)

		// Remove this srcPath from dst unmatched, if it was present
		plan.dstFileUnmatch[srcPath] = nil, false

		var srcStrong string
		if isSrcFile {
			srcStrong = srcFile.Info().Strong
		} else if srcDir, isSrcDir := srcNode.(fs.Dir); isSrcDir {
			srcStrong = srcDir.Info().Strong
		}

		var dstNode fs.FsNode
		var hasDstNode bool
		dstNode, hasDstNode = dstStore.Repo().File(srcStrong)
		if !hasDstNode {
			dstNode, hasDstNode = dstStore.Repo().Dir(srcStrong)
		}

		isDstFile := false
		if hasDstNode {
			_, isDstFile = dstNode.(fs.File)
		}

		dstFilePath := dstStore.Resolve(srcPath)
		dstFileInfo, _ := os.Stat(dstFilePath)

		// Resolve dst node that matches strong checksum with source
		if hasDstNode && isSrcFile == isDstFile {
			dstPath := fs.RelPath(dstNode)
			relocRefs[dstPath]++ // dstPath will be used in this cmd, inc ref count

			//			log.Printf("srcPath=%s dstPath=%s", srcPath, dstPath)

			if srcPath != dstPath {
				// Local dst file needs to be renamed or copied to src path
				from := &LocalPath{LocalStore: dstStore, RelPath: dstPath}
				to := &LocalPath{LocalStore: dstStore, RelPath: srcPath}
				plan.Cmds = append(plan.Cmds,
					&Transfer{From: from, To: to, relocRefs: relocRefs})
			} else {
				// Same path, keep it where it is
				plan.Cmds = append(plan.Cmds, &Keep{
					Path: &LocalPath{LocalStore: dstStore, RelPath: srcPath}})
			}

			// If its a file, figure out what to do with it
		} else if isSrcFile {

			switch {

			// Destination is not a file, so get rid of whatever is there first
			case dstFileInfo != nil && !dstFileInfo.IsRegular():
				plan.Cmds = append(plan.Cmds, &Conflict{
					Path:     &LocalPath{LocalStore: dstStore, RelPath: srcPath},
					FileInfo: dstFileInfo})
				fallthrough

			// Destination file does not exist, so full source copy needed
			case dstFileInfo == nil:
				plan.Cmds = append(plan.Cmds, &SrcFileDownload{
					SrcFile: srcFile,
					Path:    &LocalPath{LocalStore: dstStore, RelPath: srcPath}})
				break

			// Destination file exists, add block-level commands
			default:
				plan.appendFilePlan(srcFile, srcPath)
				break
			}

			// If its a directory, check for conflicting files of same name
		} else {

			if dstFileInfo != nil && !dstFileInfo.IsDirectory() {
				plan.Cmds = append(plan.Cmds, &Conflict{
					Path:     &LocalPath{LocalStore: dstStore, RelPath: dstFilePath},
					FileInfo: dstFileInfo})
			}
		}

		return !isSrcFile
	})

	return plan
}