ReconstructData takes a list of data shards and parity shards, some of which may be nil, and tries to reconstruct the missing data shards. If successful, the nil rows of data are filled in and a nil error is returned. Otherwise, an error is returned. In particular, if there are missing data shards b
(data, parity [][]byte)
| 190 | // if there are missing data shards but there aren't enough parity |
| 191 | // shards to reconstruct them, NotEnoughParityShardsError is returned. |
| 192 | func (c Coder) ReconstructData(data, parity [][]byte) error { |
| 193 | var availableRows, missingRows []int |
| 194 | var input [][]byte |
| 195 | for i, dataShard := range data { |
| 196 | if dataShard != nil { |
| 197 | availableRows = append(availableRows, i) |
| 198 | input = append(input, dataShard) |
| 199 | } else { |
| 200 | missingRows = append(missingRows, i) |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | if len(missingRows) == 0 { |
| 205 | // Nothing to reconstruct. |
| 206 | return nil |
| 207 | } |
| 208 | |
| 209 | var usedParityRows []int |
| 210 | for i := 0; i < len(parity) && len(input) < c.dataShards; i++ { |
| 211 | if parity[i] != nil { |
| 212 | usedParityRows = append(usedParityRows, i) |
| 213 | input = append(input, parity[i]) |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | if len(input) < c.dataShards { |
| 218 | return NotEnoughParityShardsError{} |
| 219 | } |
| 220 | |
| 221 | reconstructionMatrix, err := makeReconstructionMatrix(c.dataShards, availableRows, missingRows, usedParityRows, c.parityMatrix) |
| 222 | if err != nil { |
| 223 | return err |
| 224 | } |
| 225 | |
| 226 | reconstructedData := make([][]byte, len(missingRows)) |
| 227 | for i := range reconstructedData { |
| 228 | reconstructedData[i] = make([]byte, len(input[0])) |
| 229 | } |
| 230 | c.applyMatrix(reconstructionMatrix, input, reconstructedData) |
| 231 | for i, r := range missingRows { |
| 232 | data[r] = reconstructedData[i] |
| 233 | } |
| 234 | return nil |
| 235 | } |