Exemplo n.º 1
0
// DownloadFile retrieves the erasure-coded segments corresponding to a given file from a quorum.
// It reconstructs the original file from the segments using erasure.RebuildSector().
func DownloadFile(mr common.MessageRouter, fileHash crypto.Hash, length int, k int, quorum [common.QuorumSize]common.Address) (fileData []byte, err error) {
	// spawn a separate thread for each segment
	for i := range quorum {
		go func() {
			// send request
			m := new(common.Message)
			m.Destination = quorum[i]
			m.Payload = []byte{0x01}
			m.Payload = append(m.Payload, fileHash[:]...)
			mr.SendMessage(m)
			// wait for response
		}()
	}
	return
}
Exemplo n.º 2
0
// TestTCPDownloadFile tests the NewTCPServer and DownloadFile functions.
// NewTCPServer must properly initialize a TCP server.
// UploadFile splits a file into erasure-coded segments and distributes them across a quorum.
// k is the number of non-redundant segments.
// The file is padded to satisfy the erasure-coding requirements that:
//     len(fileData) = k*bytesPerSegment, and:
//     bytesPerSegment % 64 = 0
func UploadFile(mr common.MessageRouter, file *os.File, k int, quorum [common.QuorumSize]common.Address) (bytesPerSegment int, err error) {
	// read file
	fileInfo, err := file.Stat()
	if err != nil {
		return
	}
	if fileInfo.Size() > int64(common.QuorumSize*common.MaxSegmentSize) {
		err = fmt.Errorf("File exceeds maximum per-quorum size")
		return
	}
	fileData := make([]byte, fileInfo.Size())
	_, err = io.ReadFull(file, fileData)
	if err != nil {
		return
	}

	// calculate EncodeRing parameters, padding file if necessary
	bytesPerSegment = len(fileData) / k
	if bytesPerSegment%64 != 0 {
		bytesPerSegment += 64 - (bytesPerSegment % 64)
		padding := k*bytesPerSegment - len(fileData)
		fileData = append(fileData, bytes.Repeat([]byte{0x00}, padding)...)
	}

	// create erasure-coded segments
	segments, err := erasure.EncodeRing(k, bytesPerSegment, fileData)
	if err != nil {
		return
	}

	// for now we just send segment i to node i
	// this may need to be randomized for security
	for i := range quorum {
		m := new(common.Message)
		m.Destination = quorum[i]
		m.Payload = append([]byte{byte(i)}, []byte(segments[i])...)
		err = mr.SendMessage(m)
		if err != nil {
			return
		}
	}

	return
}