Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Changelog for NeoFS Node
- SNs no longer sign TTL=1 requests over mutually authenticated inter-node connections (#4100, #4159)
- Optimized GRPC read/write bufferring (#4130)
- TLS key of SN is now always read from the node wallet instead of configuration (#4131)
- SN now allocates less to forward SEARCH requests (#4116)
- SN now allocates less to forward SEARCH/GET/HEAD requests (#4116, #4160)
- SN object GET server now communicates over remote SN API version if it is lower than the local one (#4153)

### Removed
Expand Down
44 changes: 11 additions & 33 deletions pkg/services/object/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
protoencoding "github.com/nspcc-dev/neofs-sdk-go/proto/encoding"
protoobject "github.com/nspcc-dev/neofs-sdk-go/proto/object"
iprotobuf "github.com/nspcc-dev/neofs-sdk-go/proto/protobuf"
"github.com/nspcc-dev/neofs-sdk-go/proto/protobuf/protoscan"
Expand All @@ -33,8 +32,6 @@ import (
"google.golang.org/protobuf/encoding/protowire"
)

var getRequestBufferPool = mem.DefaultBufferPool()

var (
getStreamDesc = &grpc.StreamDesc{
StreamName: "Get",
Expand Down Expand Up @@ -87,7 +84,7 @@ func callRange(ctx context.Context, conn *grpc.ClientConn, request any) (grpc.Cl
// - [apistatus.ErrObjectNotFound] on 404 status
// - nil on other API statuses
// - any other transport/protocol error otherwise
func (x *getProxyContext) continueWithConn(ctx context.Context, req *protoobject.GetRequest, conn *grpc.ClientConn) error {
func (x *getProxyContext) continueWithConn(ctx context.Context, req mem.Buffer, body *protoobject.GetRequest_Body, conn *grpc.ClientConn) error {
stream, err := callGet(ctx, conn, req)
if err != nil {
return err
Expand All @@ -98,12 +95,12 @@ func (x *getProxyContext) continueWithConn(ctx context.Context, req *protoobject
var respBuf mem.BufferSlice
if err = stream.RecvMsg(&respBuf); err != nil {
if errors.Is(err, io.EOF) {
return x.validateEOF(req.Body, prog)
return x.validateEOF(body, prog)
}
return fmt.Errorf("reading the response failed: %w", err)
}

fin, sent, err := x.handleGetResponse(ctx, req.Body.Raw, &prog, respBuf)
fin, sent, err := x.handleGetResponse(ctx, body.Raw, &prog, respBuf)
if !sent {
respBuf.Free()
}
Expand Down Expand Up @@ -542,12 +539,12 @@ func (x *getECTransport) CopyECParentHeaderAndPayloadFromRemoteFirstPart(ctx con

copiedHdr, parentPldLen, partPldLen, copiedPartPld, err = x.copyRemotePart(ctx, conn, req)
if err != nil {
getRequestBufferPool.Put(x.getPartRequest)
defaultGRPCBufferPool.Put(x.getPartRequest)
return err
}

if copiedHdr {
getRequestBufferPool.Put(x.getPartRequest)
defaultGRPCBufferPool.Put(x.getPartRequest)
if copiedPartPld == partPldLen {
return nil
}
Expand Down Expand Up @@ -696,7 +693,7 @@ func (x *getECTransport) copyRemotePartRange(ctx context.Context, conn *grpc.Cli

copied, err := x.copyRemotePartRangeWithRequest(ctx, conn, request, ln, controlCh)
if err != nil || copied == ln {
getRequestBufferPool.Put(request)
defaultGRPCBufferPool.Put(request)
}

return copied, err
Expand Down Expand Up @@ -927,35 +924,16 @@ func (s *Server) makeGetECPartRequest(needSign bool, remoteServerAPIVersion vers

bodyLen := protoobject.CalculateGetRequestBodyLength(false, rngOff, rngLen, payloadOnly, nil, nil)

metaHdrLen := calculateRequestMetaHeaderLen(remoteServerAPIVersion, 1, xHdrs)

reqLen := protoencoding.CalculateRequestBodyWithMetaHeaderLength(bodyLen, metaHdrLen)
var sigCount int
if needSign {
reqLen += calculateRequestVerificationHeaderFieldLen(remoteServerAPIVersion)
}

bufItem := getRequestBufferPool.Get(reqLen)
buf := *bufItem

// body
off := protoencoding.WriteRequestBodyTagAndLength(buf, bodyLen)
off += protoobject.WriteGetRequestBody(buf[off:], cnr, parent, false, rngOff, rngLen, payloadOnly, nil, nil)
bodySlice := buf[off-bodyLen : off]

// meta header
off += writeRequestMetaHeaderToRequest(buf[off:], remoteServerAPIVersion, 1, xHdrs)

if !needSign {
return bufItem, nil
sigCount = calculateSignatureCountForAPIVersion(remoteServerAPIVersion)
}

// verification header
err := s.writeRequestSignatures(buf, off, bodySlice, buf[off-metaHdrLen:off], remoteServerAPIVersion)
if err != nil {
return nil, err
writeBodyFn := func(buf []byte) int {
return protoobject.WriteGetRequestBody(buf, cnr, parent, false, rngOff, rngLen, payloadOnly, nil, nil)
}

return bufItem, nil
return s.makeLocalRequest(sigCount, remoteServerAPIVersion, bodyLen, writeBodyFn, xHdrs)
}

func (x *getECTransport) makeGetECPartRangeRequest(needSign bool, remoteServerAPIVersion version.Version, partInfo iec.PartInfo, off, ln uint64) (*[]byte, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/services/object/head.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func callHead(ctx context.Context, conn *grpc.ClientConn, req any) (mem.BufferSl
// - (nil, nil, [apistatus.ErrObjectNotFound]) on 404 status
// - (buffered response, nil, nil) on other API statuses
// - (nil, nil, err) on any transport err
func getHeaderFromRemoteNode(ctx context.Context, conn *grpc.ClientConn, req *protoobject.HeadRequest, reqOID oid.ID) (mem.BufferSlice, iprotobuf.BuffersSlice, error) {
func getHeaderFromRemoteNode(ctx context.Context, conn *grpc.ClientConn, req mem.Buffer, reqOID oid.ID) (mem.BufferSlice, iprotobuf.BuffersSlice, error) {
respBuf, err := callHead(ctx, conn, req)
if err != nil {
return nil, iprotobuf.BuffersSlice{}, err
Expand Down
71 changes: 65 additions & 6 deletions pkg/services/object/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
iprotobuf "github.com/nspcc-dev/neofs-sdk-go/proto/protobuf"
protosession "github.com/nspcc-dev/neofs-sdk-go/proto/session"
"github.com/nspcc-dev/neofs-sdk-go/version"
"google.golang.org/grpc/mem"
"google.golang.org/protobuf/encoding/protowire"
)

Expand Down Expand Up @@ -42,6 +43,8 @@ const (
responseVerificationHeaderECDSAWIthSHA512Len = verificationHeaderECDSAWithSHA512SignatureLen * 3
)

var defaultGRPCBufferPool = mem.DefaultBufferPool()

var currentVersionResponseMetaHeader []byte

func init() {
Expand Down Expand Up @@ -285,18 +288,19 @@ func signECDSAWithSHA512(privKey ecdsa.PrivateKey, data []byte) ([]byte, error)
return sig, nil
}

func calculateRequestVerificationHeaderFieldLen(apiVersion version.Version) int {
var sigCount int

func calculateSignatureCountForAPIVersion(apiVersion version.Version) int {
switch apiVersion.Compare(version.New(2, 25)) {
default:
sigCount = 1
return 1
case -1:
sigCount = 3
return 3
case 0:
sigCount = 2
return 2
}
}

func calculateRequestVerificationHeaderFieldLen(apiVersion version.Version) int {
sigCount := calculateSignatureCountForAPIVersion(apiVersion)
return protoencoding.CalculateRequestVerificationHeaderFieldLength(sigCount * verificationHeaderECDSAWithSHA512SignatureLen)
}

Expand Down Expand Up @@ -340,3 +344,58 @@ func (s *Server) writeRequestSignatures(reqBuf []byte, bodyWithMetaLen int, body

return nil
}

func encodeRequestProtobuf(body protoencoding.Message, metaHdr protoencoding.Message, verifHdr protoencoding.Message) *[]byte {
bodyLen := body.MarshaledSize()
metaHdrLen := metaHdr.MarshaledSize()
verifHdrLen := verifHdr.MarshaledSize()

reqLen := protoencoding.CalculateRequestLength(bodyLen, metaHdrLen, verifHdrLen)

bufItem := defaultGRPCBufferPool.Get(reqLen)

buf := *bufItem
off := protoencoding.WriteRequestBodyMessage(buf, body)
off += protoencoding.WriteRequestMetaHeaderMessage(buf[off:], metaHdr)
protoencoding.WriteRequestVerificationHeaderMessage(buf[off:], verifHdr)

return bufItem
}

func (s *Server) makeLocalRequestFromBody(sigCount int, remoteServerAPIVersion version.Version, body protoencoding.Message) (*[]byte, error) {
bodyLen := body.MarshaledSize()
writeBodyFn := protoencoding.WriteStablyMarshalledMessageFunc(body)
return s.makeLocalRequest(sigCount, remoteServerAPIVersion, bodyLen, writeBodyFn, nil)
}

func (s *Server) makeLocalRequest(sigCount int, remoteServerAPIVersion version.Version, bodyLen int, writeBodyFn protoencoding.WriteMessageFunc, xHeaders []string) (*[]byte, error) {
metaHdrLen := calculateRequestMetaHeaderLen(remoteServerAPIVersion, 1, xHeaders)

reqLen := protoencoding.CalculateRequestBodyWithMetaHeaderLength(bodyLen, metaHdrLen)
if sigCount > 0 {
reqLen += protoencoding.CalculateRequestVerificationHeaderFieldLength(sigCount * verificationHeaderECDSAWithSHA512SignatureLen)
}

bufItem := defaultGRPCBufferPool.Get(reqLen)
buf := *bufItem

// body
off := protoencoding.WriteRequestBodyTagAndLength(buf, bodyLen)
off += writeBodyFn(buf[off:])
bodySlice := buf[off-bodyLen : off]

// meta header
off += writeRequestMetaHeaderToRequest(buf[off:], remoteServerAPIVersion, 1, xHeaders)

if sigCount == 0 {
return bufItem, nil
}

// verification header
err := s.writeRequestSignatures(buf, off, bodySlice, buf[off-metaHdrLen:off], remoteServerAPIVersion)
if err != nil {
return nil, err
}

return bufItem, nil
}
17 changes: 2 additions & 15 deletions pkg/services/object/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ import (
islices "github.com/nspcc-dev/neofs-node/internal/slices"
clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
protoencoding "github.com/nspcc-dev/neofs-sdk-go/proto/encoding"
protoobject "github.com/nspcc-dev/neofs-sdk-go/proto/object"
"github.com/nspcc-dev/neofs-sdk-go/version"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/mem"
)

var searchRequestBufferPool = mem.DefaultBufferPool()

func iterateSearchableContainerNodes(nodeSets [][]netmap.NodeInfo, repRules []uint, ecRules []iec.Rule, allNodes bool, f func(netmap.NodeInfo) bool) {
for i := range nodeSets {
var (
Expand Down Expand Up @@ -53,20 +50,10 @@ func iterateSearchableContainerNodes(nodeSets [][]netmap.NodeInfo, repRules []ui
}

func (s *Server) forwardSearchRequest(ctx context.Context, req *protoobject.SearchV2Request, nodeSets [][]netmap.NodeInfo) (mem.BufferSlice, error) {
bodyLen := req.Body.MarshaledSize()
metaHdrLen := req.MetaHeader.MarshaledSize()
verifHdrLen := req.VerifyHeader.MarshaledSize()

reqLen := protoencoding.CalculateRequestLength(bodyLen, metaHdrLen, verifHdrLen)

bufItem := searchRequestBufferPool.Get(reqLen)
defer searchRequestBufferPool.Put(bufItem)
bufItem := encodeRequestProtobuf(req.Body, req.MetaHeader, req.VerifyHeader)
defer defaultGRPCBufferPool.Put(bufItem)
buf := *bufItem

off := protoencoding.WriteRequestBodyMessage(buf, req.Body)
off += protoencoding.WriteRequestMetaHeaderMessage(buf[off:], req.MetaHeader)
protoencoding.WriteRequestVerificationHeaderMessage(buf[off:], req.VerifyHeader)

reqBuf := mem.SliceBuffer(buf)

for _, nodeSet := range nodeSets {
Expand Down
Loading
Loading