Skip to content

Commit 041a7c1

Browse files
committed
HD-4220: adapt get range
1 parent 98a5347 commit 041a7c1

File tree

2 files changed

+147
-35
lines changed

2 files changed

+147
-35
lines changed

backend.go

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ func (backend *Backend) ChunkInfo(fragRangeLen int, pieceSize int) ChunkInfo {
372372
if nrChunks*chunkSize != fragRangeLen {
373373
nrChunks++
374374
}
375-
376375
return ChunkInfo{
377376
ChunkSize: chunkSize,
378377
NrChunk: nrChunks,
@@ -392,7 +391,7 @@ func (backend *Backend) LinearizeMatrix(frags []ValidatedFragment, pieceSize int
392391
/* Fragments are sorted beforehand with the index of the first chunk.
393392
All chunks of a fragments share the same index. */
394393
fragsIndex := make([]int, len(frags))
395-
for i := 0; i < len(frags); i++ {
394+
for i := range frags {
396395
fragsIndex[i] = i
397396
}
398397

@@ -591,41 +590,65 @@ type RangeMatrix struct {
591590
* p4 [-[*]- -]
592591
*
593592
*/
594-
func (backend *Backend) GetRangeMatrix(startIncl, endIncl, pieceSize, fragSize int) *RangeMatrix {
595-
chunkSize := pieceSize + backend.headerSize
596-
groupSize := pieceSize * backend.K
593+
func (backend *Backend) GetRangeMatrix(startIncl, endIncl, cellDataSize, fragSize int) *RangeMatrix {
594+
nrColumns := backend.K
595+
cellSize := cellDataSize + backend.headerSize
596+
lineSize := cellDataSize * nrColumns
597597

598598
/* At this point we don't know what is the true payload size, but we
599599
can at least check that it doesn't exceed the maximum payload that
600600
this configuration can handle. */
601-
nrChunkByFrag := fragSize / chunkSize
602-
dataLenPerFrag := fragSize - nrChunkByFrag*backend.headerSize
603-
maxDataLen := dataLenPerFrag * backend.K
604-
if startIncl >= maxDataLen || endIncl >= maxDataLen || startIncl > endIncl {
601+
nrLines := fragSize / cellSize
602+
603+
/* Inside a fragment (ie, inside a column), what is the
604+
stored amount of data? */
605+
fragDataSize := fragSize - nrLines*backend.headerSize
606+
607+
maxDataSize := fragDataSize * nrColumns
608+
609+
if startIncl >= maxDataSize || endIncl >= maxDataSize || startIncl > endIncl {
605610
return nil
606611
}
607612

608-
pieceStartIncl := startIncl / pieceSize
609-
pieceEndIncl := endIncl / pieceSize
613+
/* convert cells indices to (x,y) indices */
614+
615+
/* Considering our (x,y) matrix as a single row, what
616+
are the indices of the start and end of the range we are interested in? */
617+
idxStart := startIncl / cellDataSize
618+
idxEnd := endIncl / cellDataSize
619+
620+
/* as we have the indices of the first cell and the last cell,
621+
* we can derive the indices of the first line and the last line
622+
* Based on this first line and last line, we can deduce
623+
* the amount of data to read in each fragment.
624+
*/
625+
lineStart := idxStart / nrColumns
626+
lineEnd := idxEnd / nrColumns
627+
628+
/*
629+
* as we have the indices of the first cell and the last cell,
630+
* we can compute the first column (e.g the first fragment)
631+
* where to start the read
632+
*/
633+
columnStart := idxStart % nrColumns
610634

611-
groupStartIncl := pieceStartIncl / backend.K
612-
groupEndIncl := pieceEndIncl / backend.K
635+
nrCellsToRead := (idxEnd + 1 - idxStart)
636+
dataOffset := idxStart * cellDataSize
613637

614-
fragFirstIncl := pieceStartIncl % backend.K
615-
fragCount := (pieceEndIncl + 1 - pieceStartIncl)
616-
dataOffset := pieceStartIncl * pieceSize
638+
totalLines := (maxDataSize + lineSize - 1) / lineSize
639+
isLastStripe := (lineEnd == totalLines-1)
617640

618641
/* When wrapping around, we read the full groups. */
619-
if fragFirstIncl+fragCount > backend.K {
620-
fragFirstIncl = 0
621-
fragCount = backend.K
622-
dataOffset = groupStartIncl * groupSize
642+
if columnStart+nrCellsToRead > nrColumns || isLastStripe {
643+
columnStart = 0
644+
nrCellsToRead = nrColumns
645+
dataOffset = lineStart * lineSize
623646
}
624647

625648
/* For each fragment, this is the minimum range to read -- including
626649
the header -- to decode or repair the data. */
627-
inFragRangeStartIncl := groupStartIncl * chunkSize
628-
inFragRangeEndExcl := (groupEndIncl + 1) * chunkSize
650+
inFragRangeStartIncl := lineStart * cellSize
651+
inFragRangeEndExcl := (lineEnd + 1) * cellSize
629652

630653
/* The output buffer only contains the data necessary to read the range,
631654
and the requested range must be adjusted to be relative
@@ -637,13 +660,13 @@ func (backend *Backend) GetRangeMatrix(startIncl, endIncl, pieceSize, fragSize i
637660
linearizedRangeStartIncl := startIncl - dataOffset
638661

639662
/* Decoding always works on a group boundary. */
640-
decodedRangeStartIncl := startIncl - groupStartIncl*groupSize
663+
decodedRangeStartIncl := startIncl - lineStart*lineSize
641664

642665
return &RangeMatrix{
643666
ReqStartIncl: startIncl,
644667
ReqEndIncl: endIncl,
645-
FragFirstIncl: fragFirstIncl,
646-
FragCount: fragCount,
668+
FragFirstIncl: columnStart,
669+
FragCount: nrCellsToRead,
647670
InFragRangeStartIncl: inFragRangeStartIncl,
648671
InFragRangeEndExcl: inFragRangeEndExcl,
649672
DecodedRangeStartIncl: decodedRangeStartIncl,

backend_test.go

Lines changed: 99 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -802,17 +802,107 @@ func TestEncodeM(t *testing.T) {
802802
_ = backend.Close()
803803
}
804804

805-
func TestLinearizeMatrix(t *testing.T) {
806-
assert := assert.New(t)
805+
func TestTwoLinearizeMatrix(t *testing.T) {
806+
backend, err := InitBackend(Params{Name: "isa_l_rs_vand", K: 2, M: 1, W: 8, HD: 5})
807+
require.NoError(t, err)
808+
defer func() {
809+
_ = backend.Close()
810+
}()
811+
currentChunkSize := 512
812+
dataSize := currentChunkSize*2 + 10
813+
startIncl := dataSize - 3
814+
endIncl := dataSize - 1
815+
816+
data := make([]byte, dataSize)
817+
for i := range dataSize {
818+
data[i] = byte('A' + i%26)
819+
}
820+
bm := NewBufferMatrix(currentChunkSize, len(data), backend.K)
821+
_, err = io.Copy(bm, bytes.NewReader(data))
822+
require.NoError(t, err)
823+
bm.Finish()
824+
encoded, err := backend.EncodeMatrixWithBufferMatrix(bm, currentChunkSize)
825+
require.NoError(t, err)
826+
defer encoded.Free()
807827

828+
rangeM := backend.GetRangeMatrix(startIncl, endIncl, currentChunkSize, len(encoded.Data[0]))
829+
require.NotNil(t, rangeM)
830+
831+
/* Decode the matrix as if it was requested and
832+
checks that the result matches the payload on the requested range. */
833+
frags := make([][]byte, 0)
834+
for i := 0; i < rangeM.FragCount; i++ {
835+
fragIdx := (rangeM.FragFirstIncl + i) % backend.K
836+
buffer := encoded.Data[fragIdx][rangeM.InFragRangeStartIncl:rangeM.InFragRangeEndExcl]
837+
frags = append(frags, buffer)
838+
}
839+
840+
decoded, err := backend.LinearizeMatrix(frags, currentChunkSize)
841+
require.NoError(t, err)
842+
defer decoded.Free()
843+
844+
expected := data[startIncl:endIncl]
845+
846+
linearizedRangeEndExcl := rangeM.LinearizedRangeStartIncl + (endIncl - startIncl)
847+
found := decoded.Data[rangeM.LinearizedRangeStartIncl:linearizedRangeEndExcl]
848+
849+
require.True(t, bytes.Equal(expected, found))
850+
}
851+
852+
func TestOneLinearizeMatrix(t *testing.T) {
853+
backend, err := InitBackend(Params{Name: "isa_l_rs_vand", K: 4, M: 2, W: 8, HD: 5})
854+
require.NoError(t, err)
855+
defer func() {
856+
_ = backend.Close()
857+
}()
858+
dataSize := 105623
859+
startIncl := 59441
860+
endIncl := 64149
861+
data := make([]byte, dataSize)
862+
for i := range dataSize {
863+
data[i] = byte('A' + i%26)
864+
}
865+
bm := NewBufferMatrix(DefaultChunkSize, len(data), backend.K)
866+
_, err = io.Copy(bm, bytes.NewReader(data))
867+
require.NoError(t, err)
868+
bm.Finish()
869+
encoded, err := backend.EncodeMatrixWithBufferMatrix(bm, DefaultChunkSize)
870+
require.NoError(t, err)
871+
defer encoded.Free()
872+
873+
rangeM := backend.GetRangeMatrix(startIncl, endIncl, DefaultChunkSize, len(encoded.Data[0]))
874+
require.NotNil(t, rangeM)
875+
876+
/* Decode the matrix as if it was requested and
877+
checks that the result matches the payload on the requested range. */
878+
frags := make([][]byte, 0)
879+
for i := 0; i < rangeM.FragCount; i++ {
880+
fragIdx := (rangeM.FragFirstIncl + i) % backend.K
881+
buffer := encoded.Data[fragIdx][rangeM.InFragRangeStartIncl:rangeM.InFragRangeEndExcl]
882+
frags = append(frags, buffer)
883+
}
884+
885+
decoded, err := backend.LinearizeMatrix(frags, DefaultChunkSize)
886+
require.NoError(t, err)
887+
defer decoded.Free()
888+
889+
expected := data[startIncl : endIncl+1]
890+
891+
linearizedRangeEndExcl := rangeM.LinearizedRangeStartIncl + (endIncl - startIncl) + 1
892+
found := decoded.Data[rangeM.LinearizedRangeStartIncl:linearizedRangeEndExcl]
893+
require.True(t, bytes.Equal(expected, found))
894+
}
895+
896+
func TestLinearizeMatrix(t *testing.T) {
808897
pieceSize := DefaultChunkSize
809898
k := 4
810899
m := 1
811900

812901
backend, err := InitBackend(Params{Name: "isa_l_rs_vand", K: k, M: m, W: 8, HD: m})
813-
if err != nil {
814-
t.Fatalf("cannot init backend: (%v)", err)
815-
}
902+
require.NoError(t, err)
903+
defer func() {
904+
_ = backend.Close()
905+
}()
816906

817907
rangeValues := func(values []reflect.Value, rng *rand.Rand) {
818908
dataSize := 1 + rng.Intn(7*1024*1024)
@@ -848,7 +938,7 @@ func TestLinearizeMatrix(t *testing.T) {
848938

849939
fragSize := len(encoded.Data[0])
850940
rangeM := backend.GetRangeMatrix(startIncl, endIncl, pieceSize, fragSize)
851-
assert.NotNil(rangeM)
941+
require.NotNil(t, rangeM)
852942

853943
/* Decode the matrix as if it was requested and
854944
checks that the result matches the payload on the requested range. */
@@ -860,7 +950,7 @@ func TestLinearizeMatrix(t *testing.T) {
860950
}
861951

862952
decoded, err := backend.LinearizeMatrix(frags, pieceSize)
863-
assert.Nil(err)
953+
require.NoError(t, err)
864954
defer decoded.Free()
865955

866956
expected := data[startIncl : endIncl+1]
@@ -874,9 +964,8 @@ func TestLinearizeMatrix(t *testing.T) {
874964
Values: rangeValues,
875965
}
876966

877-
if err := quick.Check(checkRange, &config); err != nil {
878-
t.Error(err)
879-
}
967+
require.NoError(t, quick.Check(checkRange, &config))
968+
880969
}
881970

882971
func TestDecodeMatrix(t *testing.T) {

0 commit comments

Comments
 (0)