Skip to content

Commit 4bbbda1

Browse files
committed
HD-4220: pack slice to their real size
1 parent 81ee4dc commit 4bbbda1

4 files changed

Lines changed: 82 additions & 22 deletions

File tree

backend.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ type EncodeData struct {
213213
Free func() // cleanup closure (to free C allocated data once it becomes useless)
214214
}
215215

216+
func (e *EncodeData) String() string {
217+
str := "EncodeData{Data: ["
218+
for i, data := range e.Data {
219+
str += fmt.Sprintf("len(data[%d]) = %+v, ", i, len(data))
220+
}
221+
str += "]}"
222+
return str
223+
}
224+
216225
// Encode is the general purpose encoding function. It encodes data according
217226
// backend params and returns an EncodeData structure containing the Fragments
218227
func (backend *Backend) Encode(data []byte) (*EncodeData, error) {
@@ -262,6 +271,7 @@ func (backend *Backend) EncodeMatrixWithBufferMatrix(bm *BufferMatrix, chunkSize
262271
C.encode_chunk_buffermatrix_prepare(backend.libecDesc, pData, pDataLen,
263272
cChunkSize, C.int(bm.FragLen()), nbFrags, &ctx)
264273

274+
var totlen int64 = 0
265275
var errCounter uint32
266276

267277
wg.Add(int(ctx.number_of_subgroup))
@@ -273,6 +283,8 @@ func (backend *Backend) EncodeMatrixWithBufferMatrix(bm *BufferMatrix, chunkSize
273283
if i == int(ctx.number_of_subgroup)-1 {
274284
fragLen = C.size_t(bm.FragLenLastSubGroup())
275285
}
286+
// totlen should be atomicall updated
287+
atomic.AddInt64(&totlen, int64(fragLen)+int64(backend.headerSize))
276288
r := C.encode_chunk_buffermatrix(backend.libecDesc, pData, pDataLen,
277289
nbFrags, &ctx, C.int(nth), fragLen)
278290

@@ -294,13 +306,14 @@ func (backend *Backend) EncodeMatrixWithBufferMatrix(bm *BufferMatrix, chunkSize
294306
result := make([][]byte, backend.K+backend.M)
295307
fragLen := ctx.frags_len
296308
flen := bm.FragLen()
309+
297310
for i := 0; i < backend.K; i++ {
298-
result[i] = data[i*flen : (i+1)*flen]
311+
result[i] = data[i*flen : (i)*flen+int(totlen)]
299312
}
300313

301314
for i := 0; i < backend.M; i++ {
302315
str := cGetArrayItem(ctx.codings, i)
303-
result[i+backend.K] = (*[1 << 30]byte)(str)[:int(C.int(fragLen)):int(C.int(fragLen))]
316+
result[i+backend.K] = (*[1 << 30]byte)(str)[:int(C.int(totlen)):int(C.int(fragLen))]
304317
}
305318

306319
return &EncodeData{result, func() {
@@ -599,6 +612,9 @@ func (backend *Backend) GetRangeMatrix(startIncl, endIncl, cellDataSize, fragSiz
599612
can at least check that it doesn't exceed the maximum payload that
600613
this configuration can handle. */
601614
nrLines := fragSize / cellSize
615+
if nrLines*cellSize < fragSize {
616+
nrLines++
617+
}
602618

603619
/* Inside a fragment (ie, inside a column), what is the
604620
stored amount of data? */
@@ -763,7 +779,8 @@ func (backend *Backend) ReconstructMatrix(frags [][]byte, fragIndex int, pieceSi
763779
dataB, data := backend.pool.New(dlen)
764780

765781
var errCounter uint32
766-
// TODO use goroutines here to leverage multicore computation
782+
783+
totLenPerFrag := int64(0)
767784
wg.Add(chunkNr)
768785
for i := 0; i < chunkNr; i++ {
769786
go func(chunkIdx int) {
@@ -774,14 +791,17 @@ func (backend *Backend) ReconstructMatrix(frags [][]byte, fragIndex int, pieceSi
774791
if err := backend.reconstruct(vect, fragIndex, data[chunkIdx*chunkSize:]); err != nil {
775792
atomic.AddUint32(&errCounter, 1)
776793
}
794+
info := GetFragmentInfo(vect[0])
795+
// atomicly add to totLenPerFrag
796+
atomic.AddInt64(&totLenPerFrag, int64(info.Size)+int64(backend.headerSize))
777797
wg.Done()
778798
}(i)
779799
}
780800
wg.Wait()
781801
if errCounter != 0 {
782802
return nil, errors.New("sub reconstruction failed")
783803
}
784-
return &DecodeData{data[:dlen:dlen], func() {
804+
return &DecodeData{data[:totLenPerFrag:dlen], func() {
785805
backend.pool.Release(dataB)
786806
}}, nil
787807
}

backend_test.go

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ func TestGC(t *testing.T) {
488488
},
489489
}
490490

491-
nbRoutines := 500
491+
nbRoutines := 1
492492

493493
for _, test := range tests {
494494
t.Run(test.name, func(_ *testing.T) {
@@ -815,16 +815,25 @@ func TestLinearizeMatrixAndReconstruct(t *testing.T) {
815815
useOldFormat bool
816816
}{
817817
{
818-
chunkSize: 512,
819-
dataSize: 512*2 + 10,
820-
startIncl: 512*2 - 3,
821-
endIncl: 512*2 - 1,
818+
chunkSize: DefaultChunkSize,
819+
dataSize: DefaultChunkSize*2 + 10,
820+
startIncl: 3,
821+
endIncl: 9,
822+
useOldFormat: false,
822823
},
823824
{
824-
chunkSize: DefaultChunkSize,
825-
dataSize: 105623,
826-
startIncl: 59441,
827-
endIncl: 64149,
825+
chunkSize: DefaultChunkSize,
826+
dataSize: DefaultChunkSize*2 + 10,
827+
startIncl: 3,
828+
endIncl: 9,
829+
useOldFormat: true,
830+
},
831+
{
832+
chunkSize: 512,
833+
dataSize: 512*2 + 10,
834+
startIncl: 512*2 - 3,
835+
endIncl: 512*2 - 1,
836+
useOldFormat: false,
828837
},
829838
{
830839
chunkSize: 512,
@@ -833,13 +842,34 @@ func TestLinearizeMatrixAndReconstruct(t *testing.T) {
833842
endIncl: 512*2 - 1,
834843
useOldFormat: true,
835844
},
845+
{
846+
chunkSize: DefaultChunkSize,
847+
dataSize: 105623,
848+
startIncl: 59441,
849+
endIncl: 64149,
850+
useOldFormat: false,
851+
},
836852
{
837853
chunkSize: DefaultChunkSize,
838854
dataSize: 105623,
839855
startIncl: 59441,
840856
endIncl: 64149,
841857
useOldFormat: true,
842858
},
859+
{
860+
chunkSize: DefaultChunkSize,
861+
dataSize: 105623,
862+
startIncl: 105610,
863+
endIncl: 105622,
864+
useOldFormat: true,
865+
},
866+
{
867+
chunkSize: DefaultChunkSize,
868+
dataSize: 105623,
869+
startIncl: 105610,
870+
endIncl: 105622,
871+
useOldFormat: false,
872+
},
843873
}
844874

845875
for _, param := range testParams {
@@ -854,9 +884,7 @@ func TestLinearizeMatrixAndReconstruct(t *testing.T) {
854884
endIncl := p.endIncl
855885

856886
data := make([]byte, dataSize)
857-
for i := range dataSize {
858-
data[i] = byte('A' + i%26)
859-
}
887+
_, _ = cryptorand.Read(data)
860888
bm := NewBufferMatrix(currentChunkSize, len(data), backend.K)
861889
if p.useOldFormat {
862890
bm.UseOldFormat()
@@ -867,9 +895,11 @@ func TestLinearizeMatrixAndReconstruct(t *testing.T) {
867895
encoded, err := backend.EncodeMatrixWithBufferMatrix(bm, currentChunkSize)
868896
require.NoError(t, err)
869897
defer encoded.Free()
898+
fmt.Printf("%+v\n", encoded)
870899

871900
rangeM := backend.GetRangeMatrix(startIncl, endIncl, currentChunkSize, len(encoded.Data[0]))
872901
require.NotNil(t, rangeM)
902+
fmt.Printf("%+v\n", rangeM)
873903

874904
/* Decode the matrix as if it was requested and
875905
checks that the result matches the payload on the requested range. */
@@ -901,8 +931,12 @@ func TestLinearizeMatrixAndReconstruct(t *testing.T) {
901931

902932
require.NoError(t, err)
903933
defer reconstructed.Free()
904-
905-
require.True(t, bytes.Equal(frags2[0], reconstructed.Data))
934+
expected2 := frags2[0]
935+
if !p.useOldFormat {
936+
lenToCompare := len(reconstructed.Data)
937+
expected2 = expected2[:lenToCompare]
938+
}
939+
require.True(t, bytes.Equal(expected2, reconstructed.Data))
906940
})
907941
}
908942
}

buffer.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package erasurecode
22

33
import (
44
"bytes"
5+
"fmt"
56
"io"
67
)
78

@@ -15,6 +16,11 @@ type BufferInfo struct {
1516
newStyle bool
1617
}
1718

19+
// Implement String interface
20+
func (b BufferInfo) String() string {
21+
return fmt.Sprintf("BufferInfo{hdrSize: %d, bufSize: %d, len: %d, k: %d, curBlock: %d, leftInBlock: %d, sizeOfLastSubGroup: %d, newStyle: %t}", b.hdrSize, b.bufSize, b.len, b.k, b.curBlock, b.leftInBlock, b.sizeOfLastSubGroup, b.newStyle)
22+
}
23+
1824
// FragLen returns the size of a "fragment" aligned to a block size (data + header)
1925
func (b BufferInfo) FragLen() int {
2026
return b.SubGroups() * (b.bufSize + b.hdrSize)
@@ -82,6 +88,10 @@ type BufferMatrix struct {
8288
BufferInfo
8389
}
8490

91+
func (b *BufferMatrix) String() string {
92+
return fmt.Sprintf("BufferMatrix{len(b): %+v,finished: %+v, BufferInfo: %+v}", len(b.b), b.finished, b.BufferInfo)
93+
}
94+
8595
// NewBufferMatrix returns a new buffer suitable for <len> data and organized
8696
// such as it can be injected into EncodeMatrixWithBuffer without allocation/copying
8797
// the data into shards

buffer_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ func TestEncodeBufferMatrix(t *testing.T) {
9898

9999
frags := encoded.Data
100100

101-
for i := 0; i < k+m; i++ {
102-
assert.Equal(t, b.FragLen(), len(frags[i]))
103-
}
104-
105101
decoded, err := backend.DecodeMatrix(frags, blockSize)
106102
assert.NoError(t, err)
107103
if err != nil {

0 commit comments

Comments
 (0)