// Constructor for creating a new erasure coding scheme. M is the total // number of shards output by the encoding. K is the number of shards // that can recreate any data that was encoded. Size is the size of the // byte array to encode. It should be divisible by K as each shard // will be Size / K in length. The maximum value for K and M is 127. func NewCode(m int, k int, size int) *Code { if m <= 0 || k <= 0 || k >= m || k > 127 || m > 127 || size < 0 { panic("Invalid erasure code params") } if size%k != 0 { panic("Size to encode is not divisable by k and therefore cannot be encoded into shards") } encodeMatrix := make([]byte, m*k) galoisTables := make([]byte, k*(m-k)*32) if k > 5 { C.gf_gen_cauchy1_matrix((*C.uchar)(&encodeMatrix[0]), C.int(m), C.int(k)) } else { C.gf_gen_rs_matrix((*C.uchar)(&encodeMatrix[0]), C.int(m), C.int(k)) } C.ec_init_tables(C.int(k), C.int(m-k), (*C.uchar)(&encodeMatrix[k*k]), (*C.uchar)(&galoisTables[0])) return &Code{ M: m, K: k, ShardLength: size / k, EncodeMatrix: encodeMatrix, galoisTables: galoisTables, decode: &decodeNode{ children: make([]*decodeNode, m), mutex: &sync.Mutex{}, }, } }
func (c *Code) getDecode(errList []byte, cache bool) (node *decodeNode) { if cache { node = c.decode.getDecode(errList, 0, byte(c.M)) } else { node = newDecodeNode(errList, byte(c.M)) } node.mutex.Lock() defer node.mutex.Unlock() if node.galoisTables == nil || node.decodeIndex == nil { node.galoisTables = make([]byte, c.K*c.M*32) node.decodeIndex = make([]byte, c.K) decodeMatrix := make([]byte, c.M*c.K) srcInErr := make([]byte, c.M) nErrs := len(errList) nSrcErrs := 0 for _, err := range errList { srcInErr[err] = 1 if int(err) < c.K { nSrcErrs++ } } C.gf_gen_decode_matrix((*C.uchar)(&c.EncodeMatrix[0]), (*C.uchar)(&decodeMatrix[0]), (*C.uchar)(&node.decodeIndex[0]), (*C.uchar)(&errList[0]), (*C.uchar)(&srcInErr[0]), C.int(nErrs), C.int(nSrcErrs), C.int(c.K), C.int(c.M)) C.ec_init_tables(C.int(c.K), C.int(nErrs), (*C.uchar)(&decodeMatrix[0]), (*C.uchar)(&node.galoisTables[0])) } return node }