From e3026d3f4c2cf6652ed8364773d5b0d0192588fe Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 15 Nov 2024 16:25:38 +0300 Subject: [PATCH 1/3] [#291] container: Add ListStream to api Since api was moved from `TrueCloudLab/frostfs-api-go` to sdk, moving changes from TrueCloudLab/frostfs-api-go#125 here. Signed-off-by: Ekaterina Lebedeva --- api/apemanager/grpc/service_grpc.pb.go | 84 +-- api/container/convert.go | 135 ++++ api/container/grpc/service_frostfs.pb.go | 769 ++++++++++++++++++++ api/container/grpc/service_frostfs_fuzz.go | 38 + api/container/grpc/service_frostfs_test.go | 20 + api/container/grpc/service_grpc.pb.go | 185 +++-- api/container/marshal.go | 62 ++ api/container/types.go | 68 ++ api/object/grpc/service_grpc.pb.go | 800 +++++++++++---------- api/rpc/container.go | 25 + api/signature/body.go | 4 + 11 files changed, 1699 insertions(+), 491 deletions(-) diff --git a/api/apemanager/grpc/service_grpc.pb.go b/api/apemanager/grpc/service_grpc.pb.go index eb11f3f..bf76cc4 100644 --- a/api/apemanager/grpc/service_grpc.pb.go +++ b/api/apemanager/grpc/service_grpc.pb.go @@ -31,37 +31,37 @@ type APEManagerServiceClient interface { // Add a rule chain for a specific target to `Policy` smart contract. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // the chain has been successfully added; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully added; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. AddChain(ctx context.Context, in *AddChainRequest, opts ...grpc.CallOption) (*AddChainResponse, error) // Remove a rule chain for a specific target from `Policy` smart contract. // RemoveChain is an idempotent operation: removal of non-existing rule chain // also means success. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // the chain has been successfully removed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully removed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. RemoveChain(ctx context.Context, in *RemoveChainRequest, opts ...grpc.CallOption) (*RemoveChainResponse, error) // List chains defined for a specific target from `Policy` smart contract. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // chains have been successfully listed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // chains have been successfully listed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. ListChains(ctx context.Context, in *ListChainsRequest, opts ...grpc.CallOption) (*ListChainsResponse, error) } @@ -107,37 +107,37 @@ type APEManagerServiceServer interface { // Add a rule chain for a specific target to `Policy` smart contract. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // the chain has been successfully added; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully added; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. AddChain(context.Context, *AddChainRequest) (*AddChainResponse, error) // Remove a rule chain for a specific target from `Policy` smart contract. // RemoveChain is an idempotent operation: removal of non-existing rule chain // also means success. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // the chain has been successfully removed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully removed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. RemoveChain(context.Context, *RemoveChainRequest) (*RemoveChainResponse, error) // List chains defined for a specific target from `Policy` smart contract. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // chains have been successfully listed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // container (as target) not found; - // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ - // the operation is denied by the service. + // - **OK** (0, SECTION_SUCCESS): \ + // chains have been successfully listed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. ListChains(context.Context, *ListChainsRequest) (*ListChainsResponse, error) } diff --git a/api/container/convert.go b/api/container/convert.go index c91bdfd..5a9a805 100644 --- a/api/container/convert.go +++ b/api/container/convert.go @@ -762,3 +762,138 @@ func (r *ListResponse) FromGRPCMessage(m grpc.Message) error { return r.ResponseHeaders.FromMessage(v) } + +func (r *ListStreamRequestBody) ToGRPCMessage() grpc.Message { + var m *container.ListStreamRequest_Body + + if r != nil { + m = new(container.ListStreamRequest_Body) + + m.SetOwnerId(r.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + } + + return m +} + +func (r *ListStreamRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListStreamRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + r.ownerID = nil + } else { + if r.ownerID == nil { + r.ownerID = new(refs.OwnerID) + } + + err = r.ownerID.FromGRPCMessage(ownerID) + } + + return err +} + +func (r *ListStreamRequest) ToGRPCMessage() grpc.Message { + var m *container.ListStreamRequest + + if r != nil { + m = new(container.ListStreamRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListStreamRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *ListStreamRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListStreamRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListStreamRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *ListStreamResponseBody) ToGRPCMessage() grpc.Message { + var m *container.ListStreamResponse_Body + + if r != nil { + m = new(container.ListStreamResponse_Body) + + m.SetContainerIds(refs.ContainerIDsToGRPCMessage(r.cidList)) + } + + return m +} + +func (r *ListStreamResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListStreamResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.cidList, err = refs.ContainerIDsFromGRPCMessage(v.GetContainerIds()) + + return err +} + +func (r *ListStreamResponse) ToGRPCMessage() grpc.Message { + var m *container.ListStreamResponse + + if r != nil { + m = new(container.ListStreamResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListStreamResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *ListStreamResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListStreamResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListStreamResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} diff --git a/api/container/grpc/service_frostfs.pb.go b/api/container/grpc/service_frostfs.pb.go index 0743824..0388293 100644 --- a/api/container/grpc/service_frostfs.pb.go +++ b/api/container/grpc/service_frostfs.pb.go @@ -3155,3 +3155,772 @@ func (x *ListResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { in.Consumed() } } + +type ListStreamRequest_Body struct { + OwnerId *grpc.OwnerID `json:"ownerId"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListStreamRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListStreamRequest_Body)(nil) + _ json.Marshaler = (*ListStreamRequest_Body)(nil) + _ json.Unmarshaler = (*ListStreamRequest_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListStreamRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.OwnerId) + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListStreamRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListStreamRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.OwnerId != nil { + x.OwnerId.EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListStreamRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListStreamRequest_Body") + } + switch fc.FieldNum { + case 1: // OwnerId + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "OwnerId") + } + x.OwnerId = new(grpc.OwnerID) + if err := x.OwnerId.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListStreamRequest_Body) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} +func (x *ListStreamRequest_Body) SetOwnerId(v *grpc.OwnerID) { + x.OwnerId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListStreamRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListStreamRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"ownerId\":" + out.RawString(prefix) + x.OwnerId.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListStreamRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListStreamRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "ownerId": + { + var f *grpc.OwnerID + f = new(grpc.OwnerID) + f.UnmarshalEasyJSON(in) + x.OwnerId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListStreamRequest struct { + Body *ListStreamRequest_Body `json:"body"` + MetaHeader *grpc1.RequestMetaHeader `json:"metaHeader"` + VerifyHeader *grpc1.RequestVerificationHeader `json:"verifyHeader"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListStreamRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ListStreamRequest)(nil) + _ json.Marshaler = (*ListStreamRequest)(nil) + _ json.Unmarshaler = (*ListStreamRequest)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListStreamRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.MetaHeader) + size += proto.NestedStructureSize(3, x.VerifyHeader) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListStreamRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListStreamRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListStreamRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListStreamRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.MetaHeader != nil { + x.MetaHeader.EmitProtobuf(mm.AppendMessage(2)) + } + if x.VerifyHeader != nil { + x.VerifyHeader.EmitProtobuf(mm.AppendMessage(3)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListStreamRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListStreamRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListStreamRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // MetaHeader + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "MetaHeader") + } + x.MetaHeader = new(grpc1.RequestMetaHeader) + if err := x.MetaHeader.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 3: // VerifyHeader + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "VerifyHeader") + } + x.VerifyHeader = new(grpc1.RequestVerificationHeader) + if err := x.VerifyHeader.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListStreamRequest) GetBody() *ListStreamRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListStreamRequest) SetBody(v *ListStreamRequest_Body) { + x.Body = v +} +func (x *ListStreamRequest) GetMetaHeader() *grpc1.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} +func (x *ListStreamRequest) SetMetaHeader(v *grpc1.RequestMetaHeader) { + x.MetaHeader = v +} +func (x *ListStreamRequest) GetVerifyHeader() *grpc1.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} +func (x *ListStreamRequest) SetVerifyHeader(v *grpc1.RequestVerificationHeader) { + x.VerifyHeader = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListStreamRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListStreamRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) + x.Body.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"metaHeader\":" + out.RawString(prefix) + x.MetaHeader.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"verifyHeader\":" + out.RawString(prefix) + x.VerifyHeader.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListStreamRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListStreamRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListStreamRequest_Body + f = new(ListStreamRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "metaHeader": + { + var f *grpc1.RequestMetaHeader + f = new(grpc1.RequestMetaHeader) + f.UnmarshalEasyJSON(in) + x.MetaHeader = f + } + case "verifyHeader": + { + var f *grpc1.RequestVerificationHeader + f = new(grpc1.RequestVerificationHeader) + f.UnmarshalEasyJSON(in) + x.VerifyHeader = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListStreamResponse_Body struct { + ContainerIds []grpc.ContainerID `json:"containerIds"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListStreamResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListStreamResponse_Body)(nil) + _ json.Marshaler = (*ListStreamResponse_Body)(nil) + _ json.Unmarshaler = (*ListStreamResponse_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListStreamResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + for i := range x.ContainerIds { + size += proto.NestedStructureSizeUnchecked(1, &x.ContainerIds[i]) + } + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListStreamResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListStreamResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.ContainerIds { + x.ContainerIds[i].EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListStreamResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListStreamResponse_Body") + } + switch fc.FieldNum { + case 1: // ContainerIds + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerIds") + } + x.ContainerIds = append(x.ContainerIds, grpc.ContainerID{}) + ff := &x.ContainerIds[len(x.ContainerIds)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListStreamResponse_Body) GetContainerIds() []grpc.ContainerID { + if x != nil { + return x.ContainerIds + } + return nil +} +func (x *ListStreamResponse_Body) SetContainerIds(v []grpc.ContainerID) { + x.ContainerIds = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListStreamResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListStreamResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerIds\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.ContainerIds { + if i != 0 { + out.RawByte(',') + } + x.ContainerIds[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListStreamResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListStreamResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerIds": + { + var f grpc.ContainerID + var list []grpc.ContainerID + in.Delim('[') + for !in.IsDelim(']') { + f = grpc.ContainerID{} + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.ContainerIds = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListStreamResponse struct { + Body *ListStreamResponse_Body `json:"body"` + MetaHeader *grpc1.ResponseMetaHeader `json:"metaHeader"` + VerifyHeader *grpc1.ResponseVerificationHeader `json:"verifyHeader"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListStreamResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ListStreamResponse)(nil) + _ json.Marshaler = (*ListStreamResponse)(nil) + _ json.Unmarshaler = (*ListStreamResponse)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListStreamResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.MetaHeader) + size += proto.NestedStructureSize(3, x.VerifyHeader) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListStreamResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListStreamResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListStreamResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListStreamResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.MetaHeader != nil { + x.MetaHeader.EmitProtobuf(mm.AppendMessage(2)) + } + if x.VerifyHeader != nil { + x.VerifyHeader.EmitProtobuf(mm.AppendMessage(3)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListStreamResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListStreamResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListStreamResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // MetaHeader + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "MetaHeader") + } + x.MetaHeader = new(grpc1.ResponseMetaHeader) + if err := x.MetaHeader.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 3: // VerifyHeader + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "VerifyHeader") + } + x.VerifyHeader = new(grpc1.ResponseVerificationHeader) + if err := x.VerifyHeader.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListStreamResponse) GetBody() *ListStreamResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListStreamResponse) SetBody(v *ListStreamResponse_Body) { + x.Body = v +} +func (x *ListStreamResponse) GetMetaHeader() *grpc1.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} +func (x *ListStreamResponse) SetMetaHeader(v *grpc1.ResponseMetaHeader) { + x.MetaHeader = v +} +func (x *ListStreamResponse) GetVerifyHeader() *grpc1.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} +func (x *ListStreamResponse) SetVerifyHeader(v *grpc1.ResponseVerificationHeader) { + x.VerifyHeader = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListStreamResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListStreamResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) + x.Body.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"metaHeader\":" + out.RawString(prefix) + x.MetaHeader.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"verifyHeader\":" + out.RawString(prefix) + x.VerifyHeader.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListStreamResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListStreamResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListStreamResponse_Body + f = new(ListStreamResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "metaHeader": + { + var f *grpc1.ResponseMetaHeader + f = new(grpc1.ResponseMetaHeader) + f.UnmarshalEasyJSON(in) + x.MetaHeader = f + } + case "verifyHeader": + { + var f *grpc1.ResponseVerificationHeader + f = new(grpc1.ResponseVerificationHeader) + f.UnmarshalEasyJSON(in) + x.VerifyHeader = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} diff --git a/api/container/grpc/service_frostfs_fuzz.go b/api/container/grpc/service_frostfs_fuzz.go index 7e6d6e6..024b237 100644 --- a/api/container/grpc/service_frostfs_fuzz.go +++ b/api/container/grpc/service_frostfs_fuzz.go @@ -157,3 +157,41 @@ func DoFuzzJSONListResponse(data []byte) int { } return 1 } +func DoFuzzProtoListStreamRequest(data []byte) int { + msg := new(ListStreamRequest) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListStreamRequest(data []byte) int { + msg := new(ListStreamRequest) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} +func DoFuzzProtoListStreamResponse(data []byte) int { + msg := new(ListStreamResponse) + if err := msg.UnmarshalProtobuf(data); err != nil { + return 0 + } + _ = msg.MarshalProtobuf(nil) + return 1 +} +func DoFuzzJSONListStreamResponse(data []byte) int { + msg := new(ListStreamResponse) + if err := msg.UnmarshalJSON(data); err != nil { + return 0 + } + _, err := msg.MarshalJSON() + if err != nil { + panic(err) + } + return 1 +} diff --git a/api/container/grpc/service_frostfs_test.go b/api/container/grpc/service_frostfs_test.go index 804b89c..2844996 100644 --- a/api/container/grpc/service_frostfs_test.go +++ b/api/container/grpc/service_frostfs_test.go @@ -89,3 +89,23 @@ func FuzzJSONListResponse(f *testing.F) { DoFuzzJSONListResponse(data) }) } +func FuzzProtoListStreamRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListStreamRequest(data) + }) +} +func FuzzJSONListStreamRequest(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListStreamRequest(data) + }) +} +func FuzzProtoListStreamResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzProtoListStreamResponse(data) + }) +} +func FuzzJSONListStreamResponse(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + DoFuzzJSONListStreamResponse(data) + }) +} diff --git a/api/container/grpc/service_grpc.pb.go b/api/container/grpc/service_grpc.pb.go index ea22604..5991e81 100644 --- a/api/container/grpc/service_grpc.pb.go +++ b/api/container/grpc/service_grpc.pb.go @@ -19,10 +19,11 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ContainerService_Put_FullMethodName = "/neo.fs.v2.container.ContainerService/Put" - ContainerService_Delete_FullMethodName = "/neo.fs.v2.container.ContainerService/Delete" - ContainerService_Get_FullMethodName = "/neo.fs.v2.container.ContainerService/Get" - ContainerService_List_FullMethodName = "/neo.fs.v2.container.ContainerService/List" + ContainerService_Put_FullMethodName = "/neo.fs.v2.container.ContainerService/Put" + ContainerService_Delete_FullMethodName = "/neo.fs.v2.container.ContainerService/Delete" + ContainerService_Get_FullMethodName = "/neo.fs.v2.container.ContainerService/Get" + ContainerService_List_FullMethodName = "/neo.fs.v2.container.ContainerService/List" + ContainerService_ListStream_FullMethodName = "/neo.fs.v2.container.ContainerService/ListStream" ) // ContainerServiceClient is the client API for ContainerService service. @@ -35,11 +36,11 @@ type ContainerServiceClient interface { // container is added into smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // request to save the container has been sent to the sidechain; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container create access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // request to save the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container create access denied. Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) // `Delete` invokes `Container` smart contract's `Delete` method and returns // response immediately. After a new block is issued in sidechain, request is @@ -47,32 +48,42 @@ type ContainerServiceClient interface { // container is added into smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // request to remove the container has been sent to the sidechain; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container delete access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // request to remove the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container delete access denied. Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) // Returns container structure from `Container` smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // container has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // requested container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied. + // - **OK** (0, SECTION_SUCCESS): \ + // container has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // requested container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied. Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) - // Returns all owner's containers from 'Container` smart contract' storage. + // Returns all owner's containers from `Container` smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // container list has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container list access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container list access denied. List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) + // Returns all owner's containers from `Container` smart contract storage + // via stream. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container list access denied. + ListStream(ctx context.Context, in *ListStreamRequest, opts ...grpc.CallOption) (ContainerService_ListStreamClient, error) } type containerServiceClient struct { @@ -119,6 +130,38 @@ func (c *containerServiceClient) List(ctx context.Context, in *ListRequest, opts return out, nil } +func (c *containerServiceClient) ListStream(ctx context.Context, in *ListStreamRequest, opts ...grpc.CallOption) (ContainerService_ListStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &ContainerService_ServiceDesc.Streams[0], ContainerService_ListStream_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &containerServiceListStreamClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ContainerService_ListStreamClient interface { + Recv() (*ListStreamResponse, error) + grpc.ClientStream +} + +type containerServiceListStreamClient struct { + grpc.ClientStream +} + +func (x *containerServiceListStreamClient) Recv() (*ListStreamResponse, error) { + m := new(ListStreamResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // ContainerServiceServer is the server API for ContainerService service. // All implementations should embed UnimplementedContainerServiceServer // for forward compatibility @@ -129,11 +172,11 @@ type ContainerServiceServer interface { // container is added into smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // request to save the container has been sent to the sidechain; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container create access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // request to save the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container create access denied. Put(context.Context, *PutRequest) (*PutResponse, error) // `Delete` invokes `Container` smart contract's `Delete` method and returns // response immediately. After a new block is issued in sidechain, request is @@ -141,32 +184,42 @@ type ContainerServiceServer interface { // container is added into smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // request to remove the container has been sent to the sidechain; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container delete access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // request to remove the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container delete access denied. Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) // Returns container structure from `Container` smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // container has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // requested container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied. + // - **OK** (0, SECTION_SUCCESS): \ + // container has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // requested container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied. Get(context.Context, *GetRequest) (*GetResponse, error) - // Returns all owner's containers from 'Container` smart contract' storage. + // Returns all owner's containers from `Container` smart contract storage. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // container list has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // container list access denied. + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container list access denied. List(context.Context, *ListRequest) (*ListResponse, error) + // Returns all owner's containers from `Container` smart contract storage + // via stream. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container list access denied. + ListStream(*ListStreamRequest, ContainerService_ListStreamServer) error } // UnimplementedContainerServiceServer should be embedded to have forward compatible implementations. @@ -185,6 +238,9 @@ func (UnimplementedContainerServiceServer) Get(context.Context, *GetRequest) (*G func (UnimplementedContainerServiceServer) List(context.Context, *ListRequest) (*ListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method List not implemented") } +func (UnimplementedContainerServiceServer) ListStream(*ListStreamRequest, ContainerService_ListStreamServer) error { + return status.Errorf(codes.Unimplemented, "method ListStream not implemented") +} // UnsafeContainerServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ContainerServiceServer will @@ -269,6 +325,27 @@ func _ContainerService_List_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _ContainerService_ListStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListStreamRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ContainerServiceServer).ListStream(m, &containerServiceListStreamServer{stream}) +} + +type ContainerService_ListStreamServer interface { + Send(*ListStreamResponse) error + grpc.ServerStream +} + +type containerServiceListStreamServer struct { + grpc.ServerStream +} + +func (x *containerServiceListStreamServer) Send(m *ListStreamResponse) error { + return x.ServerStream.SendMsg(m) +} + // ContainerService_ServiceDesc is the grpc.ServiceDesc for ContainerService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -293,6 +370,12 @@ var ContainerService_ServiceDesc = grpc.ServiceDesc{ Handler: _ContainerService_List_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListStream", + Handler: _ContainerService_ListStream_Handler, + ServerStreams: true, + }, + }, Metadata: "api/container/grpc/service.proto", } diff --git a/api/container/marshal.go b/api/container/marshal.go index 2b16669..89a6661 100644 --- a/api/container/marshal.go +++ b/api/container/marshal.go @@ -343,3 +343,65 @@ func (r *ListResponseBody) StableSize() (size int) { func (r *ListResponseBody) Unmarshal(data []byte) error { return message.Unmarshal(r, data, new(container.ListResponse_Body)) } + +func (r *ListStreamRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(listReqBodyOwnerField, buf, r.ownerID) + + return buf +} + +func (r *ListStreamRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(listReqBodyOwnerField, r.ownerID) + + return size +} + +func (r *ListStreamRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListStreamRequest_Body)) +} + +func (r *ListStreamResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + for i := range r.cidList { + offset += protoutil.NestedStructureMarshal(listRespBodyIDsField, buf[offset:], &r.cidList[i]) + } + + return buf +} + +func (r *ListStreamResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + for i := range r.cidList { + size += protoutil.NestedStructureSize(listRespBodyIDsField, &r.cidList[i]) + } + + return size +} + +func (r *ListStreamResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListStreamResponse_Body)) +} diff --git a/api/container/types.go b/api/container/types.go index 92c4706..4da3f87 100644 --- a/api/container/types.go +++ b/api/container/types.go @@ -109,6 +109,26 @@ type ListResponse struct { session.ResponseHeaders } +type ListStreamRequestBody struct { + ownerID *refs.OwnerID +} + +type ListStreamRequest struct { + body *ListStreamRequestBody + + session.RequestHeaders +} + +type ListStreamResponseBody struct { + cidList []refs.ContainerID +} + +type ListStreamResponse struct { + body *ListStreamResponseBody + + session.ResponseHeaders +} + func (a *Attribute) GetKey() string { if a != nil { return a.key @@ -444,3 +464,51 @@ func (r *ListResponse) GetBody() *ListResponseBody { func (r *ListResponse) SetBody(v *ListResponseBody) { r.body = v } + +func (r *ListStreamRequestBody) GetOwnerID() *refs.OwnerID { + if r != nil { + return r.ownerID + } + + return nil +} + +func (r *ListStreamRequestBody) SetOwnerID(v *refs.OwnerID) { + r.ownerID = v +} + +func (r *ListStreamRequest) GetBody() *ListStreamRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListStreamRequest) SetBody(v *ListStreamRequestBody) { + r.body = v +} + +func (r *ListStreamResponseBody) GetContainerIDs() []refs.ContainerID { + if r != nil { + return r.cidList + } + + return nil +} + +func (r *ListStreamResponseBody) SetContainerIDs(v []refs.ContainerID) { + r.cidList = v +} + +func (r *ListStreamResponse) GetBody() *ListStreamResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListStreamResponse) SetBody(v *ListStreamResponseBody) { + r.body = v +} diff --git a/api/object/grpc/service_grpc.pb.go b/api/object/grpc/service_grpc.pb.go index eb53afe..2054f89 100644 --- a/api/object/grpc/service_grpc.pb.go +++ b/api/object/grpc/service_grpc.pb.go @@ -42,35 +42,35 @@ type ObjectServiceClient interface { // chunks keeping the receiving order. // // Extended headers can change `Get` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` - // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one - // otherwise) of Network Map to find an object until the depth limit is - // reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` + // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one + // otherwise) of Network Map to find an object until the depth limit is + // reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // read access to the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // read access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (ObjectService_GetClient, error) // Put the object into container. Request uses gRPC stream. First message // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object @@ -80,118 +80,119 @@ type ObjectServiceClient interface { // Chunk messages SHOULD be sent in the direct order of fragmentation. // // Extended headers can change `Put` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // placement of an object of type TOMBSTONE that includes at least one - // locked object is prohibited; - // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ - // placement of an object of type LOCK that includes at least one object of - // type other than REGULAR is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // // been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Put(ctx context.Context, opts ...grpc.CallOption) (ObjectService_PutClient, error) // Delete the object from a container. There is no immediate removal // guarantee. Object will be marked for removal and deleted eventually. // // Extended headers can change `Delete` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully marked to be removed from the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // delete access to the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // the object could not be deleted because it has not been \ - // found within the container; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // deleting a locked object is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully marked to be removed from the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // delete access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // the object could not be deleted because it has not been \ + // found within the container; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // deleting a locked object is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) // Returns the object Headers without data payload. By default full header is // returned. If `main_only` request field is set, the short header with only // the very minimal information will be returned instead. // // Extended headers can change `Head` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object header has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation HEAD of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object header has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation HEAD of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error) // Search objects in container. Search query allows to match by Object // Header's filed values. Please see the corresponding FrostFS Technical // Specification section for more details. // // Extended headers can change `Search` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // objects have been successfully selected; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation SEARCH of the object is denied; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // search container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // objects have been successfully selected; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation SEARCH of the object is denied; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // search container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (ObjectService_SearchClient, error) // Get byte range of data payload. Range is set as an (offset, length) tuple. // Like in `Get` method, the response uses gRPC stream. Requested range can be @@ -199,35 +200,35 @@ type ObjectServiceClient interface { // receiving order. // // Extended headers can change `GetRange` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions of Network Map to find an object until the depth - // limit is reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // data range of the object payload has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation RANGE of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted. - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGE of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (ObjectService_GetRangeClient, error) // Returns homomorphic or regular hash of object's payload range after // applying XOR operation with the provided `salt`. Ranges are set of (offset, @@ -235,68 +236,69 @@ type ObjectServiceClient interface { // the request. Note that hash is calculated for XORed data. // // Extended headers can change `GetRangeHash` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions of Network Map to find an object until the depth - // limit is reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // data range of the object payload has been successfully hashed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation RANGEHASH of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully hashed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGEHASH of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error) // Put the prepared object into container. // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of // an object MUST be set. // // Extended headers can change `Put` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // placement of an object of type TOMBSTONE that includes at least one - // locked object is prohibited; - // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ - // placement of an object of type LOCK that includes at least one object of - // type other than REGULAR is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // // been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. PutSingle(ctx context.Context, in *PutSingleRequest, opts ...grpc.CallOption) (*PutSingleResponse, error) // Patch the object. Request uses gRPC stream. First message must set // the address of the object that is going to get patched. If the object's @@ -317,34 +319,34 @@ type ObjectServiceClient interface { // 3. The application of the same patches for the object a few times. // // Extended headers can change `Patch` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully patched and saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted. - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully patched and saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Patch(ctx context.Context, opts ...grpc.CallOption) (ObjectService_PatchClient, error) } @@ -568,35 +570,35 @@ type ObjectServiceServer interface { // chunks keeping the receiving order. // // Extended headers can change `Get` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` - // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one - // otherwise) of Network Map to find an object until the depth limit is - // reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` + // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one + // otherwise) of Network Map to find an object until the depth limit is + // reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // read access to the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // read access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Get(*GetRequest, ObjectService_GetServer) error // Put the object into container. Request uses gRPC stream. First message // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object @@ -606,118 +608,119 @@ type ObjectServiceServer interface { // Chunk messages SHOULD be sent in the direct order of fragmentation. // // Extended headers can change `Put` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // placement of an object of type TOMBSTONE that includes at least one - // locked object is prohibited; - // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ - // placement of an object of type LOCK that includes at least one object of - // type other than REGULAR is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // // been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Put(ObjectService_PutServer) error // Delete the object from a container. There is no immediate removal // guarantee. Object will be marked for removal and deleted eventually. // // Extended headers can change `Delete` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully marked to be removed from the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // delete access to the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // the object could not be deleted because it has not been \ - // found within the container; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // deleting a locked object is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully marked to be removed from the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // delete access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // the object could not be deleted because it has not been \ + // found within the container; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // deleting a locked object is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) // Returns the object Headers without data payload. By default full header is // returned. If `main_only` request field is set, the short header with only // the very minimal information will be returned instead. // // Extended headers can change `Head` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object header has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation HEAD of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object header has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation HEAD of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Head(context.Context, *HeadRequest) (*HeadResponse, error) // Search objects in container. Search query allows to match by Object // Header's filed values. Please see the corresponding FrostFS Technical // Specification section for more details. // // Extended headers can change `Search` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // objects have been successfully selected; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation SEARCH of the object is denied; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // search container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // objects have been successfully selected; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation SEARCH of the object is denied; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // search container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Search(*SearchRequest, ObjectService_SearchServer) error // Get byte range of data payload. Range is set as an (offset, length) tuple. // Like in `Get` method, the response uses gRPC stream. Requested range can be @@ -725,35 +728,35 @@ type ObjectServiceServer interface { // receiving order. // // Extended headers can change `GetRange` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions of Network Map to find an object until the depth - // limit is reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // data range of the object payload has been successfully read; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation RANGE of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted. - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGE of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. GetRange(*GetRangeRequest, ObjectService_GetRangeServer) error // Returns homomorphic or regular hash of object's payload range after // applying XOR operation with the provided `salt`. Ranges are set of (offset, @@ -761,68 +764,69 @@ type ObjectServiceServer interface { // the request. Note that hash is calculated for XORed data. // // Extended headers can change `GetRangeHash` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH ] \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. - // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ - // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ - // Will try older versions of Network Map to find an object until the depth - // limit is reached. + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // data range of the object payload has been successfully hashed; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // access to operation RANGEHASH of the object is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully hashed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGEHASH of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. GetRangeHash(context.Context, *GetRangeHashRequest) (*GetRangeHashResponse, error) // Put the prepared object into container. // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of // an object MUST be set. // // Extended headers can change `Put` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requested version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **LOCKED** (2050, SECTION_OBJECT): \ - // placement of an object of type TOMBSTONE that includes at least one - // locked object is prohibited; - // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ - // placement of an object of type LOCK that includes at least one object of - // type other than REGULAR is prohibited; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // // been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. PutSingle(context.Context, *PutSingleRequest) (*PutSingleResponse, error) // Patch the object. Request uses gRPC stream. First message must set // the address of the object that is going to get patched. If the object's @@ -843,34 +847,34 @@ type ObjectServiceServer interface { // 3. The application of the same patches for the object a few times. // // Extended headers can change `Patch` behaviour: - // * [ __SYSTEM__NETMAP_EPOCH \ - // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ - // Will use the requsted version of Network Map for object placement - // calculation. + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. // // Please refer to detailed `XHeader` description. // // Statuses: - // - **OK** (0, SECTION_SUCCESS): \ - // object has been successfully patched and saved in the container; - // - Common failures (SECTION_FAILURE_COMMON); - // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ - // write access to the container is denied; - // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ - // object not found in container; - // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ - // the requested object has been marked as deleted. - // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ - // the requested range is out of bounds; - // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ - // object storage container not found; - // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ - // access to container is denied; - // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ - // (for trusted object preparation) session private key does not exist or - // has been deleted; - // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ - // provided session token has expired. + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully patched and saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. Patch(ObjectService_PatchServer) error } diff --git a/api/rpc/container.go b/api/rpc/container.go index 9ba5c99..a759bd5 100644 --- a/api/rpc/container.go +++ b/api/rpc/container.go @@ -13,6 +13,7 @@ const ( rpcContainerGet = "Get" rpcContainerDel = "Delete" rpcContainerList = "List" + rpcContainerStream = "ListStream" rpcContainerGetEACL = "GetExtendedACL" rpcContainerUsedSpace = "AnnounceUsedSpace" ) @@ -80,3 +81,27 @@ func ListContainers( return resp, nil } + +type ListStreamResponseReader struct { + r client.MessageReader +} + +func (r *ListStreamResponseReader) Read(resp *container.ListStreamResponse) error { + return r.r.ReadMessage(resp) +} + +// ListContainersStream executes ContainerService.ListStream RPC. +func ListContainersStream( + cli *client.Client, + req *container.ListStreamRequest, + opts ...client.CallOption, +) (*ListStreamResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceContainer, rpcContainerStream), req, opts...) + if err != nil { + return nil, err + } + + return &ListStreamResponseReader{ + r: wc, + }, nil +} diff --git a/api/signature/body.go b/api/signature/body.go index 50a09e9..2467dc0 100644 --- a/api/signature/body.go +++ b/api/signature/body.go @@ -46,6 +46,10 @@ func serviceMessageBody(req any) stableMarshaler { return v.GetBody() case *container.ListResponse: return v.GetBody() + case *container.ListStreamRequest: + return v.GetBody() + case *container.ListStreamResponse: + return v.GetBody() /* Object */ case *object.PutRequest: -- 2.45.3 From 852dac14766257f5e296b252e90deb173946074e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 28 Oct 2024 18:06:01 +0300 Subject: [PATCH 2/3] [#291] container: Add ListStream method Signed-off-by: Ekaterina Lebedeva --- client/container_list_stream.go | 203 ++++++++++++++++++++++++++++++++ pool/mock_test.go | 4 + pool/pool.go | 88 ++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 client/container_list_stream.go diff --git a/client/container_list_stream.go b/client/container_list_stream.go new file mode 100644 index 0000000..5ae282a --- /dev/null +++ b/client/container_list_stream.go @@ -0,0 +1,203 @@ +package client + +import ( + "context" + "errors" + "fmt" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +// PrmContainerListStream groups parameters of ContainerListStream operation. +type PrmContainerListStream struct { + XHeaders []string + + OwnerID user.ID + + Session *session.Container +} + +func (x *PrmContainerListStream) buildRequest(c *Client) (*container.ListStreamRequest, error) { + if x.OwnerID.IsEmpty() { + return nil, errorAccountNotSet + } + + var ownerV2 refs.OwnerID + x.OwnerID.WriteToV2(&ownerV2) + + reqBody := new(container.ListStreamRequestBody) + reqBody.SetOwnerID(&ownerV2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + if x.Session != nil { + var tokv2 v2session.Token + x.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req container.ListStreamRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerListStream groups the final result values of ContainerListStream operation. +type ResContainerListStream struct { + statusRes +} + +// ContainerListReader is designed to read list of container identifiers from FrostFS system. +// +// Must be initialized using Client.ContainerListInit, any other usage is unsafe. +type ContainerListReader struct { + client *Client + cancelCtxStream context.CancelFunc + err error + res ResContainerListStream + stream interface { + Read(resp *container.ListStreamResponse) error + } + tail []refs.ContainerID +} + +// Read reads another list of the container identifiers. Works similar to +// io.Reader.Read but copies cid.ID and returns success flag instead of error. +// +// Failure reason can be received via Close. +// +// Panics if buf has zero length. +func (x *ContainerListReader) Read(buf []cid.ID) (int, bool) { + // if len(buf) == 0 { + // panic("empty buffer in ContainerListReader.ReadList") + // } + + read := copyCnrIDBuffers(buf, x.tail) + x.tail = x.tail[read:] + + if len(buf) == read { + return read, true + } + + for { + var resp container.ListStreamResponse + x.err = x.stream.Read(&resp) + if x.err != nil { + return read, false + } + + x.res.st, x.err = x.client.processResponse(&resp) + if x.err != nil || !apistatus.IsSuccessful(x.res.st) { + return read, false + } + + // read new chunk of containers + ids := resp.GetBody().GetContainerIDs() + if len(ids) == 0 { + // just skip empty lists since they are not prohibited by protocol + continue + } + + ln := copyCnrIDBuffers(buf[read:], ids) + read += ln + + if read == len(buf) { + // save the tail + x.tail = append(x.tail, ids[ln:]...) + + return read, true + } + } +} + +func copyCnrIDBuffers(dst []cid.ID, src []refs.ContainerID) int { + var i int + for ; i < len(dst) && i < len(src); i++ { + _ = dst[i].ReadFromV2(src[i]) + } + return i +} + +// Iterate iterates over the list of found container identifiers. +// f can return true to stop iteration earlier. +// +// Returns an error if container can't be read. +func (x *ContainerListReader) Iterate(f func(cid.ID) bool) error { + buf := make([]cid.ID, 1) + + for { + // Do not check first return value because `len(buf) == 1`, + // so false means nothing was read. + _, ok := x.Read(buf) + if !ok { + res, err := x.Close() + if err != nil { + return err + } + return apistatus.ErrFromStatus(res.Status()) + } + if f(buf[0]) { + return nil + } + } +} + +// Close ends reading list of the matched containers and returns the result of the operation +// along with the final results. Must be called after using the ContainerListReader. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as Go built-in error. +// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures +// codes are returned as error. +func (x *ContainerListReader) Close() (*ResContainerListStream, error) { + defer x.cancelCtxStream() + + if x.err != nil && !errors.Is(x.err, io.EOF) { + return nil, x.err + } + + return &x.res, nil +} + +// ContainerListInit initiates container selection through a remote server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit fetching of identifiers of the account-owned +// containers is done using the ContainerListReader. Exactly one return value is non-nil. +// Resulting reader must be finally closed. +// +// Returns an error if parameters are set incorrectly (see PrmContainerListStream docs). +// Context is required and must not be nil. It is used for network communication. +func (c *Client) ContainerListInit(ctx context.Context, prm PrmContainerListStream) (*ContainerListReader, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + err = signature.SignServiceMessage(&c.prm.Key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + var r ContainerListReader + ctx, r.cancelCtxStream = context.WithCancel(ctx) + + r.stream, err = rpcapi.ListContainersStream(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("open stream: %w", err) + } + r.client = c + + return &r, nil +} diff --git a/pool/mock_test.go b/pool/mock_test.go index ad9fd94..4731108 100644 --- a/pool/mock_test.go +++ b/pool/mock_test.go @@ -104,6 +104,10 @@ func (m *mockClient) containerList(context.Context, PrmContainerList) ([]cid.ID, return nil, nil } +func (m *mockClient) containerListStream(context.Context, PrmListStream) (ResListStream, error) { + return ResListStream{}, nil +} + func (m *mockClient) containerDelete(context.Context, PrmContainerDelete) error { return nil } diff --git a/pool/pool.go b/pool/pool.go index d795af8..6ca136b 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -47,6 +47,8 @@ type client interface { containerGet(context.Context, PrmContainerGet) (container.Container, error) // see clientWrapper.containerList. containerList(context.Context, PrmContainerList) ([]cid.ID, error) + // see clientWrapper.containerListStream. + containerListStream(context.Context, PrmListStream) (ResListStream, error) // see clientWrapper.containerDelete. containerDelete(context.Context, PrmContainerDelete) error // see clientWrapper.apeManagerAddChain. @@ -145,6 +147,7 @@ const ( methodContainerPut methodContainerGet methodContainerList + methodContainerListStream methodContainerDelete methodEndpointInfo methodNetworkInfo @@ -529,6 +532,75 @@ func (c *clientWrapper) containerList(ctx context.Context, prm PrmContainerList) return res.Containers(), nil } +// PrmListStream groups parameters of ListContainersStream operation. +type PrmListStream struct { + OwnerID user.ID + + Session *session.Container +} + +// ResListStream is designed to read list of object identifiers from FrostFS system. +// +// Must be initialized using Pool.ListContainersStream, any other usage is unsafe. +type ResListStream struct { + r *sdkClient.ContainerListReader + handleError func(context.Context, apistatus.Status, error) error +} + +// Read reads another list of the container identifiers. +func (x *ResListStream) Read(buf []cid.ID) (int, error) { + n, ok := x.r.Read(buf) + if !ok { + res, err := x.r.Close() + if err == nil { + return n, io.EOF + } + + var status apistatus.Status + if res != nil { + status = res.Status() + } + err = x.handleError(nil, status, err) + + return n, err + } + + return n, nil +} + +// Iterate iterates over the list of found container identifiers. +// f can return true to stop iteration earlier. +// +// Returns an error if container can't be read. +func (x *ResListStream) Iterate(f func(cid.ID) bool) error { + return x.r.Iterate(f) +} + +// Close ends reading list of the matched containers and returns the result of the operation +// along with the final results. Must be called after using the ResListStream. +func (x *ResListStream) Close() { + _, _ = x.r.Close() +} + +// containerList invokes sdkClient.ContainerList parse response status to error and return result as is. +func (c *clientWrapper) containerListStream(ctx context.Context, prm PrmListStream) (ResListStream, error) { + cl, err := c.getClient() + if err != nil { + return ResListStream{}, err + } + + cliPrm := sdkClient.PrmContainerListStream{ + OwnerID: prm.OwnerID, + Session: prm.Session, + } + + res, err := cl.ContainerListInit(ctx, cliPrm) + if err = c.handleError(ctx, nil, err); err != nil { + return ResListStream{}, fmt.Errorf("init container listing on client: %w", err) + } + return ResListStream{r: res, handleError: c.handleError}, nil +} + // containerDelete invokes sdkClient.ContainerDelete parse response status to error. // It also waits for the container to be removed from the network. func (c *clientWrapper) containerDelete(ctx context.Context, prm PrmContainerDelete) error { @@ -2887,6 +2959,22 @@ func (p *Pool) ListContainers(ctx context.Context, prm PrmContainerList) ([]cid. return cnrIDs, nil } +// ListContainersStream requests identifiers of the account-owned containers. +func (p *Pool) ListContainersStream(ctx context.Context, prm PrmListStream) (ResListStream, error) { + var res ResListStream + cp, err := p.connection() + if err != nil { + return res, err + } + + res, err = cp.containerListStream(ctx, prm) + if err != nil { + return res, fmt.Errorf("list containers stream via client '%s': %w", cp.address(), err) + } + + return res, nil +} + // DeleteContainer sends request to remove the FrostFS container and waits for the operation to complete. // // Waiting parameters can be specified using SetWaitParams. If not called, defaults are used: -- 2.45.3 From c4463df8d467a49d496ebd9816bcae57ecbf1fbd Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 10 Dec 2024 12:18:06 +0300 Subject: [PATCH 3/3] [#291] container: Rename field Account to OwnerID in PrmContainerList Renaming this field so that it matches PrmContainerListStream. Signed-off-by: Ekaterina Lebedeva --- client/container_list.go | 10 +++++----- pool/pool.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/container_list.go b/client/container_list.go index d094cdb..5c768cc 100644 --- a/client/container_list.go +++ b/client/container_list.go @@ -20,7 +20,7 @@ import ( type PrmContainerList struct { XHeaders []string - Account user.ID + OwnerID user.ID Session *session.Container } @@ -28,18 +28,18 @@ type PrmContainerList struct { // SetAccount sets identifier of the FrostFS account to list the containers. // Required parameter. // -// Deprecated: Use PrmContainerList.Account instead. +// Deprecated: Use PrmContainerList.OwnerID instead. func (x *PrmContainerList) SetAccount(id user.ID) { - x.Account = id + x.OwnerID = id } func (x *PrmContainerList) buildRequest(c *Client) (*v2container.ListRequest, error) { - if x.Account.IsEmpty() { + if x.OwnerID.IsEmpty() { return nil, errorAccountNotSet } var ownerV2 refs.OwnerID - x.Account.WriteToV2(&ownerV2) + x.OwnerID.WriteToV2(&ownerV2) reqBody := new(v2container.ListRequestBody) reqBody.SetOwnerID(&ownerV2) diff --git a/pool/pool.go b/pool/pool.go index 6ca136b..8013832 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -515,7 +515,7 @@ func (c *clientWrapper) containerList(ctx context.Context, prm PrmContainerList) } cliPrm := sdkClient.PrmContainerList{ - Account: prm.OwnerID, + OwnerID: prm.OwnerID, Session: prm.Session, } -- 2.45.3