diff --git a/pkg/storage/donut/erasure/erasure.go b/pkg/storage/donut/erasure/erasure.go new file mode 100644 index 000000000..5a2d7d0e4 --- /dev/null +++ b/pkg/storage/donut/erasure/erasure.go @@ -0,0 +1,37 @@ +package erasure + +import ( + "errors" + "io" + + "github.com/minio-io/minio/pkg/storage/donut/erasure/erasure1" +) + +type EncoderTechnique int + +const ( + // Vandermonde matrix type + Vandermonde EncoderTechnique = iota + // Cauchy matrix type + Cauchy +) + +// Write latest donut format +func Write(target io.Writer, key string, part uint8, length uint32, k, m uint8, technique EncoderTechnique, data io.Reader) error { + var versionedTechnique erasure1.EncoderTechnique + switch { + case technique == Vandermonde: + versionedTechnique = erasure1.Vandermonde + case technique == Cauchy: + versionedTechnique = erasure1.Cauchy + default: + errors.New("Unknown encoder technique") + } + return erasure1.Write(target, key, part, length, k, m, versionedTechnique, data) +} + +// Read any donut format +func Read(reader io.Reader) (io.Reader, error) { + // when version2 is created, create a method in version2 that can transform version1 structure to version2 + return nil, errors.New("Not Implemented") +} diff --git a/pkg/storage/donut/erasure/erasure1/erasure.go b/pkg/storage/donut/erasure/erasure1/erasure.go index 5cfe885b2..a40da6844 100644 --- a/pkg/storage/donut/erasure/erasure1/erasure.go +++ b/pkg/storage/donut/erasure/erasure1/erasure.go @@ -22,6 +22,11 @@ import ( "encoding/gob" "errors" "io" + "strconv" +) + +const ( + Version = uint32(1) ) // DataHeader represents the structure serialized to gob. @@ -84,7 +89,7 @@ func Write(target io.Writer, key string, part uint8, length uint32, k, m uint8, encoder.Encode(header) // write version - binary.Write(target, binary.LittleEndian, uint32(1)) + binary.Write(target, binary.LittleEndian, uint32(Version)) // write encoded header if _, err := io.Copy(target, &headerBuffer); err != nil { @@ -96,3 +101,18 @@ func Write(target io.Writer, key string, part uint8, length uint32, k, m uint8, } return nil } + +// Read an erasure block +func ReadHeader(reader io.Reader) (dataHeader DataHeader, err error) { + versionArray := make([]byte, 4) + if err := binary.Read(reader, binary.LittleEndian, versionArray); err != nil { + return dataHeader, err + } + version := binary.LittleEndian.Uint32(versionArray) + if version > Version || version == 0 { + return dataHeader, errors.New("Unknown version: " + strconv.FormatUint(uint64(version), 10)) + } + decoder := gob.NewDecoder(reader) + err = decoder.Decode(&dataHeader) + return dataHeader, err +} diff --git a/pkg/storage/donut/erasure/erasure1/erasure_test.go b/pkg/storage/donut/erasure/erasure1/erasure_test.go index 8111aeab8..37a1a3af4 100644 --- a/pkg/storage/donut/erasure/erasure1/erasure_test.go +++ b/pkg/storage/donut/erasure/erasure1/erasure_test.go @@ -66,3 +66,25 @@ func (s *MySuite) TestSingleWrite(c *C) { c.Assert(actualData.Bytes(), DeepEquals, []byte(testData)) c.Assert(err, IsNil) } + +func (s *MySuite) TestReadWrite(c *C) { + var testBuffer bytes.Buffer + testData := "Hello, World" + testHeader := DataHeader{ + Key: "testobj", + ChunkIndex: 1, + OriginalLength: uint32(len(testData)), + EncoderK: 8, + EncoderM: 8, + EncoderTechnique: Cauchy, + } + + err := Write(&testBuffer, testHeader.Key, testHeader.ChunkIndex, testHeader.OriginalLength, testHeader.EncoderK, testHeader.EncoderM, testHeader.EncoderTechnique, bytes.NewBufferString(testData)) + c.Assert(err, IsNil) + + header, err := ReadHeader(&testBuffer) + c.Assert(err, IsNil) + c.Assert(header, DeepEquals, testHeader) + c.Assert(testBuffer.Len(), Equals, len(testData)) + c.Assert(testBuffer.Bytes(), DeepEquals, []byte(testData)) +}