Example #1
0
// RebuildSector takes a Ring and returns a Sector containing the original data.
// The encoding parameters are stored in params.
// k must be equal to the number of non-redundant segments when the file was originally built.
// Because recovery is just a bunch of matrix operations, there is no way to tell if the data has been corrupted
// or if an incorrect value of k has been chosen. This error checking must happen before calling RebuildSector.
// Each Segment's Data must have the correct Index from when it was encoded.
func RebuildSector(ring []common.Segment, params *common.EncodingParams) (sec *common.Sector, err error) {
	k, b, length := params.GetValues()
	if k == 0 && b == 0 {
		err = fmt.Errorf("could not rebuild using uninitialized encoding parameters")
		return
	}

	// check for legal size of k
	if k > common.QuorumSize || k < 1 {
		err = fmt.Errorf("k must be greater than 0 but 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 > common.MaxSegmentSize*common.QuorumSize {
		err = fmt.Errorf("length must be smaller than %v", common.MaxSegmentSize*common.QuorumSize)
	}

	// check for correct number of segments
	if len(ring) < k {
		err = fmt.Errorf("insufficient segments: expected at least %v, got %v", k, len(ring))
		return
	}

	// move all data into a single slice
	var segmentData []byte
	var segmentIndices []uint8
	for i := 0; i < k; i++ {
		// verify that each segment is the correct length
		// TODO: skip bad segments and continue rebuilding if possible
		if len(ring[i].Data) != b {
			err = fmt.Errorf("at least 1 Segment's Data field is the wrong length")
			return
		}

		segmentData = append(segmentData, ring[i].Data...)
		segmentIndices = append(segmentIndices, ring[i].Index)

	}
	// call the recovery function
	C.recoverData(C.int(k), C.int(common.QuorumSize-k), C.int(b), (*C.uchar)(unsafe.Pointer(&segmentData[0])), (*C.uchar)(unsafe.Pointer(&segmentIndices[0])))

	// remove padding introduced by EncodeRing()
	sec, err = common.NewSector(segmentData[:length])
	return
}
Example #2
0
// RebuildSector takes a set of 'k' strings, each 'bytesPerSegment' in size, and recovers the original data.
// 'k' must be equal to the number of non-redundant segments when the file was originally built.
// Because recovery is just a bunch of matrix operations, there is no way to tell if the data has been corrupted
// or if an incorrect value of 'k' has been chosen. This error checking must happen before calling RebuildSector.
// The set of 'untaintedSegments' will have corresponding indicies from when they were encoded.
// There is no way to tell what the indicies are, so they must be supplied in the 'segmentIndicies' slice.
// This must be a uint8 because the C library uses a char.
//
// The output is a single byteslice that is equivalent to the data used when initially calling EncodeRing()
func RebuildSector(k int, bytesPerSegment int, untaintedSegments []string, segmentIndicies []uint8) (originalData []byte, err error) {
	// check for legal size of k and m
	m := common.QuorumSize - k
	if k > common.QuorumSize || k < 1 {
		err = fmt.Errorf("k must be greater than 0 but smaller than %v", common.QuorumSize)
		return
	}

	// check for legal size of bytesPerSegment
	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 input data is correct number of slices.
	if len(untaintedSegments) != k {
		err = fmt.Errorf("there must be k elements in untaintedSegments")
		return
	}

	// check that input indicies are correct number of indicies
	if len(segmentIndicies) != k {
		err = fmt.Errorf("there must be k elements in segmentIndicies")
		return
	}

	// move all data into a single slice for C
	originalData = make([]byte, 0, k*bytesPerSegment)
	for _, segment := range untaintedSegments {
		byteSlice := []byte(segment)

		// verify that each string is the correct length
		if len(byteSlice) != bytesPerSegment {
			err = fmt.Errorf("at least 1 of 'untaintedSegments' is the wrong length")
			return
		}

		originalData = append(originalData, byteSlice...)
	}

	// call the recovery option
	C.recoverData(C.int(k), C.int(m), C.int(bytesPerSegment), (*C.uchar)(unsafe.Pointer(&originalData[0])), (*C.uchar)(unsafe.Pointer(&segmentIndicies[0])))

	return
}