예제 #1
0
파일: rsync.go 프로젝트: jbreiding/go-sync
// MakeRSync creates an RSync object using string paths,
// inferring most of the configuration
func MakeRSync(
	InputFile,
	Source,
	OutFile string,
	Summary FileSummary,
) (r *RSync, err error) {
	useTempFile := false
	if useTempFile, err = IsSameFile(InputFile, OutFile); err != nil {
		return nil, err
	}

	inputFile, err := os.Open(InputFile)

	if err != nil {
		return
	}

	var out io.WriteCloser
	var outFilename = OutFile
	var copier closer

	if useTempFile {
		out, outFilename, err = getTempFile()

		if err != nil {
			return
		}

		copier = &fileCopyCloser{
			from: outFilename,
			to:   OutFile,
		}
	} else {
		out, err = getOutFile(OutFile)

		if err != nil {
			return
		}

		copier = nullCloser{}
	}

	// blocksource
	var source *blocksources.BlockSourceBase

	resolver := blocksources.MakeFileSizedBlockResolver(
		uint64(Summary.GetBlockSize()),
		Summary.GetFileSize(),
	)

	source = blocksources.NewHttpBlockSource(
		Source,
		DefaultConcurrency,
		resolver,
		&filechecksum.HashVerifier{
			Hash:                md5.New(),
			BlockSize:           Summary.GetBlockSize(),
			BlockChecksumGetter: Summary,
		},
	)

	r = &RSync{
		Input:   inputFile,
		Output:  out,
		Source:  source,
		Summary: Summary,
		OnClose: []closer{
			&fileCloser{inputFile, InputFile},
			&fileCloser{out, outFilename},
			copier,
		},
	}

	return
}
예제 #2
0
// This is exceedingly similar to the module Example, but uses the http blocksource and a local http server
func Example_httpBlockSource() {
	PORT := <-setupServer()
	LOCAL_URL := fmt.Sprintf("http://localhost:%v/content", PORT)

	generator := filechecksum.NewFileChecksumGenerator(BLOCK_SIZE)
	_, referenceFileIndex, checksumLookup, err := indexbuilder.BuildIndexFromString(generator, REFERENCE)

	if err != nil {
		return
	}

	fileSize := int64(len([]byte(REFERENCE)))

	// This would normally be saved in a file

	blockCount := fileSize / BLOCK_SIZE
	if fileSize%BLOCK_SIZE != 0 {
		blockCount++
	}

	fs := &BasicSummary{
		ChecksumIndex:  referenceFileIndex,
		ChecksumLookup: checksumLookup,
		BlockCount:     uint(blockCount),
		BlockSize:      uint(BLOCK_SIZE),
		FileSize:       fileSize,
	}

	/*
		// Normally, this would be:
		rsync, err := MakeRSync(
			"toPatch.file",
			"http://localhost/content",
			"out.file",
			fs,
		)
	*/
	// Need to replace the output and the input
	inputFile := bytes.NewReader([]byte(LOCAL_VERSION))
	patchedFile := bytes.NewBuffer(nil)

	resolver := blocksources.MakeFileSizedBlockResolver(
		uint64(fs.GetBlockSize()),
		fs.GetFileSize(),
	)

	rsync := &RSync{
		Input:  inputFile,
		Output: patchedFile,
		Source: blocksources.NewHttpBlockSource(
			LOCAL_URL,
			1,
			resolver,
			&filechecksum.HashVerifier{
				Hash:                md5.New(),
				BlockSize:           fs.GetBlockSize(),
				BlockChecksumGetter: fs,
			},
		),
		Summary: fs,
		OnClose: nil,
	}

	err = rsync.Patch()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	err = rsync.Close()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Printf("Patched content: \"%v\"\n", patchedFile.String())

	// Just for inspection
	remoteReferenceSource := rsync.Source.(*blocksources.BlockSourceBase)
	fmt.Printf("Downloaded Bytes: %v\n", remoteReferenceSource.ReadBytes())

	// Output:
	// Patched content: "The quick brown fox jumped over the lazy dog"
	// Downloaded Bytes: 16
}