frostfs-node/services/public/object/get.go

112 lines
2 KiB
Go
Raw Normal View History

package object
import (
"bytes"
"io"
"github.com/nspcc-dev/neofs-api-go/object"
"github.com/pkg/errors"
"go.uber.org/zap"
)
type (
getServerWriter struct {
req *object.GetRequest
srv object.Service_GetServer
respPreparer responsePreparer
}
)
const (
maxGetPayloadSize = 3584 * 1024 // 3.5 MiB
emSendObjectHead = "could not send object head"
)
var _ io.Writer = (*getServerWriter)(nil)
func (s *objectService) Get(req *object.GetRequest, server object.Service_GetServer) (err error) {
defer func() {
if r := recover(); r != nil {
s.log.Error(panicLogMsg,
zap.Stringer("request", object.RequestGet),
zap.Any("reason", r),
)
err = errServerPanic
}
err = s.statusCalculator.make(requestError{
t: object.RequestGet,
e: err,
})
}()
var r interface{}
if r, err = s.requestHandler.handleRequest(server.Context(), handleRequestParams{
request: req,
executor: s,
}); err != nil {
return err
}
obj := r.(*objectData)
var payload []byte
payload, obj.Payload = obj.Payload, nil
resp := makeGetHeaderResponse(obj.Object)
if err = s.respPreparer.prepareResponse(server.Context(), req, resp); err != nil {
return
}
if err = server.Send(resp); err != nil {
return errors.Wrap(err, emSendObjectHead)
}
_, err = io.CopyBuffer(
&getServerWriter{
req: req,
srv: server,
respPreparer: s.getChunkPreparer,
},
io.MultiReader(bytes.NewReader(payload), obj.payload),
make([]byte, maxGetPayloadSize))
return err
}
func splitBytes(data []byte, maxSize int) (result [][]byte) {
l := len(data)
if l == 0 {
return nil
}
for i := 0; i < l; i += maxSize {
last := i + maxSize
if last > l {
last = l
}
result = append(result, data[i:last])
}
return
}
func (s *getServerWriter) Write(p []byte) (int, error) {
resp := makeGetChunkResponse(p)
if err := s.respPreparer.prepareResponse(s.srv.Context(), s.req, resp); err != nil {
return 0, err
}
if err := s.srv.Send(resp); err != nil {
return 0, err
}
return len(p), nil
}