예제 #1
0
파일: erasure.go 프로젝트: Jonbeek/Sia
// EncodeRing takes a Sector and encodes it as a Ring: a set of common.QuorumSize Segments that include redundancy.
// The encoding parameters are stored in params.
// k is the number of non-redundant segments, and b is the size of each segment. b is calculated from k.
// The erasure-coding algorithm requires that the original data must be k*b in size, so it is padded here as needed.
//
// The return value is a Ring.
// The first k Segments of the Ring are the original data split up.
// The remaining Segments are newly generated redundant data.
func EncodeRing(sec *common.Sector, params *common.EncodingParams) (ring [common.QuorumSize]common.Segment, err error) {
	k, b, length := params.GetValues()

	// check for legal size of k
	if k <= 0 || k >= common.QuorumSize {
		err = fmt.Errorf("k must be greater than 0 and smaller than %v", common.QuorumSize)
		return
	}

	// check for legal size of b
	if b < common.MinSegmentSize || b > common.MaxSegmentSize {
		err = fmt.Errorf("b must be greater than %v and smaller than %v", common.MinSegmentSize, common.MaxSegmentSize)
		return
	}

	// check for legal size of length
	if length != len(sec.Data) {
		err = fmt.Errorf("length mismatch: sector length %v != parameter length %v", len(sec.Data), length)
		return
	} else if length > common.MaxSegmentSize*common.QuorumSize {
		err = fmt.Errorf("length must be smaller than %v", common.MaxSegmentSize*common.QuorumSize)
	}

	// pad data as needed
	padding := k*b - len(sec.Data)
	paddedData := append(sec.Data, bytes.Repeat([]byte{0x00}, padding)...)

	// call the encoding function
	m := common.QuorumSize - k
	redundantChunk := C.encodeRedundancy(C.int(k), C.int(m), C.int(b), (*C.char)(unsafe.Pointer(&paddedData[0])))
	redundantBytes := C.GoBytes(unsafe.Pointer(redundantChunk), C.int(m*b))

	// split paddedData into ring
	for i := 0; i < k; i++ {
		ring[i] = common.Segment{
			paddedData[i*b : (i+1)*b],
			uint8(i),
		}
	}

	// split redundantString into ring
	for i := k; i < common.QuorumSize; i++ {
		ring[i] = common.Segment{
			redundantBytes[(i-k)*b : (i-k+1)*b],
			uint8(i),
		}
	}

	// free the memory allocated by the C file
	C.free(unsafe.Pointer(redundantChunk))

	return
}
예제 #2
0
파일: erasure.go 프로젝트: jaked122/Sia
// EncodeRing takes data and produces a set of common.QuorumSize pieces that include redundancy.
// 'k' indiciates the number of non-redundant segments, and 'bytesPerSegment' indicates the size of each segment.
// 'originalData' must be 'k' * 'bytesPerSegment' in size, and should be padded before calling 'EncodeRing'.
//
// The return value is a set of strings common.QuorumSize in length.
// Each string is bytesPerSegment large.
// The first 'k' strings are the original data split up.
// The remaining strings are newly generated redundant data.
func EncodeRing(k int, bytesPerSegment int, originalData []byte) (segmentdData []string, err error) {
	// check that 'k' is legal
	if k <= 0 || k >= common.QuorumSize {
		err = fmt.Errorf("k must be greater than 0 and smaller than %v", common.QuorumSize)
		return
	}

	// check that bytesPerSegment is not too big or small
	if bytesPerSegment < common.MinSliceSize || bytesPerSegment > common.MaxSliceSize {
		err = fmt.Errorf("bytesPerSegment must be greater than %v and smaller than %v", common.MinSliceSize, common.MaxSliceSize)
		return
	}

	// check that bytesPerSegment is divisible by 8
	if bytesPerSegment%8 != 0 {
		err = fmt.Errorf("bytesPerSegment must be divisible by 8")
		return
	}

	// check that originalData is the correct size
	if len(originalData) != bytesPerSegment*k {
		err = fmt.Errorf("originalData incorrectly padded, must be of size 'bytesPerSegment' * %v - 'm'", common.QuorumSize)
		return
	}

	// call c library to encode data
	m := common.QuorumSize - k
	redundantChunk := C.encodeRedundancy(C.int(k), C.int(m), C.int(bytesPerSegment), (*C.char)(unsafe.Pointer(&originalData[0])))
	redundantString := C.GoStringN(redundantChunk, C.int(m*bytesPerSegment))

	segmentdData = make([]string, common.QuorumSize)

	// split originalData into segmentdData
	for i := 0; i < k; i++ {
		segmentdData[i] = string(originalData[i*bytesPerSegment : i*bytesPerSegment+bytesPerSegment])
	}

	// split redundantString into segmentdData
	for i := k; i < common.QuorumSize; i++ {
		segmentdData[i] = redundantString[(i-k)*bytesPerSegment : ((i-k)*bytesPerSegment)+bytesPerSegment]
	}

	// free the memory allocated by the C file
	C.free(unsafe.Pointer(redundantChunk))

	return
}