github.com/NebulousLabs/Sia@v1.3.7/modules/renter/erasure.go (about)

     1  package renter
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/klauspost/reedsolomon"
     8  
     9  	"github.com/NebulousLabs/Sia/modules"
    10  )
    11  
    12  // rsCode is a Reed-Solomon encoder/decoder. It implements the
    13  // modules.ErasureCoder interface.
    14  type rsCode struct {
    15  	enc reedsolomon.Encoder
    16  
    17  	numPieces  int
    18  	dataPieces int
    19  }
    20  
    21  // NumPieces returns the number of pieces returned by Encode.
    22  func (rs *rsCode) NumPieces() int { return rs.numPieces }
    23  
    24  // MinPieces return the minimum number of pieces that must be present to
    25  // recover the original data.
    26  func (rs *rsCode) MinPieces() int { return rs.dataPieces }
    27  
    28  // Encode splits data into equal-length pieces, some containing the original
    29  // data and some containing parity data.
    30  func (rs *rsCode) Encode(data []byte) ([][]byte, error) {
    31  	pieces, err := rs.enc.Split(data)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	// err should not be possible if Encode is called on the result of Split,
    36  	// but no harm in checking anyway.
    37  	err = rs.enc.Encode(pieces)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	return pieces, nil
    42  }
    43  
    44  // EncodeShards creates the parity shards for an already sharded input.
    45  func (rs *rsCode) EncodeShards(pieces [][]byte) ([][]byte, error) {
    46  	// Check that the caller provided the minimum amount of pieces.
    47  	if len(pieces) != rs.MinPieces() {
    48  		return nil, fmt.Errorf("invalid number of pieces given %v %v", len(pieces), rs.MinPieces())
    49  	}
    50  	// Add the parity shards to pieces.
    51  	for len(pieces) < rs.NumPieces() {
    52  		pieces = append(pieces, make([]byte, pieceSize))
    53  	}
    54  	err := rs.enc.Encode(pieces)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	return pieces, nil
    59  }
    60  
    61  // Recover recovers the original data from pieces and writes it to w.
    62  // pieces should be identical to the slice returned by Encode (length and
    63  // order must be preserved), but with missing elements set to nil.
    64  func (rs *rsCode) Recover(pieces [][]byte, n uint64, w io.Writer) error {
    65  	err := rs.enc.ReconstructData(pieces)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	return rs.enc.Join(w, pieces, int(n))
    70  }
    71  
    72  // NewRSCode creates a new Reed-Solomon encoder/decoder using the supplied
    73  // parameters.
    74  func NewRSCode(nData, nParity int) (modules.ErasureCoder, error) {
    75  	enc, err := reedsolomon.New(nData, nParity)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return &rsCode{
    80  		enc:        enc,
    81  		numPieces:  nData + nParity,
    82  		dataPieces: nData,
    83  	}, nil
    84  }