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