Compare commits

...
Sign in to create a new pull request.

24 commits

Author SHA1 Message Date
8822aedbbb [#360] bearer: Change APEOverride method prototype
* Make `APEOverride` also return flag that indicates whether bearer token
  sets ape override;
* Fix unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2025-04-28 16:47:06 +03:00
Aleksey Kravchenko
715b1e4100 [#358] pool: Add LatestReceivedEpoch to track latest response epoch
Signed-off-by: Aleksey Kravchenko <al.kravchenko@yadro.com>
2025-04-19 22:23:33 +03:00
971e740ea3
[#35] network: Use AppendComponent() for TLS encapsulation
As advocated explicitly in https://github.com/multiformats/go-multiaddr/blob/master/v015-MIGRATION.md

Answering a question about safety:
AppendComponent() appends to `a.ma`` in place.
`a.ma` is created by FromString() function,
so there is only a single goroutine appending to it.
Thus, assuming `FromString()` itself is called from a single goroutine,
no data race is introduced.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-12 21:19:30 +03:00
fc8f9637fe
[#35] go.mod: Update go-multiaddr to v0.15.0
New multiaddr release is incompatible with the old one:
https://github.com/multiformats/go-multiaddr/releases/tag/v0.15.0
https://github.com/multiformats/go-multiaddr/blob/master/v015-MIGRATION.md

Thankfully, it seems we are not affected by any breaking changes.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-12 21:19:30 +03:00
d282cd094f
[#355] netmap: Cache price and capacity attributes
They are used by HRW sorting and it makes sense to store them separately
instead of iterating over all attributes each time we need them.
It also simplifies code: we already parse them in NodeInfo.readFromV2(),
so just save the result.

```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                              │     old     │                 new                 │
                                                              │   sec/op    │   sec/op     vs base                │
Netmap_ContainerNodes/REP_2-8                                   5.923µ ± 0%   5.209µ ± 1%  -12.05% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   5.931µ ± 7%   5.088µ ± 1%  -14.22% (p=0.000 n=10)
geomean                                                         5.927µ        5.148µ       -13.14%

                                                              │     old      │                 new                 │
                                                              │     B/op     │     B/op      vs base               │
Netmap_ContainerNodes/REP_2-8                                   7.609Ki ± 0%   8.172Ki ± 0%  +7.39% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   7.031Ki ± 0%   7.469Ki ± 0%  +6.22% (p=0.000 n=10)
geomean                                                         7.315Ki        7.812Ki       +6.81%

                                                              │    old     │                 new                 │
                                                              │ allocs/op  │ allocs/op   vs base                 │
Netmap_ContainerNodes/REP_2-8                                   77.00 ± 0%   77.00 ± 0%       ~ (p=1.000 n=10) ¹
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   77.00 ± 0%   77.00 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                         77.00        77.00       +0.00%
¹ all samples are equal
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 17:47:08 +03:00
338faaf308
[#355] netmap: Remove unnecessary err declaration
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 17:47:08 +03:00
16fd3bafe0 [#354] api/netmap: Return a slice of parameters directly
`IterateParameters` does a poor job:
- it doesn't encapsulate well, because it returns a pointer,
- it has a clunky interface, compared to range loop.

I have decided to return parameter slice and not `iter.Seq` for 2
reasons:
1. There already is `SetParameters`, so `NetworkConfig` struct is
   expected to be modified.
2. This iterator uses pointers, so even with this interface the slice
   can already be changed.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 14:39:47 +00:00
661adf17bb [#353] Format deprecated notices properly
They should be in a separate paragraph, otherwise they are not
recognized.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:12:27 +00:00
f158a6b2e1 [#353] pool: Remove deprecated IterateNetworkEndpoints()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:12:27 +00:00
a0e4d16dbb [#352] container: Implement iterators over attributes
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:12:13 +00:00
88bc9eeb26 [#356] netmap: Check for attribute duplicates in NodeInfo.readFromV2()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:10:32 +00:00
684050b570 [#356] netmap/test: Cover NodeInfo.ReadFromV2() with tests
Untested code never works.
Qed.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:10:32 +00:00
1b12c9beae [#356] netmap: Fix typo in NodeInfo.readFromV2()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-07 09:10:32 +00:00
fb999fecac
[#357] netmap: Provide slice to append to in flattenNodes()
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                              │     old     │                new                 │
                                                              │   sec/op    │   sec/op     vs base               │
Netmap_ContainerNodes/REP_2-8                                   5.867µ ± 1%   5.821µ ± 0%  -0.79% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   5.786µ ± 2%   5.810µ ± 1%       ~ (p=1.000 n=10)
geomean                                                         5.826µ        5.815µ       -0.19%

                                                              │     old      │                 new                 │
                                                              │     B/op     │     B/op      vs base               │
Netmap_ContainerNodes/REP_2-8                                   7.609Ki ± 0%   7.328Ki ± 0%  -3.70% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   7.031Ki ± 0%   6.859Ki ± 0%  -2.44% (p=0.000 n=10)
geomean                                                         7.315Ki        7.090Ki       -3.07%

                                                              │    old     │                 new                 │
                                                              │ allocs/op  │ allocs/op   vs base                 │
Netmap_ContainerNodes/REP_2-8                                   77.00 ± 0%   77.00 ± 0%       ~ (p=1.000 n=10) ¹
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   77.00 ± 0%   77.00 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                         77.00        77.00       +0.00%
¹ all samples are equal
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-05 11:36:33 +03:00
6458c11e83
[#345] api/netmap: Drop deprecated single-address methods
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-04 18:22:10 +03:00
4b9b54a901
[#345] netmap: Implement an iterator over node attributes
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-04 18:22:10 +03:00
b27f172de9
[#345] netmap: Implement an iterator over node endpoints
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-04 18:22:09 +03:00
5be3415961
[#345] go.mod: Bump min go version to 1.23
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-04-04 17:26:35 +03:00
4d36a49d39 [#349] object: Make patcher apply patching for split header
* Change `PatchApplier` interface: `ApplyAttributesPatch` -> `ApplyHeaderPatch`.
  Make `ApplyHeaderPatch` receive `ApplyHeaderPatchPrm` as parameter;
* Fix `patcher`: apply patch for split header;
* Fix `patcher` unit-tests. Add test-case for split header;
* Extend `Patch` struct with `NewSplitHeader`;
* Change `ObjectPatcher` interface for client: `PatchAttributes` -> `PatchHeader`.
  Fix `objectPatcher`.
* Fix object transformer: since object header sets `SplitHeader` if it's passed.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2025-03-26 13:17:39 +03:00
76265fe9be [#349] object: Introduce SplitHeader type
* Also introduce `SplitHeader` getter and `SetSplitHeader` setter
  for `Object` type.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2025-03-26 13:17:37 +03:00
826df9303c [#349] object: Regenerate protobuf for Patch method
* `PatchRequestBody` got `NewSplitHeader` field
* Introduce `SetNewSplitHeader`, `GetNewSplitHeader`
* Fix converter and marshaler

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2025-03-26 13:17:24 +03:00
87bb55f992 [#51] add address to logs
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
2025-03-17 11:28:14 +03:00
a262a0038f [#343] pool: Fix Yoda condition
go-staticcheck recommends not to use Yoda conditions.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2025-03-10 19:24:58 +03:00
fe5b28e6bf [#338] pool: Support avg request time for ListContainerStream
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2025-03-10 19:24:58 +03:00
39 changed files with 1253 additions and 466 deletions

View file

@ -2,6 +2,7 @@ package netmap
import ( import (
"bytes" "bytes"
"iter"
"slices" "slices"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
@ -409,25 +410,6 @@ func (ni *NodeInfo) SetPublicKey(v []byte) {
ni.publicKey = v ni.publicKey = v
} }
// GetAddress returns node's network address.
//
// Deprecated: use IterateAddresses.
func (ni *NodeInfo) GetAddress() (addr string) {
ni.IterateAddresses(func(s string) bool {
addr = s
return true
})
return
}
// SetAddress sets node's network address.
//
// Deprecated: use SetAddresses.
func (ni *NodeInfo) SetAddress(v string) {
ni.SetAddresses(v)
}
// SetAddresses sets list of network addresses of the node. // SetAddresses sets list of network addresses of the node.
func (ni *NodeInfo) SetAddresses(v ...string) { func (ni *NodeInfo) SetAddresses(v ...string) {
ni.addresses = v ni.addresses = v
@ -442,10 +424,23 @@ func (ni *NodeInfo) NumberOfAddresses() int {
return 0 return 0
} }
// Addresses returns an iterator over network addresses of the node.
func (ni NodeInfo) Addresses() iter.Seq[string] {
return func(yield func(string) bool) {
for i := range ni.addresses {
if !yield(ni.addresses[i]) {
break
}
}
}
}
// IterateAddresses iterates over network addresses of the node. // IterateAddresses iterates over network addresses of the node.
// Breaks iteration on f's true return. // Breaks iteration on f's true return.
// //
// Handler should not be nil. // Handler should not be nil.
//
// Deprecated: use [NodeInfo.Addresses] instead.
func (ni *NodeInfo) IterateAddresses(f func(string) bool) { func (ni *NodeInfo) IterateAddresses(f func(string) bool) {
if ni != nil { if ni != nil {
for i := range ni.addresses { for i := range ni.addresses {
@ -582,6 +577,8 @@ type NetworkConfig struct {
} }
// NumberOfParameters returns number of network parameters. // NumberOfParameters returns number of network parameters.
//
// Deprecated: use [NetworkConfig.Parameters] instead.
func (x *NetworkConfig) NumberOfParameters() int { func (x *NetworkConfig) NumberOfParameters() int {
if x != nil { if x != nil {
return len(x.ps) return len(x.ps)
@ -590,10 +587,20 @@ func (x *NetworkConfig) NumberOfParameters() int {
return 0 return 0
} }
// Parameters returns an iterator over network parameters.
func (x *NetworkConfig) Parameters() []NetworkParameter {
if x != nil {
return x.ps
}
return nil
}
// IterateParameters iterates over network parameters. // IterateParameters iterates over network parameters.
// Breaks iteration on f's true return. // Breaks iteration on f's true return.
// //
// Handler must not be nil. // Handler must not be nil.
//
// Deprecated: use [NetworkConfig.Parameters] instead.
func (x *NetworkConfig) IterateParameters(f func(*NetworkParameter) bool) { func (x *NetworkConfig) IterateParameters(f func(*NetworkParameter) bool) {
if x != nil { if x != nil {
for i := range x.ps { for i := range x.ps {

View file

@ -2389,6 +2389,7 @@ func (r *PatchRequestBody) ToGRPCMessage() grpc.Message {
m.SetNewAttributes(AttributesToGRPC(r.newAttributes)) m.SetNewAttributes(AttributesToGRPC(r.newAttributes))
m.SetReplaceAttributes(r.replaceAttributes) m.SetReplaceAttributes(r.replaceAttributes)
m.SetPatch(r.patch.ToGRPCMessage().(*object.PatchRequest_Body_Patch)) m.SetPatch(r.patch.ToGRPCMessage().(*object.PatchRequest_Body_Patch))
m.SetNewSplitHeader(r.newSplitHeader.ToGRPCMessage().(*object.Header_Split))
} }
return m return m
@ -2437,6 +2438,20 @@ func (r *PatchRequestBody) FromGRPCMessage(m grpc.Message) error {
} }
} }
newSplitHeader := v.GetNewSplitHeader()
if newSplitHeader == nil {
r.newSplitHeader = nil
} else {
if r.newSplitHeader == nil {
r.newSplitHeader = new(SplitHeader)
}
err = r.newSplitHeader.FromGRPCMessage(newSplitHeader)
if err != nil {
return err
}
}
return nil return nil
} }

View file

@ -5181,6 +5181,9 @@ type PatchRequest_Body struct {
// merged. If the incoming `new_attributes` list contains already existing // merged. If the incoming `new_attributes` list contains already existing
// key, then it just replaces it while merging the lists. // key, then it just replaces it while merging the lists.
ReplaceAttributes *bool `protobuf:"varint,3,opt,name=replace_attributes,json=replaceAttributes" json:"replace_attributes,omitempty"` ReplaceAttributes *bool `protobuf:"varint,3,opt,name=replace_attributes,json=replaceAttributes" json:"replace_attributes,omitempty"`
// New split header for the object. This defines how the object will relate
// to other objects in a split operation.
NewSplitHeader *Header_Split `protobuf:"bytes,5,opt,name=new_split_header,json=newSplitHeader" json:"new_split_header,omitempty"`
// The patch that is applied for the object. // The patch that is applied for the object.
Patch *PatchRequest_Body_Patch `protobuf:"bytes,4,opt,name=patch" json:"patch,omitempty"` Patch *PatchRequest_Body_Patch `protobuf:"bytes,4,opt,name=patch" json:"patch,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@ -5233,6 +5236,13 @@ func (x *PatchRequest_Body) GetReplaceAttributes() bool {
return false return false
} }
func (x *PatchRequest_Body) GetNewSplitHeader() *Header_Split {
if x != nil {
return x.NewSplitHeader
}
return nil
}
func (x *PatchRequest_Body) GetPatch() *PatchRequest_Body_Patch { func (x *PatchRequest_Body) GetPatch() *PatchRequest_Body_Patch {
if x != nil { if x != nil {
return x.Patch return x.Patch
@ -5252,6 +5262,10 @@ func (x *PatchRequest_Body) SetReplaceAttributes(v bool) {
x.ReplaceAttributes = &v x.ReplaceAttributes = &v
} }
func (x *PatchRequest_Body) SetNewSplitHeader(v *Header_Split) {
x.NewSplitHeader = v
}
func (x *PatchRequest_Body) SetPatch(v *PatchRequest_Body_Patch) { func (x *PatchRequest_Body) SetPatch(v *PatchRequest_Body_Patch) {
x.Patch = v x.Patch = v
} }
@ -5270,6 +5284,13 @@ func (x *PatchRequest_Body) HasReplaceAttributes() bool {
return x.ReplaceAttributes != nil return x.ReplaceAttributes != nil
} }
func (x *PatchRequest_Body) HasNewSplitHeader() bool {
if x == nil {
return false
}
return x.NewSplitHeader != nil
}
func (x *PatchRequest_Body) HasPatch() bool { func (x *PatchRequest_Body) HasPatch() bool {
if x == nil { if x == nil {
return false return false
@ -5285,6 +5306,10 @@ func (x *PatchRequest_Body) ClearReplaceAttributes() {
x.ReplaceAttributes = nil x.ReplaceAttributes = nil
} }
func (x *PatchRequest_Body) ClearNewSplitHeader() {
x.NewSplitHeader = nil
}
func (x *PatchRequest_Body) ClearPatch() { func (x *PatchRequest_Body) ClearPatch() {
x.Patch = nil x.Patch = nil
} }
@ -5305,6 +5330,9 @@ type PatchRequest_Body_builder struct {
// merged. If the incoming `new_attributes` list contains already existing // merged. If the incoming `new_attributes` list contains already existing
// key, then it just replaces it while merging the lists. // key, then it just replaces it while merging the lists.
ReplaceAttributes *bool ReplaceAttributes *bool
// New split header for the object. This defines how the object will relate
// to other objects in a split operation.
NewSplitHeader *Header_Split
// The patch that is applied for the object. // The patch that is applied for the object.
Patch *PatchRequest_Body_Patch Patch *PatchRequest_Body_Patch
} }
@ -5316,6 +5344,7 @@ func (b0 PatchRequest_Body_builder) Build() *PatchRequest_Body {
x.Address = b.Address x.Address = b.Address
x.NewAttributes = b.NewAttributes x.NewAttributes = b.NewAttributes
x.ReplaceAttributes = b.ReplaceAttributes x.ReplaceAttributes = b.ReplaceAttributes
x.NewSplitHeader = b.NewSplitHeader
x.Patch = b.Patch x.Patch = b.Patch
return m0 return m0
} }
@ -5902,7 +5931,7 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a,
0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xb3, 0x04, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xfd, 0x04, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71,
@ -5916,7 +5945,7 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72,
0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xcf, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x99, 0x03, 0x0a, 0x04, 0x42, 0x6f,
0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e,
0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64,
@ -5928,87 +5957,92 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65,
0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
0x3f, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x48, 0x0a, 0x10, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x68, 0x65, 0x61,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61,
0x6f, 0x64, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x64, 0x65, 0x72, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x52, 0x0e, 0x6e, 0x65, 0x77, 0x53, 0x70,
0x1a, 0x59, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3a, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x6c, 0x69, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x05, 0x70, 0x61, 0x74,
0x72, 0x63, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63,
0x63, 0x74, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x50, 0x61,
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x74, 0x63, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x59, 0x0a, 0x05, 0x50, 0x61,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0xa4, 0x02, 0x0a, 0x0d, 0x74, 0x63, 0x68, 0x12, 0x3a, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x61,
0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x52, 0x61, 0x6e,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x67, 0x65, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0xa4, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65,
0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64,
0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e,
0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d,
0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72,
0x64, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
0x49, 0x64, 0x32, 0xd4, 0x05, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
0x76, 0x69, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x32, 0xd4, 0x05, 0x0a,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x50, 0x75, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x44,
0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x50, 0x75, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50,
0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x48, 0x65, 0x61, 0x64, 0x12,
0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f,
0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a,
0x04, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d,
0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72,
0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61,
0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a,
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x08, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6e,
0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e,
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61,
0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f,
0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x53, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x6e, 0x67, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x12, 0x22,
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x05, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f,
0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x63, 0x68,
0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x42, 0x62, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a,
0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x66, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6f, 0x62, 0x65, 0x28, 0x01, 0x42, 0x62, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74,
0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75,
0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x73, 0x64, 0x6b,
0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x08, 0x65, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07, 0x72, 0x70, 0x63, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f,
0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49,
0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x70, 0xe8, 0x07,
} }
var file_api_object_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42) var file_api_object_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42)
@ -6071,6 +6105,7 @@ var file_api_object_grpc_service_proto_goTypes = []any{
(grpc1.ChecksumType)(0), // 55: neo.fs.v2.refs.ChecksumType (grpc1.ChecksumType)(0), // 55: neo.fs.v2.refs.ChecksumType
(*Object)(nil), // 56: neo.fs.v2.object.Object (*Object)(nil), // 56: neo.fs.v2.object.Object
(*Header_Attribute)(nil), // 57: neo.fs.v2.object.Header.Attribute (*Header_Attribute)(nil), // 57: neo.fs.v2.object.Header.Attribute
(*Header_Split)(nil), // 58: neo.fs.v2.object.Header.Split
} }
var file_api_object_grpc_service_proto_depIdxs = []int32{ var file_api_object_grpc_service_proto_depIdxs = []int32{
20, // 0: neo.fs.v2.object.GetRequest.body:type_name -> neo.fs.v2.object.GetRequest.Body 20, // 0: neo.fs.v2.object.GetRequest.body:type_name -> neo.fs.v2.object.GetRequest.Body
@ -6163,32 +6198,33 @@ var file_api_object_grpc_service_proto_depIdxs = []int32{
56, // 87: neo.fs.v2.object.PutSingleRequest.Body.object:type_name -> neo.fs.v2.object.Object 56, // 87: neo.fs.v2.object.PutSingleRequest.Body.object:type_name -> neo.fs.v2.object.Object
48, // 88: neo.fs.v2.object.PatchRequest.Body.address:type_name -> neo.fs.v2.refs.Address 48, // 88: neo.fs.v2.object.PatchRequest.Body.address:type_name -> neo.fs.v2.refs.Address
57, // 89: neo.fs.v2.object.PatchRequest.Body.new_attributes:type_name -> neo.fs.v2.object.Header.Attribute 57, // 89: neo.fs.v2.object.PatchRequest.Body.new_attributes:type_name -> neo.fs.v2.object.Header.Attribute
40, // 90: neo.fs.v2.object.PatchRequest.Body.patch:type_name -> neo.fs.v2.object.PatchRequest.Body.Patch 58, // 90: neo.fs.v2.object.PatchRequest.Body.new_split_header:type_name -> neo.fs.v2.object.Header.Split
11, // 91: neo.fs.v2.object.PatchRequest.Body.Patch.source_range:type_name -> neo.fs.v2.object.Range 40, // 91: neo.fs.v2.object.PatchRequest.Body.patch:type_name -> neo.fs.v2.object.PatchRequest.Body.Patch
51, // 92: neo.fs.v2.object.PatchResponse.Body.object_id:type_name -> neo.fs.v2.refs.ObjectID 11, // 92: neo.fs.v2.object.PatchRequest.Body.Patch.source_range:type_name -> neo.fs.v2.object.Range
0, // 93: neo.fs.v2.object.ObjectService.Get:input_type -> neo.fs.v2.object.GetRequest 51, // 93: neo.fs.v2.object.PatchResponse.Body.object_id:type_name -> neo.fs.v2.refs.ObjectID
2, // 94: neo.fs.v2.object.ObjectService.Put:input_type -> neo.fs.v2.object.PutRequest 0, // 94: neo.fs.v2.object.ObjectService.Get:input_type -> neo.fs.v2.object.GetRequest
4, // 95: neo.fs.v2.object.ObjectService.Delete:input_type -> neo.fs.v2.object.DeleteRequest 2, // 95: neo.fs.v2.object.ObjectService.Put:input_type -> neo.fs.v2.object.PutRequest
6, // 96: neo.fs.v2.object.ObjectService.Head:input_type -> neo.fs.v2.object.HeadRequest 4, // 96: neo.fs.v2.object.ObjectService.Delete:input_type -> neo.fs.v2.object.DeleteRequest
9, // 97: neo.fs.v2.object.ObjectService.Search:input_type -> neo.fs.v2.object.SearchRequest 6, // 97: neo.fs.v2.object.ObjectService.Head:input_type -> neo.fs.v2.object.HeadRequest
12, // 98: neo.fs.v2.object.ObjectService.GetRange:input_type -> neo.fs.v2.object.GetRangeRequest 9, // 98: neo.fs.v2.object.ObjectService.Search:input_type -> neo.fs.v2.object.SearchRequest
14, // 99: neo.fs.v2.object.ObjectService.GetRangeHash:input_type -> neo.fs.v2.object.GetRangeHashRequest 12, // 99: neo.fs.v2.object.ObjectService.GetRange:input_type -> neo.fs.v2.object.GetRangeRequest
16, // 100: neo.fs.v2.object.ObjectService.PutSingle:input_type -> neo.fs.v2.object.PutSingleRequest 14, // 100: neo.fs.v2.object.ObjectService.GetRangeHash:input_type -> neo.fs.v2.object.GetRangeHashRequest
18, // 101: neo.fs.v2.object.ObjectService.Patch:input_type -> neo.fs.v2.object.PatchRequest 16, // 101: neo.fs.v2.object.ObjectService.PutSingle:input_type -> neo.fs.v2.object.PutSingleRequest
1, // 102: neo.fs.v2.object.ObjectService.Get:output_type -> neo.fs.v2.object.GetResponse 18, // 102: neo.fs.v2.object.ObjectService.Patch:input_type -> neo.fs.v2.object.PatchRequest
3, // 103: neo.fs.v2.object.ObjectService.Put:output_type -> neo.fs.v2.object.PutResponse 1, // 103: neo.fs.v2.object.ObjectService.Get:output_type -> neo.fs.v2.object.GetResponse
5, // 104: neo.fs.v2.object.ObjectService.Delete:output_type -> neo.fs.v2.object.DeleteResponse 3, // 104: neo.fs.v2.object.ObjectService.Put:output_type -> neo.fs.v2.object.PutResponse
8, // 105: neo.fs.v2.object.ObjectService.Head:output_type -> neo.fs.v2.object.HeadResponse 5, // 105: neo.fs.v2.object.ObjectService.Delete:output_type -> neo.fs.v2.object.DeleteResponse
10, // 106: neo.fs.v2.object.ObjectService.Search:output_type -> neo.fs.v2.object.SearchResponse 8, // 106: neo.fs.v2.object.ObjectService.Head:output_type -> neo.fs.v2.object.HeadResponse
13, // 107: neo.fs.v2.object.ObjectService.GetRange:output_type -> neo.fs.v2.object.GetRangeResponse 10, // 107: neo.fs.v2.object.ObjectService.Search:output_type -> neo.fs.v2.object.SearchResponse
15, // 108: neo.fs.v2.object.ObjectService.GetRangeHash:output_type -> neo.fs.v2.object.GetRangeHashResponse 13, // 108: neo.fs.v2.object.ObjectService.GetRange:output_type -> neo.fs.v2.object.GetRangeResponse
17, // 109: neo.fs.v2.object.ObjectService.PutSingle:output_type -> neo.fs.v2.object.PutSingleResponse 15, // 109: neo.fs.v2.object.ObjectService.GetRangeHash:output_type -> neo.fs.v2.object.GetRangeHashResponse
19, // 110: neo.fs.v2.object.ObjectService.Patch:output_type -> neo.fs.v2.object.PatchResponse 17, // 110: neo.fs.v2.object.ObjectService.PutSingle:output_type -> neo.fs.v2.object.PutSingleResponse
102, // [102:111] is the sub-list for method output_type 19, // 111: neo.fs.v2.object.ObjectService.Patch:output_type -> neo.fs.v2.object.PatchResponse
93, // [93:102] is the sub-list for method input_type 103, // [103:112] is the sub-list for method output_type
93, // [93:93] is the sub-list for extension type_name 94, // [94:103] is the sub-list for method input_type
93, // [93:93] is the sub-list for extension extendee 94, // [94:94] is the sub-list for extension type_name
0, // [0:93] is the sub-list for field type_name 94, // [94:94] is the sub-list for extension extendee
0, // [0:94] is the sub-list for field type_name
} }
func init() { file_api_object_grpc_service_proto_init() } func init() { file_api_object_grpc_service_proto_init() }

View file

@ -5050,6 +5050,7 @@ type PatchRequest_Body struct {
xxx_hidden_Address *grpc1.Address `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` xxx_hidden_Address *grpc1.Address `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
xxx_hidden_NewAttributes *[]*Header_Attribute `protobuf:"bytes,2,rep,name=new_attributes,json=newAttributes" json:"new_attributes,omitempty"` xxx_hidden_NewAttributes *[]*Header_Attribute `protobuf:"bytes,2,rep,name=new_attributes,json=newAttributes" json:"new_attributes,omitempty"`
xxx_hidden_ReplaceAttributes bool `protobuf:"varint,3,opt,name=replace_attributes,json=replaceAttributes" json:"replace_attributes,omitempty"` xxx_hidden_ReplaceAttributes bool `protobuf:"varint,3,opt,name=replace_attributes,json=replaceAttributes" json:"replace_attributes,omitempty"`
xxx_hidden_NewSplitHeader *Header_Split `protobuf:"bytes,5,opt,name=new_split_header,json=newSplitHeader" json:"new_split_header,omitempty"`
xxx_hidden_Patch *PatchRequest_Body_Patch `protobuf:"bytes,4,opt,name=patch" json:"patch,omitempty"` xxx_hidden_Patch *PatchRequest_Body_Patch `protobuf:"bytes,4,opt,name=patch" json:"patch,omitempty"`
XXX_raceDetectHookData protoimpl.RaceDetectHookData XXX_raceDetectHookData protoimpl.RaceDetectHookData
XXX_presence [1]uint32 XXX_presence [1]uint32
@ -5105,6 +5106,13 @@ func (x *PatchRequest_Body) GetReplaceAttributes() bool {
return false return false
} }
func (x *PatchRequest_Body) GetNewSplitHeader() *Header_Split {
if x != nil {
return x.xxx_hidden_NewSplitHeader
}
return nil
}
func (x *PatchRequest_Body) GetPatch() *PatchRequest_Body_Patch { func (x *PatchRequest_Body) GetPatch() *PatchRequest_Body_Patch {
if x != nil { if x != nil {
return x.xxx_hidden_Patch return x.xxx_hidden_Patch
@ -5122,7 +5130,11 @@ func (x *PatchRequest_Body) SetNewAttributes(v []*Header_Attribute) {
func (x *PatchRequest_Body) SetReplaceAttributes(v bool) { func (x *PatchRequest_Body) SetReplaceAttributes(v bool) {
x.xxx_hidden_ReplaceAttributes = v x.xxx_hidden_ReplaceAttributes = v
protoimpl.X.SetPresent(&(x.XXX_presence[0]), 2, 4) protoimpl.X.SetPresent(&(x.XXX_presence[0]), 2, 5)
}
func (x *PatchRequest_Body) SetNewSplitHeader(v *Header_Split) {
x.xxx_hidden_NewSplitHeader = v
} }
func (x *PatchRequest_Body) SetPatch(v *PatchRequest_Body_Patch) { func (x *PatchRequest_Body) SetPatch(v *PatchRequest_Body_Patch) {
@ -5143,6 +5155,13 @@ func (x *PatchRequest_Body) HasReplaceAttributes() bool {
return protoimpl.X.Present(&(x.XXX_presence[0]), 2) return protoimpl.X.Present(&(x.XXX_presence[0]), 2)
} }
func (x *PatchRequest_Body) HasNewSplitHeader() bool {
if x == nil {
return false
}
return x.xxx_hidden_NewSplitHeader != nil
}
func (x *PatchRequest_Body) HasPatch() bool { func (x *PatchRequest_Body) HasPatch() bool {
if x == nil { if x == nil {
return false return false
@ -5159,6 +5178,10 @@ func (x *PatchRequest_Body) ClearReplaceAttributes() {
x.xxx_hidden_ReplaceAttributes = false x.xxx_hidden_ReplaceAttributes = false
} }
func (x *PatchRequest_Body) ClearNewSplitHeader() {
x.xxx_hidden_NewSplitHeader = nil
}
func (x *PatchRequest_Body) ClearPatch() { func (x *PatchRequest_Body) ClearPatch() {
x.xxx_hidden_Patch = nil x.xxx_hidden_Patch = nil
} }
@ -5179,6 +5202,9 @@ type PatchRequest_Body_builder struct {
// merged. If the incoming `new_attributes` list contains already existing // merged. If the incoming `new_attributes` list contains already existing
// key, then it just replaces it while merging the lists. // key, then it just replaces it while merging the lists.
ReplaceAttributes *bool ReplaceAttributes *bool
// New split header for the object. This defines how the object will relate
// to other objects in a split operation.
NewSplitHeader *Header_Split
// The patch that is applied for the object. // The patch that is applied for the object.
Patch *PatchRequest_Body_Patch Patch *PatchRequest_Body_Patch
} }
@ -5190,9 +5216,10 @@ func (b0 PatchRequest_Body_builder) Build() *PatchRequest_Body {
x.xxx_hidden_Address = b.Address x.xxx_hidden_Address = b.Address
x.xxx_hidden_NewAttributes = &b.NewAttributes x.xxx_hidden_NewAttributes = &b.NewAttributes
if b.ReplaceAttributes != nil { if b.ReplaceAttributes != nil {
protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 2, 4) protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 2, 5)
x.xxx_hidden_ReplaceAttributes = *b.ReplaceAttributes x.xxx_hidden_ReplaceAttributes = *b.ReplaceAttributes
} }
x.xxx_hidden_NewSplitHeader = b.NewSplitHeader
x.xxx_hidden_Patch = b.Patch x.xxx_hidden_Patch = b.Patch
return m0 return m0
} }
@ -5779,7 +5806,7 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a,
0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xb3, 0x04, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xfd, 0x04, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71,
@ -5793,7 +5820,7 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72,
0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xcf, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x99, 0x03, 0x0a, 0x04, 0x42, 0x6f,
0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e,
0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64,
@ -5805,87 +5832,92 @@ var file_api_object_grpc_service_proto_rawDesc = []byte{
0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65,
0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
0x3f, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x48, 0x0a, 0x10, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x68, 0x65, 0x61,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61,
0x6f, 0x64, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x64, 0x65, 0x72, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x52, 0x0e, 0x6e, 0x65, 0x77, 0x53, 0x70,
0x1a, 0x59, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3a, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x6c, 0x69, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x05, 0x70, 0x61, 0x74,
0x72, 0x63, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63,
0x63, 0x74, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x50, 0x61,
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x74, 0x63, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x59, 0x0a, 0x05, 0x50, 0x61,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0xa4, 0x02, 0x0a, 0x0d, 0x74, 0x63, 0x68, 0x12, 0x3a, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x61,
0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x52, 0x61, 0x6e,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x67, 0x65, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0xa4, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65,
0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64,
0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e,
0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d,
0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72,
0x64, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
0x49, 0x64, 0x32, 0xd4, 0x05, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
0x76, 0x69, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x32, 0xd4, 0x05, 0x0a,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x50, 0x75, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x44,
0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x50, 0x75, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50,
0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x48, 0x65, 0x61, 0x64, 0x12,
0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f,
0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65,
0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a,
0x04, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76,
0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f,
0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d,
0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66,
0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72,
0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61,
0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a,
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x08, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6e,
0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e,
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61,
0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f,
0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x53, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e,
0x6e, 0x67, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74,
0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x12, 0x22,
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x05, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f,
0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x63, 0x68,
0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x42, 0x62, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a,
0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x66, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6f, 0x62, 0x65, 0x28, 0x01, 0x42, 0x62, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74,
0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75,
0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x73, 0x64, 0x6b,
0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x08, 0x65, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, 0xe8, 0x07, 0x72, 0x70, 0x63, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f,
0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49,
0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x70, 0xe8, 0x07,
} }
var file_api_object_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42) var file_api_object_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42)
@ -5948,6 +5980,7 @@ var file_api_object_grpc_service_proto_goTypes = []any{
(grpc1.ChecksumType)(0), // 55: neo.fs.v2.refs.ChecksumType (grpc1.ChecksumType)(0), // 55: neo.fs.v2.refs.ChecksumType
(*Object)(nil), // 56: neo.fs.v2.object.Object (*Object)(nil), // 56: neo.fs.v2.object.Object
(*Header_Attribute)(nil), // 57: neo.fs.v2.object.Header.Attribute (*Header_Attribute)(nil), // 57: neo.fs.v2.object.Header.Attribute
(*Header_Split)(nil), // 58: neo.fs.v2.object.Header.Split
} }
var file_api_object_grpc_service_proto_depIdxs = []int32{ var file_api_object_grpc_service_proto_depIdxs = []int32{
20, // 0: neo.fs.v2.object.GetRequest.body:type_name -> neo.fs.v2.object.GetRequest.Body 20, // 0: neo.fs.v2.object.GetRequest.body:type_name -> neo.fs.v2.object.GetRequest.Body
@ -6040,32 +6073,33 @@ var file_api_object_grpc_service_proto_depIdxs = []int32{
56, // 87: neo.fs.v2.object.PutSingleRequest.Body.object:type_name -> neo.fs.v2.object.Object 56, // 87: neo.fs.v2.object.PutSingleRequest.Body.object:type_name -> neo.fs.v2.object.Object
48, // 88: neo.fs.v2.object.PatchRequest.Body.address:type_name -> neo.fs.v2.refs.Address 48, // 88: neo.fs.v2.object.PatchRequest.Body.address:type_name -> neo.fs.v2.refs.Address
57, // 89: neo.fs.v2.object.PatchRequest.Body.new_attributes:type_name -> neo.fs.v2.object.Header.Attribute 57, // 89: neo.fs.v2.object.PatchRequest.Body.new_attributes:type_name -> neo.fs.v2.object.Header.Attribute
40, // 90: neo.fs.v2.object.PatchRequest.Body.patch:type_name -> neo.fs.v2.object.PatchRequest.Body.Patch 58, // 90: neo.fs.v2.object.PatchRequest.Body.new_split_header:type_name -> neo.fs.v2.object.Header.Split
11, // 91: neo.fs.v2.object.PatchRequest.Body.Patch.source_range:type_name -> neo.fs.v2.object.Range 40, // 91: neo.fs.v2.object.PatchRequest.Body.patch:type_name -> neo.fs.v2.object.PatchRequest.Body.Patch
51, // 92: neo.fs.v2.object.PatchResponse.Body.object_id:type_name -> neo.fs.v2.refs.ObjectID 11, // 92: neo.fs.v2.object.PatchRequest.Body.Patch.source_range:type_name -> neo.fs.v2.object.Range
0, // 93: neo.fs.v2.object.ObjectService.Get:input_type -> neo.fs.v2.object.GetRequest 51, // 93: neo.fs.v2.object.PatchResponse.Body.object_id:type_name -> neo.fs.v2.refs.ObjectID
2, // 94: neo.fs.v2.object.ObjectService.Put:input_type -> neo.fs.v2.object.PutRequest 0, // 94: neo.fs.v2.object.ObjectService.Get:input_type -> neo.fs.v2.object.GetRequest
4, // 95: neo.fs.v2.object.ObjectService.Delete:input_type -> neo.fs.v2.object.DeleteRequest 2, // 95: neo.fs.v2.object.ObjectService.Put:input_type -> neo.fs.v2.object.PutRequest
6, // 96: neo.fs.v2.object.ObjectService.Head:input_type -> neo.fs.v2.object.HeadRequest 4, // 96: neo.fs.v2.object.ObjectService.Delete:input_type -> neo.fs.v2.object.DeleteRequest
9, // 97: neo.fs.v2.object.ObjectService.Search:input_type -> neo.fs.v2.object.SearchRequest 6, // 97: neo.fs.v2.object.ObjectService.Head:input_type -> neo.fs.v2.object.HeadRequest
12, // 98: neo.fs.v2.object.ObjectService.GetRange:input_type -> neo.fs.v2.object.GetRangeRequest 9, // 98: neo.fs.v2.object.ObjectService.Search:input_type -> neo.fs.v2.object.SearchRequest
14, // 99: neo.fs.v2.object.ObjectService.GetRangeHash:input_type -> neo.fs.v2.object.GetRangeHashRequest 12, // 99: neo.fs.v2.object.ObjectService.GetRange:input_type -> neo.fs.v2.object.GetRangeRequest
16, // 100: neo.fs.v2.object.ObjectService.PutSingle:input_type -> neo.fs.v2.object.PutSingleRequest 14, // 100: neo.fs.v2.object.ObjectService.GetRangeHash:input_type -> neo.fs.v2.object.GetRangeHashRequest
18, // 101: neo.fs.v2.object.ObjectService.Patch:input_type -> neo.fs.v2.object.PatchRequest 16, // 101: neo.fs.v2.object.ObjectService.PutSingle:input_type -> neo.fs.v2.object.PutSingleRequest
1, // 102: neo.fs.v2.object.ObjectService.Get:output_type -> neo.fs.v2.object.GetResponse 18, // 102: neo.fs.v2.object.ObjectService.Patch:input_type -> neo.fs.v2.object.PatchRequest
3, // 103: neo.fs.v2.object.ObjectService.Put:output_type -> neo.fs.v2.object.PutResponse 1, // 103: neo.fs.v2.object.ObjectService.Get:output_type -> neo.fs.v2.object.GetResponse
5, // 104: neo.fs.v2.object.ObjectService.Delete:output_type -> neo.fs.v2.object.DeleteResponse 3, // 104: neo.fs.v2.object.ObjectService.Put:output_type -> neo.fs.v2.object.PutResponse
8, // 105: neo.fs.v2.object.ObjectService.Head:output_type -> neo.fs.v2.object.HeadResponse 5, // 105: neo.fs.v2.object.ObjectService.Delete:output_type -> neo.fs.v2.object.DeleteResponse
10, // 106: neo.fs.v2.object.ObjectService.Search:output_type -> neo.fs.v2.object.SearchResponse 8, // 106: neo.fs.v2.object.ObjectService.Head:output_type -> neo.fs.v2.object.HeadResponse
13, // 107: neo.fs.v2.object.ObjectService.GetRange:output_type -> neo.fs.v2.object.GetRangeResponse 10, // 107: neo.fs.v2.object.ObjectService.Search:output_type -> neo.fs.v2.object.SearchResponse
15, // 108: neo.fs.v2.object.ObjectService.GetRangeHash:output_type -> neo.fs.v2.object.GetRangeHashResponse 13, // 108: neo.fs.v2.object.ObjectService.GetRange:output_type -> neo.fs.v2.object.GetRangeResponse
17, // 109: neo.fs.v2.object.ObjectService.PutSingle:output_type -> neo.fs.v2.object.PutSingleResponse 15, // 109: neo.fs.v2.object.ObjectService.GetRangeHash:output_type -> neo.fs.v2.object.GetRangeHashResponse
19, // 110: neo.fs.v2.object.ObjectService.Patch:output_type -> neo.fs.v2.object.PatchResponse 17, // 110: neo.fs.v2.object.ObjectService.PutSingle:output_type -> neo.fs.v2.object.PutSingleResponse
102, // [102:111] is the sub-list for method output_type 19, // 111: neo.fs.v2.object.ObjectService.Patch:output_type -> neo.fs.v2.object.PatchResponse
93, // [93:102] is the sub-list for method input_type 103, // [103:112] is the sub-list for method output_type
93, // [93:93] is the sub-list for extension type_name 94, // [94:103] is the sub-list for method input_type
93, // [93:93] is the sub-list for extension extendee 94, // [94:94] is the sub-list for extension type_name
0, // [0:93] is the sub-list for field type_name 94, // [94:94] is the sub-list for extension extendee
0, // [0:94] is the sub-list for field type_name
} }
func init() { file_api_object_grpc_service_proto_init() } func init() { file_api_object_grpc_service_proto_init() }

View file

@ -136,10 +136,11 @@ const (
patchRequestBodyPatchRangeField = 1 patchRequestBodyPatchRangeField = 1
patchRequestBodyPatchChunkField = 2 patchRequestBodyPatchChunkField = 2
patchRequestBodyAddrField = 1 patchRequestBodyAddrField = 1
patchRequestBodyNewAttrsField = 2 patchRequestBodyNewAttrsField = 2
patchRequestBodyReplaceAttrField = 3 patchRequestBodyReplaceAttrField = 3
patchRequestBodyPatchField = 4 patchRequestBodyPatchField = 4
patchRequestBodyNewSplitHeaderField = 5
patchResponseBodyObjectIDField = 1 patchResponseBodyObjectIDField = 1
) )
@ -1372,7 +1373,8 @@ func (r *PatchRequestBody) StableMarshal(buf []byte) []byte {
offset += proto.NestedStructureMarshal(patchRequestBodyNewAttrsField, buf[offset:], &r.newAttributes[i]) offset += proto.NestedStructureMarshal(patchRequestBodyNewAttrsField, buf[offset:], &r.newAttributes[i])
} }
offset += proto.BoolMarshal(patchRequestBodyReplaceAttrField, buf[offset:], r.replaceAttributes) offset += proto.BoolMarshal(patchRequestBodyReplaceAttrField, buf[offset:], r.replaceAttributes)
proto.NestedStructureMarshal(patchRequestBodyPatchField, buf[offset:], r.patch) offset += proto.NestedStructureMarshal(patchRequestBodyPatchField, buf[offset:], r.patch)
proto.NestedStructureMarshal(patchRequestBodyNewSplitHeaderField, buf[offset:], r.newSplitHeader)
return buf return buf
} }
@ -1389,6 +1391,7 @@ func (r *PatchRequestBody) StableSize() int {
} }
size += proto.BoolSize(patchRequestBodyReplaceAttrField, r.replaceAttributes) size += proto.BoolSize(patchRequestBodyReplaceAttrField, r.replaceAttributes)
size += proto.NestedStructureSize(patchRequestBodyPatchField, r.patch) size += proto.NestedStructureSize(patchRequestBodyPatchField, r.patch)
size += proto.NestedStructureSize(patchRequestBodyNewSplitHeaderField, r.newSplitHeader)
return size return size
} }

View file

@ -360,6 +360,8 @@ type PatchRequestBody struct {
newAttributes []Attribute newAttributes []Attribute
newSplitHeader *SplitHeader
replaceAttributes bool replaceAttributes bool
patch *PatchRequestBodyPatch patch *PatchRequestBodyPatch
@ -1591,6 +1593,14 @@ func (r *PatchRequestBody) SetReplaceAttributes(replace bool) {
r.replaceAttributes = replace r.replaceAttributes = replace
} }
func (r *PatchRequestBody) SetNewSplitHeader(newSplitHeader *SplitHeader) {
r.newSplitHeader = newSplitHeader
}
func (r *PatchRequestBody) GetNewSplitHeader() *SplitHeader {
return r.newSplitHeader
}
func (r *PatchRequestBody) GetPatch() *PatchRequestBodyPatch { func (r *PatchRequestBody) GetPatch() *PatchRequestBodyPatch {
if r != nil { if r != nil {
return r.patch return r.patch

View file

@ -313,15 +313,10 @@ func (b *Token) SetAPEOverride(v APEOverride) {
b.apeOverrideSet = true b.apeOverrideSet = true
} }
// APEOverride returns APE override set by SetAPEOverride. // APEOverride returns APE override set by SetAPEOverride and a flag that indicates whether override
// // is set for the token.
// Zero Token has zero APEOverride. func (b *Token) APEOverride() (override APEOverride, isSet bool) {
func (b *Token) APEOverride() APEOverride { return b.apeOverride, b.apeOverrideSet
if b.apeOverrideSet {
return b.apeOverride
}
return APEOverride{}
} }
// SetImpersonate mark token as impersonate to consider token signer as request owner. // SetImpersonate mark token as impersonate to consider token signer as request owner.

View file

@ -93,7 +93,8 @@ func TestToken_SetAPEOverrides(t *testing.T) {
val2 := filled val2 := filled
require.NoError(t, val2.Unmarshal(val.Marshal())) require.NoError(t, val2.Unmarshal(val.Marshal()))
require.Zero(t, val2.APEOverride()) _, isSet := val2.APEOverride()
require.False(t, isSet)
val2 = filled val2 = filled
@ -101,14 +102,16 @@ func TestToken_SetAPEOverrides(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd)) require.NoError(t, val2.UnmarshalJSON(jd))
require.Zero(t, val2.APEOverride()) _, isSet = val2.APEOverride()
require.False(t, isSet)
// set value // set value
tApe := bearertest.APEOverride() tApe := bearertest.APEOverride()
val.SetAPEOverride(tApe) val.SetAPEOverride(tApe)
require.Equal(t, tApe, val.APEOverride()) _, isSet = val.APEOverride()
require.True(t, isSet)
val.WriteToV2(&m) val.WriteToV2(&m)
require.NotNil(t, m.GetBody().GetAPEOverride()) require.NotNil(t, m.GetBody().GetAPEOverride())
@ -117,7 +120,8 @@ func TestToken_SetAPEOverrides(t *testing.T) {
val2 = filled val2 = filled
require.NoError(t, val2.Unmarshal(val.Marshal())) require.NoError(t, val2.Unmarshal(val.Marshal()))
apeOverride := val2.APEOverride() apeOverride, isSet := val2.APEOverride()
require.True(t, isSet)
require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2())) require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2()))
val2 = filled val2 = filled
@ -126,7 +130,8 @@ func TestToken_SetAPEOverrides(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd)) require.NoError(t, val2.UnmarshalJSON(jd))
apeOverride = val.APEOverride() apeOverride, isSet = val.APEOverride()
require.True(t, isSet)
require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2())) require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2()))
} }

View file

@ -26,11 +26,19 @@ import (
// usage is unsafe. // usage is unsafe.
type ObjectPatcher interface { type ObjectPatcher interface {
// PatchAttributes patches attributes. Attributes can be patched no more than once, // PatchAttributes patches attributes. Attributes can be patched no more than once,
// otherwise, the server returns an error. // otherwise, the server returns an error. `PatchAttributes` and `PatchHeader` are mutually
// exclusive - only one method can be used.
// //
// Result means success. Failure reason can be received via Close. // Result means success. Failure reason can be received via Close.
PatchAttributes(ctx context.Context, newAttrs []object.Attribute, replace bool) bool PatchAttributes(ctx context.Context, newAttrs []object.Attribute, replace bool) bool
// PatchHeader patches object's header. Header can be patched no more than once,
// otherwise, the server returns an error. `PatchAttributes` and `PatchHeader` are mutually
// exclusive - only one method can be used.
//
// Result means success. Failure reason can be received via Close.
PatchHeader(ctx context.Context, prm PatchHeaderPrm) bool
// PatchPayload patches the object's payload. // PatchPayload patches the object's payload.
// //
// PatchPayload receives `payloadReader` and thus the payload of the patch is read and sent by chunks of // PatchPayload receives `payloadReader` and thus the payload of the patch is read and sent by chunks of
@ -60,6 +68,14 @@ type ObjectPatcher interface {
Close(_ context.Context) (*ResObjectPatch, error) Close(_ context.Context) (*ResObjectPatch, error)
} }
type PatchHeaderPrm struct {
NewSplitHeader *object.SplitHeader
NewAttributes []object.Attribute
ReplaceAttributes bool
}
// ResObjectPatch groups resulting values of ObjectPatch operation. // ResObjectPatch groups resulting values of ObjectPatch operation.
type ResObjectPatch struct { type ResObjectPatch struct {
statusRes statusRes
@ -163,6 +179,15 @@ func (x *objectPatcher) PatchAttributes(_ context.Context, newAttrs []object.Att
}) })
} }
func (x *objectPatcher) PatchHeader(_ context.Context, prm PatchHeaderPrm) bool {
return x.patch(&object.Patch{
Address: x.addr,
NewAttributes: prm.NewAttributes,
ReplaceAttributes: prm.ReplaceAttributes,
NewSplitHeader: prm.NewSplitHeader,
})
}
func (x *objectPatcher) PatchPayload(_ context.Context, rng *object.Range, payloadReader io.Reader) bool { func (x *objectPatcher) PatchPayload(_ context.Context, rng *object.Range, payloadReader io.Reader) bool {
offset := rng.GetOffset() offset := rng.GetOffset()

View file

@ -177,7 +177,7 @@ func TestObjectPatcher(t *testing.T) {
maxChunkLen: test.maxChunkLen, maxChunkLen: test.maxChunkLen,
} }
success := patcher.PatchAttributes(context.Background(), nil, false) success := patcher.PatchHeader(context.Background(), PatchHeaderPrm{})
require.True(t, success) require.True(t, success)
success = patcher.PatchPayload(context.Background(), test.rng, bytes.NewReader([]byte(test.patchPayload))) success = patcher.PatchPayload(context.Background(), test.rng, bytes.NewReader([]byte(test.patchPayload)))

View file

@ -5,6 +5,7 @@ import (
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"iter"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -337,10 +338,41 @@ func (x Container) Attribute(key string) string {
return "" return ""
} }
// Attributes returns an iterator over all Container attributes.
//
// See also [Container.SetAttribute], [Container.UserAttributes].
func (x Container) Attributes() iter.Seq2[string, string] {
return func(yield func(string, string) bool) {
attrs := x.v2.GetAttributes()
for i := range attrs {
if !yield(attrs[i].GetKey(), attrs[i].GetValue()) {
return
}
}
}
}
// Attributes returns an iterator over all non-system Container attributes.
//
// See also [Container.SetAttribute], [Container.Attributes].
func (x Container) UserAttributes() iter.Seq2[string, string] {
return func(yield func(string, string) bool) {
for key, value := range x.Attributes() {
if !strings.HasPrefix(key, container.SysAttributePrefix) {
if !yield(key, value) {
return
}
}
}
}
}
// IterateAttributes iterates over all Container attributes and passes them // IterateAttributes iterates over all Container attributes and passes them
// into f. The handler MUST NOT be nil. // into f. The handler MUST NOT be nil.
// //
// See also SetAttribute, Attribute. // See also SetAttribute, Attribute.
//
// Deprecated: use [Container.Attributes] instead.
func (x Container) IterateAttributes(f func(key, val string)) { func (x Container) IterateAttributes(f func(key, val string)) {
attrs := x.v2.GetAttributes() attrs := x.v2.GetAttributes()
for i := range attrs { for i := range attrs {
@ -352,6 +384,8 @@ func (x Container) IterateAttributes(f func(key, val string)) {
// into f. The handler MUST NOT be nil. // into f. The handler MUST NOT be nil.
// //
// See also SetAttribute, Attribute. // See also SetAttribute, Attribute.
//
// Deprecated: use [Container.UserAttributes] instead.
func (x Container) IterateUserAttributes(f func(key, val string)) { func (x Container) IterateUserAttributes(f func(key, val string)) {
attrs := x.v2.GetAttributes() attrs := x.v2.GetAttributes()
for _, attr := range attrs { for _, attr := range attrs {

View file

@ -2,6 +2,7 @@ package container_test
import ( import (
"crypto/sha256" "crypto/sha256"
"maps"
"strconv" "strconv"
"testing" "testing"
"time" "time"
@ -159,9 +160,9 @@ func TestContainer_Attribute(t *testing.T) {
val.SetAttribute(attrKey2, attrVal2) val.SetAttribute(attrKey2, attrVal2)
var i int var i int
val.IterateUserAttributes(func(key, val string) { for range val.UserAttributes() {
i++ i++
}) }
require.Equal(t, 1, i) require.Equal(t, 1, i)
var msg v2container.Container var msg v2container.Container
@ -177,11 +178,7 @@ func TestContainer_Attribute(t *testing.T) {
require.Equal(t, attrVal1, val2.Attribute(attrKey1)) require.Equal(t, attrVal1, val2.Attribute(attrKey1))
require.Equal(t, attrVal2, val2.Attribute(attrKey2)) require.Equal(t, attrVal2, val2.Attribute(attrKey2))
m := map[string]string{} m := maps.Collect(val2.Attributes())
val2.IterateAttributes(func(key, val string) {
m[key] = val
})
require.GreaterOrEqual(t, len(m), 2) require.GreaterOrEqual(t, len(m), 2)
require.Equal(t, attrVal1, m[attrKey1]) require.Equal(t, attrVal1, m[attrKey1])

View file

@ -0,0 +1,95 @@
package container_test
import (
"testing"
containerAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
"github.com/stretchr/testify/require"
)
func TestContainer_Attributes(t *testing.T) {
t.Run("empty", func(t *testing.T) {
var n container.Container
t.Run("attributes", func(t *testing.T) {
for range n.Attributes() {
t.Fatalf("handler is called, but it shouldn't")
}
})
t.Run("user attributes", func(t *testing.T) {
for range n.UserAttributes() {
t.Fatalf("handler is called, but it shouldn't")
}
})
})
var n container.Container
n.SetAttribute(containerAPI.SysAttributeName, "myname")
n.SetAttribute("key1", "value1")
n.SetAttribute("key2", "value2")
n.SetAttribute(containerAPI.SysAttributeZone, "test")
t.Run("break", func(t *testing.T) {
t.Run("attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.Attributes() {
if key == "key2" {
break
}
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{{containerAPI.SysAttributeName, "myname"}, {"key1", "value1"}}, res)
})
t.Run("user attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.UserAttributes() {
if key == "key2" {
break
}
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{{"key1", "value1"}}, res)
})
})
t.Run("continue", func(t *testing.T) {
t.Run("attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.Attributes() {
if key == "key2" {
continue
}
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{{containerAPI.SysAttributeName, "myname"}, {"key1", "value1"}, {containerAPI.SysAttributeZone, "test"}}, res)
})
t.Run("user attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.UserAttributes() {
if key == "key2" {
continue
}
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{{"key1", "value1"}}, res)
})
})
t.Run("attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.Attributes() {
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{
{containerAPI.SysAttributeName, "myname"},
{"key1", "value1"},
{"key2", "value2"},
{containerAPI.SysAttributeZone, "test"},
}, res)
})
t.Run("user attributes", func(t *testing.T) {
var res [][2]string
for key, value := range n.UserAttributes() {
res = append(res, [2]string{key, value})
}
require.Equal(t, [][2]string{{"key1", "value1"}, {"key2", "value2"}}, res)
})
}

20
go.mod
View file

@ -1,6 +1,6 @@
module git.frostfs.info/TrueCloudLab/frostfs-sdk-go module git.frostfs.info/TrueCloudLab/frostfs-sdk-go
go 1.22 go 1.23.0
require ( require (
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
@ -14,11 +14,11 @@ require (
github.com/klauspost/reedsolomon v1.12.1 github.com/klauspost/reedsolomon v1.12.1
github.com/mailru/easyjson v0.7.7 github.com/mailru/easyjson v0.7.7
github.com/mr-tron/base58 v1.2.0 github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.14.0 github.com/multiformats/go-multiaddr v0.15.0
github.com/nspcc-dev/neo-go v0.106.2 github.com/nspcc-dev/neo-go v0.106.2
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/sync v0.10.0 golang.org/x/sync v0.12.0
google.golang.org/grpc v1.69.2 google.golang.org/grpc v1.69.2
google.golang.org/protobuf v1.36.1 google.golang.org/protobuf v1.36.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -30,9 +30,9 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/golang/snappy v0.0.1 // indirect github.com/golang/snappy v0.0.1 // indirect
github.com/gorilla/websocket v1.5.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect
github.com/ipfs/go-cid v0.0.7 // indirect github.com/ipfs/go-cid v0.5.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect
@ -49,12 +49,12 @@ require (
github.com/twmb/murmur3 v1.1.8 // indirect github.com/twmb/murmur3 v1.1.8 // indirect
go.etcd.io/bbolt v1.3.9 // indirect go.etcd.io/bbolt v1.3.9 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.31.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.23.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/blake3 v1.4.0 // indirect
) )

59
go.sum
View file

@ -62,12 +62,12 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/reedsolomon v1.12.1 h1:NhWgum1efX1x58daOBGCFWcxtEhOhXKKl1HAPQUp03Q= github.com/klauspost/reedsolomon v1.12.1 h1:NhWgum1efX1x58daOBGCFWcxtEhOhXKKl1HAPQUp03Q=
github.com/klauspost/reedsolomon v1.12.1/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs= github.com/klauspost/reedsolomon v1.12.1/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -76,31 +76,22 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= github.com/multiformats/go-multiaddr v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo=
github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 h1:mD9hU3v+zJcnHAVmHnZKt3I++tvn30gBj2rP2PocZMk= github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 h1:mD9hU3v+zJcnHAVmHnZKt3I++tvn30gBj2rP2PocZMk=
@ -167,14 +158,13 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@ -182,8 +172,8 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -194,19 +184,18 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -235,7 +224,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=

View file

@ -54,7 +54,7 @@ var (
// capacity and price. // capacity and price.
func newWeightFunc(capNorm, priceNorm normalizer) weightFunc { func newWeightFunc(capNorm, priceNorm normalizer) weightFunc {
return func(n NodeInfo) float64 { return func(n NodeInfo) float64 {
return capNorm.Normalize(float64(n.capacity())) * priceNorm.Normalize(float64(n.Price())) return capNorm.Normalize(float64(n.capacity)) * priceNorm.Normalize(float64(n.price))
} }
} }

View file

@ -97,8 +97,8 @@ func defaultWeightFunc(ns nodes) weightFunc {
minV := newMinAgg() minV := newMinAgg()
for i := range ns { for i := range ns {
mean.Add(float64(ns[i].capacity())) mean.Add(float64(ns[i].capacity))
minV.Add(float64(ns[i].Price())) minV.Add(float64(ns[i].price))
} }
return newWeightFunc( return newWeightFunc(

View file

@ -133,9 +133,9 @@ func (c *context) matchKeyValue(f *netmap.Filter, b NodeInfo) bool {
switch f.GetKey() { switch f.GetKey() {
case attrPrice: case attrPrice:
attr = b.Price() attr = b.price
case attrCapacity: case attrCapacity:
attr = b.capacity() attr = b.capacity
default: default:
var err error var err error

View file

@ -139,20 +139,12 @@ func (n nodes) appendWeightsTo(wf weightFunc, w []float64) []float64 {
return w return w
} }
func flattenNodes(ns []nodes) nodes { // flattenNodes flattens ns nested list and appends the result to the target slice.
var sz, i int func flattenNodes(target nodes, ns []nodes) nodes {
for i = range ns {
sz += len(ns[i])
}
result := make(nodes, 0, sz)
for i := range ns { for i := range ns {
result = append(result, ns[i]...) target = append(target, ns[i]...)
} }
return target
return result
} }
// PlacementVectors sorts container nodes returned by ContainerNodes method // PlacementVectors sorts container nodes returned by ContainerNodes method
@ -287,7 +279,7 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e
return nil, err return nil, err
} }
result[i] = append(result[i], flattenNodes(nodes)...) result[i] = flattenNodes(result[i], nodes)
if unique { if unique {
c.addUsedNodes(result[i]...) c.addUsedNodes(result[i]...)
@ -304,14 +296,14 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e
if err != nil { if err != nil {
return nil, err return nil, err
} }
result[i] = append(result[i], flattenNodes(nodes)...) result[i] = flattenNodes(result[i], nodes)
c.addUsedNodes(result[i]...) c.addUsedNodes(result[i]...)
} else { } else {
nodes, ok := c.selections[sName] nodes, ok := c.selections[sName]
if !ok { if !ok {
return nil, fmt.Errorf("selector not found: REPLICA '%s'", sName) return nil, fmt.Errorf("selector not found: REPLICA '%s'", sName)
} }
result[i] = append(result[i], flattenNodes(nodes)...) result[i] = flattenNodes(result[i], nodes)
} }
} }

View file

@ -30,20 +30,19 @@ func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool)
return errors.New("missing network config") return errors.New("missing network config")
} }
if checkFieldPresence && c.NumberOfParameters() <= 0 { if checkFieldPresence && len(c.Parameters()) == 0 {
return errors.New("missing network parameters") return errors.New("missing network parameters")
} }
var err error var err error
mNames := make(map[string]struct{}, c.NumberOfParameters()) mNames := make(map[string]struct{}, len(c.Parameters()))
c.IterateParameters(func(prm *netmap.NetworkParameter) bool { for _, prm := range c.Parameters() {
name := string(prm.GetKey()) name := string(prm.GetKey())
_, was := mNames[name] _, was := mNames[name]
if was { if was {
err = fmt.Errorf("duplicated parameter name: %s", name) return fmt.Errorf("duplicated parameter name: %s", name)
return true
} }
mNames[name] = struct{}{} mNames[name] = struct{}{}
@ -67,14 +66,8 @@ func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool)
} }
if err != nil { if err != nil {
err = fmt.Errorf("invalid %s parameter: %w", name, err) return fmt.Errorf("invalid %s parameter: %w", name, err)
} }
return err != nil
})
if err != nil {
return err
} }
x.m = m x.m = m
@ -152,41 +145,29 @@ func (x *NetworkInfo) setConfig(name string, val []byte) {
return return
} }
found := false prms := c.Parameters()
prms := make([]netmap.NetworkParameter, 0, c.NumberOfParameters()) for i := range prms {
if bytes.Equal(prms[i].GetKey(), []byte(name)) {
c.IterateParameters(func(prm *netmap.NetworkParameter) bool { prms[i].SetValue(val)
found = bytes.Equal(prm.GetKey(), []byte(name)) return
if found {
prm.SetValue(val)
} else {
prms = append(prms, *prm)
} }
return found
})
if !found {
prms = append(prms, netmap.NetworkParameter{})
prms[len(prms)-1].SetKey([]byte(name))
prms[len(prms)-1].SetValue(val)
c.SetParameters(prms...)
} }
prms = append(prms, netmap.NetworkParameter{})
prms[len(prms)-1].SetKey([]byte(name))
prms[len(prms)-1].SetValue(val)
c.SetParameters(prms...)
} }
func (x NetworkInfo) configValue(name string) (res []byte) { func (x NetworkInfo) configValue(name string) (res []byte) {
x.m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool { for _, prm := range x.m.GetNetworkConfig().Parameters() {
if string(prm.GetKey()) == name { if string(prm.GetKey()) == name {
res = prm.GetValue() return prm.GetValue()
return true
} }
}
return false return nil
})
return
} }
// SetRawNetworkParameter sets named FrostFS network parameter whose value is // SetRawNetworkParameter sets named FrostFS network parameter whose value is
@ -218,7 +199,7 @@ func (x *NetworkInfo) RawNetworkParameter(name string) []byte {
func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []byte)) { func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []byte)) {
c := x.m.GetNetworkConfig() c := x.m.GetNetworkConfig()
c.IterateParameters(func(prm *netmap.NetworkParameter) bool { for _, prm := range c.Parameters() {
name := string(prm.GetKey()) name := string(prm.GetKey())
switch name { switch name {
default: default:
@ -237,9 +218,7 @@ func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []by
configHomomorphicHashingDisabled, configHomomorphicHashingDisabled,
configMaintenanceModeAllowed: configMaintenanceModeAllowed:
} }
}
return false
})
} }
func (x *NetworkInfo) setConfigUint64(name string, num uint64) { func (x *NetworkInfo) setConfigUint64(name string, num uint64) {

View file

@ -76,16 +76,10 @@ func testConfigValue(t *testing.T,
var m netmap.NetworkInfo var m netmap.NetworkInfo
x.WriteToV2(&m) x.WriteToV2(&m)
require.EqualValues(t, 1, m.GetNetworkConfig().NumberOfParameters()) var p netmap.NetworkParameter
found := false p.SetKey([]byte(v2Key))
m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool { p.SetValue(v2Val(exp))
require.False(t, found) require.Equal(t, []netmap.NetworkParameter{p}, m.GetNetworkConfig().Parameters())
require.Equal(t, []byte(v2Key), prm.GetKey())
require.Equal(t, v2Val(exp), prm.GetValue())
found = true
return false
})
require.True(t, found)
} }
setter(&x, val1) setter(&x, val1)

View file

@ -3,6 +3,7 @@ package netmap
import ( import (
"errors" "errors"
"fmt" "fmt"
"iter"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
@ -25,6 +26,9 @@ import (
type NodeInfo struct { type NodeInfo struct {
m netmap.NodeInfo m netmap.NodeInfo
hash uint64 hash uint64
capacity uint64
price uint64
} }
// reads NodeInfo from netmap.NodeInfo message. If checkFieldPresence is set, // reads NodeInfo from netmap.NodeInfo message. If checkFieldPresence is set,
@ -32,6 +36,7 @@ type NodeInfo struct {
// presented field according to FrostFS API V2 protocol. // presented field according to FrostFS API V2 protocol.
func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error { func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error {
var err error var err error
var capacity, price uint64
binPublicKey := m.GetPublicKey() binPublicKey := m.GetPublicKey()
if checkFieldPresence && len(binPublicKey) == 0 { if checkFieldPresence && len(binPublicKey) == 0 {
@ -49,18 +54,18 @@ func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error
if key == "" { if key == "" {
return fmt.Errorf("empty key of the attribute #%d", i) return fmt.Errorf("empty key of the attribute #%d", i)
} else if _, ok := mAttr[key]; ok { } else if _, ok := mAttr[key]; ok {
return fmt.Errorf("duplicated attbiuted %s", key) return fmt.Errorf("duplicate attributes %s", key)
} }
mAttr[key] = struct{}{}
switch { switch {
case key == attrCapacity: case key == attrCapacity:
_, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64) capacity, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("invalid %s attribute: %w", attrCapacity, err) return fmt.Errorf("invalid %s attribute: %w", attrCapacity, err)
} }
case key == attrPrice: case key == attrPrice:
var err error price, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64)
_, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("invalid %s attribute: %w", attrPrice, err) return fmt.Errorf("invalid %s attribute: %w", attrPrice, err)
} }
@ -73,6 +78,8 @@ func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error
x.m = m x.m = m
x.hash = hrw.Hash(binPublicKey) x.hash = hrw.Hash(binPublicKey)
x.capacity = capacity
x.price = price
return nil return nil
} }
@ -200,12 +207,28 @@ func (x NodeInfo) NumberOfNetworkEndpoints() int {
// FrostFS system requirements. // FrostFS system requirements.
// //
// See also SetNetworkEndpoints. // See also SetNetworkEndpoints.
//
// Deprecated: use [NodeInfo.NetworkEndpoints] instead.
func (x NodeInfo) IterateNetworkEndpoints(f func(string) bool) { func (x NodeInfo) IterateNetworkEndpoints(f func(string) bool) {
x.m.IterateAddresses(f) for s := range x.NetworkEndpoints() {
if f(s) {
return
}
}
}
// NetworkEndpoints returns an iterator over network endpoints announced by the
// node.
//
// See also SetNetworkEndpoints.
func (x NodeInfo) NetworkEndpoints() iter.Seq[string] {
return x.m.Addresses()
} }
// IterateNetworkEndpoints is an extra-sugared function over IterateNetworkEndpoints // IterateNetworkEndpoints is an extra-sugared function over IterateNetworkEndpoints
// method which allows to unconditionally iterate over all node's network endpoints. // method which allows to unconditionally iterate over all node's network endpoints.
//
// Deprecated: use [NodeInfo.NetworkEndpoints] instead.
func IterateNetworkEndpoints(node NodeInfo, f func(string)) { func IterateNetworkEndpoints(node NodeInfo, f func(string)) {
node.IterateNetworkEndpoints(func(addr string) bool { node.IterateNetworkEndpoints(func(addr string) bool {
f(addr) f(addr)
@ -235,46 +258,21 @@ func (x *NodeInfo) setNumericAttribute(key string, num uint64) {
// price is announced. // price is announced.
func (x *NodeInfo) SetPrice(price uint64) { func (x *NodeInfo) SetPrice(price uint64) {
x.setNumericAttribute(attrPrice, price) x.setNumericAttribute(attrPrice, price)
x.price = price
} }
// Price returns price set using SetPrice. // Price returns price set using SetPrice.
// //
// Zero NodeInfo has zero price. // Zero NodeInfo has zero price.
func (x NodeInfo) Price() uint64 { func (x NodeInfo) Price() uint64 {
val := x.Attribute(attrPrice) return x.price
if val == "" {
return 0
}
price, err := strconv.ParseUint(val, 10, 64)
if err != nil {
panic(fmt.Sprintf("unexpected price parsing error %s: %v", val, err))
}
return price
} }
// SetCapacity sets the storage capacity declared by the node. By default, zero // SetCapacity sets the storage capacity declared by the node. By default, zero
// capacity is announced. // capacity is announced.
func (x *NodeInfo) SetCapacity(capacity uint64) { func (x *NodeInfo) SetCapacity(capacity uint64) {
x.setNumericAttribute(attrCapacity, capacity) x.setNumericAttribute(attrCapacity, capacity)
} x.capacity = capacity
// capacity returns capacity set using SetCapacity.
//
// Zero NodeInfo has zero capacity.
func (x NodeInfo) capacity() uint64 {
val := x.Attribute(attrCapacity)
if val == "" {
return 0
}
capacity, err := strconv.ParseUint(val, 10, 64)
if err != nil {
panic(fmt.Sprintf("unexpected capacity parsing error %s: %v", val, err))
}
return capacity
} }
const attrUNLOCODE = "UN-LOCODE" const attrUNLOCODE = "UN-LOCODE"
@ -393,8 +391,22 @@ func (x NodeInfo) NumberOfAttributes() int {
return len(x.m.GetAttributes()) return len(x.m.GetAttributes())
} }
// Attributes returns an iterator over node attributes.
func (x NodeInfo) Attributes() iter.Seq2[string, string] {
return func(yield func(string, string) bool) {
a := x.m.GetAttributes()
for i := range a {
if !yield(a[i].GetKey(), a[i].GetValue()) {
break
}
}
}
}
// IterateAttributes iterates over all node attributes and passes the into f. // IterateAttributes iterates over all node attributes and passes the into f.
// Handler MUST NOT be nil. // Handler MUST NOT be nil.
//
// Deprecated: use [NodeInfo.Attributes] instead.
func (x NodeInfo) IterateAttributes(f func(key, value string)) { func (x NodeInfo) IterateAttributes(f func(key, value string)) {
a := x.m.GetAttributes() a := x.m.GetAttributes()
for i := range a { for i := range a {
@ -411,6 +423,17 @@ func (x *NodeInfo) SetAttribute(key, value string) {
panic("empty value in SetAttribute") panic("empty value in SetAttribute")
} }
// NodeInfo with non-numeric `Price`` or `Capacity` attributes
// is considered invalid by NodeInfo.readFromV2().
// Here we have no way to signal an error, and panic seems an overkill.
// So, set cached fields only if we can parse the value and 0 parsing fails.
switch key {
case attrPrice:
x.price, _ = strconv.ParseUint(value, 10, 64)
case attrCapacity:
x.capacity, _ = strconv.ParseUint(value, 10, 64)
}
a := x.m.GetAttributes() a := x.m.GetAttributes()
for i := range a { for i := range a {
if a[i].GetKey() == key { if a[i].GetKey() == key {

View file

@ -1,12 +1,94 @@
package netmap package netmap
import ( import (
"fmt"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestNodeInfo_NetworkEndpoints(t *testing.T) {
t.Run("empty", func(t *testing.T) {
var n NodeInfo
for range n.NetworkEndpoints() {
t.Fatalf("handler is called, but it shouldn't")
}
})
var n NodeInfo
n.SetNetworkEndpoints("1", "2", "3")
t.Run("break", func(t *testing.T) {
var res []string
for s := range n.NetworkEndpoints() {
if s == "2" {
break
}
res = append(res, s)
}
require.Equal(t, []string{"1"}, res)
})
t.Run("continue", func(t *testing.T) {
var res []string
for s := range n.NetworkEndpoints() {
if s == "2" {
continue
}
res = append(res, s)
}
require.Equal(t, []string{"1", "3"}, res)
})
var res []string
for s := range n.NetworkEndpoints() {
res = append(res, s)
}
require.Equal(t, []string{"1", "2", "3"}, res)
}
func TestNodeInfo_Attributes(t *testing.T) {
t.Run("empty", func(t *testing.T) {
var n NodeInfo
for range n.Attributes() {
t.Fatalf("handler is called, but it shouldn't")
}
})
var n NodeInfo
n.SetAttribute("key1", "value1")
n.SetAttribute("key2", "value2")
n.SetAttribute("key3", "value3")
t.Run("break", func(t *testing.T) {
var res [][2]string
for k, v := range n.Attributes() {
if k == "key2" {
break
}
res = append(res, [2]string{k, v})
}
require.Equal(t, [][2]string{{"key1", "value1"}}, res)
})
t.Run("continue", func(t *testing.T) {
var res [][2]string
for k, v := range n.Attributes() {
if k == "key2" {
continue
}
res = append(res, [2]string{k, v})
}
require.Equal(t, [][2]string{{"key1", "value1"}, {"key3", "value3"}}, res)
})
var res [][2]string
for k, v := range n.Attributes() {
res = append(res, [2]string{k, v})
}
require.Equal(t, [][2]string{{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}, res)
}
func TestNodeInfo_SetAttribute(t *testing.T) { func TestNodeInfo_SetAttribute(t *testing.T) {
var n NodeInfo var n NodeInfo
@ -117,3 +199,85 @@ func TestNodeInfo_Clone(t *testing.T) {
require.True(t, c != &ni) require.True(t, c != &ni)
require.True(t, &(c.PublicKey()[0]) != &(ni.PublicKey()[0])) require.True(t, &(c.PublicKey()[0]) != &(ni.PublicKey()[0]))
} }
func TestNodeInfo_Unmarshal(t *testing.T) {
pk, err := keys.NewPrivateKey()
require.NoError(t, err)
attrs := make([]netmap.Attribute, 2)
for i := range attrs {
attrs[i].SetKey(fmt.Sprintf("key%d", i))
attrs[i].SetValue(fmt.Sprintf("value%d", i))
}
goodNodeInfo := func() netmap.NodeInfo {
var nodev2 netmap.NodeInfo
nodev2.SetPublicKey(pk.PublicKey().Bytes())
nodev2.SetAddresses("127.0.0.1:2025")
nodev2.SetState(netmap.Online)
nodev2.SetAttributes(attrs)
return nodev2
}
// Check that goodNodeInfo indeed returns good node.
// Otherwise, the whole test is garbage.
require.NoError(t, new(NodeInfo).ReadFromV2(goodNodeInfo()))
t.Run("empty public key", func(t *testing.T) {
n := goodNodeInfo()
n.SetPublicKey(nil)
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n), "missing public key")
})
t.Run("missing addresses", func(t *testing.T) {
n := goodNodeInfo()
n.SetAddresses()
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n), "missing network endpoints")
})
t.Run("empty attribute key", func(t *testing.T) {
n := goodNodeInfo()
var a netmap.Attribute
a.SetValue("non-empty")
n.SetAttributes(append(attrs, a))
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n),
fmt.Sprintf("empty key of the attribute #%d", len(attrs)))
})
t.Run("empty attribute value", func(t *testing.T) {
n := goodNodeInfo()
var a netmap.Attribute
a.SetKey("non-empty-key")
n.SetAttributes(append(attrs, a))
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n),
"empty value of the attribute non-empty-key")
})
t.Run("invalid price attribute", func(t *testing.T) {
n := goodNodeInfo()
var a netmap.Attribute
a.SetKey(attrPrice)
a.SetValue("not a number")
n.SetAttributes(append(attrs, a))
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n),
fmt.Sprintf("invalid %s attribute", attrPrice))
})
t.Run("invalid capacity attribute", func(t *testing.T) {
n := goodNodeInfo()
var a netmap.Attribute
a.SetKey(attrCapacity)
a.SetValue("not a number")
n.SetAttributes(append(attrs, a))
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n),
fmt.Sprintf("invalid %s attribute", attrCapacity))
})
t.Run("duplicate attributes", func(t *testing.T) {
n := goodNodeInfo()
var a netmap.Attribute
a.SetKey("key1")
a.SetValue("value3")
n.SetAttributes(append(attrs, a))
require.ErrorContains(t, new(NodeInfo).ReadFromV2(n),
"duplicate attributes key1")
})
}

View file

@ -191,7 +191,7 @@ func TestPlacementPolicy_DeterministicOrder(t *testing.T) {
nss[i] = v[i] nss[i] = v[i]
} }
ns := flattenNodes(nss) ns := flattenNodes(nil, nss)
require.Equal(t, 2, len(ns)) require.Equal(t, 2, len(ns))
return ns[0].Hash(), ns[1].Hash() return ns[0].Hash(), ns[1].Hash()
} }

View file

@ -345,6 +345,32 @@ func (o *Object) SetAttributes(v ...Attribute) {
}) })
} }
// SplitHeader returns split header of the object. If it's set, then split header
// defines how the object relates to other objects in a split operation.
func (o *Object) SplitHeader() (splitHeader *SplitHeader) {
if v2 := (*object.Object)(o).
GetHeader().
GetSplit(); v2 != nil {
splitHeader = NewSplitHeaderFromV2(v2)
}
return
}
// SetSplitHeader sets split header.
func (o *Object) SetSplitHeader(v *SplitHeader) {
o.setSplitFields(func(sh *object.SplitHeader) {
v2 := v.ToV2()
sh.SetParent(v2.GetParent())
sh.SetPrevious(v2.GetPrevious())
sh.SetParentHeader(v2.GetParentHeader())
sh.SetParentSignature(v2.GetParentSignature())
sh.SetChildren(v2.GetChildren())
sh.SetSplitID(v2.GetSplitID())
})
}
// PreviousID returns identifier of the previous sibling object. // PreviousID returns identifier of the previous sibling object.
func (o *Object) PreviousID() (v oid.ID, isSet bool) { func (o *Object) PreviousID() (v oid.ID, isSet bool) {
v2 := (*object.Object)(o) v2 := (*object.Object)(o)

View file

@ -18,6 +18,10 @@ type Patch struct {
// filled with NewAttributes. Otherwise, the attributes are just merged. // filled with NewAttributes. Otherwise, the attributes are just merged.
ReplaceAttributes bool ReplaceAttributes bool
// A new split header which is set to object's header. If `nil`, then split header patching
// is ignored.
NewSplitHeader *SplitHeader
// Payload patch. If this field is not set, then it assumed such Patch patches only // Payload patch. If this field is not set, then it assumed such Patch patches only
// header (see NewAttributes, ReplaceAttributes). // header (see NewAttributes, ReplaceAttributes).
PayloadPatch *PayloadPatch PayloadPatch *PayloadPatch
@ -41,6 +45,8 @@ func (p *Patch) ToV2() *v2object.PatchRequestBody {
v2.SetNewAttributes(attrs) v2.SetNewAttributes(attrs)
v2.SetReplaceAttributes(p.ReplaceAttributes) v2.SetReplaceAttributes(p.ReplaceAttributes)
v2.SetNewSplitHeader(p.NewSplitHeader.ToV2())
v2.SetPatch(p.PayloadPatch.ToV2()) v2.SetPatch(p.PayloadPatch.ToV2())
return v2 return v2
@ -63,6 +69,8 @@ func (p *Patch) FromV2(patch *v2object.PatchRequestBody) {
p.ReplaceAttributes = patch.GetReplaceAttributes() p.ReplaceAttributes = patch.GetReplaceAttributes()
p.NewSplitHeader = NewSplitHeaderFromV2(patch.GetNewSplitHeader())
if v2patch := patch.GetPatch(); v2patch != nil { if v2patch := patch.GetPatch(); v2patch != nil {
p.PayloadPatch = new(PayloadPatch) p.PayloadPatch = new(PayloadPatch)
p.PayloadPatch.FromV2(v2patch) p.PayloadPatch.FromV2(v2patch)

View file

@ -11,10 +11,12 @@ import (
) )
var ( var (
ErrOffsetExceedsSize = errors.New("patch offset exceeds object size") ErrOffsetExceedsSize = errors.New("patch offset exceeds object size")
ErrInvalidPatchOffsetOrder = errors.New("invalid patch offset order") ErrInvalidPatchOffsetOrder = errors.New("invalid patch offset order")
ErrPayloadPatchIsNil = errors.New("nil payload patch") ErrPayloadPatchIsNil = errors.New("nil payload patch")
ErrAttrPatchAlreadyApplied = errors.New("attribute patch already applied") ErrAttrPatchAlreadyApplied = errors.New("attribute patch already applied")
ErrHeaderPatchAlreadyApplied = errors.New("header patch already applied")
ErrSplitHeaderPatchAppliedWithPayloadPatch = errors.New("split header patch applied with payload patch")
) )
// PatchRes is the result of patch application. // PatchRes is the result of patch application.
@ -27,13 +29,24 @@ type PatchApplier interface {
// ApplyAttributesPatch applies the patch only for the object's attributes. // ApplyAttributesPatch applies the patch only for the object's attributes.
// //
// ApplyAttributesPatch can't be invoked few times, otherwise it returns `ErrAttrPatchAlreadyApplied` error. // ApplyAttributesPatch can't be invoked few times, otherwise it returns `ErrAttrPatchAlreadyApplied` error.
// `ApplyHeaderPatch` and `ApplyAttributesPatch` are mutually exclusive - only one method can be used.
// //
// The call is idempotent for the original header if it's invoked with empty `newAttrs` and // The call is idempotent for the original header if it's invoked with empty `newAttrs` and
// `replaceAttrs = false`. // `replaceAttrs = false`.
ApplyAttributesPatch(ctx context.Context, newAttrs []objectSDK.Attribute, replaceAttrs bool) error ApplyAttributesPatch(ctx context.Context, newAttrs []objectSDK.Attribute, replaceAttrs bool) error
// ApplyHeaderPatch applies the patch only for the object's attributes.
//
// ApplyHeaderPatch can't be invoked few times, otherwise it returns `ErrHeaderPatchAlreadyApplied` error.
// `ApplyHeaderPatch` and `ApplyAttributesPatch` are mutually exclusive - only one method can be used.
//
// The call is idempotent for the original header if it's invoked with `ApplyHeaderPatchPrm` with not set fields.
ApplyHeaderPatch(ctx context.Context, prm ApplyHeaderPatchPrm) error
// ApplyPayloadPatch applies the patch for the object's payload. // ApplyPayloadPatch applies the patch for the object's payload.
// //
// ApplyPayloadPatch returns `ErrSplitHeaderPatchAppliedWithPayloadPatch` when attempting to apply it with a split header patch.
//
// ApplyPayloadPatch returns `ErrPayloadPatchIsNil` error if patch is nil. // ApplyPayloadPatch returns `ErrPayloadPatchIsNil` error if patch is nil.
ApplyPayloadPatch(ctx context.Context, payloadPatch *objectSDK.PayloadPatch) error ApplyPayloadPatch(ctx context.Context, payloadPatch *objectSDK.PayloadPatch) error
@ -41,6 +54,14 @@ type PatchApplier interface {
Close(context.Context) (PatchRes, error) Close(context.Context) (PatchRes, error)
} }
type ApplyHeaderPatchPrm struct {
NewSplitHeader *objectSDK.SplitHeader
NewAttributes []objectSDK.Attribute
ReplaceAttributes bool
}
// RangeProvider is the interface that provides a method to get original object payload // RangeProvider is the interface that provides a method to get original object payload
// by a given range. // by a given range.
type RangeProvider interface { type RangeProvider interface {
@ -61,7 +82,9 @@ type patcher struct {
hdr *objectSDK.Object hdr *objectSDK.Object
attrPatchAlreadyApplied bool hdrPatchAlreadyApplied bool
splitHeaderPatchAlreadyApplied bool
readerBuffSize int readerBuffSize int
} }
@ -107,10 +130,10 @@ func New(prm Params) PatchApplier {
func (p *patcher) ApplyAttributesPatch(ctx context.Context, newAttrs []objectSDK.Attribute, replaceAttrs bool) error { func (p *patcher) ApplyAttributesPatch(ctx context.Context, newAttrs []objectSDK.Attribute, replaceAttrs bool) error {
defer func() { defer func() {
p.attrPatchAlreadyApplied = true p.hdrPatchAlreadyApplied = true
}() }()
if p.attrPatchAlreadyApplied { if p.hdrPatchAlreadyApplied {
return ErrAttrPatchAlreadyApplied return ErrAttrPatchAlreadyApplied
} }
@ -127,7 +150,38 @@ func (p *patcher) ApplyAttributesPatch(ctx context.Context, newAttrs []objectSDK
return nil return nil
} }
func (p *patcher) ApplyHeaderPatch(ctx context.Context, prm ApplyHeaderPatchPrm) error {
defer func() {
p.hdrPatchAlreadyApplied = true
}()
if p.hdrPatchAlreadyApplied {
return ErrHeaderPatchAlreadyApplied
}
if prm.NewSplitHeader != nil {
p.hdr.SetSplitHeader(prm.NewSplitHeader)
p.splitHeaderPatchAlreadyApplied = true
}
if prm.ReplaceAttributes {
p.hdr.SetAttributes(prm.NewAttributes...)
} else if len(prm.NewAttributes) > 0 {
mergedAttrs := mergeAttributes(prm.NewAttributes, p.hdr.Attributes())
p.hdr.SetAttributes(mergedAttrs...)
}
if err := p.objectWriter.WriteHeader(ctx, p.hdr); err != nil {
return fmt.Errorf("writer header: %w", err)
}
return nil
}
func (p *patcher) ApplyPayloadPatch(ctx context.Context, payloadPatch *objectSDK.PayloadPatch) error { func (p *patcher) ApplyPayloadPatch(ctx context.Context, payloadPatch *objectSDK.PayloadPatch) error {
if p.splitHeaderPatchAlreadyApplied {
return ErrSplitHeaderPatchAppliedWithPayloadPatch
}
if payloadPatch == nil { if payloadPatch == nil {
return ErrPayloadPatchIsNil return ErrPayloadPatchIsNil
} }

View file

@ -106,7 +106,11 @@ func TestPatchRevert(t *testing.T) {
patcher := New(prm) patcher := New(prm)
err := patcher.ApplyAttributesPatch(context.Background(), modifPatch.NewAttributes, modifPatch.ReplaceAttributes) err := patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.NoError(t, err) require.NoError(t, err)
err = patcher.ApplyPayloadPatch(context.Background(), modifPatch.PayloadPatch) err = patcher.ApplyPayloadPatch(context.Background(), modifPatch.PayloadPatch)
@ -145,7 +149,11 @@ func TestPatchRevert(t *testing.T) {
patcher = New(prm) patcher = New(prm)
err = patcher.ApplyAttributesPatch(context.Background(), revertPatch.NewAttributes, revertPatch.ReplaceAttributes) err = patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: revertPatch.NewSplitHeader,
NewAttributes: revertPatch.NewAttributes,
ReplaceAttributes: revertPatch.ReplaceAttributes,
})
require.NoError(t, err) require.NoError(t, err)
err = patcher.ApplyPayloadPatch(context.Background(), revertPatch.PayloadPatch) err = patcher.ApplyPayloadPatch(context.Background(), revertPatch.PayloadPatch)
@ -157,7 +165,7 @@ func TestPatchRevert(t *testing.T) {
require.Equal(t, originalObjectPayload, patchedPatchedObj.Payload()) require.Equal(t, originalObjectPayload, patchedPatchedObj.Payload())
} }
func TestPatchRepeatAttributePatch(t *testing.T) { func TestPatchRepeatHeaderPatch(t *testing.T) {
obj, _ := newTestObject() obj, _ := newTestObject()
modifPatch := &objectSDK.Patch{} modifPatch := &objectSDK.Patch{}
@ -187,11 +195,142 @@ func TestPatchRepeatAttributePatch(t *testing.T) {
patcher := New(prm) patcher := New(prm)
err := patcher.ApplyAttributesPatch(context.Background(), modifPatch.NewAttributes, modifPatch.ReplaceAttributes) err := patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.NoError(t, err) require.NoError(t, err)
err = patcher.ApplyAttributesPatch(context.Background(), modifPatch.NewAttributes, modifPatch.ReplaceAttributes) err = patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
require.ErrorIs(t, err, ErrAttrPatchAlreadyApplied) NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.ErrorIs(t, err, ErrHeaderPatchAlreadyApplied)
}
func TestPatchSplitHeader(t *testing.T) {
obj, _ := newTestObject()
const (
splitIDStr = "a59c9f87-14bc-4a61-95d1-7eb10f036163"
parentStr = "9cRjAaPqUt5zaDAjBkSCqFfPdkE8dHJ7mtRupRjPWp6E"
previosStr = "6WaTd9HobT4Z52NnKWHAtjqtQu2Ww5xZwNdT4ptshkKE"
)
splitID := objectSDK.NewSplitID()
require.NoError(t, splitID.Parse(splitIDStr))
var par, prev oid.ID
require.NoError(t, par.DecodeString(parentStr))
require.NoError(t, prev.DecodeString(previosStr))
splitHdr := objectSDK.NewSplitHeader()
splitHdr.SetSplitID(splitID)
splitHdr.SetParentID(par)
splitHdr.SetPreviousID(prev)
originalObjectPayload := []byte("*******************")
obj.SetPayload(originalObjectPayload)
obj.SetPayloadSize(uint64(len(originalObjectPayload)))
rangeProvider := &mockRangeProvider{
originalObjectPayload: originalObjectPayload,
}
t.Run("no payload patch", func(t *testing.T) {
patchedObj, _ := newTestObject()
wr := &mockPatchedObjectWriter{
obj: patchedObj,
}
modifPatch := &objectSDK.Patch{
NewSplitHeader: splitHdr,
}
prm := Params{
Header: obj.CutPayload(),
RangeProvider: rangeProvider,
ObjectWriter: wr,
}
patcher := New(prm)
err := patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.NoError(t, err)
splitHdrFromPatchedObj := patchedObj.SplitHeader()
require.NotNil(t, splitHdrFromPatchedObj)
patchObjParID, isSet := splitHdrFromPatchedObj.ParentID()
require.True(t, isSet)
require.True(t, patchObjParID.Equals(par))
patchObjPrevID, isSet := splitHdrFromPatchedObj.PreviousID()
require.True(t, isSet)
require.True(t, patchObjPrevID.Equals(prev))
require.Equal(t, splitHdrFromPatchedObj.SplitID().String(), splitID.String())
})
t.Run("with payload patch", func(t *testing.T) {
patchedObj, _ := newTestObject()
wr := &mockPatchedObjectWriter{
obj: patchedObj,
}
modifPatch := &objectSDK.Patch{
NewSplitHeader: splitHdr,
PayloadPatch: &objectSDK.PayloadPatch{
Range: rangeWithOffestWithLength(10, 0),
Chunk: []byte(""),
},
}
prm := Params{
Header: obj.CutPayload(),
RangeProvider: rangeProvider,
ObjectWriter: wr,
}
patcher := New(prm)
err := patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.NoError(t, err)
splitHdrFromPatchedObj := patchedObj.SplitHeader()
require.NotNil(t, splitHdrFromPatchedObj)
patchObjParID, isSet := splitHdrFromPatchedObj.ParentID()
require.True(t, isSet)
require.True(t, patchObjParID.Equals(par))
patchObjPrevID, isSet := splitHdrFromPatchedObj.PreviousID()
require.True(t, isSet)
require.True(t, patchObjPrevID.Equals(prev))
require.Equal(t, splitHdrFromPatchedObj.SplitID().String(), splitID.String())
err = patcher.ApplyPayloadPatch(context.Background(), modifPatch.PayloadPatch)
require.Error(t, err, ErrSplitHeaderPatchAppliedWithPayloadPatch)
})
} }
func TestPatchEmptyPayloadPatch(t *testing.T) { func TestPatchEmptyPayloadPatch(t *testing.T) {
@ -224,7 +363,11 @@ func TestPatchEmptyPayloadPatch(t *testing.T) {
patcher := New(prm) patcher := New(prm)
err := patcher.ApplyAttributesPatch(context.Background(), modifPatch.NewAttributes, modifPatch.ReplaceAttributes) err := patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: modifPatch.NewSplitHeader,
NewAttributes: modifPatch.NewAttributes,
ReplaceAttributes: modifPatch.ReplaceAttributes,
})
require.NoError(t, err) require.NoError(t, err)
err = patcher.ApplyPayloadPatch(context.Background(), nil) err = patcher.ApplyPayloadPatch(context.Background(), nil)
@ -599,7 +742,11 @@ func TestPatch(t *testing.T) {
for i, patch := range test.patches { for i, patch := range test.patches {
if i == 0 { if i == 0 {
_ = patcher.ApplyAttributesPatch(context.Background(), patch.NewAttributes, patch.ReplaceAttributes) _ = patcher.ApplyHeaderPatch(context.Background(), ApplyHeaderPatchPrm{
NewSplitHeader: patch.NewSplitHeader,
NewAttributes: patch.NewAttributes,
ReplaceAttributes: patch.ReplaceAttributes,
})
} }
if patch.PayloadPatch == nil { if patch.PayloadPatch == nil {

124
object/split_header.go Normal file
View file

@ -0,0 +1,124 @@
package object
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
)
// SplitHeader is an object's header component that defines the relationship
// between this object and other objects if the object is part of a split operation.
type SplitHeader object.SplitHeader
// NewSplitHeaderFromV2 wraps v2 SplitHeader message to SplitHeader.
func NewSplitHeaderFromV2(v2 *object.SplitHeader) *SplitHeader {
return (*SplitHeader)(v2)
}
// NewSplitHeader creates blank SplitHeader instance.
func NewSplitHeader() *SplitHeader {
return NewSplitHeaderFromV2(new(object.SplitHeader))
}
func (sh *SplitHeader) ToV2() *object.SplitHeader {
return (*object.SplitHeader)(sh)
}
func (sh *SplitHeader) ParentID() (v oid.ID, isSet bool) {
v2 := (*object.SplitHeader)(sh)
if id := v2.GetParent(); id != nil {
_ = v.ReadFromV2(*id)
isSet = true
}
return
}
func (sh *SplitHeader) SetParentID(v oid.ID) {
v2 := new(refs.ObjectID)
v.WriteToV2(v2)
(*object.SplitHeader)(sh).SetParent(v2)
}
func (sh *SplitHeader) PreviousID() (v oid.ID, isSet bool) {
v2 := (*object.SplitHeader)(sh)
if id := v2.GetPrevious(); id != nil {
_ = v.ReadFromV2(*id)
isSet = true
}
return
}
func (sh *SplitHeader) SetPreviousID(v oid.ID) {
v2 := new(refs.ObjectID)
v.WriteToV2(v2)
(*object.SplitHeader)(sh).SetPrevious(v2)
}
func (sh *SplitHeader) ParentSignature() *frostfscrypto.Signature {
v2 := (*object.SplitHeader)(sh)
if parSigV2 := v2.GetParentSignature(); parSigV2 != nil {
parSig := new(frostfscrypto.Signature)
_ = parSig.ReadFromV2(*parSigV2)
}
return nil
}
func (sh *SplitHeader) SetParentSignature(v *frostfscrypto.Signature) {
var parSigV2 *refs.Signature
if v != nil {
parSigV2 = new(refs.Signature)
v.WriteToV2(parSigV2)
}
(*object.SplitHeader)(sh).SetParentSignature(parSigV2)
}
func (sh *SplitHeader) ParentHeader() (parentHeader *Object) {
v2 := (*object.SplitHeader)(sh)
if parHdr := v2.GetParentHeader(); parHdr != nil {
parentHeader = New()
parentHeader.setHeaderField(func(h *object.Header) {
*h = *v2.GetParentHeader()
})
}
return
}
func (sh *SplitHeader) SetParentHeader(parentHeader *Object) {
(*object.SplitHeader)(sh).SetParentHeader(parentHeader.ToV2().GetHeader())
}
func (sh *SplitHeader) Children() (res []oid.ID) {
v2 := (*object.SplitHeader)(sh)
if children := v2.GetChildren(); len(children) > 0 {
res = make([]oid.ID, len(children))
for i := range children {
_ = res[i].ReadFromV2(children[i])
}
}
return
}
func (sh *SplitHeader) SetChildren(children []oid.ID) {
v2Children := make([]refs.ObjectID, len(children))
for i := range children {
children[i].WriteToV2(&v2Children[i])
}
(*object.SplitHeader)(sh).SetChildren(v2Children)
}
func (sh *SplitHeader) SplitID() *SplitID {
return NewSplitIDFromV2((*object.SplitHeader)(sh).GetSplitID())
}
func (sh *SplitHeader) SetSplitID(v *SplitID) {
(*object.SplitHeader)(sh).SetSplitID(v.ToV2())
}

View file

@ -116,9 +116,14 @@ func fromObject(obj *object.Object) *object.Object {
res.SetAttributes(obj.Attributes()...) res.SetAttributes(obj.Attributes()...)
res.SetType(obj.Type()) res.SetType(obj.Type())
// obj.SetSplitID creates splitHeader but we don't need to do it in case // There are two ways to specify split information:
// of small objects, so we should make nil check. // 1. Using explicit SplitHeader. Thus, we only propagate whole split information
if obj.SplitID() != nil { // if it's already set in the source object (use-case: Patch method).
// 2. Using SplitID - will automatically generate a SplitHeader, but this is not requiered for
// small objects.
if obj.SplitHeader() != nil {
res.SetSplitHeader(obj.SplitHeader())
} else if obj.SplitID() != nil {
res.SetSplitID(obj.SplitID()) res.SetSplitID(obj.SplitID())
} }

View file

@ -66,7 +66,7 @@ func (a *Address) FromString(s string) error {
if err == nil { if err == nil {
a.ma, err = multiaddr.NewMultiaddr(s) a.ma, err = multiaddr.NewMultiaddr(s)
if err == nil && hasTLS { if err == nil && hasTLS {
a.ma = a.ma.Encapsulate(tls) a.ma = a.ma.AppendComponent(tls)
} }
} }
} }

View file

@ -9,7 +9,7 @@ const (
) )
// tls var is used for (un)wrapping other multiaddrs around TLS multiaddr. // tls var is used for (un)wrapping other multiaddrs around TLS multiaddr.
var tls, _ = multiaddr.NewMultiaddr("/" + tlsProtocolName) var tls, _ = multiaddr.NewComponent(tlsProtocolName, "")
// IsTLSEnabled searches for wrapped TLS protocol in multiaddr. // IsTLSEnabled searches for wrapped TLS protocol in multiaddr.
func (a Address) IsTLSEnabled() bool { func (a Address) IsTLSEnabled() bool {

View file

@ -90,6 +90,8 @@ func (m MethodIndex) String() string {
return "containerGet" return "containerGet"
case methodContainerList: case methodContainerList:
return "containerList" return "containerList"
case methodContainerListStream:
return "containerListStream"
case methodContainerDelete: case methodContainerDelete:
return "containerDelete" return "containerDelete"
case methodEndpointInfo: case methodEndpointInfo:
@ -457,13 +459,16 @@ type PrmListStream struct {
// //
// Must be initialized using Pool.ListContainersStream, any other usage is unsafe. // Must be initialized using Pool.ListContainersStream, any other usage is unsafe.
type ResListStream struct { type ResListStream struct {
r *sdkClient.ContainerListReader r *sdkClient.ContainerListReader
handleError func(context.Context, apistatus.Status, error) error elapsedTimeCallback func(time.Duration)
handleError func(context.Context, apistatus.Status, error) error
} }
// Read reads another list of the container identifiers. // Read reads another list of the container identifiers.
func (x *ResListStream) Read(buf []cid.ID) (int, error) { func (x *ResListStream) Read(buf []cid.ID) (int, error) {
start := time.Now()
n, ok := x.r.Read(buf) n, ok := x.r.Read(buf)
x.elapsedTimeCallback(time.Since(start))
if !ok { if !ok {
res, err := x.r.Close() res, err := x.r.Close()
if err == nil { if err == nil {
@ -487,7 +492,14 @@ func (x *ResListStream) Read(buf []cid.ID) (int, error) {
// //
// Returns an error if container can't be read. // Returns an error if container can't be read.
func (x *ResListStream) Iterate(f func(cid.ID) bool) error { func (x *ResListStream) Iterate(f func(cid.ID) bool) error {
return x.r.Iterate(f) start := time.Now()
err := x.r.Iterate(func(id cid.ID) bool {
x.elapsedTimeCallback(time.Since(start))
stop := f(id)
start = time.Now()
return stop
})
return err
} }
// Close ends reading list of the matched containers and returns the result of the operation // Close ends reading list of the matched containers and returns the result of the operation
@ -508,11 +520,19 @@ func (c *clientWrapper) containerListStream(ctx context.Context, prm PrmListStre
Session: prm.Session, Session: prm.Session,
} }
res, err := cl.ContainerListInit(ctx, cliPrm) start := time.Now()
cnrRdr, err := cl.ContainerListInit(ctx, cliPrm)
c.incRequests(time.Since(start), methodContainerListStream)
if err = c.handleError(ctx, nil, err); err != nil { if err = c.handleError(ctx, nil, err); err != nil {
return ResListStream{}, fmt.Errorf("init container listing on client: %w", err) return ResListStream{}, fmt.Errorf("init container listing on client: %w", err)
} }
return ResListStream{r: res, handleError: c.handleError}, nil return ResListStream{
r: cnrRdr,
elapsedTimeCallback: func(elapsed time.Duration) {
c.incRequests(elapsed, methodContainerListStream)
},
handleError: c.handleError,
}, nil
} }
// containerDelete invokes sdkClient.ContainerDelete parse response status to error. // containerDelete invokes sdkClient.ContainerDelete parse response status to error.

View file

@ -2,6 +2,7 @@ package pool
import ( import (
"context" "context"
"fmt"
sdkClient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" sdkClient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
@ -134,7 +135,7 @@ func (it *internalTarget) putAsStream(ctx context.Context, o *object.Object) err
it.res.OID = res.StoredObjectID() it.res.OID = res.StoredObjectID()
it.res.Epoch = res.StoredEpoch() it.res.Epoch = res.StoredEpoch()
} }
return err return fmt.Errorf("put as stream '%s': %w", it.address, err)
} }
func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (bool, error) { func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (bool, error) {
@ -151,7 +152,7 @@ func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (b
res, err := it.client.ObjectPutSingle(ctx, cliPrm) res, err := it.client.ObjectPutSingle(ctx, cliPrm)
if err != nil && status.Code(err) == codes.Unimplemented { if err != nil && status.Code(err) == codes.Unimplemented {
return false, err return false, fmt.Errorf("address '%s': %w", it.address, err)
} }
if err == nil { if err == nil {
@ -166,5 +167,5 @@ func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (b
} }
return true, nil return true, nil
} }
return true, err return true, fmt.Errorf("try put single '%s': %w", it.address, err)
} }

View file

@ -1110,6 +1110,12 @@ func (p *Pool) PatchObject(ctx context.Context, prm PrmObjectPatch) (ResPatchObj
return res, nil return res, nil
} }
// LatestReceivedEpoch returns the epoch number extracted from the metadata
// of responses received from the client pool's most recent request.
func (p *Pool) LatestReceivedEpoch() uint64 {
return p.cache.Epoch()
}
// PutObject writes an object through a remote server using FrostFS API protocol. // PutObject writes an object through a remote server using FrostFS API protocol.
func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (ResPutObject, error) { func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (ResPutObject, error) {
cnr, _ := prm.hdr.ContainerID() cnr, _ := prm.hdr.ContainerID()
@ -1646,7 +1652,7 @@ func (p *Pool) GetSplitInfo(ctx context.Context, cnrID cid.ID, objID oid.ID, tok
case errors.As(err, &errSplit): case errors.As(err, &errSplit):
return errSplit.SplitInfo(), nil return errSplit.SplitInfo(), nil
case err == nil || errors.As(err, &errECInfo): case err == nil || errors.As(err, &errECInfo):
return nil, relations.ErrNoSplitInfo return nil, fmt.Errorf("failed to get raw object header %w", relations.ErrNoSplitInfo)
default: default:
return nil, fmt.Errorf("failed to get raw object header: %w", err) return nil, fmt.Errorf("failed to get raw object header: %w", err)
} }

View file

@ -372,7 +372,7 @@ func TestUpdateNodesHealth(t *testing.T) {
changed := tc.wasHealthy != tc.willHealthy changed := tc.wasHealthy != tc.willHealthy
require.Equalf(t, tc.willHealthy, cli.isHealthy(), "healthy status should be: %v", tc.willHealthy) require.Equalf(t, tc.willHealthy, cli.isHealthy(), "healthy status should be: %v", tc.willHealthy)
require.Equalf(t, changed, 1 == log.Len(), "healthy status should be changed: %v", changed) require.Equalf(t, changed, log.Len() == 1, "healthy status should be changed: %v", changed)
}) })
} }
} }

View file

@ -97,6 +97,11 @@ func (n NodeStatistic) AverageListContainer() time.Duration {
return n.averageTime(methodContainerList) return n.averageTime(methodContainerList)
} }
// AverageListContainerStream returns average time to perform ContainerListStream request.
func (n NodeStatistic) AverageListContainerStream() time.Duration {
return n.averageTime(methodContainerListStream)
}
// AverageDeleteContainer returns average time to perform ContainerDelete request. // AverageDeleteContainer returns average time to perform ContainerDelete request.
func (n NodeStatistic) AverageDeleteContainer() time.Duration { func (n NodeStatistic) AverageDeleteContainer() time.Duration {
return n.averageTime(methodContainerDelete) return n.averageTime(methodContainerDelete)

View file

@ -49,11 +49,11 @@ func (c *treeClient) dial(ctx context.Context) error {
var err error var err error
c.client, err = c.createClient() c.client, err = c.createClient()
if err != nil { if err != nil {
return err return fmt.Errorf("couldn't dial '%s': %w", c.address, err)
} }
if _, err = rpcapi.Healthcheck(c.client, &tree.HealthcheckRequest{}, rpcclient.WithContext(ctx)); err != nil { if _, err = rpcapi.Healthcheck(c.client, &tree.HealthcheckRequest{}, rpcclient.WithContext(ctx)); err != nil {
return fmt.Errorf("healthcheck tree service: %w", err) return fmt.Errorf("healthcheck tree service '%s': %w", c.address, err)
} }
c.healthy = true c.healthy = true
@ -127,5 +127,9 @@ func (c *treeClient) close() error {
if c.client == nil || c.client.Conn() == nil { if c.client == nil || c.client.Conn() == nil {
return nil return nil
} }
return c.client.Conn().Close() err := c.client.Conn().Close()
if err != nil {
return fmt.Errorf("address '%s': %w", c.address, err)
}
return nil
} }

View file

@ -295,7 +295,7 @@ func (p *Pool) Dial(ctx context.Context) error {
for j, node := range nodes { for j, node := range nodes {
clients[j] = newTreeClient(node.Address(), p.dialOptions, p.nodeDialTimeout, p.streamTimeout) clients[j] = newTreeClient(node.Address(), p.dialOptions, p.nodeDialTimeout, p.streamTimeout)
if err := clients[j].dial(ctx); err != nil { if err := clients[j].dial(ctx); err != nil {
p.log(zap.WarnLevel, "failed to dial tree client", zap.String("address", node.Address()), zap.Error(err)) p.log(zap.WarnLevel, "failed to dial tree client", zap.Error(err))
continue continue
} }
@ -1081,21 +1081,16 @@ func (p *Pool) deleteClientFromMap(hash uint64) {
} }
func (p *Pool) getNewTreeClient(ctx context.Context, node netmap.NodeInfo) (*treeClient, error) { func (p *Pool) getNewTreeClient(ctx context.Context, node netmap.NodeInfo) (*treeClient, error) {
var ( for endpoint := range node.NetworkEndpoints() {
treeCl *treeClient
err error
)
node.IterateNetworkEndpoints(func(endpoint string) bool {
var addr network.Address var addr network.Address
if err = addr.FromString(endpoint); err != nil { if err := addr.FromString(endpoint); err != nil {
p.log(zap.WarnLevel, "can't parse endpoint", zap.String("endpoint", endpoint), zap.Error(err)) p.log(zap.WarnLevel, "can't parse endpoint", zap.String("endpoint", endpoint), zap.Error(err))
return false continue
} }
newTreeCl := newTreeClient(addr.URIAddr(), p.dialOptions, p.nodeDialTimeout, p.streamTimeout) newTreeCl := newTreeClient(addr.URIAddr(), p.dialOptions, p.nodeDialTimeout, p.streamTimeout)
if err = newTreeCl.dial(ctx); err != nil { if err := newTreeCl.dial(ctx); err != nil {
p.log(zap.WarnLevel, "failed to dial tree client", zap.String("address", addr.URIAddr()), zap.Error(err)) p.log(zap.WarnLevel, "failed to dial tree client", zap.Error(err))
// We have to close connection here after failed `dial()`. // We have to close connection here after failed `dial()`.
// This is NOT necessary in object pool and regular tree pool without netmap support, because: // This is NOT necessary in object pool and regular tree pool without netmap support, because:
@ -1103,21 +1098,16 @@ func (p *Pool) getNewTreeClient(ctx context.Context, node netmap.NodeInfo) (*tre
// - regular tree pool is going to reuse connection by calling `redialIfNecessary()`. // - regular tree pool is going to reuse connection by calling `redialIfNecessary()`.
// Tree pool with netmap support does not operate with background goroutine, so we have to close connection immediately. // Tree pool with netmap support does not operate with background goroutine, so we have to close connection immediately.
if err = newTreeCl.close(); err != nil { if err = newTreeCl.close(); err != nil {
p.log(zap.WarnLevel, "failed to close recently dialed tree client", zap.String("address", addr.URIAddr()), zap.Error(err)) p.log(zap.WarnLevel, "failed to close recently dialed tree client", zap.Error(err))
} }
return false continue
} }
treeCl = newTreeCl return newTreeCl, nil
return true
})
if treeCl == nil {
return nil, fmt.Errorf("tree client wasn't initialized")
} }
return treeCl, nil return nil, fmt.Errorf("tree client wasn't initialized")
} }
func shouldTryAgain(err error) bool { func shouldTryAgain(err error) bool {