// 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 }
// 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 }