forked from TrueCloudLab/frostfs-s3-gw
81 lines
1.3 KiB
Go
81 lines
1.3 KiB
Go
|
package layer
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
|
||
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||
|
)
|
||
|
|
||
|
type partObj struct {
|
||
|
OID oid.ID
|
||
|
Size uint64
|
||
|
}
|
||
|
|
||
|
// implements io.Reader of payloads of the object list stored in the FrostFS network.
|
||
|
type multiObjectReader struct {
|
||
|
ctx context.Context
|
||
|
|
||
|
layer *layer
|
||
|
|
||
|
off, ln uint64
|
||
|
|
||
|
prm getFrostFSParams
|
||
|
|
||
|
curReader io.Reader
|
||
|
|
||
|
parts []partObj
|
||
|
}
|
||
|
|
||
|
func (x *multiObjectReader) Read(p []byte) (n int, err error) {
|
||
|
if x.curReader != nil {
|
||
|
n, err = x.curReader.Read(p)
|
||
|
if !errors.Is(err, io.EOF) {
|
||
|
return n, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(x.parts) == 0 {
|
||
|
return n, io.EOF
|
||
|
}
|
||
|
|
||
|
for x.off != 0 {
|
||
|
if x.parts[0].Size < x.off {
|
||
|
x.parts = x.parts[1:]
|
||
|
x.off -= x.parts[0].Size
|
||
|
} else {
|
||
|
x.prm.off = x.off
|
||
|
x.off = 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
x.prm.oid = x.parts[0].OID
|
||
|
|
||
|
if x.ln != 0 {
|
||
|
if x.parts[0].Size < x.prm.off+x.ln {
|
||
|
x.prm.ln = x.parts[0].Size - x.prm.off
|
||
|
x.ln -= x.prm.ln
|
||
|
} else {
|
||
|
x.prm.ln = x.ln
|
||
|
x.ln = 0
|
||
|
x.parts = x.parts[:1]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
x.curReader, err = x.layer.initFrostFSObjectPayloadReader(x.ctx, x.prm)
|
||
|
if err != nil {
|
||
|
return n, fmt.Errorf("init payload reader for the next part: %w", err)
|
||
|
}
|
||
|
|
||
|
x.prm.off = 0
|
||
|
x.prm.ln = 0
|
||
|
|
||
|
x.parts = x.parts[1:]
|
||
|
|
||
|
next, err := x.Read(p[n:])
|
||
|
|
||
|
return n + next, err
|
||
|
}
|